* [PATCH rdma-next v4 0/6] RDMA/irdma: Add support for ioctl
@ 2026-10-30 18:15 David Hu
2026-10-30 18:15 ` [PATCH rdma-next v4 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-30 18:15 UTC (permalink / raw)
To: Mustafa Ismail, Shiraz Saleem, Leon Romanovsky, Jason Gunthorpe
Cc: Jacob Moroni, intel-wired-lan, linux-rdma, linux-kernel, David Hu
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 v4:
- Reject dma-buf queue creation in iWARP mode and enforce page-offset
alignment unconditionally in irdma_setup_q_pbl_from_umem() (Jacob)
- Bound attr->cqe in irdma_create_user_cq() to prevent cq_pages overflow (Sashiko)
- Fix to irdma_cq_free_rsrc() was sent separately (Sashiko)
- Link to v3: https://lore.kernel.org/all/20261016202909.1289496-1-dhu@x6u.co/
Changes in v3:
- Improve patch 4/6 to split umode cq creation to a new callback
.create_user_cq() (irdma_create_user_cq) (Leon)
- Clean up duplicate bounds and NULL checks in cq creation path (Leon)
- Link to v2: https://lore.kernel.org/all/20261015011940.4122452-1-dhu@x6u.co/
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 | 759 ++++++++++++++++++++--------
include/uapi/rdma/irdma-abi.h | 5 +
3 files changed, 573 insertions(+), 203 deletions(-)
base-commit: c3e8e9451e6f1b69f685b75e0fbf14f3d0fb2539
--
2.56.0.317.g454f8302e1-goog
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH rdma-next v4 1/6] RDMA/irdma: Plumb uverbs_attr_bundle for QP, SRQ
2026-10-30 18:15 [PATCH rdma-next v4 0/6] RDMA/irdma: Add support for ioctl David Hu
@ 2026-10-30 18:15 ` David Hu
2026-10-30 18:23 ` sashiko-bot
2026-10-30 18:15 ` [PATCH rdma-next v4 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-30 18:15 UTC (permalink / raw)
To: Mustafa Ismail, Shiraz Saleem, Leon Romanovsky, Jason Gunthorpe
Cc: Jacob Moroni, intel-wired-lan, linux-rdma, linux-kernel, David Hu
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 c91c55917de9..811b1d532599 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.317.g454f8302e1-goog
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH rdma-next v4 2/6] RDMA/irdma: Register irdma UVERBS ioctl namespace
2026-10-30 18:15 [PATCH rdma-next v4 0/6] RDMA/irdma: Add support for ioctl David Hu
2026-10-30 18:15 ` [PATCH rdma-next v4 1/6] RDMA/irdma: Plumb uverbs_attr_bundle for QP, SRQ David Hu
@ 2026-10-30 18:15 ` David Hu
2026-10-30 18:23 ` sashiko-bot
2026-10-30 18:15 ` [PATCH rdma-next v4 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-30 18:15 UTC (permalink / raw)
To: Mustafa Ismail, Shiraz Saleem, Leon Romanovsky, Jason Gunthorpe
Cc: Jacob Moroni, intel-wired-lan, linux-rdma, linux-kernel, David Hu
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 811b1d532599..dd824720671c 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
@@ -5602,6 +5618,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.317.g454f8302e1-goog
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH rdma-next v4 3/6] RDMA/irdma: Support UMEM attribute for QP creation
2026-10-30 18:15 [PATCH rdma-next v4 0/6] RDMA/irdma: Add support for ioctl David Hu
2026-10-30 18:15 ` [PATCH rdma-next v4 1/6] RDMA/irdma: Plumb uverbs_attr_bundle for QP, SRQ David Hu
2026-10-30 18:15 ` [PATCH rdma-next v4 2/6] RDMA/irdma: Register irdma UVERBS ioctl namespace David Hu
@ 2026-10-30 18:15 ` David Hu
2026-10-30 18:26 ` sashiko-bot
2026-10-30 18:15 ` [PATCH rdma-next v4 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-30 18:15 UTC (permalink / raw)
To: Mustafa Ismail, Shiraz Saleem, Leon Romanovsky, Jason Gunthorpe
Cc: Jacob Moroni, intel-wired-lan, linux-rdma, linux-kernel, David Hu
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 | 132 +++++++++++++++++++++++++---
2 files changed, 127 insertions(+), 17 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 dd824720671c..578c2d4b4d3c 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;
@@ -3460,6 +3501,7 @@ 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)
{
@@ -3475,7 +3517,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;
iwmr->len = region->length;
@@ -3503,6 +3545,68 @@ 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;
+
+ /* Catch page not starting on OS page boundary */
+ if (ib_umem_offset(region))
+ return ERR_PTR(-EINVAL);
+
+ /* iWarp: Reject queue dma-buf as it is not supported */
+ if (!rdma_protocol_roce(&iwdev->ibdev, 1) && region->is_dmabuf)
+ 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)
@@ -3648,7 +3752,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;
@@ -3747,7 +3851,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.317.g454f8302e1-goog
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH rdma-next v4 4/6] RDMA/irdma: Split CQ setup to umode and kmode
2026-10-30 18:15 [PATCH rdma-next v4 0/6] RDMA/irdma: Add support for ioctl David Hu
` (2 preceding siblings ...)
2026-10-30 18:15 ` [PATCH rdma-next v4 3/6] RDMA/irdma: Support UMEM attribute for QP creation David Hu
@ 2026-10-30 18:15 ` David Hu
2026-10-30 18:30 ` sashiko-bot
2026-10-30 18:15 ` [PATCH rdma-next v4 5/6] RDMA/irdma: Support UMEM attribute for CQ creation David Hu
2026-10-30 18:15 ` [PATCH rdma-next v4 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-30 18:15 UTC (permalink / raw)
To: Mustafa Ismail, Shiraz Saleem, Leon Romanovsky, Jason Gunthorpe
Cc: Jacob Moroni, intel-wired-lan, linux-rdma, linux-kernel, David Hu
From: David Hu <xuehaohu@google.com>
Add user mode cq callback `irdma_create_user_cq()` to separate out user
mode creation logic from kernel mode cq.
Original common setup logic is broken into shared helper routines, so
duplicate code can be avoided. Core creation logic is preserved to be
identical to original routine, however.
Signed-off-by: David Hu <xuehaohu@google.com>
---
drivers/infiniband/hw/irdma/verbs.c | 416 +++++++++++++++++-----------
1 file changed, 252 insertions(+), 164 deletions(-)
diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
index 578c2d4b4d3c..9f4905fdb791 100644
--- a/drivers/infiniband/hw/irdma/verbs.c
+++ b/drivers/infiniband/hw/irdma/verbs.c
@@ -2624,41 +2624,198 @@ static inline int cq_validate_flags(u32 flags, u8 hw_rev)
return flags & ~IB_UVERBS_CQ_FLAGS_TIMESTAMP_COMPLETION ? -EOPNOTSUPP : 0;
}
-/**
- * irdma_create_cq - create cq
- * @ibcq: CQ allocated
- * @attr: attributes for cq
- * @attrs: uverbs attribute bundle
- */
-static int irdma_create_cq(struct ib_cq *ibcq,
- const struct ib_cq_init_attr *attr,
- struct uverbs_attr_bundle *attrs)
+static int __irdma_create_cq(struct irdma_device *iwdev,
+ struct irdma_cq *iwcq,
+ struct irdma_cq_init_info *info,
+ struct ib_udata *udata)
{
-#define IRDMA_CREATE_CQ_MIN_RESP_LEN offsetofend(struct irdma_create_cq_resp, cq_size)
- struct ib_udata *udata = &attrs->driver_udata;
- struct ib_device *ibdev = ibcq->device;
- struct irdma_device *iwdev = to_iwdev(ibdev);
struct irdma_pci_f *rf = iwdev->rf;
- struct irdma_cq *iwcq = to_iwcq(ibcq);
- u32 cq_num = 0;
- struct irdma_sc_cq *cq;
- struct irdma_sc_dev *dev = &rf->sc_dev;
- struct irdma_cq_init_info info = {};
struct irdma_cqp_request *cqp_request;
+ struct irdma_sc_cq *cq = &iwcq->sc_cq;
struct cqp_cmds_info *cqp_info;
- struct irdma_cq_uk_init_info *ukinfo = &info.cq_uk_init_info;
- unsigned long flags;
int err_code;
+
+ info->shadow_read_threshold = min(info->cq_uk_init_info.cq_size / 2,
+ (u32)IRDMA_MAX_CQ_READ_THRESH);
+
+ if (irdma_sc_cq_init(cq, info)) {
+ ibdev_dbg(&iwdev->ibdev, "VERBS: init cq fail\n");
+ err_code = -EPROTO;
+ goto cq_free_rsrc;
+ }
+
+ cqp_request = irdma_alloc_and_get_cqp_request(&rf->cqp, true);
+ if (!cqp_request) {
+ err_code = -ENOMEM;
+ goto cq_free_rsrc;
+ }
+
+ cqp_info = &cqp_request->info;
+ cqp_info->cqp_cmd = IRDMA_OP_CQ_CREATE;
+ cqp_info->post_sq = 1;
+ cqp_info->in.u.cq_create.cq = cq;
+ cqp_info->in.u.cq_create.check_overflow = true;
+ cqp_info->in.u.cq_create.scratch = (uintptr_t)cqp_request;
+ err_code = irdma_handle_cqp_op(rf, cqp_request);
+ irdma_put_cqp_request(&rf->cqp, cqp_request);
+ if (err_code)
+ goto cq_free_rsrc;
+
+ if (udata) {
+ struct irdma_create_cq_resp resp = {};
+
+ resp.cq_id = info->cq_uk_init_info.cq_id;
+ resp.cq_size = info->cq_uk_init_info.cq_size;
+ err_code = ib_respond_udata(udata, resp);
+ if (err_code)
+ goto cq_destroy;
+ }
+
+ init_completion(&iwcq->free_cq);
+
+ /* Populate table entry after CQ is fully created. */
+ smp_store_release(&rf->cq_table[iwcq->cq_num], iwcq);
+
+ return 0;
+cq_destroy:
+ irdma_cq_wq_destroy(rf, cq);
+cq_free_rsrc:
+ irdma_cq_free_rsrc(rf, iwcq);
+
+ return err_code;
+}
+
+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;
- err_code = cq_validate_flags(attr->flags, dev->hw_attrs.uk_attrs.hw_rev);
+ 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 uverbs_attr_bundle *attrs)
+{
+ struct ib_udata *udata = &attrs->driver_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;
- if (udata && udata->outlen < IRDMA_CREATE_CQ_MIN_RESP_LEN)
- 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 (!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;
+}
+
+static int irdma_alloc_cq(struct irdma_device *iwdev,
+ struct irdma_cq *iwcq,
+ const struct ib_cq_init_attr *attr,
+ struct irdma_cq_init_info *info)
+{
+ 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;
+ struct irdma_sc_cq *cq;
+ bool cqe_64byte_ena;
+ u32 cq_num = 0;
+ int err_code;
err_code = irdma_alloc_rsrc(rf, rf->allocated_cqs, rf->max_cq, &cq_num,
&rf->next_cq);
@@ -2674,169 +2831,99 @@ static int irdma_create_cq(struct ib_cq *ibcq,
iwcq->cq_num = cq_num;
iwcq->iwpbl = NULL;
iwcq->iwpbl_shadow = NULL;
- info.dev = dev;
+ info->dev = dev;
ukinfo->cq_size = max(entries, 4);
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;
+ iwcq->ibcq.cqe = ukinfo->cq_size;
if (attr->comp_vector < rf->ceqs_count)
- info.ceq_id = attr->comp_vector;
- info.ceq_id_valid = true;
- info.ceqe_mask = 1;
- 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;
- }
+ info->ceq_id = attr->comp_vector;
+ info->ceq_id_valid = true;
+ info->ceqe_mask = 1;
+ info->type = IRDMA_CQ_TYPE_IWARP;
+ info->vsi = &iwdev->vsi;
- 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);
+ return 0;
+}
- 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;
+/**
+ * irdma_create_user_cq - create user cq
+ * @ibcq: CQ allocated
+ * @attr: attributes for cq
+ * @attrs: uverbs attribute bundle
+ */
+static int irdma_create_user_cq(struct ib_cq *ibcq,
+ const struct ib_cq_init_attr *attr,
+ struct uverbs_attr_bundle *attrs)
+{
+#define IRDMA_CREATE_CQ_MIN_RESP_LEN offsetofend(struct irdma_create_cq_resp, cq_size)
+ struct ib_udata *udata = &attrs->driver_udata;
+ struct ib_device *ibdev = ibcq->device;
+ struct irdma_device *iwdev = to_iwdev(ibdev);
+ struct irdma_pci_f *rf = iwdev->rf;
+ struct irdma_cq *iwcq = to_iwcq(ibcq);
+ struct irdma_sc_dev *dev = &rf->sc_dev;
+ struct irdma_cq_init_info info = {};
+ int err_code;
- if (entries < 1 || entries > rf->max_cqe) {
- err_code = -EINVAL;
- goto cq_free_rsrc;
- }
+ err_code = cq_validate_flags(attr->flags, dev->hw_attrs.uk_attrs.hw_rev);
+ if (err_code)
+ return err_code;
- entries += 2;
- if (!cqe_64byte_ena && dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_2)
- entries *= 2;
+ if (udata->outlen < IRDMA_CREATE_CQ_MIN_RESP_LEN)
+ return -EINVAL;
- if (entries & 1)
- entries += 1; /* cq size must be an even number */
+ err_code = irdma_alloc_cq(iwdev, iwcq, attr, &info);
+ if (err_code)
+ return err_code;
- if (entries * cqe_size == IRDMA_HW_PAGE_SIZE)
- entries += 2;
+ err_code = irdma_setup_umode_cq(iwdev, iwcq, &info, attrs);
+ if (err_code)
+ goto cq_free_rsrc;
- ukinfo->cq_size = entries;
+ return __irdma_create_cq(iwdev, iwcq, &info, udata);
+cq_free_rsrc:
+ irdma_cq_free_rsrc(rf, iwcq);
- 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;
- }
+ return err_code;
+}
- 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;
- }
+/**
+ * irdma_create_cq - create kmode cq
+ * @ibcq: CQ allocated
+ * @attr: attributes for cq
+ * @attrs: uverbs attribute bundle
+ */
+static int irdma_create_cq(struct ib_cq *ibcq,
+ const struct ib_cq_init_attr *attr,
+ struct uverbs_attr_bundle *attrs)
+{
+ struct ib_device *ibdev = ibcq->device;
+ struct irdma_device *iwdev = to_iwdev(ibdev);
+ struct irdma_pci_f *rf = iwdev->rf;
+ struct irdma_cq *iwcq = to_iwcq(ibcq);
+ struct irdma_sc_dev *dev = &rf->sc_dev;
+ struct irdma_cq_init_info info = {};
+ int err_code;
- info.shadow_read_threshold = min(info.cq_uk_init_info.cq_size / 2,
- (u32)IRDMA_MAX_CQ_READ_THRESH);
+ err_code = cq_validate_flags(attr->flags, dev->hw_attrs.uk_attrs.hw_rev);
+ if (err_code)
+ return err_code;
- if (irdma_sc_cq_init(cq, &info)) {
- ibdev_dbg(&iwdev->ibdev, "VERBS: init cq fail\n");
- err_code = -EPROTO;
- goto cq_free_rsrc;
- }
+ if (attr->cqe > rf->max_cqe)
+ return -EINVAL;
- cqp_request = irdma_alloc_and_get_cqp_request(&rf->cqp, true);
- if (!cqp_request) {
- err_code = -ENOMEM;
- goto cq_free_rsrc;
- }
+ err_code = irdma_alloc_cq(iwdev, iwcq, attr, &info);
+ if (err_code)
+ return err_code;
- cqp_info = &cqp_request->info;
- cqp_info->cqp_cmd = IRDMA_OP_CQ_CREATE;
- cqp_info->post_sq = 1;
- cqp_info->in.u.cq_create.cq = cq;
- cqp_info->in.u.cq_create.check_overflow = true;
- cqp_info->in.u.cq_create.scratch = (uintptr_t)cqp_request;
- err_code = irdma_handle_cqp_op(rf, cqp_request);
- irdma_put_cqp_request(&rf->cqp, cqp_request);
+ err_code = irdma_setup_kmode_cq(iwdev, iwcq, &info, attr);
if (err_code)
goto cq_free_rsrc;
- if (udata) {
- struct irdma_create_cq_resp resp = {};
-
- resp.cq_id = info.cq_uk_init_info.cq_id;
- resp.cq_size = info.cq_uk_init_info.cq_size;
- err_code = ib_respond_udata(udata, resp);
- if (err_code)
- goto cq_destroy;
- }
-
- init_completion(&iwcq->free_cq);
-
- /* Populate table entry after CQ is fully created. */
- smp_store_release(&rf->cq_table[cq_num], iwcq);
-
- return 0;
-cq_destroy:
- irdma_cq_wq_destroy(rf, cq);
+ return __irdma_create_cq(iwdev, iwcq, &info, NULL);
cq_free_rsrc:
irdma_cq_free_rsrc(rf, iwcq);
@@ -5643,6 +5730,7 @@ static const struct ib_device_ops irdma_dev_ops = {
.alloc_pd = irdma_alloc_pd,
.alloc_ucontext = irdma_alloc_ucontext,
.create_cq = irdma_create_cq,
+ .create_user_cq = irdma_create_user_cq,
.create_qp = irdma_create_qp,
.dealloc_driver = irdma_ib_dealloc_device,
.dealloc_mw = irdma_dealloc_mw,
--
2.56.0.317.g454f8302e1-goog
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH rdma-next v4 5/6] RDMA/irdma: Support UMEM attribute for CQ creation
2026-10-30 18:15 [PATCH rdma-next v4 0/6] RDMA/irdma: Add support for ioctl David Hu
` (3 preceding siblings ...)
2026-10-30 18:15 ` [PATCH rdma-next v4 4/6] RDMA/irdma: Split CQ setup to umode and kmode David Hu
@ 2026-10-30 18:15 ` David Hu
2026-10-30 18:33 ` sashiko-bot
2026-10-30 18:15 ` [PATCH rdma-next v4 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-30 18:15 UTC (permalink / raw)
To: Mustafa Ismail, Shiraz Saleem, Leon Romanovsky, Jason Gunthorpe
Cc: Jacob Moroni, intel-wired-lan, linux-rdma, linux-kernel, David Hu
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 | 132 +++++++++++++++++++++++-----
1 file changed, 111 insertions(+), 21 deletions(-)
diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
index 9f4905fdb791..41e56ab8aa6d 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) {
@@ -2746,14 +2768,18 @@ static int irdma_setup_umode_cq(struct irdma_device *iwdev,
struct irdma_cq_init_info *info,
struct uverbs_attr_bundle *attrs)
{
+ struct irdma_cq_uk_init_info *ukinfo = &info->cq_uk_init_info;
struct ib_udata *udata = &attrs->driver_udata;
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,
@@ -2767,26 +2793,87 @@ 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 (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 (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 {
@@ -2872,6 +2959,9 @@ static int irdma_create_user_cq(struct ib_cq *ibcq,
if (err_code)
return err_code;
+ if (attr->cqe > rf->max_cqe * 2)
+ return -EINVAL;
+
if (udata->outlen < IRDMA_CREATE_CQ_MIN_RESP_LEN)
return -EINVAL;
--
2.56.0.317.g454f8302e1-goog
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH rdma-next v4 6/6] RDMA/irdma: Support UMEM attribute for SRQ creation
2026-10-30 18:15 [PATCH rdma-next v4 0/6] RDMA/irdma: Add support for ioctl David Hu
` (4 preceding siblings ...)
2026-10-30 18:15 ` [PATCH rdma-next v4 5/6] RDMA/irdma: Support UMEM attribute for CQ creation David Hu
@ 2026-10-30 18:15 ` David Hu
2026-10-30 18:34 ` sashiko-bot
5 siblings, 1 reply; 13+ messages in thread
From: David Hu @ 2026-10-30 18:15 UTC (permalink / raw)
To: Mustafa Ismail, Shiraz Saleem, Leon Romanovsky, Jason Gunthorpe
Cc: Jacob Moroni, intel-wired-lan, linux-rdma, linux-kernel, David Hu
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 41e56ab8aa6d..7e8a5e481730 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.317.g454f8302e1-goog
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH rdma-next v4 2/6] RDMA/irdma: Register irdma UVERBS ioctl namespace
2026-10-30 18:15 ` [PATCH rdma-next v4 2/6] RDMA/irdma: Register irdma UVERBS ioctl namespace David Hu
@ 2026-10-30 18:23 ` sashiko-bot
0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-10-30 18:23 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.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261030181512.2056056-1-dhu@x6u.co?part=2
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH rdma-next v4 1/6] RDMA/irdma: Plumb uverbs_attr_bundle for QP, SRQ
2026-10-30 18:15 ` [PATCH rdma-next v4 1/6] RDMA/irdma: Plumb uverbs_attr_bundle for QP, SRQ David Hu
@ 2026-10-30 18:23 ` sashiko-bot
0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-10-30 18:23 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.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261030181512.2056056-1-dhu@x6u.co?part=1
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH rdma-next v4 3/6] RDMA/irdma: Support UMEM attribute for QP creation
2026-10-30 18:15 ` [PATCH rdma-next v4 3/6] RDMA/irdma: Support UMEM attribute for QP creation David Hu
@ 2026-10-30 18:26 ` sashiko-bot
0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-10-30 18:26 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 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
> [ ... ]
> 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>
Sashiko has reviewed this patch and found no issues.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261030181512.2056056-1-dhu@x6u.co?part=3
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH rdma-next v4 4/6] RDMA/irdma: Split CQ setup to umode and kmode
2026-10-30 18:15 ` [PATCH rdma-next v4 4/6] RDMA/irdma: Split CQ setup to umode and kmode David Hu
@ 2026-10-30 18:30 ` sashiko-bot
0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-10-30 18:30 UTC (permalink / raw)
To: David Hu; +Cc: linux-rdma
> From: David Hu <xuehaohu@google.com>
>
> Add user mode cq callback `irdma_create_user_cq()` to separate out user
> mode creation logic from kernel mode cq.
>
> Original common setup logic is broken into shared helper routines, so
> duplicate code can be avoided. Core creation logic is preserved to be
> identical to original routine, however.
>
> Signed-off-by: David Hu <xuehaohu@google.com>
Sashiko has reviewed this patch and found no issues.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261030181512.2056056-1-dhu@x6u.co?part=4
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH rdma-next v4 5/6] RDMA/irdma: Support UMEM attribute for CQ creation
2026-10-30 18:15 ` [PATCH rdma-next v4 5/6] RDMA/irdma: Support UMEM attribute for CQ creation David Hu
@ 2026-10-30 18:33 ` sashiko-bot
0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-10-30 18:33 UTC (permalink / raw)
To: David Hu; +Cc: intel-wired-lan, linux-rdma
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] RDMA/irdma: wrong DMA direction in irdma_setup_umode_cq() via ib_umem_get_cq_buf()
--
commit 8981c5869a8245f4b87a31412a16b517815f3a39
Author: David Hu <xuehaohu@google.com>
RDMA/irdma: Support UMEM attribute for CQ creation
This commit adds support for one-step user-mode CQ buffer creation using
UVERBS_ATTR_CREATE_CQ_BUF_UMEM and IRDMA_IB_ATTR_CREATE_CQ_SHADOW_BUF_UMEM,
sets up hardware PBLEs directly from the pinned UMEMs, and adds UMEM and PBLE
cleanup in irdma_cq_free_rsrc() and irdma_resize_cq().
> diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
> index 9f4905fdb791a..41e56ab8aa6df 100644
> --- a/drivers/infiniband/hw/irdma/verbs.c
> +++ b/drivers/infiniband/hw/irdma/verbs.c
[ ... ]
> @@ -2767,26 +2793,87 @@ 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 (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);
[Severity: Medium]
When IRDMA_FEATURE_CQ_RESIZE is not set in
rf->sc_dev.hw_attrs.uk_attrs.feature_flags, the UMEM passed via
UVERBS_ATTR_CREATE_CQ_BUF_UMEM backs both the CQ ring and the trailing shadow
area page (shadow_pgcnt is IRDMA_SHADOW_PGCNT, and irdma_setup_umode_cq()
later sets info->shadow_area_pa = cqmr->shadow from that same UMEM).
However, ib_umem_get_cq_buf() in drivers/infiniband/core/umem.c hardcodes
DMA_FROM_DEVICE instead of deriving DMA_BIDIRECTIONAL from
IB_ACCESS_LOCAL_WRITE:
drivers/infiniband/core/umem.c:ib_umem_get_cq_buf() {
return ib_umem_get_from_attrs(device, attrs,
UVERBS_ATTR_CREATE_CQ_BUF_UMEM,
uverbs_create_cq_get_buffer_desc,
size, access, DMA_FROM_DEVICE);
}
Since the CPU writes the CQ head index to the shadow area and hardware reads
shadow_area_pa via DMA, mapping this UMEM with DMA_FROM_DEVICE omits IOMMU
read permissions (and skips CPU-to-device bounce buffer syncs).
Should irdma_setup_umode_cq() use ib_umem_get_attr() with
UVERBS_ATTR_CREATE_CQ_BUF_UMEM when IRDMA_FEATURE_CQ_RESIZE is not set (or
unconditionally, as noted in the commit message) so the buffer is mapped with
DMA_BIDIRECTIONAL?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261030181512.2056056-1-dhu@x6u.co?part=5
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH rdma-next v4 6/6] RDMA/irdma: Support UMEM attribute for SRQ creation
2026-10-30 18:15 ` [PATCH rdma-next v4 6/6] RDMA/irdma: Support UMEM attribute for SRQ creation David Hu
@ 2026-10-30 18:34 ` sashiko-bot
0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-10-30 18:34 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.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261030181512.2056056-1-dhu@x6u.co?part=6
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2026-10-30 18:34 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-30 18:15 [PATCH rdma-next v4 0/6] RDMA/irdma: Add support for ioctl David Hu
2026-10-30 18:15 ` [PATCH rdma-next v4 1/6] RDMA/irdma: Plumb uverbs_attr_bundle for QP, SRQ David Hu
2026-10-30 18:23 ` sashiko-bot
2026-10-30 18:15 ` [PATCH rdma-next v4 2/6] RDMA/irdma: Register irdma UVERBS ioctl namespace David Hu
2026-10-30 18:23 ` sashiko-bot
2026-10-30 18:15 ` [PATCH rdma-next v4 3/6] RDMA/irdma: Support UMEM attribute for QP creation David Hu
2026-10-30 18:26 ` sashiko-bot
2026-10-30 18:15 ` [PATCH rdma-next v4 4/6] RDMA/irdma: Split CQ setup to umode and kmode David Hu
2026-10-30 18:30 ` sashiko-bot
2026-10-30 18:15 ` [PATCH rdma-next v4 5/6] RDMA/irdma: Support UMEM attribute for CQ creation David Hu
2026-10-30 18:33 ` sashiko-bot
2026-10-30 18:15 ` [PATCH rdma-next v4 6/6] RDMA/irdma: Support UMEM attribute for SRQ creation David Hu
2026-10-30 18:34 ` sashiko-bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox