Commit 0ac6f405 authored by Yishai Hadas's avatar Yishai Hadas Committed by Leon Romanovsky
Browse files

RDMA/uverbs: Add DMABUF object type and operations



Expose DMABUF functionality to userspace through the uverbs interface,
enabling InfiniBand/RDMA devices to export PCI based memory regions
(e.g. device memory) as DMABUF file descriptors. This allows
zero-copy sharing of RDMA memory with other subsystems that support the
dma-buf framework.

A new UVERBS_OBJECT_DMABUF object type and allocation method were
introduced.

During allocation, uverbs invokes the driver to supply the
rdma_user_mmap_entry associated with the given page offset (pgoff).

Based on the returned rdma_user_mmap_entry, uverbs requests the driver
to provide the corresponding physical-memory details as well as the
driver’s PCI provider information.

Using this information, dma_buf_export() is called; if it succeeds,
uobj->object is set to the underlying file pointer returned by the
dma-buf framework.

The file descriptor number follows the standard uverbs allocation flow,
but the file pointer comes from the dma-buf subsystem, including its own
fops and private data.

When an mmap entry is removed, uverbs iterates over its associated
DMABUFs, marks them as revoked, and calls dma_buf_move_notify() so that
their importers are notified.

The same procedure applies during the disassociate flow; final cleanup
occurs when the application closes the file.

Signed-off-by: default avatarYishai Hadas <yishaih@nvidia.com>
Signed-off-by: default avatarEdward Srouji <edwards@nvidia.com>
Link: https://patch.msgid.link/20260201-dmabuf-export-v3-2-da238b614fe3@nvidia.com


Signed-off-by: default avatarLeon Romanovsky <leon@kernel.org>
parent 9ad95a0f
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ ib_umad-y := user_mad.o
ib_uverbs-y :=			uverbs_main.o uverbs_cmd.o uverbs_marshall.o \
				rdma_core.o uverbs_std_types.o uverbs_ioctl.o \
				uverbs_std_types_cq.o \
				uverbs_std_types_dmabuf.o \
				uverbs_std_types_dmah.o \
				uverbs_std_types_flow_action.o uverbs_std_types_dm.o \
				uverbs_std_types_mr.o uverbs_std_types_counters.o \
+2 −0
Original line number Diff line number Diff line
@@ -2765,6 +2765,7 @@ void ib_set_device_ops(struct ib_device *dev, const struct ib_device_ops *ops)
	SET_DEVICE_OP(dev_ops, map_mr_sg);
	SET_DEVICE_OP(dev_ops, map_mr_sg_pi);
	SET_DEVICE_OP(dev_ops, mmap);
	SET_DEVICE_OP(dev_ops, mmap_get_pfns);
	SET_DEVICE_OP(dev_ops, mmap_free);
	SET_DEVICE_OP(dev_ops, modify_ah);
	SET_DEVICE_OP(dev_ops, modify_cq);
@@ -2775,6 +2776,7 @@ void ib_set_device_ops(struct ib_device *dev, const struct ib_device_ops *ops)
	SET_DEVICE_OP(dev_ops, modify_srq);
	SET_DEVICE_OP(dev_ops, modify_wq);
	SET_DEVICE_OP(dev_ops, peek_cq);
	SET_DEVICE_OP(dev_ops, pgoff_to_mmap_entry);
	SET_DEVICE_OP(dev_ops, pre_destroy_cq);
	SET_DEVICE_OP(dev_ops, poll_cq);
	SET_DEVICE_OP(dev_ops, port_groups);
+24 −0
Original line number Diff line number Diff line
@@ -5,9 +5,13 @@
 * Copyright 2019 Marvell. All rights reserved.
 */
#include <linux/xarray.h>
#include <linux/dma-buf.h>
#include <linux/dma-resv.h>
#include "uverbs.h"
#include "core_priv.h"

MODULE_IMPORT_NS("DMA_BUF");

/**
 * rdma_umap_priv_init() - Initialize the private data of a vma
 *
@@ -229,12 +233,29 @@ EXPORT_SYMBOL(rdma_user_mmap_entry_put);
 */
void rdma_user_mmap_entry_remove(struct rdma_user_mmap_entry *entry)
{
	struct ib_uverbs_dmabuf_file *uverbs_dmabuf, *tmp;

	if (!entry)
		return;

	mutex_lock(&entry->dmabufs_lock);
	xa_lock(&entry->ucontext->mmap_xa);
	entry->driver_removed = true;
	xa_unlock(&entry->ucontext->mmap_xa);
	list_for_each_entry_safe(uverbs_dmabuf, tmp, &entry->dmabufs, dmabufs_elm) {
		dma_resv_lock(uverbs_dmabuf->dmabuf->resv, NULL);
		list_del(&uverbs_dmabuf->dmabufs_elm);
		uverbs_dmabuf->revoked = true;
		dma_buf_move_notify(uverbs_dmabuf->dmabuf);
		dma_resv_wait_timeout(uverbs_dmabuf->dmabuf->resv,
				      DMA_RESV_USAGE_BOOKKEEP, false,
				      MAX_SCHEDULE_TIMEOUT);
		dma_resv_unlock(uverbs_dmabuf->dmabuf->resv);
		kref_put(&uverbs_dmabuf->kref, ib_uverbs_dmabuf_done);
		wait_for_completion(&uverbs_dmabuf->comp);
	}
	mutex_unlock(&entry->dmabufs_lock);

	kref_put(&entry->ref, rdma_user_mmap_entry_free);
}
EXPORT_SYMBOL(rdma_user_mmap_entry_remove);
@@ -274,6 +295,9 @@ int rdma_user_mmap_entry_insert_range(struct ib_ucontext *ucontext,
		return -EINVAL;

	kref_init(&entry->ref);
	INIT_LIST_HEAD(&entry->dmabufs);
	mutex_init(&entry->dmabufs_lock);

	entry->ucontext = ucontext;

	/*
+16 −12
Original line number Diff line number Diff line
@@ -809,21 +809,10 @@ const struct uverbs_obj_type_class uverbs_idr_class = {
};
EXPORT_SYMBOL(uverbs_idr_class);

/*
 * Users of UVERBS_TYPE_ALLOC_FD should set this function as the struct
 * file_operations release method.
 */
int uverbs_uobject_fd_release(struct inode *inode, struct file *filp)
int uverbs_uobject_release(struct ib_uobject *uobj)
{
	struct ib_uverbs_file *ufile;
	struct ib_uobject *uobj;

	/*
	 * This can only happen if the fput came from alloc_abort_fd_uobject()
	 */
	if (!filp->private_data)
		return 0;
	uobj = filp->private_data;
	ufile = uobj->ufile;

	if (down_read_trylock(&ufile->hw_destroy_rwsem)) {
@@ -850,6 +839,21 @@ int uverbs_uobject_fd_release(struct inode *inode, struct file *filp)
	uverbs_uobject_put(uobj);
	return 0;
}

/*
 * Users of UVERBS_TYPE_ALLOC_FD should set this function as the struct
 * file_operations release method.
 */
int uverbs_uobject_fd_release(struct inode *inode, struct file *filp)
{
	/*
	 * This can only happen if the fput came from alloc_abort_fd_uobject()
	 */
	if (!filp->private_data)
		return 0;

	return uverbs_uobject_release(filp->private_data);
}
EXPORT_SYMBOL(uverbs_uobject_fd_release);

/*
+1 −0
Original line number Diff line number Diff line
@@ -156,6 +156,7 @@ extern const struct uapi_definition uverbs_def_obj_counters[];
extern const struct uapi_definition uverbs_def_obj_cq[];
extern const struct uapi_definition uverbs_def_obj_device[];
extern const struct uapi_definition uverbs_def_obj_dm[];
extern const struct uapi_definition uverbs_def_obj_dmabuf[];
extern const struct uapi_definition uverbs_def_obj_dmah[];
extern const struct uapi_definition uverbs_def_obj_flow_action[];
extern const struct uapi_definition uverbs_def_obj_intf[];
Loading