OSDN Git Service

IPoIB/cm: Initialize RX before moving QP to RTR
authorMichael S. Tsirkin <mst@dev.mellanox.co.il>
Tue, 19 Jun 2007 10:40:41 +0000 (13:40 +0300)
committerRoland Dreier <rolandd@cisco.com>
Thu, 21 Jun 2007 20:03:50 +0000 (13:03 -0700)
Fix a crasher bug in IPoIB CM: once a QP is in the RTR state, a
receive completion (or even an asynchronous error) might be observed
on this QP, so we have to initialize all of our receive data
structures before moving to the RTR state.

As an optimization (since modify_qp might take a long time), the
jiffies update done when moving RX to the passive_ids list is also
left in place to reduce the chance of the RX being misdetected as
stale.

This fixes bug <https://bugs.openfabrics.org/show_bug.cgi?id=662>.

Signed-off-by: Michael S. Tsirkin <mst@dev.mellanox.co.il>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
drivers/infiniband/ulp/ipoib/ipoib_cm.c

index 076a0bb..c64249f 100644 (file)
@@ -309,6 +309,11 @@ static int ipoib_cm_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *even
                return -ENOMEM;
        p->dev = dev;
        p->id = cm_id;
+       cm_id->context = p;
+       p->state = IPOIB_CM_RX_LIVE;
+       p->jiffies = jiffies;
+       INIT_LIST_HEAD(&p->list);
+
        p->qp = ipoib_cm_create_rx_qp(dev, p);
        if (IS_ERR(p->qp)) {
                ret = PTR_ERR(p->qp);
@@ -320,24 +325,24 @@ static int ipoib_cm_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *even
        if (ret)
                goto err_modify;
 
+       spin_lock_irq(&priv->lock);
+       queue_delayed_work(ipoib_workqueue,
+                          &priv->cm.stale_task, IPOIB_CM_RX_DELAY);
+       /* Add this entry to passive ids list head, but do not re-add it
+        * if IB_EVENT_QP_LAST_WQE_REACHED has moved it to flush list. */
+       p->jiffies = jiffies;
+       if (p->state == IPOIB_CM_RX_LIVE)
+               list_move(&p->list, &priv->cm.passive_ids);
+       spin_unlock_irq(&priv->lock);
+
        ret = ipoib_cm_send_rep(dev, cm_id, p->qp, &event->param.req_rcvd, psn);
        if (ret) {
                ipoib_warn(priv, "failed to send REP: %d\n", ret);
-               goto err_rep;
+               if (ib_modify_qp(p->qp, &ipoib_cm_err_attr, IB_QP_STATE))
+                       ipoib_warn(priv, "unable to move qp to error state\n");
        }
-
-       cm_id->context = p;
-       p->jiffies = jiffies;
-       p->state = IPOIB_CM_RX_LIVE;
-       spin_lock_irq(&priv->lock);
-       if (list_empty(&priv->cm.passive_ids))
-               queue_delayed_work(ipoib_workqueue,
-                                  &priv->cm.stale_task, IPOIB_CM_RX_DELAY);
-       list_add(&p->list, &priv->cm.passive_ids);
-       spin_unlock_irq(&priv->lock);
        return 0;
 
-err_rep:
 err_modify:
        ib_destroy_qp(p->qp);
 err_qp: