* [PATCH rdma-next v2 0/6] RDMA/irdma: Add support for ioctl
@ 2026-10-15 1:19 David Hu
2026-10-15 1:19 ` [PATCH rdma-next v2 1/6] RDMA/irdma: Plumb uverbs_attr_bundle for QP, SRQ David Hu
` (5 more replies)
0 siblings, 6 replies; 13+ messages in thread
From: David Hu @ 2026-10-15 1:19 UTC (permalink / raw)
To: Tatyana Nikolova, Jason Gunthorpe, Leon Romanovsky
Cc: linux-rdma, linux-kernel, jmoroni, eagleshaw, xuehaohu
From: David Hu <xuehaohu@google.com>
Hello,
This patch series introduces support for uverbs ioctl queue creation
(QP, CQ, and SRQ) in the irdma driver. This series makes progress towards
modernizing irdma. This enables 1-step queue creation from pinned UMEMs
and shared dma-buf heaps (system_cc_shared), providing RDMA support for
Confidential Computing (CoCo) guest environments where memory encryption
otherwise prevents standard host-VA-based queues from operating.
Historically, irdma relied on legacy write() commands for queue setup.
This series modernizes irdma's queue creation path by adopting the ioctl
infrastructure:
1. Plumbs uverbs_attr_bundle into the irdma QP and SRQ creation routines.
2. Registers irdma's UVERBS ioctl namespace definition for QP, CQ, and SRQ.
3. Implements 1-step queue buffer creation for QP, CQ, and SRQ using
UVERBS_ATTR_CREATE_*_BUF_UMEM attributes and ib_umem_get_attr(),
configuring hardware Page Buffer Lists (PBLs) directly from pinned umems.
4. Split CQ creation setup logic by umode and kmode into separate
routines to be consistent with other queue creation logic.
5. Adds support for driver-specific shadow area UMEM attributes during CQ
creation with CQ resize capability.
6. Preserves backward compatibility with legacy 2-step write() path
registrations when UMEM attributes are not provided.
User space rdma-core PR: https://github.com/linux-rdma/rdma-core/pull/1766
Testing:
Verified with rc_pingpong, srq_pingpong, and dmabuf_pingpong over irdma
devices in Confidential VM environments.
Changes in v2:
- Add patch 4/6 to split out setup logic from irdma_create_cq() into
umode and kmode helpers (Leon).
- Rewrap commit messages to ~75 characters (Leon).
- Fix a pble/umem resource leak in irdma_resize_cq() (Sashiko).
- Link to v1: https://lore.kernel.org/all/20261011011022.1445352-1-dhu@x6u.co/
David Hu (6):
RDMA/irdma: Plumb uverbs_attr_bundle for QP, SRQ
RDMA/irdma: Register irdma UVERBS ioctl namespace
RDMA/irdma: Support UMEM attribute for QP creation
RDMA/irdma: Split CQ setup to umode and kmode
RDMA/irdma: Support UMEM attribute for CQ creation
RDMA/irdma: Support UMEM attribute for SRQ creation
drivers/infiniband/hw/irdma/utils.c | 12 +-
drivers/infiniband/hw/irdma/verbs.c | 574 +++++++++++++++++++++-------
include/uapi/rdma/irdma-abi.h | 5 +
3 files changed, 444 insertions(+), 147 deletions(-)
base-commit: d2c08575500145dc5cb55075cd9b177626531613
--
2.56.0.385.gd3acb90ef8-goog
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH rdma-next v2 1/6] RDMA/irdma: Plumb uverbs_attr_bundle for QP, SRQ
2026-10-15 1:19 [PATCH rdma-next v2 0/6] RDMA/irdma: Add support for ioctl David Hu
@ 2026-10-15 1:19 ` David Hu
2026-10-15 1:31 ` sashiko-bot
2026-10-15 1:19 ` [PATCH rdma-next v2 2/6] RDMA/irdma: Register irdma UVERBS ioctl namespace David Hu
` (4 subsequent siblings)
5 siblings, 1 reply; 13+ messages in thread
From: David Hu @ 2026-10-15 1:19 UTC (permalink / raw)
To: Tatyana Nikolova, Jason Gunthorpe, Leon Romanovsky
Cc: linux-rdma, linux-kernel, jmoroni, eagleshaw, xuehaohu
From: David Hu <xuehaohu@google.com>
In preparation to support modern UVERBS ioctl attributes (such
as UVERBS_ATTR_UMEM for CoCo DMA bounce buffers), we pass down
`uverbs_attr_bundle` for inner QP, SRQ routines. Since standard
uAPIs provide `ib_udata`, we derive it via the helper macro,
`rdma_udata_to_uverbs_attr_bundle`. `irdma_create_cq()` supports
`uverbs_attr_bundle` already, therefore, this patch fills the gap for QP
and SRQ.
QP, SRQ uAPI will now have `ib_udata`, and CQ uAPI has `uverbs_attr_bundle`
as a top level input. However, we think it is a future project to unify
them.
Signed-off-by: David Hu <xuehaohu@google.com>
---
drivers/infiniband/hw/irdma/verbs.c | 19 +++++++++++++++----
1 file changed, 15 insertions(+), 4 deletions(-)
diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
index 71d7ae7baa47..10c790fdfc57 100644
--- a/drivers/infiniband/hw/irdma/verbs.c
+++ b/drivers/infiniband/hw/irdma/verbs.c
@@ -637,13 +637,15 @@ static void irdma_setup_virt_qp(struct irdma_device *iwdev,
* @iwqp: qp ptr (user or kernel)
* @info: initialize info to return
* @init_attr: Initial QP create attributes
+ * @attrs: uverbs attribute bundle
*/
static int irdma_setup_umode_qp(struct irdma_ucontext *ucontext,
struct irdma_create_qp_req *req,
struct irdma_device *iwdev,
struct irdma_qp *iwqp,
struct irdma_qp_init_info *info,
- struct ib_qp_init_attr *init_attr)
+ struct ib_qp_init_attr *init_attr,
+ struct uverbs_attr_bundle *attrs)
{
struct irdma_qp_uk_init_info *ukinfo = &info->qp_uk_init_info;
unsigned long flags;
@@ -981,10 +983,14 @@ static int irdma_create_qp(struct ib_qp *ibqp,
struct irdma_qp_init_info init_info = {};
struct irdma_qp_host_ctx_info *ctx_info;
struct irdma_create_qp_req ureq = {};
+ struct uverbs_attr_bundle *attrs = NULL;
struct irdma_srq *iwsrq;
bool srq_valid = false;
u32 srq_id = 0;
+ if (udata)
+ attrs = rdma_udata_to_uverbs_attr_bundle(udata);
+
if (init_attr->srq) {
iwsrq = to_iwsrq(init_attr->srq);
srq_valid = true;
@@ -1071,7 +1077,7 @@ static int irdma_create_qp(struct ib_qp *ibqp,
init_info.qp_uk_init_info.abi_ver = iwpd->sc_pd.abi_ver;
err_code = irdma_setup_umode_qp(ucontext, &ureq, iwdev, iwqp,
- &init_info, init_attr);
+ &init_info, init_attr, attrs);
} else {
INIT_DELAYED_WORK(&iwqp->dwork_flush, irdma_flush_worker);
init_info.qp_uk_init_info.abi_ver = IRDMA_ABI_VER;
@@ -2337,7 +2343,8 @@ static int irdma_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
static int irdma_setup_umode_srq(struct irdma_device *iwdev,
struct irdma_srq *iwsrq,
struct irdma_srq_init_info *info,
- struct ib_udata *udata)
+ struct ib_udata *udata,
+ struct uverbs_attr_bundle *attrs)
{
struct irdma_create_srq_req req = {};
struct irdma_ucontext *ucontext;
@@ -2420,6 +2427,7 @@ static int irdma_create_srq(struct ib_srq *ibsrq,
struct ib_srq_attr *attr = &initattrs->attr;
struct irdma_pd *iwpd = to_iwpd(ibsrq->pd);
struct irdma_srq *iwsrq = to_iwsrq(ibsrq);
+ struct uverbs_attr_bundle *attrs = NULL;
struct irdma_srq_uk_init_info *ukinfo;
struct irdma_cqp_request *cqp_request;
struct irdma_srq_init_info info = {};
@@ -2430,6 +2438,9 @@ static int irdma_create_srq(struct ib_srq *ibsrq,
u32 depth;
u8 shift;
+ if (udata)
+ attrs = rdma_udata_to_uverbs_attr_bundle(udata);
+
uk_attrs = &rf->sc_dev.hw_attrs.uk_attrs;
ukinfo = &info.srq_uk_init_info;
@@ -2470,7 +2481,7 @@ static int irdma_create_srq(struct ib_srq *ibsrq,
attr->max_wr = iwsrq->max_wr;
if (udata)
- err_code = irdma_setup_umode_srq(iwdev, iwsrq, &info, udata);
+ err_code = irdma_setup_umode_srq(iwdev, iwsrq, &info, udata, attrs);
else
err_code = irdma_setup_kmode_srq(iwdev, iwsrq, &info, depth,
shift);
--
2.56.0.385.gd3acb90ef8-goog
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH rdma-next v2 2/6] RDMA/irdma: Register irdma UVERBS ioctl namespace
2026-10-15 1:19 [PATCH rdma-next v2 0/6] RDMA/irdma: Add support for ioctl David Hu
2026-10-15 1:19 ` [PATCH rdma-next v2 1/6] RDMA/irdma: Plumb uverbs_attr_bundle for QP, SRQ David Hu
@ 2026-10-15 1:19 ` David Hu
2026-10-15 1:33 ` sashiko-bot
2026-10-15 1:19 ` [PATCH rdma-next v2 3/6] RDMA/irdma: Support UMEM attribute for QP creation David Hu
` (3 subsequent siblings)
5 siblings, 1 reply; 13+ messages in thread
From: David Hu @ 2026-10-15 1:19 UTC (permalink / raw)
To: Tatyana Nikolova, Jason Gunthorpe, Leon Romanovsky
Cc: linux-rdma, linux-kernel, jmoroni, eagleshaw, xuehaohu
From: David Hu <xuehaohu@google.com>
An irdma UVERBS module is now created. An irdma specific shadow buf is
defined for CQ, while QP and SRQ reuses core's uapi definitions. This
works since core builds shared core ioctl parsing tree first, before adding
driver specific `uapi_definition`.
Destroy paths are automatically handled by core dispatchers, as objects
are now registered in the parsing tree and no additional driver specifics
are needed in destroy ioctls. Resize, Query, and Modify continue to go
through write() cmds.
Signed-off-by: David Hu <xuehaohu@google.com>
---
drivers/infiniband/hw/irdma/verbs.c | 18 ++++++++++++++++++
include/uapi/rdma/irdma-abi.h | 5 +++++
2 files changed, 23 insertions(+)
diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
index 10c790fdfc57..b2ffdc8e3d67 100644
--- a/drivers/infiniband/hw/irdma/verbs.c
+++ b/drivers/infiniband/hw/irdma/verbs.c
@@ -1,6 +1,22 @@
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/* Copyright (c) 2015 - 2021 Intel Corporation */
#include "main.h"
+#include <rdma/uverbs_ioctl.h>
+#define UVERBS_MODULE_NAME irdma
+#include <rdma/uverbs_named_ioctl.h>
+#include <rdma/ib_user_ioctl_cmds.h>
+
+ADD_UVERBS_ATTRIBUTES_SIMPLE(
+ irdma_cq_attrs,
+ UVERBS_OBJECT_CQ,
+ UVERBS_METHOD_CQ_CREATE,
+ UVERBS_ATTR_UMEM(IRDMA_IB_ATTR_CREATE_CQ_SHADOW_BUF_UMEM, UA_OPTIONAL)
+);
+
+static const struct uapi_definition irdma_uapi_defs[] = {
+ UAPI_DEF_CHAIN_OBJ_TREE(UVERBS_OBJECT_CQ, &irdma_cq_attrs),
+ {}
+};
/**
* irdma_query_device - get device attributes
@@ -5629,6 +5645,8 @@ static void irdma_init_rdma_device(struct irdma_device *iwdev)
iwdev->ibdev.phys_port_cnt = 1;
iwdev->ibdev.num_comp_vectors = iwdev->rf->ceqs_count;
iwdev->ibdev.dev.parent = &pcidev->dev;
+ if (IS_ENABLED(CONFIG_INFINIBAND_USER_ACCESS))
+ iwdev->ibdev.driver_def = irdma_uapi_defs;
ib_set_device_ops(&iwdev->ibdev, &irdma_dev_ops);
if (iwdev->rf->rdma_ver == IRDMA_GEN_1)
ib_set_device_ops(&iwdev->ibdev, &irdma_gen1_dev_ops);
diff --git a/include/uapi/rdma/irdma-abi.h b/include/uapi/rdma/irdma-abi.h
index 38155affc8b4..a1a26529aa85 100644
--- a/include/uapi/rdma/irdma-abi.h
+++ b/include/uapi/rdma/irdma-abi.h
@@ -10,6 +10,7 @@
#define IRDMA_ABI_H
#include <linux/types.h>
+#include <rdma/ib_user_ioctl_cmds.h>
/* irdma must support legacy GEN_1 i40iw kernel
* and user-space whose last ABI ver is 5
@@ -23,6 +24,10 @@ enum irdma_memreg_type {
IRDMA_MEMREG_TYPE_SRQ = 3,
};
+enum irdma_ib_create_cq_attrs {
+ IRDMA_IB_ATTR_CREATE_CQ_SHADOW_BUF_UMEM = UVERBS_ID_DRIVER_NS_WITH_UHW,
+};
+
enum {
IRDMA_ALLOC_UCTX_USE_RAW_ATTR = 1 << 0,
IRDMA_ALLOC_UCTX_MIN_HW_WQ_SIZE = 1 << 1,
--
2.56.0.385.gd3acb90ef8-goog
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH rdma-next v2 3/6] RDMA/irdma: Support UMEM attribute for QP creation
2026-10-15 1:19 [PATCH rdma-next v2 0/6] RDMA/irdma: Add support for ioctl David Hu
2026-10-15 1:19 ` [PATCH rdma-next v2 1/6] RDMA/irdma: Plumb uverbs_attr_bundle for QP, SRQ David Hu
2026-10-15 1:19 ` [PATCH rdma-next v2 2/6] RDMA/irdma: Register irdma UVERBS ioctl namespace David Hu
@ 2026-10-15 1:19 ` David Hu
2026-10-15 1:36 ` sashiko-bot
2026-10-15 1:19 ` [PATCH rdma-next v2 4/6] RDMA/irdma: Split CQ setup to umode and kmode David Hu
` (2 subsequent siblings)
5 siblings, 1 reply; 13+ messages in thread
From: David Hu @ 2026-10-15 1:19 UTC (permalink / raw)
To: Tatyana Nikolova, Jason Gunthorpe, Leon Romanovsky
Cc: linux-rdma, linux-kernel, jmoroni, eagleshaw, xuehaohu
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
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH rdma-next v2 4/6] RDMA/irdma: Split CQ setup to umode and kmode
2026-10-15 1:19 [PATCH rdma-next v2 0/6] RDMA/irdma: Add support for ioctl David Hu
` (2 preceding siblings ...)
2026-10-15 1:19 ` [PATCH rdma-next v2 3/6] RDMA/irdma: Support UMEM attribute for QP creation David Hu
@ 2026-10-15 1:19 ` David Hu
2026-10-15 1:30 ` sashiko-bot
2026-10-15 1:19 ` [PATCH rdma-next v2 5/6] RDMA/irdma: Support UMEM attribute for CQ creation David Hu
2026-10-15 1:19 ` [PATCH rdma-next v2 6/6] RDMA/irdma: Support UMEM attribute for SRQ creation David Hu
5 siblings, 1 reply; 13+ messages in thread
From: David Hu @ 2026-10-15 1:19 UTC (permalink / raw)
To: Tatyana Nikolova, Jason Gunthorpe, Leon Romanovsky
Cc: linux-rdma, linux-kernel, jmoroni, eagleshaw, xuehaohu
From: David Hu <xuehaohu@google.com>
This split is similar to QP, and SRQ that is already present in existing
irdma driver. Only variable plumbing was done, while umode and kmode setup
logic is identical as before.
Signed-off-by: David Hu <xuehaohu@google.com>
---
drivers/infiniband/hw/irdma/verbs.c | 232 +++++++++++++++-------------
1 file changed, 126 insertions(+), 106 deletions(-)
diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
index ab25445f3828..7162b37fa6ff 100644
--- a/drivers/infiniband/hw/irdma/verbs.c
+++ b/drivers/infiniband/hw/irdma/verbs.c
@@ -2624,6 +2624,126 @@ static inline int cq_validate_flags(u32 flags, u8 hw_rev)
return flags & ~IB_UVERBS_CQ_FLAGS_TIMESTAMP_COMPLETION ? -EOPNOTSUPP : 0;
}
+static int irdma_setup_kmode_cq(struct irdma_device *iwdev,
+ struct irdma_cq *iwcq,
+ struct irdma_cq_init_info *info,
+ const struct ib_cq_init_attr *attr)
+{
+ struct irdma_cq_uk_init_info *ukinfo = &info->cq_uk_init_info;
+ struct irdma_pci_f *rf = iwdev->rf;
+ struct irdma_sc_dev *dev = &rf->sc_dev;
+ int entries = attr->cqe;
+ bool cqe_64byte_ena;
+ u8 cqe_size;
+ int rsize;
+
+ if (entries < 1 || entries > rf->max_cqe)
+ return -EINVAL;
+
+ cqe_64byte_ena = dev->hw_attrs.uk_attrs.feature_flags & IRDMA_FEATURE_64_BYTE_CQE ?
+ true : false;
+ cqe_size = cqe_64byte_ena ? 64 : 32;
+
+ entries += 2;
+ if (!cqe_64byte_ena && dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_2)
+ entries *= 2;
+
+ if (entries & 1)
+ entries += 1; /* cq size must be an even number */
+
+ if (entries * cqe_size == IRDMA_HW_PAGE_SIZE)
+ entries += 2;
+
+ ukinfo->cq_size = entries;
+
+ if (cqe_64byte_ena)
+ rsize = ukinfo->cq_size * sizeof(struct irdma_extended_cqe);
+ else
+ rsize = ukinfo->cq_size * sizeof(struct irdma_cqe);
+ iwcq->kmem.size = ALIGN(round_up(rsize, 256), 256);
+ iwcq->kmem.va = dma_alloc_coherent(dev->hw->device,
+ iwcq->kmem.size,
+ &iwcq->kmem.pa, GFP_KERNEL);
+ if (!iwcq->kmem.va)
+ return -ENOMEM;
+
+ iwcq->kmem_shadow.size = ALIGN(IRDMA_SHADOW_AREA_SIZE << 3, 64);
+ iwcq->kmem_shadow.va = dma_alloc_coherent(dev->hw->device,
+ iwcq->kmem_shadow.size,
+ &iwcq->kmem_shadow.pa,
+ GFP_KERNEL);
+ if (!iwcq->kmem_shadow.va)
+ return -ENOMEM;
+
+ info->shadow_area_pa = iwcq->kmem_shadow.pa;
+ ukinfo->shadow_area = iwcq->kmem_shadow.va;
+ ukinfo->cq_base = iwcq->kmem.va;
+ info->cq_base_pa = iwcq->kmem.pa;
+
+ return 0;
+}
+
+static int irdma_setup_umode_cq(struct irdma_device *iwdev,
+ struct irdma_cq *iwcq,
+ struct irdma_cq_init_info *info,
+ struct ib_udata *udata)
+{
+ struct irdma_create_cq_req req = {};
+ struct irdma_pci_f *rf = iwdev->rf;
+ struct irdma_ucontext *ucontext;
+ struct irdma_cq_mr *cqmr_shadow;
+ struct irdma_cq_mr *cqmr;
+ unsigned long flags;
+ int err_code;
+
+ iwcq->user_mode = true;
+ ucontext = rdma_udata_to_drv_context(udata, struct irdma_ucontext,
+ ibucontext);
+ /* Even though the last member of struct irdma_create_cq_req
+ * was always user_shadow_area, we need backwards compat with
+ * the legacy i40iw struct i40iw_ucreate_cq which stopped
+ * at user_cq_buffer.
+ */
+ err_code = ib_copy_validate_udata_in(udata, req, user_cq_buf);
+ if (err_code)
+ return err_code;
+
+ spin_lock_irqsave(&ucontext->cq_reg_mem_list_lock, flags);
+ iwcq->iwpbl = irdma_get_pbl((unsigned long)req.user_cq_buf,
+ &ucontext->cq_reg_mem_list);
+ spin_unlock_irqrestore(&ucontext->cq_reg_mem_list_lock, flags);
+ if (!iwcq->iwpbl)
+ return -EPROTO;
+
+ cqmr = &iwcq->iwpbl->cq_mr;
+
+ if (rf->sc_dev.hw_attrs.uk_attrs.feature_flags &
+ IRDMA_FEATURE_CQ_RESIZE) {
+ spin_lock_irqsave(&ucontext->cq_reg_mem_list_lock, flags);
+ iwcq->iwpbl_shadow =
+ irdma_get_pbl((unsigned long)req.user_shadow_area,
+ &ucontext->cq_reg_mem_list);
+ spin_unlock_irqrestore(&ucontext->cq_reg_mem_list_lock, flags);
+
+ if (!iwcq->iwpbl_shadow)
+ return -EPROTO;
+
+ cqmr_shadow = &iwcq->iwpbl_shadow->cq_mr;
+ info->shadow_area_pa = cqmr_shadow->cq_pbl.addr;
+ } else {
+ info->shadow_area_pa = cqmr->shadow;
+ }
+ if (iwcq->iwpbl->pbl_allocated) {
+ info->virtual_map = true;
+ info->pbl_chunk_size = 1;
+ info->first_pm_pbl_idx = cqmr->cq_pbl.idx;
+ } else {
+ info->cq_base_pa = cqmr->cq_pbl.addr;
+ }
+
+ return 0;
+}
+
/**
* irdma_create_cq - create cq
* @ibcq: CQ allocated
@@ -2647,11 +2767,9 @@ static int irdma_create_cq(struct ib_cq *ibcq,
struct irdma_cqp_request *cqp_request;
struct cqp_cmds_info *cqp_info;
struct irdma_cq_uk_init_info *ukinfo = &info.cq_uk_init_info;
- unsigned long flags;
int err_code;
int entries = attr->cqe;
bool cqe_64byte_ena;
- u8 cqe_size;
err_code = cq_validate_flags(attr->flags, dev->hw_attrs.uk_attrs.hw_rev);
if (err_code)
@@ -2679,7 +2797,6 @@ static int irdma_create_cq(struct ib_cq *ibcq,
ukinfo->cq_id = cq_num;
cqe_64byte_ena = dev->hw_attrs.uk_attrs.feature_flags & IRDMA_FEATURE_64_BYTE_CQE ?
true : false;
- cqe_size = cqe_64byte_ena ? 64 : 32;
ukinfo->avoid_mem_cflct = cqe_64byte_ena;
iwcq->ibcq.cqe = info.cq_uk_init_info.cq_size;
if (attr->comp_vector < rf->ceqs_count)
@@ -2689,109 +2806,12 @@ static int irdma_create_cq(struct ib_cq *ibcq,
info.type = IRDMA_CQ_TYPE_IWARP;
info.vsi = &iwdev->vsi;
- if (udata) {
- struct irdma_ucontext *ucontext;
- struct irdma_create_cq_req req = {};
- struct irdma_cq_mr *cqmr;
- struct irdma_cq_mr *cqmr_shadow;
-
- iwcq->user_mode = true;
- ucontext =
- rdma_udata_to_drv_context(udata, struct irdma_ucontext,
- ibucontext);
- /* Even though the last member of struct irdma_create_cq_req
- * was always user_shadow_area, we need backwards compat with
- * the legacy i40iw struct i40iw_ucreate_cq which stopped
- * at user_cq_buffer.
- */
- err_code = ib_copy_validate_udata_in(udata, req, user_cq_buf);
- if (err_code)
- goto cq_free_rsrc;
-
- spin_lock_irqsave(&ucontext->cq_reg_mem_list_lock, flags);
- iwcq->iwpbl = irdma_get_pbl((unsigned long)req.user_cq_buf,
- &ucontext->cq_reg_mem_list);
- spin_unlock_irqrestore(&ucontext->cq_reg_mem_list_lock, flags);
- if (!iwcq->iwpbl) {
- err_code = -EPROTO;
- goto cq_free_rsrc;
- }
-
- cqmr = &iwcq->iwpbl->cq_mr;
-
- if (rf->sc_dev.hw_attrs.uk_attrs.feature_flags &
- IRDMA_FEATURE_CQ_RESIZE) {
- spin_lock_irqsave(&ucontext->cq_reg_mem_list_lock, flags);
- iwcq->iwpbl_shadow = irdma_get_pbl(
- (unsigned long)req.user_shadow_area,
- &ucontext->cq_reg_mem_list);
- spin_unlock_irqrestore(&ucontext->cq_reg_mem_list_lock, flags);
-
- if (!iwcq->iwpbl_shadow) {
- err_code = -EPROTO;
- goto cq_free_rsrc;
- }
- cqmr_shadow = &iwcq->iwpbl_shadow->cq_mr;
- info.shadow_area_pa = cqmr_shadow->cq_pbl.addr;
- } else {
- info.shadow_area_pa = cqmr->shadow;
- }
- if (iwcq->iwpbl->pbl_allocated) {
- info.virtual_map = true;
- info.pbl_chunk_size = 1;
- info.first_pm_pbl_idx = cqmr->cq_pbl.idx;
- } else {
- info.cq_base_pa = cqmr->cq_pbl.addr;
- }
- } else {
- /* Kmode allocations */
- int rsize;
-
- if (entries < 1 || entries > rf->max_cqe) {
- err_code = -EINVAL;
- goto cq_free_rsrc;
- }
-
- entries += 2;
- if (!cqe_64byte_ena && dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_2)
- entries *= 2;
-
- if (entries & 1)
- entries += 1; /* cq size must be an even number */
-
- if (entries * cqe_size == IRDMA_HW_PAGE_SIZE)
- entries += 2;
-
- ukinfo->cq_size = entries;
-
- if (cqe_64byte_ena)
- rsize = info.cq_uk_init_info.cq_size * sizeof(struct irdma_extended_cqe);
- else
- rsize = info.cq_uk_init_info.cq_size * sizeof(struct irdma_cqe);
- iwcq->kmem.size = ALIGN(round_up(rsize, 256), 256);
- iwcq->kmem.va = dma_alloc_coherent(dev->hw->device,
- iwcq->kmem.size,
- &iwcq->kmem.pa, GFP_KERNEL);
- if (!iwcq->kmem.va) {
- err_code = -ENOMEM;
- goto cq_free_rsrc;
- }
-
- iwcq->kmem_shadow.size = ALIGN(IRDMA_SHADOW_AREA_SIZE << 3,
- 64);
- iwcq->kmem_shadow.va = dma_alloc_coherent(dev->hw->device,
- iwcq->kmem_shadow.size,
- &iwcq->kmem_shadow.pa,
- GFP_KERNEL);
- if (!iwcq->kmem_shadow.va) {
- err_code = -ENOMEM;
- goto cq_free_rsrc;
- }
- info.shadow_area_pa = iwcq->kmem_shadow.pa;
- ukinfo->shadow_area = iwcq->kmem_shadow.va;
- ukinfo->cq_base = iwcq->kmem.va;
- info.cq_base_pa = iwcq->kmem.pa;
- }
+ if (udata)
+ err_code = irdma_setup_umode_cq(iwdev, iwcq, &info, udata);
+ else
+ err_code = irdma_setup_kmode_cq(iwdev, iwcq, &info, attr);
+ if (err_code)
+ goto cq_free_rsrc;
info.shadow_read_threshold = min(info.cq_uk_init_info.cq_size / 2,
(u32)IRDMA_MAX_CQ_READ_THRESH);
--
2.56.0.385.gd3acb90ef8-goog
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH rdma-next v2 5/6] RDMA/irdma: Support UMEM attribute for CQ creation
2026-10-15 1:19 [PATCH rdma-next v2 0/6] RDMA/irdma: Add support for ioctl David Hu
` (3 preceding siblings ...)
2026-10-15 1:19 ` [PATCH rdma-next v2 4/6] RDMA/irdma: Split CQ setup to umode and kmode David Hu
@ 2026-10-15 1:19 ` David Hu
2026-10-15 1:33 ` sashiko-bot
2026-10-15 1:19 ` [PATCH rdma-next v2 6/6] RDMA/irdma: Support UMEM attribute for SRQ creation David Hu
5 siblings, 1 reply; 13+ messages in thread
From: David Hu @ 2026-10-15 1:19 UTC (permalink / raw)
To: Tatyana Nikolova, Jason Gunthorpe, Leon Romanovsky
Cc: linux-rdma, linux-kernel, jmoroni, eagleshaw, xuehaohu
From: David Hu <xuehaohu@google.com>
Support the standard 1-step queue buffer creation model for CQ by
`UVERBS_ATTR_CREATE_CQ_BUF_UMEM`, `IRDMA_IB_ATTR_CREATE_CQ_SHADOW_BUF_UMEM`
via `ib_umem_get_attr()`.
Set up hardware pble directly from the pinned CQ and shadow umems via
`irdma_setup_q_pbl_from_umem()`.
Proper umem and pble cleanup are added into existing `irdma_cq_free_rsrc()`
upon CQ destruction.
We maintain backward compatibility for legacy 2-step registration if UMEM
attributes are not provided.
`irdma_resize_cq()` will have a possibility to deal with a pble/mr that
is created via one-step logic, after this change. Therefore, a proper
cleanup is added.
Signed-off-by: David Hu <xuehaohu@google.com>
---
drivers/infiniband/hw/irdma/verbs.c | 135 +++++++++++++++++++++++-----
1 file changed, 112 insertions(+), 23 deletions(-)
diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
index 7162b37fa6ff..4f0831813119 100644
--- a/drivers/infiniband/hw/irdma/verbs.c
+++ b/drivers/infiniband/hw/irdma/verbs.c
@@ -2028,13 +2028,24 @@ static void irdma_cq_free_rsrc(struct irdma_pci_f *rf, struct irdma_cq *iwcq)
if (iwcq->iwpbl) {
iwmr = iwcq->iwpbl->iwmr;
- refcount_dec(&iwmr->user_ring_refs);
+ if (iwmr && refcount_dec_and_test(&iwmr->user_ring_refs)) {
+ ib_umem_release(iwmr->region);
+ if (iwcq->iwpbl->pbl_allocated)
+ irdma_free_pble(rf->pble_rsrc, &iwcq->iwpbl->pble_alloc);
+ kfree(iwmr);
+ }
}
if (iwcq->iwpbl_shadow) {
iwmr = iwcq->iwpbl_shadow->iwmr;
- refcount_dec(&iwmr->user_ring_refs);
+ if (iwmr && refcount_dec_and_test(&iwmr->user_ring_refs)) {
+ ib_umem_release(iwmr->region);
+ if (iwcq->iwpbl_shadow->pbl_allocated)
+ irdma_free_pble(rf->pble_rsrc,
+ &iwcq->iwpbl_shadow->pble_alloc);
+ kfree(iwmr);
+ }
}
}
@@ -2161,6 +2172,7 @@ static int irdma_resize_cq(struct ib_cq *ibcq, unsigned int entries,
struct irdma_dma_mem kmem_buf;
struct irdma_cq_mr *cqmr_buf;
struct irdma_pbl *iwpbl_buf = NULL;
+ struct irdma_pbl *old_iwpbl = NULL;
struct irdma_device *iwdev;
struct irdma_pci_f *rf;
struct irdma_cq_buf *cq_buf = NULL;
@@ -2273,17 +2285,12 @@ static int irdma_resize_cq(struct ib_cq *ibcq, unsigned int entries,
spin_lock_irqsave(&iwcq->lock, flags);
if (udata) {
- struct irdma_pbl *old_iwpbl = iwcq->iwpbl;
+ old_iwpbl = iwcq->iwpbl;
/* Only update if the resize was successful. Otherwise, HW is
* still pointing to the old PBL.
*/
iwcq->iwpbl = iwpbl_buf;
- if (old_iwpbl) {
- struct irdma_mr *old_iwmr = old_iwpbl->iwmr;
-
- refcount_dec(&old_iwmr->user_ring_refs);
- }
}
if (cq_buf) {
cq_buf->kmem_buf = iwcq->kmem;
@@ -2298,6 +2305,21 @@ static int irdma_resize_cq(struct ib_cq *ibcq, unsigned int entries,
ibcq->cqe = info.cq_size - 1;
spin_unlock_irqrestore(&iwcq->lock, flags);
+ /* Old pble/umem is cleaned up outside spinlock's atomic context
+ * since both of them take sleepable lock.
+ */
+ if (old_iwpbl) {
+ struct irdma_mr *old_iwmr = old_iwpbl->iwmr;
+
+ if (old_iwmr && refcount_dec_and_test(&old_iwmr->user_ring_refs)) {
+ ib_umem_release(old_iwmr->region);
+ if (old_iwpbl->pbl_allocated)
+ irdma_free_pble(rf->pble_rsrc,
+ &old_iwpbl->pble_alloc);
+ kfree(old_iwmr);
+ }
+ }
+
return 0;
error:
if (iwpbl_buf) {
@@ -2686,15 +2708,20 @@ static int irdma_setup_kmode_cq(struct irdma_device *iwdev,
static int irdma_setup_umode_cq(struct irdma_device *iwdev,
struct irdma_cq *iwcq,
struct irdma_cq_init_info *info,
- struct ib_udata *udata)
+ struct ib_udata *udata,
+ struct uverbs_attr_bundle *attrs)
{
+ struct irdma_cq_uk_init_info *ukinfo = &info->cq_uk_init_info;
struct irdma_create_cq_req req = {};
struct irdma_pci_f *rf = iwdev->rf;
+ struct irdma_sc_dev *dev = &rf->sc_dev;
struct irdma_ucontext *ucontext;
struct irdma_cq_mr *cqmr_shadow;
struct irdma_cq_mr *cqmr;
unsigned long flags;
+ bool cqe_64byte_ena;
int err_code;
+ u8 cqe_size;
iwcq->user_mode = true;
ucontext = rdma_udata_to_drv_context(udata, struct irdma_ucontext,
@@ -2708,26 +2735,88 @@ static int irdma_setup_umode_cq(struct irdma_device *iwdev,
if (err_code)
return err_code;
- spin_lock_irqsave(&ucontext->cq_reg_mem_list_lock, flags);
- iwcq->iwpbl = irdma_get_pbl((unsigned long)req.user_cq_buf,
- &ucontext->cq_reg_mem_list);
- spin_unlock_irqrestore(&ucontext->cq_reg_mem_list_lock, flags);
- if (!iwcq->iwpbl)
- return -EPROTO;
+ cqe_64byte_ena = dev->hw_attrs.uk_attrs.feature_flags & IRDMA_FEATURE_64_BYTE_CQE ?
+ true : false;
+ cqe_size = cqe_64byte_ena ? 64 : 32;
+
+ if (attrs && uverbs_attr_is_valid(attrs, UVERBS_ATTR_CREATE_CQ_BUF_UMEM)) {
+ struct ib_umem *umem;
+ struct irdma_mem_reg_req cq_req = {};
+ u8 shadow_pgcnt = (rf->sc_dev.hw_attrs.uk_attrs.feature_flags &
+ IRDMA_FEATURE_CQ_RESIZE) ? 0 : IRDMA_SHADOW_PGCNT;
+ u32 min_size;
+
+ cq_req.cq_pages = DIV_ROUND_UP(ukinfo->cq_size * cqe_size,
+ IRDMA_HW_PAGE_SIZE);
+ min_size = (cq_req.cq_pages + shadow_pgcnt) << IRDMA_HW_PAGE_SHIFT;
+
+ umem = ib_umem_get_cq_buf(&iwdev->ibdev, attrs, min_size,
+ IB_ACCESS_LOCAL_WRITE);
+ if (IS_ERR(umem))
+ return PTR_ERR(umem);
+
+ iwcq->iwpbl = irdma_setup_q_pbl_from_umem(iwdev, umem, NULL,
+ IRDMA_MEMREG_TYPE_CQ, &cq_req);
+ if (IS_ERR(iwcq->iwpbl)) {
+ err_code = PTR_ERR(iwcq->iwpbl);
+ iwcq->iwpbl = NULL;
+ ib_umem_release(umem);
+ return err_code;
+ }
+ } else {
+ if (!req.user_cq_buf)
+ return -EINVAL;
+
+ spin_lock_irqsave(&ucontext->cq_reg_mem_list_lock, flags);
+ iwcq->iwpbl = irdma_get_pbl((unsigned long)req.user_cq_buf,
+ &ucontext->cq_reg_mem_list);
+ spin_unlock_irqrestore(&ucontext->cq_reg_mem_list_lock, flags);
+ if (!iwcq->iwpbl)
+ return -EPROTO;
+ }
cqmr = &iwcq->iwpbl->cq_mr;
if (rf->sc_dev.hw_attrs.uk_attrs.feature_flags &
IRDMA_FEATURE_CQ_RESIZE) {
- spin_lock_irqsave(&ucontext->cq_reg_mem_list_lock, flags);
- iwcq->iwpbl_shadow =
- irdma_get_pbl((unsigned long)req.user_shadow_area,
- &ucontext->cq_reg_mem_list);
- spin_unlock_irqrestore(&ucontext->cq_reg_mem_list_lock, flags);
+ if (attrs &&
+ uverbs_attr_is_valid(attrs, IRDMA_IB_ATTR_CREATE_CQ_SHADOW_BUF_UMEM)) {
+ struct ib_umem *shadow_umem;
+ struct irdma_mem_reg_req shadow_req = {
+ .cq_pages = IRDMA_SHADOW_PGCNT,
+ };
+
+ shadow_umem =
+ ib_umem_get_attr(&iwdev->ibdev, attrs,
+ IRDMA_IB_ATTR_CREATE_CQ_SHADOW_BUF_UMEM,
+ IRDMA_SHADOW_AREA_SIZE << 3,
+ IB_ACCESS_LOCAL_WRITE);
+ if (IS_ERR(shadow_umem))
+ return PTR_ERR(shadow_umem);
+
+ iwcq->iwpbl_shadow =
+ irdma_setup_q_pbl_from_umem(iwdev, shadow_umem, NULL,
+ IRDMA_MEMREG_TYPE_CQ,
+ &shadow_req);
+ if (IS_ERR(iwcq->iwpbl_shadow)) {
+ err_code = PTR_ERR(iwcq->iwpbl_shadow);
+ iwcq->iwpbl_shadow = NULL;
+ ib_umem_release(shadow_umem);
+ return err_code;
+ }
+ } else {
+ if (!req.user_shadow_area)
+ return -EINVAL;
- if (!iwcq->iwpbl_shadow)
- return -EPROTO;
+ spin_lock_irqsave(&ucontext->cq_reg_mem_list_lock, flags);
+ iwcq->iwpbl_shadow =
+ irdma_get_pbl((unsigned long)req.user_shadow_area,
+ &ucontext->cq_reg_mem_list);
+ spin_unlock_irqrestore(&ucontext->cq_reg_mem_list_lock, flags);
+ if (!iwcq->iwpbl_shadow)
+ return -EPROTO;
+ }
cqmr_shadow = &iwcq->iwpbl_shadow->cq_mr;
info->shadow_area_pa = cqmr_shadow->cq_pbl.addr;
} else {
@@ -2807,7 +2896,7 @@ static int irdma_create_cq(struct ib_cq *ibcq,
info.vsi = &iwdev->vsi;
if (udata)
- err_code = irdma_setup_umode_cq(iwdev, iwcq, &info, udata);
+ err_code = irdma_setup_umode_cq(iwdev, iwcq, &info, udata, attrs);
else
err_code = irdma_setup_kmode_cq(iwdev, iwcq, &info, attr);
if (err_code)
--
2.56.0.385.gd3acb90ef8-goog
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH rdma-next v2 6/6] RDMA/irdma: Support UMEM attribute for SRQ creation
2026-10-15 1:19 [PATCH rdma-next v2 0/6] RDMA/irdma: Add support for ioctl David Hu
` (4 preceding siblings ...)
2026-10-15 1:19 ` [PATCH rdma-next v2 5/6] RDMA/irdma: Support UMEM attribute for CQ creation David Hu
@ 2026-10-15 1:19 ` David Hu
2026-10-15 1:32 ` sashiko-bot
5 siblings, 1 reply; 13+ messages in thread
From: David Hu @ 2026-10-15 1:19 UTC (permalink / raw)
To: Tatyana Nikolova, Jason Gunthorpe, Leon Romanovsky
Cc: linux-rdma, linux-kernel, jmoroni, eagleshaw, xuehaohu
From: David Hu <xuehaohu@google.com>
Support the standard 1-step queue buffer creation for SRQ by
`UVERBS_ATTR_CREATE_SRQ_BUF_UMEM` via `ib_umem_get_attr()`.
Set up hardware pble directly from the pinned SRQ umem via
`irdma_setup_q_pbl_from_umem()`.
Proper umem and pble cleanup, and error unwind are added into existing
`irdma_srq_free_rsrc()` upon SRQ destruction.
We maintain backward compatibility for the legacy 2-step registration if
the UMEM attribute is not provided.
Signed-off-by: David Hu <xuehaohu@google.com>
---
drivers/infiniband/hw/irdma/verbs.c | 68 ++++++++++++++++++++++++-----
1 file changed, 58 insertions(+), 10 deletions(-)
diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
index 4f0831813119..5d085933c7f0 100644
--- a/drivers/infiniband/hw/irdma/verbs.c
+++ b/drivers/infiniband/hw/irdma/verbs.c
@@ -1996,9 +1996,16 @@ static void irdma_srq_free_rsrc(struct irdma_pci_f *rf, struct irdma_srq *iwsrq)
iwsrq->kmem.va = NULL;
} else {
/* Not called in any failure path, so iwpbl is valid. */
- struct irdma_mr *iwmr = iwsrq->iwpbl->iwmr;
+ if (iwsrq->iwpbl) {
+ struct irdma_mr *iwmr = iwsrq->iwpbl->iwmr;
- refcount_dec(&iwmr->user_ring_refs);
+ if (iwmr && refcount_dec_and_test(&iwmr->user_ring_refs)) {
+ ib_umem_release(iwmr->region);
+ if (iwsrq->iwpbl->pbl_allocated)
+ irdma_free_pble(rf->pble_rsrc, &iwsrq->iwpbl->pble_alloc);
+ kfree(iwmr);
+ }
+ }
}
irdma_free_rsrc(rf, rf->allocated_srqs, srq->srq_uk.srq_id);
@@ -2425,6 +2432,7 @@ static int irdma_setup_umode_srq(struct irdma_device *iwdev,
struct ib_udata *udata,
struct uverbs_attr_bundle *attrs)
{
+ struct irdma_srq_uk_init_info *ukinfo = &info->srq_uk_init_info;
struct irdma_create_srq_req req = {};
struct irdma_ucontext *ucontext;
struct irdma_srq_mr *srqmr;
@@ -2440,14 +2448,49 @@ static int irdma_setup_umode_srq(struct irdma_device *iwdev,
if (ret)
return ret;
- spin_lock_irqsave(&ucontext->srq_reg_mem_list_lock, flags);
- iwpbl = irdma_get_pbl((unsigned long)req.user_srq_buf,
- &ucontext->srq_reg_mem_list);
- spin_unlock_irqrestore(&ucontext->srq_reg_mem_list_lock, flags);
- if (!iwpbl)
- return -EPROTO;
+ if (attrs && uverbs_attr_is_valid(attrs, UVERBS_ATTR_CREATE_SRQ_BUF_UMEM)) {
+ struct irdma_mem_reg_req srq_req = {};
+ struct ib_umem *umem;
+ u32 total;
+ u8 shift;
- iwsrq->iwpbl = iwpbl;
+ irdma_get_wqe_shift(ukinfo->uk_attrs, ukinfo->max_srq_frag_cnt, 0, &shift);
+ srq_req.rq_pages =
+ DIV_ROUND_UP((ukinfo->srq_size << shift) * IRDMA_QP_WQE_MIN_SIZE,
+ IRDMA_HW_PAGE_SIZE);
+ total = srq_req.rq_pages + IRDMA_SHADOW_PGCNT;
+
+ umem = ib_umem_get_attr(&iwdev->ibdev, attrs,
+ UVERBS_ATTR_CREATE_SRQ_BUF_UMEM,
+ total << IRDMA_HW_PAGE_SHIFT,
+ IB_ACCESS_LOCAL_WRITE);
+ if (IS_ERR(umem))
+ return PTR_ERR(umem);
+
+ iwsrq->iwpbl = irdma_setup_q_pbl_from_umem(iwdev, umem,
+ iwsrq->ibsrq.pd,
+ IRDMA_MEMREG_TYPE_SRQ,
+ &srq_req);
+ if (IS_ERR(iwsrq->iwpbl)) {
+ ret = PTR_ERR(iwsrq->iwpbl);
+ iwsrq->iwpbl = NULL;
+ ib_umem_release(umem);
+ return ret;
+ }
+ iwpbl = iwsrq->iwpbl;
+ } else {
+ if (!req.user_srq_buf)
+ return -EINVAL;
+
+ spin_lock_irqsave(&ucontext->srq_reg_mem_list_lock, flags);
+ iwpbl = irdma_get_pbl((unsigned long)req.user_srq_buf,
+ &ucontext->srq_reg_mem_list);
+ spin_unlock_irqrestore(&ucontext->srq_reg_mem_list_lock, flags);
+ if (!iwpbl)
+ return -EPROTO;
+
+ iwsrq->iwpbl = iwpbl;
+ }
srqmr = &iwpbl->srq_mr;
if (iwpbl->pbl_allocated) {
@@ -2615,7 +2658,12 @@ static int irdma_create_srq(struct ib_srq *ibsrq,
if (iwsrq->user_mode && iwsrq->iwpbl) {
struct irdma_mr *iwmr = iwsrq->iwpbl->iwmr;
- refcount_dec(&iwmr->user_ring_refs);
+ if (iwmr && refcount_dec_and_test(&iwmr->user_ring_refs)) {
+ ib_umem_release(iwmr->region);
+ if (iwsrq->iwpbl->pbl_allocated)
+ irdma_free_pble(rf->pble_rsrc, &iwsrq->iwpbl->pble_alloc);
+ kfree(iwmr);
+ }
}
irdma_free_rsrc(rf, rf->allocated_srqs, iwsrq->srq_num);
return err_code;
--
2.56.0.385.gd3acb90ef8-goog
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH rdma-next v2 4/6] RDMA/irdma: Split CQ setup to umode and kmode
2026-10-15 1:19 ` [PATCH rdma-next v2 4/6] RDMA/irdma: Split CQ setup to umode and kmode David Hu
@ 2026-10-15 1:30 ` sashiko-bot
0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-10-15 1:30 UTC (permalink / raw)
To: David Hu; +Cc: linux-rdma
> From: David Hu <xuehaohu@google.com>
>
> This split is similar to QP, and SRQ that is already present in existing
> irdma driver. Only variable plumbing was done, while umode and kmode setup
> logic is identical as before.
>
> Signed-off-by: David Hu <xuehaohu@google.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261015011940.4122452-1-dhu@x6u.co?part=4
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH rdma-next v2 1/6] RDMA/irdma: Plumb uverbs_attr_bundle for QP, SRQ
2026-10-15 1:19 ` [PATCH rdma-next v2 1/6] RDMA/irdma: Plumb uverbs_attr_bundle for QP, SRQ David Hu
@ 2026-10-15 1:31 ` sashiko-bot
0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-10-15 1:31 UTC (permalink / raw)
To: David Hu; +Cc: linux-rdma
> From: David Hu <xuehaohu@google.com>
>
> In preparation to support modern UVERBS ioctl attributes (such
> as UVERBS_ATTR_UMEM for CoCo DMA bounce buffers), we pass down
> `uverbs_attr_bundle` for inner QP, SRQ routines. Since standard
> uAPIs provide `ib_udata`, we derive it via the helper macro,
> `rdma_udata_to_uverbs_attr_bundle`. `irdma_create_cq()` supports
> `uverbs_attr_bundle` already, therefore, this patch fills the gap for QP
> and SRQ.
>
> QP, SRQ uAPI will now have `ib_udata`, and CQ uAPI has `uverbs_attr_bundle`
> as a top level input. However, we think it is a future project to unify
> them.
>
> Signed-off-by: David Hu <xuehaohu@google.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261015011940.4122452-1-dhu@x6u.co?part=1
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH rdma-next v2 6/6] RDMA/irdma: Support UMEM attribute for SRQ creation
2026-10-15 1:19 ` [PATCH rdma-next v2 6/6] RDMA/irdma: Support UMEM attribute for SRQ creation David Hu
@ 2026-10-15 1:32 ` sashiko-bot
0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-10-15 1:32 UTC (permalink / raw)
To: David Hu; +Cc: linux-rdma
> From: David Hu <xuehaohu@google.com>
>
> Support the standard 1-step queue buffer creation for SRQ by
> `UVERBS_ATTR_CREATE_SRQ_BUF_UMEM` via `ib_umem_get_attr()`.
>
> Set up hardware pble directly from the pinned SRQ umem via
> `irdma_setup_q_pbl_from_umem()`.
>
> Proper umem and pble cleanup, and error unwind are added into existing
> `irdma_srq_free_rsrc()` upon SRQ destruction.
>
> We maintain backward compatibility for the legacy 2-step registration if
> the UMEM attribute is not provided.
>
> Signed-off-by: David Hu <xuehaohu@google.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261015011940.4122452-1-dhu@x6u.co?part=6
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH rdma-next v2 5/6] RDMA/irdma: Support UMEM attribute for CQ creation
2026-10-15 1:19 ` [PATCH rdma-next v2 5/6] RDMA/irdma: Support UMEM attribute for CQ creation David Hu
@ 2026-10-15 1:33 ` sashiko-bot
0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-10-15 1:33 UTC (permalink / raw)
To: David Hu; +Cc: linux-rdma
> From: David Hu <xuehaohu@google.com>
>
> Support the standard 1-step queue buffer creation model for CQ by
> `UVERBS_ATTR_CREATE_CQ_BUF_UMEM`, `IRDMA_IB_ATTR_CREATE_CQ_SHADOW_BUF_UMEM`
> via `ib_umem_get_attr()`.
>
> Set up hardware pble directly from the pinned CQ and shadow umems via
> `irdma_setup_q_pbl_from_umem()`.
>
> Proper umem and pble cleanup are added into existing `irdma_cq_free_rsrc()`
> upon CQ destruction.
>
> We maintain backward compatibility for legacy 2-step registration if UMEM
> attributes are not provided.
>
> `irdma_resize_cq()` will have a possibility to deal with a pble/mr that
> is created via one-step logic, after this change. Therefore, a proper
> cleanup is added.
>
> Signed-off-by: David Hu <xuehaohu@google.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261015011940.4122452-1-dhu@x6u.co?part=5
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH rdma-next v2 2/6] RDMA/irdma: Register irdma UVERBS ioctl namespace
2026-10-15 1:19 ` [PATCH rdma-next v2 2/6] RDMA/irdma: Register irdma UVERBS ioctl namespace David Hu
@ 2026-10-15 1:33 ` sashiko-bot
0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-10-15 1:33 UTC (permalink / raw)
To: David Hu; +Cc: linux-rdma
> From: David Hu <xuehaohu@google.com>
>
> An irdma UVERBS module is now created. An irdma specific shadow buf is
> defined for CQ, while QP and SRQ reuses core's uapi definitions. This
> works since core builds shared core ioctl parsing tree first, before adding
> driver specific `uapi_definition`.
>
> Destroy paths are automatically handled by core dispatchers, as objects
> are now registered in the parsing tree and no additional driver specifics
> are needed in destroy ioctls. Resize, Query, and Modify continue to go
> through write() cmds.
>
> Signed-off-by: David Hu <xuehaohu@google.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261015011940.4122452-1-dhu@x6u.co?part=2
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH rdma-next v2 3/6] RDMA/irdma: Support UMEM attribute for QP creation
2026-10-15 1:19 ` [PATCH rdma-next v2 3/6] RDMA/irdma: Support UMEM attribute for QP creation David Hu
@ 2026-10-15 1:36 ` sashiko-bot
0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-10-15 1:36 UTC (permalink / raw)
To: David Hu; +Cc: linux-rdma
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] rdma: resource leak of qp_num in irdma_create_qp() error path
--
commit c4616d335368961fe171e368fb4fc4f2e2fa096d
Author: David Hu <xuehaohu@google.com>
RDMA/irdma: Support UMEM attribute for QP creation
This commit introduces support for the standard 1-step queue buffer creation
model for QPs by using UVERBS_ATTR_CREATE_QP_BUF_UMEM and ib_umem_get_attr().
It allocates the backing MR and programs the hardware pble directly from the
pinned umem, adding cleanup routines to irdma_free_qp_rsrc() upon destruction.
> diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
> index b2ffdc8e3d677..ab25445f38282 100644
> --- a/drivers/infiniband/hw/irdma/verbs.c
> +++ b/drivers/infiniband/hw/irdma/verbs.c
[ ... ]
> @@ -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;
> + }
[Severity: Medium]
If the newly added UMEM QP setup fails and returns an error here,
irdma_create_qp() will jump to its error path:
drivers/infiniband/hw/irdma/verbs.c:irdma_create_qp() {
...
if (udata) {
...
err_code = irdma_setup_umode_qp(ucontext, &ureq, iwdev, iwqp,
&init_info, init_attr, attrs);
} else {
...
if (err_code) {
ibdev_dbg(&iwdev->ibdev, "VERBS: setup qp failed\n");
goto error;
}
...
error:
irdma_free_qp_rsrc(iwqp);
return err_code;
}
However, at this point irdma_sc_qp_init() has not yet been executed, so
iwqp->sc_qp.qp_uk.qp_id is still uninitialized (0).
Does this cause irdma_free_qp_rsrc() to read a 0 value for qp_num and bypass
the deallocation logic (if (qp_num > 2)), permanently leaking the allocated
QP ID from the rf->allocated_qps bitmap?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261015011940.4122452-1-dhu@x6u.co?part=3
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2026-10-15 1:36 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-15 1:19 [PATCH rdma-next v2 0/6] RDMA/irdma: Add support for ioctl David Hu
2026-10-15 1:19 ` [PATCH rdma-next v2 1/6] RDMA/irdma: Plumb uverbs_attr_bundle for QP, SRQ David Hu
2026-10-15 1:31 ` sashiko-bot
2026-10-15 1:19 ` [PATCH rdma-next v2 2/6] RDMA/irdma: Register irdma UVERBS ioctl namespace David Hu
2026-10-15 1:33 ` sashiko-bot
2026-10-15 1:19 ` [PATCH rdma-next v2 3/6] RDMA/irdma: Support UMEM attribute for QP creation David Hu
2026-10-15 1:36 ` sashiko-bot
2026-10-15 1:19 ` [PATCH rdma-next v2 4/6] RDMA/irdma: Split CQ setup to umode and kmode David Hu
2026-10-15 1:30 ` sashiko-bot
2026-10-15 1:19 ` [PATCH rdma-next v2 5/6] RDMA/irdma: Support UMEM attribute for CQ creation David Hu
2026-10-15 1:33 ` sashiko-bot
2026-10-15 1:19 ` [PATCH rdma-next v2 6/6] RDMA/irdma: Support UMEM attribute for SRQ creation David Hu
2026-10-15 1:32 ` sashiko-bot
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.