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 <[EMAIL PROTECTED]>
Signed-off-by: Ramachandra K <[EMAIL PROTECTED]>
---

 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 {
_______________________________________________
ewg mailing list
[email protected]
http://lists.openfabrics.org/cgi-bin/mailman/listinfo/ewg

Reply via email to