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)
_______________________________________________
openib-general mailing list
[EMAIL PROTECTED]
http://openib.org/mailman/listinfo/openib-general

To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general

Reply via email to