[ewg] [PATCH 7/10 VNIC] Retry sending CM requests on failure

Ramachandra K ramachandra.kuchimanchi at qlogic.com
Tue Aug 21 07:26:09 PDT 2007


On CM request sending failure, retry sending CM requests for 10 minutes.
After 10 minutes stop retrying and send a timed out message.

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

 drivers/infiniband/ulp/vnic/vnic_ib.c     |    2 +-
 drivers/infiniband/ulp/vnic/vnic_viport.c |   37 +++++++++++++++++++++++++++++
 drivers/infiniband/ulp/vnic/vnic_viport.h |    1 +
 3 files changed, 39 insertions(+), 1 deletions(-)

diff --git a/drivers/infiniband/ulp/vnic/vnic_ib.c b/drivers/infiniband/ulp/vnic/vnic_ib.c
index ced4f04..a11eed2 100644
--- a/drivers/infiniband/ulp/vnic/vnic_ib.c
+++ b/drivers/infiniband/ulp/vnic/vnic_ib.c
@@ -396,7 +396,7 @@ int vnic_ib_cm_handler(struct ib_cm_id *
 	case IB_CM_REQ_ERROR:
 		IB_ERROR("sending CM REQ failed\n");
 		err = 1;
-		disconn = 1;
+		viport->retry = 1;
 		break;
 	case IB_CM_REP_RECEIVED:
 		IB_INFO("CM REP recvd\n");
diff --git a/drivers/infiniband/ulp/vnic/vnic_viport.c b/drivers/infiniband/ulp/vnic/vnic_viport.c
index 8c3c845..26ec4a2 100644
--- a/drivers/infiniband/ulp/vnic/vnic_viport.c
+++ b/drivers/infiniband/ulp/vnic/vnic_viport.c
@@ -48,6 +48,10 @@
 
 #define VIPORT_DISCONN_TIMER	10000 /*in ms*/
 
+#define MAX_RETRY_INTERVAL 	  20000  /* 20 seconds*/
+#define RETRY_INCREMENT		  5000   /* 5 seconds */
+#define MAX_CONNECT_RETRY_TIMEOUT 600000 /* 10 minutes*/
+
 DECLARE_WAIT_QUEUE_HEAD(viport_queue);
 LIST_HEAD(viport_list);
 DECLARE_COMPLETION(viport_thread_exit);
@@ -55,6 +59,8 @@ spinlock_t viport_list_lock = SPIN_LOCK_
 
 int viport_thread = -1;
 int viport_thread_end = 0;
+static u32 total_retry_duration = 0;
+static u32 retry_duration = 0;
 
 static void viport_timer(struct viport *viport, int timeout);
 struct viport *viport_allocate(struct viport_config *config)
@@ -609,6 +615,8 @@ static int viport_handle_xchgpool_states
 				viport->updates |= NEED_LINK_CONFIG;
 			spin_unlock_irq(&viport->lock);
 			viport->link_state = LINK_IDLE;
+			retry_duration = 0;
+			total_retry_duration = 0;
 			break;
 		default:
 			return -1;
@@ -914,6 +922,35 @@ static int viport_handle_disconn_states(
 					  viport->parent);
 			if (viport->disconnect != 0)
 				viport->link_state = LINK_UNINITIALIZED;
+			else if (viport->retry == 1) {
+				viport->retry = 0;
+			/*
+			 * Check if the initial retry interval has crossed
+			 * 20 seconds.
+			 * The retry interval is initially 5 seconds which
+                         * is incremented by 5. Once it is 20 the interval
+                         * is fixed to 20 seconds till 10 minutes,
+			 * after which retrying is stopped
+			 */
+				if (retry_duration  < MAX_RETRY_INTERVAL)
+					retry_duration += RETRY_INCREMENT;
+
+				total_retry_duration += retry_duration;
+
+				if (total_retry_duration >=
+					MAX_CONNECT_RETRY_TIMEOUT) {
+					viport->link_state = LINK_UNINITIALIZED;
+					printk("Timed out after retrying"
+					       " for retry_duration %d msecs\n"
+						, retry_duration);
+				}
+				else {
+					viport->connect = DELAY;
+					viport->link_state = LINK_RETRYWAIT;
+				}
+				viport_timer(viport,
+				     msecs_to_jiffies(retry_duration));
+			}
 			else {
 				u32 duration = 500 + ((net_random()) & 0x1FF);
 				if (!viport->parent->is_primary_path)
diff --git a/drivers/infiniband/ulp/vnic/vnic_viport.h b/drivers/infiniband/ulp/vnic/vnic_viport.h
index 6ad7a08..b144fac 100644
--- a/drivers/infiniband/ulp/vnic/vnic_viport.h
+++ b/drivers/infiniband/ulp/vnic/vnic_viport.h
@@ -123,6 +123,7 @@ struct viport {
 	u32				errored;
 	enum { WAIT, DELAY, NOW }	connect;
 	u32				disconnect;
+	u32 				retry;
 	wait_queue_head_t		disconnect_queue;
 	int				timer_active;
 	struct timer_list		timer;



More information about the ewg mailing list