[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