[ofa-general] [PATCH] RDMA:nes: improve cm_id reference count handling

Faisal Latif faisal.latif at intel.com
Tue Apr 14 14:20:18 PDT 2009


We are now calling cm_id's ref count increment from only connect, accept,
reject, and listen. The ref count will only be derecremented when
cm_node is freed.

Couple of error handling improvements while doing the cm_id reference count
enhancement are also included.

Signed-off-by: Faisal Latif <faisal.latif at intel.com>
---
 drivers/infiniband/hw/nes/nes_cm.c    |   41 +++++++++++++++-----------------
 drivers/infiniband/hw/nes/nes_hw.c    |    1 -
 drivers/infiniband/hw/nes/nes_verbs.c |    2 -
 3 files changed, 19 insertions(+), 25 deletions(-)

diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
index 61da9d3..57d867e 100644
--- a/drivers/infiniband/hw/nes/nes_cm.c
+++ b/drivers/infiniband/hw/nes/nes_cm.c
@@ -490,7 +490,6 @@ static void nes_retrans_expired(struct nes_cm_node *cm_node)
 static void handle_recv_entry(struct nes_cm_node *cm_node, u32 rem_node)
 {
 	struct nes_timer_entry *recv_entry = cm_node->recv_entry;
-	struct iw_cm_id *cm_id = cm_node->cm_id;
 	struct nes_qp *nesqp;
 	unsigned long qplockflags;
 
@@ -522,8 +521,6 @@ static void handle_recv_entry(struct nes_cm_node *cm_node, u32 rem_node)
 		/* TIME_WAIT state */
 		rem_ref_cm_node(cm_node->cm_core, cm_node);
 	}
-	if (cm_node->cm_id)
-		cm_id->rem_ref(cm_id);
 	kfree(recv_entry);
 	cm_node->recv_entry = NULL;
 }
@@ -994,8 +991,6 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,
 					event.cm_info.cm_id = cm_node->cm_id;
 					cm_event_reset(&event);
 
-					rem_ref_cm_node(cm_node->cm_core,
-							 cm_node);
 
 				}
 			}
@@ -1219,6 +1214,7 @@ static int rem_ref_cm_node(struct nes_cm_core *cm_core,
 {
 	unsigned long flags;
 	struct nes_qp *nesqp;
+	struct iw_cm_id *cm_id = cm_node->cm_id;
 
 	if (!cm_node)
 		return -EINVAL;
@@ -1260,6 +1256,14 @@ static int rem_ref_cm_node(struct nes_cm_core *cm_core,
 		nes_rem_ref(&nesqp->ibqp);
 		cm_node->nesqp = NULL;
 	}
+	if (cm_id) {
+		if (cm_node->listener) {
+			if (cm_node->cm_id != cm_node->listener->cm_id)
+				cm_id->rem_ref(cm_id);
+		} else {
+			cm_id->rem_ref(cm_id);
+		}
+	}
 
 	kfree(cm_node);
 	return 0;
@@ -1410,14 +1414,10 @@ static void handle_rst_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
 		drop_packet(skb);
 		break;
 	case NES_CM_STATE_LAST_ACK:
-		cm_node->cm_id->rem_ref(cm_node->cm_id);
+	case NES_CM_STATE_FIN_WAIT1:
 	case NES_CM_STATE_TIME_WAIT:
-		cm_node->state = NES_CM_STATE_CLOSED;
-		rem_ref_cm_node(cm_node->cm_core, cm_node);
-		drop_packet(skb);
+		passive_open_err(cm_node, skb, reset);
 		break;
-	case NES_CM_STATE_FIN_WAIT1:
-		nes_debug(NES_DBG_CM, "Bad state %s[%u]\n", __func__, __LINE__);
 	default:
 		drop_packet(skb);
 		break;
@@ -1721,7 +1721,6 @@ static int handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
 	case NES_CM_STATE_CLOSING:
 		cleanup_retrans_entry(cm_node);
 		cm_node->state = NES_CM_STATE_CLOSED;
-		cm_node->cm_id->rem_ref(cm_node->cm_id);
 		rem_ref_cm_node(cm_node->cm_core, cm_node);
 		drop_packet(skb);
 		break;
@@ -2101,6 +2100,7 @@ static int mini_cm_reject(struct nes_cm_core *cm_core,
 		passive_state = atomic_add_return(1, &cm_node->passive_state);
 		if (passive_state == NES_SEND_RESET_EVENT) {
 			cm_node->state = NES_CM_STATE_CLOSED;
+			cm_id->add_ref(cm_id);
 			rem_ref_cm_node(cm_core, cm_node);
 		} else {
 			ret = send_mpa_reject(cm_node);
@@ -2126,7 +2126,6 @@ static int mini_cm_reject(struct nes_cm_core *cm_core,
 
 		cm_id = loopback->cm_id;
 		rem_ref_cm_node(cm_core, loopback);
-		cm_id->rem_ref(cm_id);
 	}
 
 	return ret;
@@ -2588,7 +2587,6 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp)
 				nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret);
 			}
 
-			cm_id->rem_ref(cm_id);
 
 			spin_lock_irqsave(&nesqp->lock, flags);
 			if (nesqp->flush_issued == 0) {
@@ -2708,7 +2706,6 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
 	/* associate the node with the QP */
 	nesqp->cm_node = (void *)cm_node;
 	cm_node->nesqp = nesqp;
-	nes_add_ref(&nesqp->ibqp);
 
 	nes_debug(NES_DBG_CM, "QP%u, cm_node=%p, jiffies = %lu listener = %p\n",
 		nesqp->hwqp.qp_id, cm_node, jiffies, cm_node->listener);
@@ -2761,6 +2758,9 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
 			nes_debug(NES_DBG_CM, "Unable to register memory region"
 					"for lSMM for cm_node = %p \n",
 					cm_node);
+			pci_free_consistent(nesdev->pcidev,
+				nesqp->private_data_len+sizeof(struct ietf_mpa_frame),
+				nesqp->ietf_frame, nesqp->ietf_frame_pbase);
 			return -ENOMEM;
 		}
 
@@ -2797,6 +2797,8 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
 
 
 	/* Cache the cm_id in the qp */
+	nes_add_ref(&nesqp->ibqp);
+	cm_id->add_ref(cm_id);
 	nesqp->cm_id = cm_id;
 	cm_node->cm_id = cm_id;
 
@@ -2875,8 +2877,7 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
 			sizeof(struct ietf_mpa_frame));
 
 
-	/* notify OF layer that accept event was successful */
-	cm_id->add_ref(cm_id);
+	/* notify OF layer that accept event was successfull */
 
 	cm_event.event = IW_CM_EVENT_ESTABLISHED;
 	cm_event.status = IW_CM_EVENT_STATUS_ACCEPTED;
@@ -3360,7 +3361,6 @@ static void cm_event_connect_error(struct nes_cm_event *event)
 	if (ret)
 		printk(KERN_ERR "%s[%u] OFA CM event_handler returned, "
 			"ret=%d\n", __func__, __LINE__, ret);
-	cm_id->rem_ref(cm_id);
 
 	rem_ref_cm_node(event->cm_node->cm_core, event->cm_node);
 	return;
@@ -3400,7 +3400,6 @@ static void cm_event_reset(struct nes_cm_event *event)
 	cm_event.private_data_len = 0;
 
 	ret = cm_id->event_handler(cm_id, &cm_event);
-	cm_id->add_ref(cm_id);
 	atomic_inc(&cm_closes);
 	cm_event.event = IW_CM_EVENT_CLOSE;
 	cm_event.status = IW_CM_EVENT_STATUS_OK;
@@ -3416,7 +3415,7 @@ static void cm_event_reset(struct nes_cm_event *event)
 
 
 	/* notify OF layer about this connection error event */
-	cm_id->rem_ref(cm_id);
+	rem_ref_cm_node(event->cm_node->cm_core, event->cm_node);
 
 	return;
 }
@@ -3518,7 +3517,6 @@ static int nes_cm_post_event(struct nes_cm_event *event)
 {
 	atomic_inc(&event->cm_node->cm_core->events_posted);
 	add_ref_cm_node(event->cm_node);
-	event->cm_info.cm_id->add_ref(event->cm_info.cm_id);
 	INIT_WORK(&event->event_work, nes_cm_event_handler);
 	nes_debug(NES_DBG_CM, "cm_node=%p queue_work, event=%p\n",
 		event->cm_node, event);
@@ -3590,7 +3588,6 @@ static void nes_cm_event_handler(struct work_struct *work)
 	}
 
 	atomic_dec(&cm_core->events_posted);
-	event->cm_info.cm_id->rem_ref(event->cm_info.cm_id);
 	rem_ref_cm_node(cm_core, event->cm_node);
 	kfree(event);
 
diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c
index d6fc9ae..9c9e4ff 100644
--- a/drivers/infiniband/hw/nes/nes_hw.c
+++ b/drivers/infiniband/hw/nes/nes_hw.c
@@ -2944,7 +2944,6 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
 		case NES_AEQE_AEID_LLP_FIN_RECEIVED:
 			nesqp = *((struct nes_qp **)&context);
 			if (atomic_inc_return(&nesqp->close_timer_started) == 1) {
-				nesqp->cm_id->add_ref(nesqp->cm_id);
 				schedule_nes_timer(nesqp->cm_node, (struct sk_buff *)nesqp,
 						NES_TIMER_TYPE_CLOSE, 1, 0);
 				nes_debug(NES_DBG_AEQ, "QP%u Not decrementing QP refcount (%d),"
diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c
index dab7e2f..ad9c1f5 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.c
+++ b/drivers/infiniband/hw/nes/nes_verbs.c
@@ -1542,7 +1542,6 @@ static int nes_destroy_qp(struct ib_qp *ibqp)
 				"QP%u. cm_id = %p, refcount = %u. \n",
 				nesqp->hwqp.qp_id, cm_id, atomic_read(&nesqp->refcount));
 
-		cm_id->rem_ref(cm_id);
 		ret = cm_id->event_handler(cm_id, &cm_event);
 		if (ret)
 			nes_debug(NES_DBG_QP, "OFA CM event_handler returned, ret=%d\n", ret);
@@ -3178,7 +3177,6 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
 				if (nesqp->cm_id) {
 					/* These two are for the timer thread */
 					if (atomic_inc_return(&nesqp->close_timer_started) == 1) {
-						nesqp->cm_id->add_ref(nesqp->cm_id);
 						nes_debug(NES_DBG_MOD_QP, "QP%u Not decrementing QP refcount (%d),"
 								" need ae to finish up, original_last_aeq = 0x%04X."
 								" last_aeq = 0x%04X, scheduling timer.\n",
-- 
1.5.3.3




More information about the general mailing list