[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