[PATCH] IB: really reset QPs
authorRoland Dreier <roland@eddore.topspincom.com>
Wed, 7 Sep 2005 16:43:23 +0000 (09:43 -0700)
committerRoland Dreier <rolandd@cisco.com>
Wed, 7 Sep 2005 16:48:52 +0000 (09:48 -0700)
When we modify a QP to the RESET state, completely clean up the QP
so that it is really and truly reset.

Signed-off-by: Roland Dreier <rolandd@cisco.com>
drivers/infiniband/hw/mthca/mthca_qp.c

index 0164b84..c753f73 100644 (file)
@@ -220,6 +220,16 @@ static void *get_send_wqe(struct mthca_qp *qp, int n)
                         (PAGE_SIZE - 1));
 }
 
+static void mthca_wq_init(struct mthca_wq *wq)
+{
+       spin_lock_init(&wq->lock);
+       wq->next_ind  = 0;
+       wq->last_comp = wq->max - 1;
+       wq->head      = 0;
+       wq->tail      = 0;
+       wq->last      = NULL;
+}
+
 void mthca_qp_event(struct mthca_dev *dev, u32 qpn,
                    enum ib_event_type event_type)
 {
@@ -833,8 +843,8 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
                store_attrs(to_msqp(qp), attr, attr_mask);
 
        /*
-        * If we are moving QP0 to RTR, bring the IB link up; if we
-        * are moving QP0 to RESET or ERROR, bring the link back down.
+        * If we moved QP0 to RTR, bring the IB link up; if we moved
+        * QP0 to RESET or ERROR, bring the link back down.
         */
        if (is_qp0(dev, qp)) {
                if (cur_state != IB_QPS_RTR &&
@@ -848,6 +858,26 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
                        mthca_CLOSE_IB(dev, to_msqp(qp)->port, &status);
        }
 
+       /*
+        * If we moved a kernel QP to RESET, clean up all old CQ
+        * entries and reinitialize the QP.
+        */
+       if (!err && new_state == IB_QPS_RESET && !qp->ibqp.uobject) {
+               mthca_cq_clean(dev, to_mcq(qp->ibqp.send_cq)->cqn, qp->qpn,
+                              qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL);
+               if (qp->ibqp.send_cq != qp->ibqp.recv_cq)
+                       mthca_cq_clean(dev, to_mcq(qp->ibqp.recv_cq)->cqn, qp->qpn,
+                                      qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL);
+
+               mthca_wq_init(&qp->sq);
+               mthca_wq_init(&qp->rq);
+
+               if (mthca_is_memfree(dev)) {
+                       *qp->sq.db = 0;
+                       *qp->rq.db = 0;
+               }
+       }
+
        return err;
 }
 
@@ -1003,16 +1033,6 @@ static void mthca_free_memfree(struct mthca_dev *dev,
        }
 }
 
-static void mthca_wq_init(struct mthca_wq* wq)
-{
-       spin_lock_init(&wq->lock);
-       wq->next_ind  = 0;
-       wq->last_comp = wq->max - 1;
-       wq->head      = 0;
-       wq->tail      = 0;
-       wq->last      = NULL;
-}
-
 static int mthca_alloc_qp_common(struct mthca_dev *dev,
                                 struct mthca_pd *pd,
                                 struct mthca_cq *send_cq,