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