[openib-general] [PATCH] collapse MAD function calls

Sean Hefty mshefty at ichips.intel.com
Fri Nov 12 16:45:09 PST 2004


This patch callapses several function calls into one when activating
the MAD QPs.  This avoids repeated allocation/freeing of memory.

I have plans to examine the QP transitions to the reset
state to see if these are necessary and if a race condition exists
between shutting down a port and processing a receive completion.

- Sean

Index: core/mad.c
===================================================================
--- core/mad.c	(revision 1222)
+++ core/mad.c	(working copy)
@@ -90,8 +90,6 @@
 				    struct ib_mad_send_wc *mad_send_wc);
 static void timeout_sends(void *data);
 static int solicited_mad(struct ib_mad *mad);
-static int ib_mad_change_qp_state_to_rts(struct ib_qp *qp,
-					 enum ib_qp_state cur_state);
 
 /*
  * Returns a ib_mad_port_private structure or NULL for a device/port
@@ -1396,13 +1394,21 @@
 		} else
 			ib_mad_send_done_handler(port_priv, wc);
 	} else {
+		struct ib_qp_attr *attr;
+
 		/* Transition QP to RTS and fail offending send */
-		ret = ib_mad_change_qp_state_to_rts(qp_info->qp, IB_QPS_SQE);
-		if (ret)
-			printk(KERN_ERR PFX "mad_error_handler - unable to "
-			       "transition QP to RTS : %d\n", ret);
+		attr = kmalloc(sizeof *attr, GFP_KERNEL);
+		if (attr) {
+			attr->qp_state = IB_QPS_RTS;
+			ret = ib_modify_qp(qp_info->qp, attr, IB_QP_STATE);
+			kfree(attr);
+			if (ret)
+				printk(KERN_ERR PFX "mad_error_handler - "
+				       "ib_modify_qp to RTS : %d\n", ret);
+			else
+				mark_sends_for_retry(qp_info);
+		}
 		ib_mad_send_done_handler(port_priv, wc);
-		mark_sends_for_retry(qp_info);
 	}
 }
 
@@ -1692,172 +1698,51 @@
 }
 
 /*
- * Return all the posted send MADs
- */
-static void ib_mad_return_posted_send_mads(struct ib_mad_qp_info *qp_info)
-{
-	unsigned long flags;
-
-	/* Just clear port send posted MAD list... revisit!!! */
-	spin_lock_irqsave(&qp_info->send_queue.lock, flags);
-	INIT_LIST_HEAD(&qp_info->send_queue.list);
-	qp_info->send_queue.count = 0;
-	INIT_LIST_HEAD(&qp_info->overflow_list);
-	spin_unlock_irqrestore(&qp_info->send_queue.lock, flags);
-}
-
-/*
- * Modify QP into Init state
- */
-static inline int ib_mad_change_qp_state_to_init(struct ib_qp *qp)
-{
-	int ret;
-	struct ib_qp_attr *attr;
-	int attr_mask;
-
-	attr =  kmalloc(sizeof *attr, GFP_KERNEL);
-	if (!attr) {
-		printk(KERN_ERR PFX "Couldn't allocate memory for "
-		       "ib_qp_attr\n");
-		return -ENOMEM;
-	}
-
-	attr->qp_state = IB_QPS_INIT;
-	/*
-	 * PKey index for QP1 is irrelevant but
-	 * one is needed for the Reset to Init transition.
-	 */
-	attr->pkey_index = 0;
-	/* QKey is 0 for QP0 */
-	if (qp->qp_num == 0)
-		attr->qkey = 0;
-	else
-		attr->qkey = IB_QP1_QKEY;
-	attr_mask = IB_QP_STATE | IB_QP_PKEY_INDEX | IB_QP_QKEY;
-
-	ret = ib_modify_qp(qp, attr, attr_mask);
-	kfree(attr);
-
-	if (ret)
-		printk(KERN_WARNING PFX "ib_mad_change_qp_state_to_init "
-		       "ret = %d\n", ret);
-	return ret;
-}
-
-/*
- * Modify QP into Ready-To-Receive state
- */
-static inline int ib_mad_change_qp_state_to_rtr(struct ib_qp *qp)
-{
-	int ret;
-	struct ib_qp_attr *attr;
-	int attr_mask;
-
-	attr =  kmalloc(sizeof *attr, GFP_KERNEL);
-	if (!attr) {
-		printk(KERN_ERR PFX "Couldn't allocate memory for "
-		       "ib_qp_attr\n");
-		return -ENOMEM;
-	}
-
-	attr->qp_state = IB_QPS_RTR;
-	attr_mask = IB_QP_STATE;
-
-	ret = ib_modify_qp(qp, attr, attr_mask);
-	kfree(attr);
-
-	if (ret)
-		printk(KERN_WARNING PFX "ib_mad_change_qp_state_to_rtr "
-		       "ret = %d\n", ret);
-	return ret;
-}
-
-/*
- * Modify QP into Ready-To-Send state
- */
-static int ib_mad_change_qp_state_to_rts(struct ib_qp *qp,
-					 enum ib_qp_state cur_state)
-{
-	int ret;
-	struct ib_qp_attr *attr;
-	int attr_mask;
-
-	attr = kmalloc(sizeof *attr, GFP_KERNEL);
-	if (!attr) {
-		printk(KERN_ERR PFX "Couldn't allocate memory for "
-		       "ib_qp_attr\n");
-		return -ENOMEM;
-	}
-	attr->qp_state = IB_QPS_RTS;
-	attr_mask = IB_QP_STATE;
-	if (cur_state == IB_QPS_RTR) {
-		attr->sq_psn = IB_MAD_SEND_Q_PSN;
-		attr_mask |= IB_QP_SQ_PSN;
-	}
-	ret = ib_modify_qp(qp, attr, attr_mask);
-	kfree(attr);
-
-	if (ret)
-		printk(KERN_WARNING PFX "ib_mad_change_qp_state_to_rts "
-		       "ret = %d\n", ret);
-	return ret;
-}
-
-/*
- * Modify QP into Reset state
+ * Start the port
  */
-static inline int ib_mad_change_qp_state_to_reset(struct ib_qp *qp)
+static int ib_mad_port_start(struct ib_mad_port_private *port_priv)
 {
-	int ret;
+	int ret, i;
 	struct ib_qp_attr *attr;
-	int attr_mask;
+	struct ib_qp *qp;
 
 	attr = kmalloc(sizeof *attr, GFP_KERNEL);
  	if (!attr) {
-		printk(KERN_ERR PFX "Couldn't allocate memory for "
-		       "ib_qp_attr\n");
+		printk(KERN_ERR PFX "Couldn't kmalloc ib_qp_attr\n");
 		return -ENOMEM;
 	}
 
-	attr->qp_state = IB_QPS_RESET;
-	attr_mask = IB_QP_STATE;
-
-	ret = ib_modify_qp(qp, attr, attr_mask);
-	kfree(attr);
-
-	if (ret)
-		printk(KERN_WARNING PFX "ib_mad_change_qp_state_to_reset "
-		       "ret = %d\n", ret);
-	return ret;
-}
-
-/*
- * Start the port
- */
-static int ib_mad_port_start(struct ib_mad_port_private *port_priv)
-{
-	int ret, i, ret2;
-
 	for (i = 0; i < IB_MAD_QPS_CORE; i++) {
-		ret = ib_mad_change_qp_state_to_init(port_priv->qp_info[i].qp);
+		qp = port_priv->qp_info[i].qp;
+		/*
+		 * PKey index for QP1 is irrelevant but
+		 * one is needed for the Reset to Init transition.
+		 */
+		attr->qp_state = IB_QPS_INIT;
+		attr->pkey_index = 0;
+		attr->qkey = (qp->qp_num == 0) ? 0 : IB_QP1_QKEY;
+		ret = ib_modify_qp(qp, attr, IB_QP_STATE |
+					     IB_QP_PKEY_INDEX | IB_QP_QKEY);
 		if (ret) {
 			printk(KERN_ERR PFX "Couldn't change QP%d state to "
-			       "INIT\n", i);
+			       "INIT: %d\n", i, ret);
 			goto error;
 		}
 
-		ret = ib_mad_change_qp_state_to_rtr(port_priv->qp_info[i].qp);
+		attr->qp_state = IB_QPS_RTR;
+		ret = ib_modify_qp(qp, attr, IB_QP_STATE);
 		if (ret) {
 			printk(KERN_ERR PFX "Couldn't change QP%d state to "
-			       "RTR\n", i);
+			       "RTR: %d\n", i, ret);
 			goto error;
 		}
 
-		ret = ib_mad_change_qp_state_to_rts(port_priv->qp_info[i].qp,
-						    IB_QPS_RTR);
+		attr->qp_state = IB_QPS_RTS;
+		attr->sq_psn = IB_MAD_SEND_Q_PSN;
+		ret = ib_modify_qp(qp, attr, IB_QP_STATE | IB_QP_SQ_PSN);
 		if (ret) {
 			printk(KERN_ERR PFX "Couldn't change QP%d state to "
-			       "RTS\n", i);
+				"RTS: %d\n", i, ret);
 			goto error;
 		}
 	}
@@ -1865,30 +1750,28 @@
 	ret = ib_req_notify_cq(port_priv->cq, IB_CQ_NEXT_COMP);
 	if (ret) {
 		printk(KERN_ERR PFX "Failed to request completion "
-		       "notification\n");
+			"notification: %d\n", ret);
 		goto error;
 	}
 
 	for (i = 0; i < IB_MAD_QPS_CORE; i++) {
 		ret = ib_mad_post_receive_mads(&port_priv->qp_info[i], NULL);
 		if (ret) {
-			printk(KERN_ERR PFX "Couldn't post receive "
-			       "requests\n");
+			printk(KERN_ERR PFX "Couldn't post receive WRs\n");
 			goto error;
 		}
 	}
-	return 0;
+	goto out;
 
 error:
 	for (i = 0; i < IB_MAD_QPS_CORE; i++) {
+		attr->qp_state = IB_QPS_RESET;
+		ret = ib_modify_qp(port_priv->qp_info[i].qp, attr, IB_QP_STATE);
 		ib_mad_return_posted_recv_mads(&port_priv->qp_info[i]);
-		ret2 = ib_mad_change_qp_state_to_reset(port_priv->
-						       qp_info[i].qp);
-		if (ret2) {
-			printk(KERN_ERR PFX "ib_mad_port_start: Couldn't "
-			       "change QP%d state to RESET\n", i);
-		}
 	}
+
+out:
+	kfree(attr);
 	return ret;
 }
 
@@ -1898,19 +1781,26 @@
 static void ib_mad_port_stop(struct ib_mad_port_private *port_priv)
 {
 	int i, ret;
+	struct ib_qp_attr *attr;
 
-	for (i = 0; i < IB_MAD_QPS_CORE; i++) {
-		ret = ib_mad_change_qp_state_to_reset(
-						port_priv->qp_info[i].qp);
-		if (ret) {
-			printk(KERN_ERR PFX "ib_mad_port_stop: Couldn't change"
-			       " %s port %d QP%d state to RESET\n",
-			       port_priv->device->name, port_priv->port_num,
-			       i);
+	attr = kmalloc(sizeof *attr, GFP_KERNEL);
+	if (attr) {
+		attr->qp_state = IB_QPS_RESET;
+		for (i = 0; i < IB_MAD_QPS_CORE; i++) {
+			ret = ib_modify_qp(port_priv->qp_info[i].qp, attr,
+					   IB_QP_STATE);
+			if (ret)
+				printk(KERN_ERR PFX "ib_mad_port_stop: "
+				       "Couldn't change %s port %d QP%d "
+				       "state to RESET\n",
+				       port_priv->device->name,
+				       port_priv->port_num, i);
 		}
-		ib_mad_return_posted_recv_mads(&port_priv->qp_info[i]);
-		ib_mad_return_posted_send_mads(&port_priv->qp_info[i]);
+		kfree(attr);
 	}
+
+	for (i = 0; i < IB_MAD_QPS_CORE; i++)
+		ib_mad_return_posted_recv_mads(&port_priv->qp_info[i]);
 }
 
 static void qp_event_handler(struct ib_event *event, void *qp_context)



More information about the general mailing list