From: Jiri Pirko <jiri@resnulli.us>
To: linux-rdma@vger.kernel.org
Cc: jgg@ziepe.ca, leon@kernel.org, mrgolin@amazon.com,
gal.pressman@linux.dev, sleybo@amazon.com, parav@nvidia.com,
mbloch@nvidia.com, yanjun.zhu@linux.dev,
marco.crivellari@suse.com, roman.gushchin@linux.dev,
phaddad@nvidia.com, lirongqing@baidu.com, ynachum@amazon.com,
huangjunxian6@hisilicon.com, kalesh-anakkur.purayil@broadcom.com,
ohartoov@nvidia.com, michaelgur@nvidia.com, shayd@nvidia.com,
edwards@nvidia.com, sriharsha.basavapatna@broadcom.com,
andrew.gospodarek@broadcom.com, selvin.xavier@broadcom.com
Subject: [PATCH rdma-next v4 03/16] RDMA/core: Introduce generic buffer descriptor infrastructure for umem
Date: Thu, 7 May 2026 14:52:18 +0200 [thread overview]
Message-ID: <20260507125231.2950751-4-jiri@resnulli.us> (raw)
In-Reply-To: <20260507125231.2950751-1-jiri@resnulli.us>
From: Jiri Pirko <jiri@nvidia.com>
Introduce a per-attribute UVERBS_ATTR_UMEM model so each uverbs
command's umem set is explicit in its UAPI definition. Add
driver-facing wrapper helpers that pin a umem on demand from an
attribute or a VA addr; the driver owns the returned umem and
releases it from its destroy/error paths.
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
v3->v4:
- removed dmesg print from ib_umem_get() legacy filler check
v2->v3:
- pushed out desc processing to ib_umem_get_desc()
- replaced UVERBS_ATTR_BUFFERS array with per-attribute UVERBS_ATTR_UMEM
- struct ib_uverbs_buffer_desc: dropped .index, moved .type first,
bumped reserved to __u32 reserved[2]
- added canonical ib_umem_get() + two inline wrappers
(_attr, _attr_or_va)
- dropped ib_umem_list_* family + ib_umem_release_non_listed()
---
drivers/infiniband/core/umem.c | 101 ++++++++++++++++++++++++
include/rdma/ib_umem.h | 55 +++++++++++++
include/rdma/uverbs_ioctl.h | 12 +++
include/uapi/rdma/ib_user_ioctl_verbs.h | 23 ++++++
4 files changed, 191 insertions(+)
diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
index 0056f23af57b..da7dcb227271 100644
--- a/drivers/infiniband/core/umem.c
+++ b/drivers/infiniband/core/umem.c
@@ -269,6 +269,107 @@ static struct ib_umem *__ib_umem_get_va(struct ib_device *device,
return ret ? ERR_PTR(ret) : umem;
}
+static struct ib_umem *
+ib_umem_get_desc(struct ib_device *device,
+ const struct ib_uverbs_buffer_desc *desc, int access)
+{
+ struct ib_umem_dmabuf *umem_dmabuf;
+
+ if (desc->reserved[0] || desc->reserved[1])
+ return ERR_PTR(-EINVAL);
+
+ switch (desc->type) {
+ case IB_UVERBS_BUFFER_TYPE_DMABUF:
+ umem_dmabuf = ib_umem_dmabuf_get_pinned(device, desc->addr,
+ desc->length, desc->fd,
+ access);
+ if (IS_ERR(umem_dmabuf))
+ return ERR_CAST(umem_dmabuf);
+ return &umem_dmabuf->umem;
+ case IB_UVERBS_BUFFER_TYPE_VA:
+ return __ib_umem_get_va(device, desc->addr, desc->length,
+ access);
+ default:
+ return ERR_PTR(-EINVAL);
+ }
+}
+
+/**
+ * ib_umem_get - Canonical on-demand umem getter.
+ * @device: IB device.
+ * @udata: uverbs udata bundle (may be NULL).
+ * @attr_id: per-command UMEM attribute id; consulted if @udata is set.
+ * @legacy_filler: optional command-specific legacy attr filler.
+ * invoked if @udata is set.
+ * @va_fallback: if true, build a VA-typed desc with @addr.
+ * @addr: user VA, used if @va_fallback is true.
+ * @size: driver-required minimum length.
+ * @access: IB access flags forwarded to ib_umem_get_desc().
+ *
+ * Return: valid umem on success, ERR_PTR(...) on error, NULL
+ * if no source produced a buffer (only possible when @va_fallback is false).
+ */
+struct ib_umem *ib_umem_get(struct ib_device *device, struct ib_udata *udata,
+ u16 attr_id,
+ ib_umem_buf_desc_filler_t legacy_filler,
+ bool va_fallback, u64 addr, size_t size, int access)
+{
+ struct uverbs_attr_bundle *attrs = NULL;
+ struct ib_uverbs_buffer_desc desc = {};
+ bool have_desc = false;
+ struct ib_umem *umem;
+ int ret;
+
+ if (udata)
+ attrs = container_of(udata, struct uverbs_attr_bundle,
+ driver_udata);
+
+ if (attrs) {
+ ret = uverbs_copy_from(&desc, attrs, attr_id);
+ if (!ret)
+ have_desc = true;
+ else if (ret != -ENOENT)
+ return ERR_PTR(ret);
+ }
+
+ if (attrs && legacy_filler) {
+ struct ib_uverbs_buffer_desc legacy_desc = {};
+
+ ret = legacy_filler(attrs, &legacy_desc);
+ if (!ret) {
+ if (have_desc)
+ return ERR_PTR(-EINVAL);
+ memcpy(&desc, &legacy_desc, sizeof(desc));
+ have_desc = true;
+ } else if (ret != -ENODATA) {
+ return ERR_PTR(ret);
+ }
+ }
+
+ if (have_desc)
+ goto have_desc;
+
+ if (!va_fallback)
+ return NULL;
+
+ desc = (struct ib_uverbs_buffer_desc){
+ .type = IB_UVERBS_BUFFER_TYPE_VA,
+ .addr = addr,
+ .length = size,
+ };
+
+have_desc:
+ umem = ib_umem_get_desc(device, &desc, access);
+ if (IS_ERR(umem))
+ return umem;
+ if (umem->length < size) {
+ ib_umem_release(umem);
+ return ERR_PTR(-EINVAL);
+ }
+ return umem;
+}
+EXPORT_SYMBOL(ib_umem_get);
+
/**
* ib_umem_get_va - Pin and DMA map userspace memory.
*
diff --git a/include/rdma/ib_umem.h b/include/rdma/ib_umem.h
index 25e90766892e..4897c7599fa3 100644
--- a/include/rdma/ib_umem.h
+++ b/include/rdma/ib_umem.h
@@ -73,10 +73,44 @@ static inline size_t ib_umem_num_pages(struct ib_umem *umem)
{
return ib_umem_num_dma_blocks(umem, PAGE_SIZE);
}
+
+struct ib_udata;
+struct ib_uverbs_buffer_desc;
+struct uverbs_attr_bundle;
+
+/*
+ * Per-command legacy buffer-desc filler.
+ * Returns 0 on success (desc filled), -ENODATA if no legacy attrs apply,
+ * negative errno on validation failure.
+ */
+typedef int (*ib_umem_buf_desc_filler_t)(struct uverbs_attr_bundle *attrs,
+ struct ib_uverbs_buffer_desc *desc);
+
#ifdef CONFIG_INFINIBAND_USER_MEM
+struct ib_umem *ib_umem_get(struct ib_device *device, struct ib_udata *udata,
+ u16 attr_id,
+ ib_umem_buf_desc_filler_t legacy_filler,
+ bool va_fallback, u64 addr, size_t size, int access);
struct ib_umem *ib_umem_get_va(struct ib_device *device, unsigned long addr,
size_t size, int access);
+
+static inline struct ib_umem *
+ib_umem_get_attr(struct ib_device *device, struct ib_udata *udata,
+ u16 attr_id, size_t size, int access)
+{
+ return ib_umem_get(device, udata, attr_id, NULL,
+ false, 0, size, access);
+}
+
+static inline struct ib_umem *
+ib_umem_get_attr_or_va(struct ib_device *device, struct ib_udata *udata,
+ u16 attr_id, u64 addr, size_t size, int access)
+{
+ return ib_umem_get(device, udata, attr_id, NULL,
+ true, addr, size, access);
+}
+
void ib_umem_release(struct ib_umem *umem);
int ib_umem_copy_from(void *dst, struct ib_umem *umem, size_t offset,
size_t length);
@@ -160,12 +194,33 @@ void ib_umem_dmabuf_revoke(struct ib_umem_dmabuf *umem_dmabuf);
#include <linux/err.h>
+static inline struct ib_umem *
+ib_umem_get(struct ib_device *device, struct ib_udata *udata, u16 attr_id,
+ ib_umem_buf_desc_filler_t legacy_filler, bool va_fallback, u64 addr,
+ size_t size, int access)
+{
+ return ERR_PTR(-EOPNOTSUPP);
+}
static inline struct ib_umem *ib_umem_get_va(struct ib_device *device,
unsigned long addr, size_t size,
int access)
{
return ERR_PTR(-EOPNOTSUPP);
}
+static inline struct ib_umem *ib_umem_get_attr(struct ib_device *device,
+ struct ib_udata *udata,
+ u16 attr_id, size_t size,
+ int access)
+{
+ return ERR_PTR(-EOPNOTSUPP);
+}
+static inline struct ib_umem *ib_umem_get_attr_or_va(struct ib_device *device,
+ struct ib_udata *udata,
+ u16 attr_id, u64 addr,
+ size_t size, int access)
+{
+ return ERR_PTR(-EOPNOTSUPP);
+}
static inline void ib_umem_release(struct ib_umem *umem) { }
static inline int ib_umem_copy_from(void *dst, struct ib_umem *umem, size_t offset,
size_t length) {
diff --git a/include/rdma/uverbs_ioctl.h b/include/rdma/uverbs_ioctl.h
index e2af17da3e32..76e94ede668e 100644
--- a/include/rdma/uverbs_ioctl.h
+++ b/include/rdma/uverbs_ioctl.h
@@ -590,6 +590,18 @@ struct uapi_definition {
UA_OPTIONAL, \
.is_udata = 1)
+/*
+ * Per-attribute UMEM descriptor. The payload is a single
+ * struct ib_uverbs_buffer_desc identifying a memory region backed by
+ * dma-buf or user virtual address. _access selects UA_OPTIONAL or
+ * UA_MANDATORY. Drivers obtain a umem from the attribute via the
+ * ib_umem_get_*() wrapper helpers.
+ */
+#define UVERBS_ATTR_UMEM(_attr_id, _access) \
+ UVERBS_ATTR_PTR_IN(_attr_id, \
+ UVERBS_ATTR_TYPE(struct ib_uverbs_buffer_desc), \
+ _access)
+
/* =================================================
* Parsing infrastructure
* =================================================
diff --git a/include/uapi/rdma/ib_user_ioctl_verbs.h b/include/uapi/rdma/ib_user_ioctl_verbs.h
index 90c5cd8e7753..6dfb95d56770 100644
--- a/include/uapi/rdma/ib_user_ioctl_verbs.h
+++ b/include/uapi/rdma/ib_user_ioctl_verbs.h
@@ -273,4 +273,27 @@ struct ib_uverbs_gid_entry {
__u32 netdev_ifindex; /* It is 0 if there is no netdev associated with it */
};
+enum ib_uverbs_buffer_type {
+ IB_UVERBS_BUFFER_TYPE_DMABUF,
+ IB_UVERBS_BUFFER_TYPE_VA,
+};
+
+/*
+ * Describes a single buffer backed by dma-buf or user virtual address.
+ * Used as the payload of a per-attribute UVERBS_ATTR_UMEM-typed attribute.
+ *
+ * @type: buffer type from enum ib_uverbs_buffer_type
+ * @fd: dma-buf file descriptor (valid for IB_UVERBS_BUFFER_TYPE_DMABUF)
+ * @reserved: must be zero
+ * @addr: offset within dma-buf, or user virtual address for VA
+ * @length: buffer length in bytes
+ */
+struct ib_uverbs_buffer_desc {
+ __u32 type;
+ __s32 fd;
+ __u32 reserved[2];
+ __aligned_u64 addr;
+ __aligned_u64 length;
+};
+
#endif
--
2.53.0
next prev parent reply other threads:[~2026-05-07 12:52 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-07 12:52 [PATCH rdma-next v4 00/16] RDMA: Introduce generic buffer descriptor infrastructure for umem Jiri Pirko
2026-05-07 12:52 ` [PATCH rdma-next v4 01/16] RDMA/umem: Rename ib_umem_get() to ib_umem_get_va() Jiri Pirko
2026-05-07 12:52 ` [PATCH rdma-next v4 02/16] RDMA/umem: Split ib_umem_get_va() into a thin wrapper around __ib_umem_get_va() Jiri Pirko
2026-05-07 12:52 ` Jiri Pirko [this message]
2026-05-07 12:52 ` [PATCH rdma-next v4 04/16] RDMA/umem: Route ib_umem_get_va() through ib_umem_get() Jiri Pirko
2026-05-07 12:52 ` [PATCH rdma-next v4 05/16] RDMA/uverbs: Inline _uverbs_get_const_{signed,unsigned}() Jiri Pirko
2026-05-07 12:52 ` [PATCH rdma-next v4 06/16] RDMA/uverbs: Push out CQ buffer umem processing into a helper Jiri Pirko
2026-05-07 12:52 ` [PATCH rdma-next v4 07/16] RDMA/uverbs: Add CQ buffer UMEM attribute and driver helpers Jiri Pirko
2026-05-07 12:52 ` [PATCH rdma-next v4 08/16] RDMA/efa: Use ib_umem_get_cq_buf() for user CQ buffer Jiri Pirko
2026-05-07 12:52 ` [PATCH rdma-next v4 09/16] RDMA/mlx5: Use ib_umem_get_cq_buf_or_va() " Jiri Pirko
2026-05-07 12:52 ` [PATCH rdma-next v4 10/16] RDMA/bnxt_re: " Jiri Pirko
2026-05-07 12:52 ` [PATCH rdma-next v4 11/16] RDMA/mlx4: Use ib_umem_get_cq_buf() " Jiri Pirko
2026-05-07 12:52 ` [PATCH rdma-next v4 12/16] RDMA/uverbs: Remove legacy umem field from struct ib_cq Jiri Pirko
2026-05-07 12:52 ` [PATCH rdma-next v4 13/16] RDMA/uverbs: Use UMEM attributes for QP creation Jiri Pirko
2026-05-07 12:52 ` [PATCH rdma-next v4 14/16] RDMA/mlx5: Use UMEM attributes for QP buffers in create_qp Jiri Pirko
2026-05-07 12:52 ` [PATCH rdma-next v4 15/16] RDMA/mlx5: Use UMEM attribute for CQ doorbell record Jiri Pirko
2026-05-07 12:52 ` [PATCH rdma-next v4 16/16] RDMA/mlx5: Use UMEM attribute for QP " Jiri Pirko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260507125231.2950751-4-jiri@resnulli.us \
--to=jiri@resnulli.us \
--cc=andrew.gospodarek@broadcom.com \
--cc=edwards@nvidia.com \
--cc=gal.pressman@linux.dev \
--cc=huangjunxian6@hisilicon.com \
--cc=jgg@ziepe.ca \
--cc=kalesh-anakkur.purayil@broadcom.com \
--cc=leon@kernel.org \
--cc=linux-rdma@vger.kernel.org \
--cc=lirongqing@baidu.com \
--cc=marco.crivellari@suse.com \
--cc=mbloch@nvidia.com \
--cc=michaelgur@nvidia.com \
--cc=mrgolin@amazon.com \
--cc=ohartoov@nvidia.com \
--cc=parav@nvidia.com \
--cc=phaddad@nvidia.com \
--cc=roman.gushchin@linux.dev \
--cc=selvin.xavier@broadcom.com \
--cc=shayd@nvidia.com \
--cc=sleybo@amazon.com \
--cc=sriharsha.basavapatna@broadcom.com \
--cc=yanjun.zhu@linux.dev \
--cc=ynachum@amazon.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox