RDMA/rxe: Enforce IBA C11-17
authorBob Pearson <rpearsonhpe@gmail.com>
Thu, 21 Apr 2022 01:40:40 +0000 (20:40 -0500)
committerJason Gunthorpe <jgg@nvidia.com>
Mon, 9 May 2022 12:03:45 +0000 (09:03 -0300)
Add a counter to keep track of the number of WQs connected to a CQ and
return an error if destroy_cq() is called while the counter is non zero.

Link: https://lore.kernel.org/r/20220421014042.26985-8-rpearsonhpe@gmail.com
Signed-off-by: Bob Pearson <rpearsonhpe@gmail.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
drivers/infiniband/sw/rxe/rxe_qp.c
drivers/infiniband/sw/rxe/rxe_verbs.c
drivers/infiniband/sw/rxe/rxe_verbs.h

index a801175..22e9b85 100644 (file)
@@ -322,6 +322,9 @@ int rxe_qp_from_init(struct rxe_dev *rxe, struct rxe_qp *qp, struct rxe_pd *pd,
        qp->scq                 = scq;
        qp->srq                 = srq;
 
+       atomic_inc(&rcq->num_wq);
+       atomic_inc(&scq->num_wq);
+
        rxe_qp_init_misc(rxe, qp, init);
 
        err = rxe_qp_init_req(rxe, qp, init, udata, uresp);
@@ -341,6 +344,9 @@ err2:
        rxe_queue_cleanup(qp->sq.queue);
        qp->sq.queue = NULL;
 err1:
+       atomic_dec(&rcq->num_wq);
+       atomic_dec(&scq->num_wq);
+
        qp->pd = NULL;
        qp->rcq = NULL;
        qp->scq = NULL;
@@ -798,10 +804,14 @@ static void rxe_qp_do_cleanup(struct work_struct *work)
        if (qp->rq.queue)
                rxe_queue_cleanup(qp->rq.queue);
 
+       atomic_dec(&qp->scq->num_wq);
        if (qp->scq)
                rxe_put(qp->scq);
+
+       atomic_dec(&qp->rcq->num_wq);
        if (qp->rcq)
                rxe_put(qp->rcq);
+
        if (qp->pd)
                rxe_put(qp->pd);
 
index 198afb0..9d99585 100644 (file)
@@ -795,6 +795,12 @@ static int rxe_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata)
 {
        struct rxe_cq *cq = to_rcq(ibcq);
 
+       /* See IBA C11-17: The CI shall return an error if this Verb is
+        * invoked while a Work Queue is still associated with the CQ.
+        */
+       if (atomic_read(&cq->num_wq))
+               return -EINVAL;
+
        rxe_cq_disable(cq);
 
        rxe_put(cq);
index 86068d7..ac464e6 100644 (file)
@@ -67,6 +67,7 @@ struct rxe_cq {
        bool                    is_dying;
        bool                    is_user;
        struct tasklet_struct   comp_task;
+       atomic_t                num_wq;
 };
 
 enum wqe_state {