From: David Hu <dhu@x6u.co>
To: Tatyana Nikolova <tatyana.e.nikolova@intel.com>,
Jason Gunthorpe <jgg@ziepe.ca>, Leon Romanovsky <leon@kernel.org>
Cc: linux-rdma@vger.kernel.org, linux-kernel@vger.kernel.org,
jmoroni@google.com, eagleshaw@google.com,
David Hu <xuehaohu@google.com>
Subject: [PATCH rdma-next 3/5] RDMA/irdma: Support UMEM attribute for QP creation
Date: Sun, 11 Oct 2026 01:10:20 +0000 [thread overview]
Message-ID: <20261011011022.1445352-4-dhu@x6u.co> (raw)
In-Reply-To: <20261011011022.1445352-1-dhu@x6u.co>
From: David Hu <xuehaohu@google.com>
Support the standard 1-step queue buffer creation
model for QP by using `UVERBS_ATTR_CREATE_QP_BUF_UMEM`
and `ib_umem_get_attr()`.
Add `irdma_setup_q_pbl_from_umem()` to allocate the
backing MR and program hardware pble directly from
the pinned umem. Proper umem and pble cleanup is
added to `irdma_free_qp_rsrc()` upon QP destruction.
We retain backward compatibility for legacy 2-step
registration if the UMEM attribute is not provided.
`irdma_alloc_iwmr()` assumed there is always a valid
PD, which is valid for regular MR, and QP. That is
not the case for CQ. This modernization fixes
`irdma_alloc_iwmr()` to take in an `ibdev` to avoid
a potential NULL dereference.
Note for MR teardown: This patch unifies the teardown
of legacy 2-step queue MR and modern 1-step dummy MR
via,
`refcount_dec_and_test(&iwmr->user_ring_refs)`
For legacy queue MR, ref count starts at 2 (one by
queue, and one by `ib_mr`), it goes to 1 during
queue teardown, while deferring memory teardown to
`irdma_dereg_mr`.
For 1-step dummy MR, ref count starts at 1, and
teardown happens cleanly here.
The teardown sequence (`ib_umem_release`, `irdma_free_pble`,
`kfree`) is inlined in `utils.c` here because
`irdma_free_iwmr` is statically scoped in `verbs.c`.
Combining was considered, and we think it belongs
to a future project.
Signed-off-by: David Hu <xuehaohu@google.com>
---
drivers/infiniband/hw/irdma/utils.c | 12 ++-
drivers/infiniband/hw/irdma/verbs.c | 130 ++++++++++++++++++++++++----
2 files changed, 124 insertions(+), 18 deletions(-)
diff --git a/drivers/infiniband/hw/irdma/utils.c b/drivers/infiniband/hw/irdma/utils.c
index 290ad02ed657..1e5694a4fd91 100644
--- a/drivers/infiniband/hw/irdma/utils.c
+++ b/drivers/infiniband/hw/irdma/utils.c
@@ -1170,9 +1170,15 @@ void irdma_free_qp_rsrc(struct irdma_qp *iwqp)
kfree(iwqp->kqp.rq_wrid_mem);
if (iwqp->user_mode && iwqp->iwpbl) {
- struct irdma_mr *iwmr = iwqp->iwpbl->iwmr;
-
- refcount_dec(&iwmr->user_ring_refs);
+ struct irdma_pbl *iwpbl = iwqp->iwpbl;
+ struct irdma_mr *iwmr = iwpbl->iwmr;
+
+ if (iwmr && refcount_dec_and_test(&iwmr->user_ring_refs)) {
+ ib_umem_release(iwmr->region);
+ if (iwpbl->pbl_allocated)
+ irdma_free_pble(rf->pble_rsrc, &iwpbl->pble_alloc);
+ kfree(iwmr);
+ }
}
}
diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
index b2ffdc8e3d67..ab25445f3828 100644
--- a/drivers/infiniband/hw/irdma/verbs.c
+++ b/drivers/infiniband/hw/irdma/verbs.c
@@ -18,6 +18,12 @@ static const struct uapi_definition irdma_uapi_defs[] = {
{}
};
+static struct irdma_pbl *irdma_setup_q_pbl_from_umem(struct irdma_device *iwdev,
+ struct ib_umem *region,
+ struct ib_pd *pd,
+ enum irdma_memreg_type reg_type,
+ struct irdma_mem_reg_req *req);
+
/**
* irdma_query_device - get device attributes
* @ibdev: device pointer from stack
@@ -670,17 +676,6 @@ static int irdma_setup_umode_qp(struct irdma_ucontext *ucontext,
iwqp->ctx_info.qp_compl_ctx = req->user_compl_ctx;
iwqp->user_mode = 1;
- spin_lock_irqsave(&ucontext->qp_reg_mem_list_lock, flags);
- iwqp->iwpbl = irdma_get_pbl((unsigned long)req->user_wqe_bufs,
- &ucontext->qp_reg_mem_list);
- spin_unlock_irqrestore(&ucontext->qp_reg_mem_list_lock, flags);
-
- if (!iwqp->iwpbl) {
- ret = -ENODATA;
- ibdev_dbg(&iwdev->ibdev, "VERBS: no pbl info\n");
- return ret;
- }
-
if (!ucontext->use_raw_attrs) {
/**
* Maintain backward compat with older ABI which passes sq and
@@ -713,6 +708,52 @@ static int irdma_setup_umode_qp(struct irdma_ucontext *ucontext,
ukinfo->rq_size = ukinfo->rq_depth >> ukinfo->rq_shift;
}
+ if (attrs && uverbs_attr_is_valid(attrs, UVERBS_ATTR_CREATE_QP_BUF_UMEM)) {
+ struct irdma_mem_reg_req qp_req = {};
+ struct ib_umem *umem;
+ u32 total;
+
+ /* Legacy context does not provide depth info */
+ if (!ucontext->use_raw_attrs)
+ return -EOPNOTSUPP;
+
+ qp_req.sq_pages = DIV_ROUND_UP(ukinfo->sq_depth * IRDMA_QP_WQE_MIN_SIZE,
+ IRDMA_HW_PAGE_SIZE);
+ /* In case srq is used, this will be a single page */
+ qp_req.rq_pages = DIV_ROUND_UP(ukinfo->rq_depth * IRDMA_QP_WQE_MIN_SIZE,
+ IRDMA_HW_PAGE_SIZE);
+ total = qp_req.sq_pages + qp_req.rq_pages + IRDMA_SHADOW_PGCNT;
+
+ umem = ib_umem_get_attr(&iwdev->ibdev, attrs,
+ UVERBS_ATTR_CREATE_QP_BUF_UMEM,
+ total << IRDMA_HW_PAGE_SHIFT,
+ IB_ACCESS_LOCAL_WRITE);
+ if (IS_ERR(umem))
+ return PTR_ERR(umem);
+
+ iwqp->iwpbl = irdma_setup_q_pbl_from_umem(iwdev, umem,
+ iwqp->ibqp.pd,
+ IRDMA_MEMREG_TYPE_QP,
+ &qp_req);
+ if (IS_ERR(iwqp->iwpbl)) {
+ ret = PTR_ERR(iwqp->iwpbl);
+ iwqp->iwpbl = NULL;
+ ib_umem_release(umem);
+ return ret;
+ }
+ } else {
+ spin_lock_irqsave(&ucontext->qp_reg_mem_list_lock, flags);
+ iwqp->iwpbl = irdma_get_pbl((unsigned long)req->user_wqe_bufs,
+ &ucontext->qp_reg_mem_list);
+ spin_unlock_irqrestore(&ucontext->qp_reg_mem_list_lock, flags);
+
+ if (!iwqp->iwpbl) {
+ ret = -ENODATA;
+ ibdev_dbg(&iwdev->ibdev, "VERBS: no pbl info\n");
+ return ret;
+ }
+ }
+
irdma_setup_virt_qp(iwdev, iwqp, info);
return 0;
@@ -3490,10 +3531,11 @@ static int irdma_reg_user_mr_type_mem(struct irdma_mr *iwmr, int access,
}
static struct irdma_mr *irdma_alloc_iwmr(struct ib_umem *region,
+ struct ib_device *ibdev,
struct ib_pd *pd, u64 virt,
enum irdma_memreg_type reg_type)
{
- struct irdma_device *iwdev = to_iwdev(pd->device);
+ struct irdma_device *iwdev = to_iwdev(ibdev);
struct irdma_pbl *iwpbl;
struct irdma_mr *iwmr;
unsigned long pgsz_bitmap;
@@ -3507,7 +3549,7 @@ static struct irdma_mr *irdma_alloc_iwmr(struct ib_umem *region,
iwpbl->iwmr = iwmr;
iwmr->region = region;
iwmr->ibmr.pd = pd;
- iwmr->ibmr.device = pd->device;
+ iwmr->ibmr.device = ibdev;
iwmr->ibmr.iova = virt;
iwmr->type = reg_type;
@@ -3532,6 +3574,64 @@ static void irdma_free_iwmr(struct irdma_mr *iwmr)
kfree(iwmr);
}
+static struct irdma_pbl *irdma_setup_q_pbl_from_umem(struct irdma_device *iwdev,
+ struct ib_umem *region,
+ struct ib_pd *pd,
+ enum irdma_memreg_type reg_type,
+ struct irdma_mem_reg_req *req)
+{
+ struct irdma_pbl *iwpbl;
+ struct irdma_mr *iwmr;
+ u32 total;
+ u8 lvl;
+ int err;
+
+ /* iWarp: Catch page not starting on OS page boundary */
+ if (!rdma_protocol_roce(&iwdev->ibdev, 1) && ib_umem_offset(region))
+ return ERR_PTR(-EINVAL);
+
+ iwmr = irdma_alloc_iwmr(region, &iwdev->ibdev, pd, region->address, reg_type);
+ if (IS_ERR(iwmr))
+ return ERR_CAST(iwmr);
+
+ iwpbl = &iwmr->iwpbl;
+
+ switch (reg_type) {
+ case IRDMA_MEMREG_TYPE_QP:
+ total = req->sq_pages + req->rq_pages + IRDMA_SHADOW_PGCNT;
+ lvl = (req->sq_pages + req->rq_pages) > 2 ? PBLE_LEVEL_1 : PBLE_LEVEL_0;
+ break;
+ case IRDMA_MEMREG_TYPE_CQ:
+ total = req->cq_pages +
+ ((iwdev->rf->sc_dev.hw_attrs.uk_attrs.feature_flags &
+ IRDMA_FEATURE_CQ_RESIZE) ? 0 : IRDMA_SHADOW_PGCNT);
+ lvl = req->cq_pages > 1 ? PBLE_LEVEL_1 : PBLE_LEVEL_0;
+ break;
+ case IRDMA_MEMREG_TYPE_SRQ:
+ total = req->rq_pages + IRDMA_SHADOW_PGCNT;
+ lvl = req->rq_pages > 1 ? PBLE_LEVEL_1 : PBLE_LEVEL_0;
+ break;
+ default:
+ err = -EINVAL;
+ goto err_free_mr;
+ }
+
+ if (total > iwmr->page_cnt) {
+ err = -EINVAL;
+ goto err_free_mr;
+ }
+
+ err = irdma_handle_q_mem(iwdev, req, iwpbl, lvl);
+ if (err)
+ goto err_free_mr;
+
+ return iwpbl;
+
+err_free_mr:
+ irdma_free_iwmr(iwmr);
+ return ERR_PTR(err);
+}
+
static int irdma_reg_user_mr_type_qp(struct irdma_mem_reg_req req,
struct ib_udata *udata,
struct irdma_mr *iwmr)
@@ -3677,7 +3777,7 @@ static struct ib_mr *irdma_reg_user_mr(struct ib_pd *pd, u64 start, u64 len,
return (struct ib_mr *)region;
}
- iwmr = irdma_alloc_iwmr(region, pd, virt, req.reg_type);
+ iwmr = irdma_alloc_iwmr(region, pd->device, pd, virt, req.reg_type);
if (IS_ERR(iwmr)) {
ib_umem_release(region);
return (struct ib_mr *)iwmr;
@@ -3776,7 +3876,7 @@ static struct ib_mr *irdma_reg_user_mr_dmabuf(struct ib_pd *pd, u64 start,
return ERR_CAST(umem_dmabuf);
}
- iwmr = irdma_alloc_iwmr(&umem_dmabuf->umem, pd, virt, IRDMA_MEMREG_TYPE_MEM);
+ iwmr = irdma_alloc_iwmr(&umem_dmabuf->umem, pd->device, pd, virt, IRDMA_MEMREG_TYPE_MEM);
if (IS_ERR(iwmr)) {
err = PTR_ERR(iwmr);
goto err_release;
--
2.56.0.385.gd3acb90ef8-goog
next prev parent reply other threads:[~2026-10-11 1:11 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-11 1:10 [PATCH rdma-next 0/5] RDMA/irdma: Add support for ioctl David Hu
2026-10-11 1:10 ` [PATCH rdma-next 1/5] RDMA/irdma: Plumb uverbs_attr_bundle for QP, SRQ David Hu
2026-10-11 1:10 ` [PATCH rdma-next 2/5] RDMA/irdma: Register irdma UVERBS ioctl namespace David Hu
2026-10-11 1:10 ` David Hu [this message]
2026-10-11 1:10 ` [PATCH rdma-next 4/5] RDMA/irdma: Support UMEM attribute for CQ creation David Hu
2026-10-12 14:17 ` Leon Romanovsky
2026-10-12 21:15 ` David Hu
2026-10-11 1:10 ` [PATCH rdma-next 5/5] RDMA/irdma: Support UMEM attribute for SRQ creation David Hu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261011011022.1445352-4-dhu@x6u.co \
--to=dhu@x6u.co \
--cc=eagleshaw@google.com \
--cc=jgg@ziepe.ca \
--cc=jmoroni@google.com \
--cc=leon@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-rdma@vger.kernel.org \
--cc=tatyana.e.nikolova@intel.com \
--cc=xuehaohu@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®