aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMichael S. Tsirkin <mst@dev.mellanox.co.il>2007-06-19 06:40:41 -0400
committerRoland Dreier <rolandd@cisco.com>2007-06-21 16:03:50 -0400
commit3ec7393a6858a1716e74aa81be6af76fd180021d (patch)
tree2f797894f98a1321605dbcf2610c6349bd92003a /drivers
parent24bce5080306bd5255cbda3d6b09a29d5515b470 (diff)
IPoIB/cm: Initialize RX before moving QP to RTR
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_cm.c29
1 files changed, 17 insertions, 12 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
index 076a0bbb63d7..c64249f7caed 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
@@ -309,6 +309,11 @@ static int ipoib_cm_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *even
309 return -ENOMEM; 309 return -ENOMEM;
310 p->dev = dev; 310 p->dev = dev;
311 p->id = cm_id; 311 p->id = cm_id;
312 cm_id->context = p;
313 p->state = IPOIB_CM_RX_LIVE;
314 p->jiffies = jiffies;
315 INIT_LIST_HEAD(&p->list);
316
312 p->qp = ipoib_cm_create_rx_qp(dev, p); 317 p->qp = ipoib_cm_create_rx_qp(dev, p);
313 if (IS_ERR(p->qp)) { 318 if (IS_ERR(p->qp)) {
314 ret = PTR_ERR(p->qp); 319 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
320 if (ret) 325 if (ret)
321 goto err_modify; 326 goto err_modify;
322 327
328 spin_lock_irq(&priv->lock);
329 queue_delayed_work(ipoib_workqueue,
330 &priv->cm.stale_task, IPOIB_CM_RX_DELAY);
331 /* Add this entry to passive ids list head, but do not re-add it
332 * if IB_EVENT_QP_LAST_WQE_REACHED has moved it to flush list. */
333 p->jiffies = jiffies;
334 if (p->state == IPOIB_CM_RX_LIVE)
335 list_move(&p->list, &priv->cm.passive_ids);
336 spin_unlock_irq(&priv->lock);
337
323 ret = ipoib_cm_send_rep(dev, cm_id, p->qp, &event->param.req_rcvd, psn); 338 ret = ipoib_cm_send_rep(dev, cm_id, p->qp, &event->param.req_rcvd, psn);
324 if (ret) { 339 if (ret) {
325 ipoib_warn(priv, "failed to send REP: %d\n", ret); 340 ipoib_warn(priv, "failed to send REP: %d\n", ret);
326 goto err_rep; 341 if (ib_modify_qp(p->qp, &ipoib_cm_err_attr, IB_QP_STATE))
342 ipoib_warn(priv, "unable to move qp to error state\n");
327 } 343 }
328
329 cm_id->context = p;
330 p->jiffies = jiffies;
331 p->state = IPOIB_CM_RX_LIVE;
332 spin_lock_irq(&priv->lock);
333 if (list_empty(&priv->cm.passive_ids))
334 queue_delayed_work(ipoib_workqueue,
335 &priv->cm.stale_task, IPOIB_CM_RX_DELAY);
336 list_add(&p->list, &priv->cm.passive_ids);
337 spin_unlock_irq(&priv->lock);
338 return 0; 344 return 0;
339 345
340err_rep:
341err_modify: 346err_modify:
342 ib_destroy_qp(p->qp); 347 ib_destroy_qp(p->qp);
343err_qp: 348err_qp: