[ewg] [PATCH IB/VNIC] BUG FIX for VNIC hang on CM Reject

Ramachandra Kuchimanchi ramachandra.kuchimanchi at qlogic.com
Mon Mar 26 07:55:29 PDT 2007


From: Poornima Kamath <poornima.kamath at qlogic.com>
Signed-Off-By: Ramachandra Kuchimanchi <ramachandra.kuchimanchi at qlogic.com>

This is a fix for the VNIC hanging on stopping the service when there is a CM
Reject.
---

 drivers/infiniband/ulp/vnic/vnic_ib.c     |   12 ++++++------
 drivers/infiniband/ulp/vnic/vnic_ib.h     |    1 -
 drivers/infiniband/ulp/vnic/vnic_viport.c |    4 ----
 3 files changed, 6 insertions(+), 11 deletions(-)

diff --git a/drivers/infiniband/ulp/vnic/vnic_ib.c b/drivers/infiniband/ulp/vnic/vnic_ib.c
index 56ae9f7..f3a40d1 100644
--- a/drivers/infiniband/ulp/vnic/vnic_ib.c
+++ b/drivers/infiniband/ulp/vnic/vnic_ib.c
@@ -395,6 +395,7 @@ int vnic_ib_cm_handler(struct ib_cm_id *
 	switch (event->event) {
 	case IB_CM_REQ_ERROR:
 		IB_ERROR("sending CM REQ failed\n");
+		err = 1;
 		disconn = 1;
 		break;
 	case IB_CM_REP_RECEIVED:
@@ -417,6 +418,7 @@ int vnic_ib_cm_handler(struct ib_cm_id *
 			printk(KERN_ERR "reason code : 0x%x\n",
 			       event->param.rej_rcvd.reason);
 
+		err = 1;
 		disconn = 1;
 		break;
 	case IB_CM_MRA_RECEIVED:
@@ -439,17 +441,15 @@ int vnic_ib_cm_handler(struct ib_cm_id *
 
 	}
 
+	if (disconn)
+		viport->disconnect = 1;
+
 	if (err) {
 		ib_conn->state = IB_CONN_DISCONNECTED;
 		viport_failure(viport);
 	}
 
-	if (disconn) {
-		ib_conn->state = IB_CONN_DISCONNECTED;
-		viport_disconnect(viport);
-
-	}
-	complete(&ib_conn->done);
+	viport_kick(viport);
 	return 0;
 }
 
diff --git a/drivers/infiniband/ulp/vnic/vnic_ib.h b/drivers/infiniband/ulp/vnic/vnic_ib.h
index f009876..ad66c24 100644
--- a/drivers/infiniband/ulp/vnic/vnic_ib.h
+++ b/drivers/infiniband/ulp/vnic/vnic_ib.h
@@ -63,7 +63,6 @@ struct vnic_ib_conn {
 	struct ib_qp		*qp;
 	struct ib_cq		*cq;
 	struct ib_cm_id		*cm_id;
-	struct completion	done;
 #ifdef CONFIG_INFINIBAND_VNIC_STATS
 	struct {
 		cycles_t	connection_time;
diff --git a/drivers/infiniband/ulp/vnic/vnic_viport.c b/drivers/infiniband/ulp/vnic/vnic_viport.c
index 1dee71a..a19fd4c 100644
--- a/drivers/infiniband/ulp/vnic/vnic_viport.c
+++ b/drivers/infiniband/ulp/vnic/vnic_viport.c
@@ -428,7 +428,6 @@ static int viport_handle_control_states(
 	do {
 		switch(old_state = viport->link_state) {
 		case LINK_CONTROLCONNECT:
-			init_completion(&(viport->control.ib_conn.done));
 			if (vnic_ib_cm_connect(&viport->control.ib_conn))
 				viport->link_state = LINK_CLEANUPDATA;
 			else
@@ -436,7 +435,6 @@ static int viport_handle_control_states(
 			break;
 		case LINK_CONTROLCONNECTWAIT:
 			LINK_STATE("state LINK_CONTROLCONNECTWAIT\n");
-			wait_for_completion(&(viport->control.ib_conn.done));
 			if (control_is_connected(&viport->control))
 				viport->link_state = LINK_INITVNICREQ;
 			if (viport->errored) {
@@ -530,7 +528,6 @@ static int viport_handle_data_states(str
 			break;
 		case LINK_DATACONNECT:
 			LINK_STATE("state LINK_DATACONNECT\n");
-			init_completion(&viport->data.ib_conn.done);
 			if (data_connect(&viport->data))
 				viport->link_state = LINK_RESETCONTROL;
 			else
@@ -538,7 +535,6 @@ static int viport_handle_data_states(str
 			break;
 		case LINK_DATACONNECTWAIT:
 			LINK_STATE("state LINK_DATACONNECTWAIT\n");
-			wait_for_completion(&viport->data.ib_conn.done);
 			control_process_async(&viport->control);
 			if (data_is_connected(&viport->data))
 				viport->link_state = LINK_XCHGPOOLREQ;





More information about the ewg mailing list