RDMA/siw: publish QP after initialization

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: f29dd55b02 ("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>
This commit is contained in:
Ruoyu Wang
2026-07-02 14:37:03 -03:00
committed by Jason Gunthorpe
parent 9f0f2d2121
commit bb27fcc67c
+24 -20
View File
@@ -318,6 +318,7 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
struct siw_ucontext *uctx = struct siw_ucontext *uctx =
rdma_udata_to_drv_context(udata, struct siw_ucontext, rdma_udata_to_drv_context(udata, struct siw_ucontext,
base_ucontext); base_ucontext);
struct siw_uresp_create_qp uresp = {};
unsigned long flags; unsigned long flags;
int num_sqe, num_rqe, rv = 0; int num_sqe, num_rqe, rv = 0;
size_t length; 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->rq_lock);
spin_lock_init(&qp->orq_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 /* All queue indices are derived from modulo operations
* on a free running 'get' (consumer) and 'put' (producer) * on a free running 'get' (consumer) and 'put' (producer)
* unsigned counter. Having queue sizes at power of two * 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) { if (qp->sendq == NULL) {
rv = -ENOMEM; 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_REQ_WR) {
if (attrs->sq_sig_type == IB_SIGNAL_ALL_WR) if (attrs->sq_sig_type == IB_SIGNAL_ALL_WR)
qp->attrs.flags |= SIW_SIGNAL_ALL_WR; qp->attrs.flags |= SIW_SIGNAL_ALL_WR;
else { else {
rv = -EINVAL; rv = -EINVAL;
goto err_out_xa; goto err_out;
} }
} }
qp->pd = pd; 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) { if (qp->recvq == NULL) {
rv = -ENOMEM; rv = -ENOMEM;
goto err_out_xa; goto err_out;
} }
qp->attrs.rq_size = num_rqe; 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; qp->attrs.state = SIW_QP_STATE_IDLE;
if (udata) { if (udata) {
struct siw_uresp_create_qp uresp = {};
uresp.num_sqe = num_sqe; uresp.num_sqe = num_sqe;
uresp.num_rqe = num_rqe; uresp.num_rqe = num_rqe;
uresp.qp_id = qp_id(qp);
if (qp->sendq) { if (qp->sendq) {
length = num_sqe * sizeof(struct siw_sqe); 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); length, &uresp.sq_key);
if (!qp->sq_entry) { if (!qp->sq_entry) {
rv = -ENOMEM; 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) { if (!qp->rq_entry) {
uresp.sq_key = SIW_INVAL_UOBJ_KEY; uresp.sq_key = SIW_INVAL_UOBJ_KEY;
rv = -ENOMEM; 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)) { if (udata->outlen < sizeof(uresp)) {
rv = -EINVAL; rv = -EINVAL;
@@ -478,22 +485,19 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
if (rv) if (rv)
goto err_out_xa; 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); INIT_LIST_HEAD(&qp->devq);
spin_lock_irqsave(&sdev->lock, flags); spin_lock_irqsave(&sdev->lock, flags);
list_add_tail(&qp->devq, &sdev->qp_list); list_add_tail(&qp->devq, &sdev->qp_list);
spin_unlock_irqrestore(&sdev->lock, flags); spin_unlock_irqrestore(&sdev->lock, flags);
init_completion(&qp->qp_free);
return 0; return 0;
err_out_xa: err_out_xa:
xa_erase(&sdev->qp_xa, qp_id(qp)); xa_erase(&sdev->qp_xa, qp_id(qp));
err_out_tx:
siw_put_tx_cpu(qp->tx_cpu);
err_out:
if (uctx) { if (uctx) {
rdma_user_mmap_entry_remove(qp->sq_entry); rdma_user_mmap_entry_remove(qp->sq_entry);
rdma_user_mmap_entry_remove(qp->rq_entry); rdma_user_mmap_entry_remove(qp->rq_entry);