]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
RDMA/siw: publish QP after initialization
authorRuoyu Wang <ruoyuw560@gmail.com>
Tue, 30 Jun 2026 06:00:40 +0000 (14:00 +0800)
committerJason Gunthorpe <jgg@nvidia.com>
Thu, 2 Jul 2026 17:37:03 +0000 (14:37 -0300)
siw_create_qp() currently calls siw_qp_add() before the queues, CQ
pointers, state, completion, and device list entry are ready. A QPN
lookup can therefore reach a QP that is still being constructed.

Move siw_qp_add() to the end of siw_create_qp(), after QP
initialization and before adding the QP to the siw device list.

Fixes: f29dd55b0236 ("rdma/siw: queue pair methods")
Link: https://patch.msgid.link/r/20260630060040.966461-1-ruoyuw560@gmail.com
Suggested-by: Bernard Metzler <bernard.metzler@linux.dev>
Signed-off-by: Ruoyu Wang <ruoyuw560@gmail.com>
Acked-by: Bernard Metzler <bernard.metzler@linux.dev>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
drivers/infiniband/sw/siw/siw_verbs.c

index b74ac85c1b8b8bcc8b83133f467f3e253f08ec7f..2349c08c32ede920f412791dd3aab1aec45344e3 100644 (file)
@@ -318,6 +318,7 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
        struct siw_ucontext *uctx =
                rdma_udata_to_drv_context(udata, struct siw_ucontext,
                                          base_ucontext);
+       struct siw_uresp_create_qp uresp = {};
        unsigned long flags;
        int num_sqe, num_rqe, rv = 0;
        size_t length;
@@ -371,11 +372,6 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
        spin_lock_init(&qp->rq_lock);
        spin_lock_init(&qp->orq_lock);
 
-       rv = siw_qp_add(sdev, qp);
-       if (rv)
-               goto err_atomic;
-
-
        /* All queue indices are derived from modulo operations
         * on a free running 'get' (consumer) and 'put' (producer)
         * unsigned counter. Having queue sizes at power of two
@@ -393,14 +389,14 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
 
        if (qp->sendq == NULL) {
                rv = -ENOMEM;
-               goto err_out_xa;
+               goto err_out;
        }
        if (attrs->sq_sig_type != IB_SIGNAL_REQ_WR) {
                if (attrs->sq_sig_type == IB_SIGNAL_ALL_WR)
                        qp->attrs.flags |= SIW_SIGNAL_ALL_WR;
                else {
                        rv = -EINVAL;
-                       goto err_out_xa;
+                       goto err_out;
                }
        }
        qp->pd = pd;
@@ -426,7 +422,7 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
 
                if (qp->recvq == NULL) {
                        rv = -ENOMEM;
-                       goto err_out_xa;
+                       goto err_out;
                }
                qp->attrs.rq_size = num_rqe;
        }
@@ -441,11 +437,8 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
        qp->attrs.state = SIW_QP_STATE_IDLE;
 
        if (udata) {
-               struct siw_uresp_create_qp uresp = {};
-
                uresp.num_sqe = num_sqe;
                uresp.num_rqe = num_rqe;
-               uresp.qp_id = qp_id(qp);
 
                if (qp->sendq) {
                        length = num_sqe * sizeof(struct siw_sqe);
@@ -454,7 +447,7 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
                                                      length, &uresp.sq_key);
                        if (!qp->sq_entry) {
                                rv = -ENOMEM;
-                               goto err_out_xa;
+                               goto err_out;
                        }
                }
 
@@ -466,9 +459,23 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
                        if (!qp->rq_entry) {
                                uresp.sq_key = SIW_INVAL_UOBJ_KEY;
                                rv = -ENOMEM;
-                               goto err_out_xa;
+                               goto err_out;
                        }
                }
+       }
+       qp->tx_cpu = siw_get_tx_cpu(sdev);
+       if (qp->tx_cpu < 0) {
+               rv = -EINVAL;
+               goto err_out;
+       }
+       init_completion(&qp->qp_free);
+
+       rv = siw_qp_add(sdev, qp);
+       if (rv)
+               goto err_out_tx;
+
+       if (udata) {
+               uresp.qp_id = qp_id(qp);
 
                if (udata->outlen < sizeof(uresp)) {
                        rv = -EINVAL;
@@ -478,22 +485,19 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
                if (rv)
                        goto err_out_xa;
        }
-       qp->tx_cpu = siw_get_tx_cpu(sdev);
-       if (qp->tx_cpu < 0) {
-               rv = -EINVAL;
-               goto err_out_xa;
-       }
+
        INIT_LIST_HEAD(&qp->devq);
        spin_lock_irqsave(&sdev->lock, flags);
        list_add_tail(&qp->devq, &sdev->qp_list);
        spin_unlock_irqrestore(&sdev->lock, flags);
 
-       init_completion(&qp->qp_free);
-
        return 0;
 
 err_out_xa:
        xa_erase(&sdev->qp_xa, qp_id(qp));
+err_out_tx:
+       siw_put_tx_cpu(qp->tx_cpu);
+err_out:
        if (uctx) {
                rdma_user_mmap_entry_remove(qp->sq_entry);
                rdma_user_mmap_entry_remove(qp->rq_entry);