[ewg] [PATCH 3/10 VNIC] Improvements for EVIC scalability

Ramachandra K ramachandra.kuchimanchi at qlogic.com
Tue Aug 21 07:23:42 PDT 2007


Improve EVIC scalability by delaying host connections. Increase the time to
wait for a control response to handle the case when there are many hosts
trying to reconnect to the EVIC.

From: Poornima Kamath <poornima.kamath at qlogic.com>
Signed-off-by: Ramachandra K <ramachandra.kuchimanchi at qlogic.com>
---

 drivers/infiniband/ulp/vnic/vnic_config.c  |   15 +++++++++--
 drivers/infiniband/ulp/vnic/vnic_config.h  |    4 ++-
 drivers/infiniband/ulp/vnic/vnic_main.c    |    5 ++--
 drivers/infiniband/ulp/vnic/vnic_netpath.h |    1 +
 drivers/infiniband/ulp/vnic/vnic_viport.c  |   39 ++++++++++++++++++++++------
 drivers/infiniband/ulp/vnic/vnic_viport.h  |    3 +-
 6 files changed, 52 insertions(+), 15 deletions(-)

diff --git a/drivers/infiniband/ulp/vnic/vnic_config.c b/drivers/infiniband/ulp/vnic/vnic_config.c
index 0447427..e9db52d 100644
--- a/drivers/infiniband/ulp/vnic/vnic_config.c
+++ b/drivers/infiniband/ulp/vnic/vnic_config.c
@@ -55,7 +55,6 @@ static u16 max_mtu = MAX_MTU;
 
 static u32 default_no_path_timeout = DEFAULT_NO_PATH_TIMEOUT;
 static u32 sa_path_rec_get_timeout = SA_PATH_REC_GET_TIMEOUT;
-
 static u32 default_primary_reconnect_timeout =
 				    DEFAULT_PRIMARY_RECONNECT_TIMEOUT;
 static u32 default_primary_switch_timeout = DEFAULT_PRIMARY_SWITCH_TIMEOUT;
@@ -64,6 +63,7 @@ static int default_prefer_primary
 static int use_rx_csum = VNIC_USE_RX_CSUM;
 static int use_tx_csum = VNIC_USE_TX_CSUM;
 
+static u32 control_response_timeout = CONTROL_RSP_TIMEOUT;
 module_param(max_mtu, ushort, 0444);
 MODULE_PARM_DESC(max_mtu, "Maximum MTU size (1500-9500). Default is 9500");
 
@@ -91,6 +91,11 @@ module_param(sa_path_rec_get_timeout, ui
 MODULE_PARM_DESC(sa_path_rec_get_timeout, "Time out value in milliseconds"
 		 " for SA path record get queries");
 
+module_param(control_response_timeout, uint, 0444);
+MODULE_PARM_DESC(control_response_timeout, "Time out value in milliseconds"
+		 " to wait for response to control requests");
+
+
 static void config_control_defaults(struct control_config *control_config,
 				    struct path_param *params)
 {
@@ -133,7 +138,7 @@ static void config_control_defaults(stru
 	control_config->vnic_instance = params->instance;
 	control_config->max_address_entries = MAX_ADDRESS_ENTRIES;
 	control_config->min_address_entries = MIN_ADDRESS_ENTRIES;
-	control_config->rsp_timeout = msecs_to_jiffies(CONTROL_RSP_TIMEOUT);
+	control_config->rsp_timeout = msecs_to_jiffies(control_response_timeout);
 }
 
 static void config_data_defaults(struct data_config *data_config,
@@ -331,6 +336,12 @@ int config_start(void)
 	sa_path_rec_get_timeout = max_t(u32, sa_path_rec_get_timeout,
 					MIN_SA_TIMEOUT);
 
+	control_response_timeout = min_t(u32, control_response_timeout,
+					 MIN_CONTROL_RSP_TIMEOUT);
+
+	control_response_timeout = max_t(u32, control_response_timeout,
+					 MAX_CONTROL_RSP_TIMEOUT);
+
 	if (!default_no_path_timeout)
 		default_no_path_timeout = DEFAULT_NO_PATH_TIMEOUT;
 
diff --git a/drivers/infiniband/ulp/vnic/vnic_config.h b/drivers/infiniband/ulp/vnic/vnic_config.h
index 03cbf9c..e0a473d 100644
--- a/drivers/infiniband/ulp/vnic/vnic_config.h
+++ b/drivers/infiniband/ulp/vnic/vnic_config.h
@@ -100,7 +100,9 @@ enum {
 };
 
 enum {
-	CONTROL_RSP_TIMEOUT		= 1000	/* 1 sec */
+	CONTROL_RSP_TIMEOUT		= 1000,	/* 1 sec */
+	MIN_CONTROL_RSP_TIMEOUT		= 1000,	/* 1  sec */
+	MAX_CONTROL_RSP_TIMEOUT		= 60000	/* 60 sec */
 };
 
 /* infiniband connection parameters */
diff --git a/drivers/infiniband/ulp/vnic/vnic_main.c b/drivers/infiniband/ulp/vnic/vnic_main.c
index e15d3f9..eab123b 100644
--- a/drivers/infiniband/ulp/vnic/vnic_main.c
+++ b/drivers/infiniband/ulp/vnic/vnic_main.c
@@ -465,9 +465,10 @@ static void update_path_and_reconnect(st
 		netpath->path_idx = config->path_idx;
 		netpath->connect_time = jiffies;
 		delay = 0;
-	} else if (config->path_idx != netpath->path_idx)
+	} else if (config->path_idx != netpath->path_idx) {
 		delay = 0;
-
+		netpath->path_idx = config->path_idx;
+	}
 	viport_connect(netpath->viport, delay);
 }
 
diff --git a/drivers/infiniband/ulp/vnic/vnic_netpath.h b/drivers/infiniband/ulp/vnic/vnic_netpath.h
index a5ee45c..51fa3a8 100644
--- a/drivers/infiniband/ulp/vnic/vnic_netpath.h
+++ b/drivers/infiniband/ulp/vnic/vnic_netpath.h
@@ -53,6 +53,7 @@ struct netpath {
 	size_t			path_idx;
 	u32			connect_time;
 	int			second_bias;
+	u8			is_primary_path;
 	struct timer_list	timer;
 	enum netpath_ts		timer_state;
 	struct class_dev_info	class_dev_info;
diff --git a/drivers/infiniband/ulp/vnic/vnic_viport.c b/drivers/infiniband/ulp/vnic/vnic_viport.c
index a19fd4c..8c3c845 100644
--- a/drivers/infiniband/ulp/vnic/vnic_viport.c
+++ b/drivers/infiniband/ulp/vnic/vnic_viport.c
@@ -35,6 +35,7 @@
 #include <linux/netdevice.h>
 #include <linux/completion.h>
 #include <linux/delay.h>
+#include <linux/net.h>
 
 #include "vnic_util.h"
 #include "vnic_main.h"
@@ -55,6 +56,7 @@ spinlock_t viport_list_lock = SPIN_LOCK_
 int viport_thread = -1;
 int viport_thread_end = 0;
 
+static void viport_timer(struct viport *viport, int timeout);
 struct viport *viport_allocate(struct viport_config *config)
 {
 	struct viport *viport;
@@ -67,19 +69,18 @@ struct viport *viport_allocate(struct vi
 	}
 
 	viport->state = VIPORT_DISCONNECTED;
-	viport->link_state = LINK_RETRYWAIT;
+	viport->link_state = LINK_FIRSTCONNECT;
 	viport->connect = WAIT;
 	viport->new_mtu = 1500;
 	viport->new_flags = 0;
 	viport->config = config;
+	viport->connect = DELAY;
 
 	spin_lock_init(&viport->lock);
 	init_waitqueue_head(&viport->stats_queue);
 	init_waitqueue_head(&viport->disconnect_queue);
 	INIT_LIST_HEAD(&viport->list_ptrs);
 
-	viport_kick(viport);
-
 	return viport;
 }
 
@@ -87,12 +88,18 @@ void viport_connect(struct viport * vipo
 {
 	VIPORT_FUNCTION("viport_connect()\n");
 
-	if (delay)
-		viport->connect = DELAY;
+	if (viport->connect != DELAY)
+		viport->connect = (delay) ? DELAY : NOW;
+	if (viport->link_state == LINK_FIRSTCONNECT){
+		u32 duration;
+		duration = (net_random() & 0x1ff);
+		if (!viport->parent->is_primary_path)
+			duration += 0x1ff;
+		viport->link_state = LINK_RETRYWAIT;
+		viport_timer(viport,duration);
+	}
 	else
-		viport->connect = NOW;
-
-	viport_kick(viport);
+		viport_kick(viport);
 }
 
 void viport_disconnect(struct viport *viport)
@@ -908,8 +915,12 @@ static int viport_handle_disconn_states(
 			if (viport->disconnect != 0)
 				viport->link_state = LINK_UNINITIALIZED;
 			else {
+				u32 duration = 500 + ((net_random()) & 0x1FF);
+				if (!viport->parent->is_primary_path)
+					duration += 0x1ff;
 				viport_timer(viport,
-				     msecs_to_jiffies(VIPORT_DISCONN_TIMER));
+					     msecs_to_jiffies(duration));
+				viport->connect = DELAY;
 				viport->link_state = LINK_RETRYWAIT;
 			}
 			break;
@@ -930,6 +941,16 @@ static int viport_handle_disconn_states(
 				viport->link_state = LINK_INITIALIZE;
 			}
 			break;
+		case LINK_FIRSTCONNECT:
+			viport->stats.ethernet_status = 0;
+			viport->updates = 0;
+			wake_up(&viport->stats_queue);
+			if (viport->disconnect !=0) {
+				viport_timer_stop(viport);
+				viport->link_state = LINK_UNINITIALIZED;
+			}
+
+			break;
 		default:
 			return -1;
 		}
diff --git a/drivers/infiniband/ulp/vnic/vnic_viport.h b/drivers/infiniband/ulp/vnic/vnic_viport.h
index 5ddf524..6ad7a08 100644
--- a/drivers/infiniband/ulp/vnic/vnic_viport.h
+++ b/drivers/infiniband/ulp/vnic/vnic_viport.h
@@ -77,7 +77,8 @@ enum link_state {
 	LINK_CLEANUPDATA	= 32,
 	LINK_CLEANUPCONTROL	= 33,
 	LINK_DISCONNECTED	= 34,
-	LINK_RETRYWAIT		= 35
+	LINK_RETRYWAIT		= 35,
+	LINK_FIRSTCONNECT	= 36
 };
 
 enum {



More information about the ewg mailing list