* [PATCH v2 00/23] DMA-buf mapping types
@ 2026-11-05 6:40 Alistair Popple
2026-11-05 6:40 ` [PATCH v2 01/23] treewide: Rename dma_buf_(un)map_attachment() to dma_buf_(un)map_sgt() Alistair Popple
` (23 more replies)
0 siblings, 24 replies; 26+ messages in thread
From: Alistair Popple @ 2026-11-05 6:40 UTC (permalink / raw)
To: Christian König, Sumit Semwal, Thomas Hellström,
Simona Vetter, Matthew Brost, Vivek Kasireddy, Dongwon Kim,
Kevin Tian, Xu Yilun, Karl Mehltretter, Baolu Lu, Felix Kuehling,
Alex Deucher, dri-devel, intel-xe, amd-gfx, linux-media,
linaro-mm-sig, linux-rdma, iommu, Keith Busch, Jens Axboe,
Christoph Hellwig, Sagi Grimberg, linux-nvme, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Mina Almasry, netdev, Alexey Kardashevskiy, zhipingz, treding,
jhubbard, Jason Gunthorpe, Leon Romanovsky
Cc: Alistair Popple
This is v2 of the DMA-buf mapping types series [1]. It keeps the framework
and the SGT conversions from the RFC but defers the final mapping type
selection until the first pin/map of the buffer.
At pin/map the exporter chooses one of the types matched, taking the other
attachments and the buffer's placement into account. That choice is held by the
core until the exporter explicitly invalidates the attachment. This ensures
unmap/remap cannot cause buffer movement and ping/pong.
Future work will build on top of this series to add an iommufd importer type
per the plan in [2], separate out PCIe P2P as its own mapping type and convert
XGMI to an exclusive mapping type.
Why mapping types
-----------------
Since its introduction, DMA-buf has only supported using scatterlist for
the exporter and importer to exchange address information. This is not
sufficient for all use cases as dma_addr_t is a very specific and limited
type that should not be abused for things unrelated to the DMA API.
There are several motivations for addressing this now:
1) VFIO to IOMMUFD and KVM requires a physical address, not a dma_addr_t
scatterlist, it cannot be represented in the scatterlist structure
2) xe vGPU requires the host driver to accept a DMABUF from VFIO of its
own VF and convert it into an internal VRAM address on the PF
3) We are starting to look at replacement datastructures for
scatterlist
4) Ideas around UALink/etc are suggesting not using the DMA API
5) Private interconnects, such as XGMI, are forced to work around this using
driver-specific hacks.
None of these can be achieved using scatterlist. This series introduces a
"mapping type" mechanism allowing dma-buf to negotiate compatibility between
different types and support alternate mapping options. See the description of
patch 2 for more details.
Selecting mapping type
----------------------
Importers and exporters list possible mapping types with the exporter
responsible for selecting the final type at pin/map time under the dma_resv
lock. A matching phase at attachment time eliminates types which statically
cannot be supported for a given exporter/importer.
This was done in response to review comments on the RFC. Karl found that the
RFC's match callback ran on an uninitialised attachment [3]. Christian noted
that the final decision has to be made under the dma_resv lock before a
mapping is created, not at attach [4], and Thomas proposed the three steps
followed here: agree the possible types at attach, select at map, hold the
selection until invalidate_mappings() [5]. Christian also noted that remaps
must not change type or placement as that makes buffers ping/pong [6].
The dma-buf core enforces that last point by calling select_mapping() only on
the first pin/map after attach or after an invalidate. The pin/map type can
therefore only change once the exporter has explicitly invalidated the mapping.
Future work
-----------
This series stops at the SGT type so that the framework and the
attach/pin/map contract can be reviewed on their own. I already have
proof-of-concept conversions of both PCIe P2P (building on Thomas's work [7])
and XGMI to separate mapping types. If those would be helpful for reviewing
this series let me know and I will post them.
Alternatively this series could be split up with patches 1-9 & 22-23 adding the
general framework and the rest adding the conversions later.
Further work, per [2], is an iommufd importer type to replace the private
vfio/iommufd interface and allow other DMA-bufs to be imported into iommufd.
Testing
-------
- KUnit dma-buf-mapping suite (patches 22 and 23) passes.
- Every patch compile-tested with a config enabling all converted drivers.
Changes since v1 [9]
--------------------
- Rebased onto v7.4-rc1. The rename also covers the new nvme-pci DMA-buf
importer and devmem's switch to pinning. xe's dynamic-debug knob for the
p2pdma distance check (3bc497a40178) is dropped, since the check is now
done by the core at match time, and amdgpu's PREEMPT-domain import
decision (78cdd96ab497) asks the negotiated match set instead of
attach->peer2peer.
- The dma_buf_map_attachment()/dma_buf_unmap_attachment() rename is now the
first patch, squashed into one, and uses the shorter dma_buf_map_sgt() and
dma_buf_unmap_sgt() names (Christian [9]).
- Dropped dma_buf_mapping_attach() and the dma_buf_sgt_attach() /
dma_buf_sgt_dynamic_attach() renames. Importers that support more than
the SGT type list them in a static dma_buf_attach_ops
->supported_mapping_types table. The importing device is passed to the
mapping types through the match arguments rather than stored in each
entry. dma_buf_attach() and dma_buf_dynamic_attach() are unchanged for
everyone else (Christian [9]).
- The selected type is an index into the attachment's match set, read
through dma_buf_attach_map_type(), instead of a copy in attach->map_type.
finish_match() fills the match set entry directly and select_mapping()
returns the index.
- A failed pin or map only undoes a selection it made itself, so a map
failing under a held pin keeps the pinned type and a failed first pin
leaves the attachment unselected; KUnit tests for both (Karl [10]).
- dma_buf_match_mapping() returns -EOPNOTSUPP when the two sides have no
type in common, keeping -EINVAL for an empty list, which restores the
error xe's own tests expect (Sashiko).
- New DMA_SGT_EXPORTER_REQUIRES_P2P flavour that requires a P2P capable
importer without a pci_p2pdma_distance() check at match time, used by
vfio and uverbs so iommufd's non-PCI device can still attach and so no
pci_dev is dereferenced outside the dma_resv lock (Sashiko).
- The SGT P2P distance check is quiet, as it was in xe and amdgpu before
the conversion (Sashiko).
- Fixed a NULL importer_ops dereference in dma_buf_dynamic_attach() and the
NULL check order in dma_buf_unmap_sgt() (Sashiko).
- Signed-off-by added to every patch (Jason). Patch 4 is now authored by me
with Jason as co-developer, as little of the original remains.
- Not addressed: the Tegra fault with CONFIG_DMABUF_DEBUG that Karl
reported [12] is a pre-existing Tegra bug being fixed separately.
Changes since RFC v1 [1]
------------------------
- Dropped the PAL type and its vfio/iommufd users (RFC 21-25).
- Rebased onto v7.3-rc5: move_notify is now invalidate_mappings,
CONFIG_DMABUF_MOVE_NOTIFY is gone, new amdxdna/panfrost/panthor
exporters converted, kzalloc_obj().
- Patch 1 records the whole match set in a fixed-size array in the
attachment; patch 3 initialises the attachment before match_mapping()
(Karl); patch 15 holds a pci_dev reference instead of asserting the resv
lock (Baolu).
- New patches 5, 6 and 7: exporter selection at pin/map with core-enforced
stickiness, match set queries, and dma_buf_mapping_map()/unmap().
- xe and amdgpu conversions written against the final API; amdgpu's XGMI
override rewrites the recorded match set entry.
- New patch 26 with KUnit tests for the selection contract.
[1] https://lore.kernel.org/all/0-v1-b5cab63049c0+191af-dmabuf_map_type_jgg@nvidia.com/
[2] https://lore.kernel.org/all/20260422150000.GK3199414@nvidia.com/
[3] https://lore.kernel.org/all/20261016202653.97339-1-kmehltretter@gmail.com/
[4] https://lore.kernel.org/all/d08a26ed-ded7-4447-bf7b-88597ee7df0e@amd.com/
[5] https://lore.kernel.org/all/8d4cb20b70ac4c3f36d8d631769757158af2ac8e.camel@linux.intel.com/
[6] https://lore.kernel.org/all/7b4dc988-5dbd-40e4-b17a-47b6eaf4bf81@amd.com/
[7] https://gitlab.freedesktop.org/thomash/xe-vibe/-/commit/7452df0fc858a7dc5ccac0e2037852cb7ab64d61
[8] https://lore.kernel.org/all/20261026053623.202642-1-apopple@nvidia.com/
[9] https://lore.kernel.org/all/3151a820-c583-4968-8440-673a9e390446@amd.com/
[10] https://lore.kernel.org/all/7193d384-5e28-4f85-8004-1dc9318d5c1c@amd.com/
[11] https://lore.kernel.org/all/at8IQZ34wkHQ_5PL@gmail.com/
[12] https://lore.kernel.org/all/auAIO0y09SXk34CN@gmail.com/
---
Alistair Popple (5):
dma-buf: Negotiate the mapping type in dma_buf_dynamic_attach()
dma-buf: Let the exporter select mapping type at pin/map
dma-buf: Add match set queries for exporter placement decisions
dma-buf: Add dma_buf_mapping_map() returning a type-tagged mapping
dma-buf: Add kunit tests for mapping type selection
Jason Gunthorpe (18):
treewide: Rename dma_buf_(un)map_attachment() to dma_buf_(un)map_sgt()
dma-buf: Introduce DMA-buf mapping types
dma-buf: Add the SGT DMA mapping type
dma-buf: Route SGT related actions through the attachment's mapping type
dma-buf: Allow single exporter drivers to avoid the match_mapping function
drm: Check the SGT ops for drm_gem_map_dma_buf()
dma-buf: Convert all the simple exporters to use SGT mapping type
drm/vmwgfx: Use match_mapping instead of dummy calls
accel/habanalabs: Use the SGT_P2P mapping type
drm/xe/dma-buf: Use the SGT mapping type
drm/amdgpu: Use the SGT mapping type
vfio/pci: Change the DMA-buf exporter to use mapping_type
RDMA/uverbs: Use the SGT_P2P mapping type
dma-buf: Update dma_buf_phys_vec_to_sgt() to use the SGT mapping type
iio: buffer: convert to use the SGT mapping type
functionfs: convert to use the SGT mapping type
dma-buf: Remove unused SGT stuff from the common structures
dma-buf: Add kunit tests for mapping type
drivers/accel/amdxdna/amdxdna_cbuf.c | 8 +-
drivers/accel/amdxdna/amdxdna_gem.c | 11 +-
drivers/accel/amdxdna/amdxdna_ubuf.c | 8 +-
drivers/accel/habanalabs/common/memory.c | 54 +-
drivers/accel/ivpu/ivpu_gem.c | 6 +-
drivers/accel/ivpu/ivpu_gem_userptr.c | 11 +-
drivers/accel/qaic/qaic_data.c | 6 +-
drivers/dma-buf/Makefile | 1 +
drivers/dma-buf/dma-buf-mapping.c | 291 ++++++-
drivers/dma-buf/dma-buf.c | 266 ++++--
drivers/dma-buf/heaps/cma_heap.c | 12 +-
drivers/dma-buf/heaps/system_heap.c | 13 +-
drivers/dma-buf/st-dma-mapping.c | 896 +++++++++++++++++++++
drivers/dma-buf/udmabuf.c | 8 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 136 ++--
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 4 +-
drivers/gpu/drm/armada/armada_gem.c | 28 +-
drivers/gpu/drm/drm_prime.c | 28 +-
drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c | 16 +-
drivers/gpu/drm/i915/gem/i915_gem_object.c | 2 +-
.../gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c | 4 +-
drivers/gpu/drm/i915/gem/selftests/mock_dmabuf.c | 8 +-
drivers/gpu/drm/msm/msm_gem_prime.c | 7 +-
drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c | 9 +-
drivers/gpu/drm/panfrost/panfrost_gem.c | 13 +-
drivers/gpu/drm/panthor/panthor_gem.c | 11 +-
drivers/gpu/drm/tegra/gem.c | 26 +-
drivers/gpu/drm/virtio/virtgpu_prime.c | 19 +-
drivers/gpu/drm/vmwgfx/vmwgfx_prime.c | 32 +-
drivers/gpu/drm/xe/xe_bo.c | 16 +-
drivers/gpu/drm/xe/xe_dma_buf.c | 79 +-
drivers/iio/industrialio-buffer.c | 13 +-
drivers/infiniband/core/umem_dmabuf.c | 8 +-
drivers/infiniband/core/uverbs_std_types_dmabuf.c | 30 +-
drivers/iommu/iommufd/selftest.c | 18 +-
drivers/media/common/videobuf2/videobuf2-core.c | 2 +-
.../media/common/videobuf2/videobuf2-dma-contig.c | 23 +-
drivers/media/common/videobuf2/videobuf2-dma-sg.c | 18 +-
drivers/media/common/videobuf2/videobuf2-vmalloc.c | 13 +-
.../media/platform/nvidia/tegra-vde/dmabuf-cache.c | 6 +-
drivers/misc/fastrpc.c | 18 +-
drivers/nvme/host/pci-dmabuf.c | 6 +-
drivers/tee/tee_heap.c | 13 +-
drivers/usb/gadget/function/f_fs.c | 9 +-
drivers/vfio/pci/vfio_pci_dmabuf.c | 26 +-
drivers/xen/gntdev-dmabuf.c | 27 +-
include/linux/dma-buf-mapping.h | 420 ++++++++++
include/linux/dma-buf.h | 234 ++++--
include/trace/events/dma_buf.h | 2 +-
io_uring/zcrx.c | 6 +-
net/core/devmem.c | 8 +-
samples/vfio-mdev/mbochs.c | 10 +-
sound/soc/fsl/fsl_asrc_m2m.c | 12 +-
53 files changed, 2415 insertions(+), 536 deletions(-)
---
base-commit: 6628e7d4c6b25c8d18f1345e3a20d21829aae7e4
change-id: 20261105-dma_mapping_type_v4-f71180b977e8
Best regards,
--
Alistair Popple <apopple@nvidia.com>
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH v2 01/23] treewide: Rename dma_buf_(un)map_attachment() to dma_buf_(un)map_sgt()
2026-11-05 6:40 [PATCH v2 00/23] DMA-buf mapping types Alistair Popple
@ 2026-11-05 6:40 ` Alistair Popple
2026-11-05 9:55 ` Christian König
2026-11-05 6:40 ` [PATCH v2 02/23] dma-buf: Introduce DMA-buf mapping types Alistair Popple
` (22 subsequent siblings)
23 siblings, 1 reply; 26+ messages in thread
From: Alistair Popple @ 2026-11-05 6:40 UTC (permalink / raw)
To: Christian König, Sumit Semwal, Thomas Hellström,
Simona Vetter, Matthew Brost, Vivek Kasireddy, Dongwon Kim,
Kevin Tian, Xu Yilun, Karl Mehltretter, Baolu Lu, Felix Kuehling,
Alex Deucher, dri-devel, intel-xe, amd-gfx, linux-media,
linaro-mm-sig, linux-rdma, iommu, Keith Busch, Jens Axboe,
Christoph Hellwig, Sagi Grimberg, linux-nvme, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Mina Almasry, netdev, Alexey Kardashevskiy, zhipingz, treding,
jhubbard, Jason Gunthorpe, Leon Romanovsky
Cc: Alistair Popple
From: Jason Gunthorpe <jgg@nvidia.com>
These map and unmap functions only work with SGT importers. Rename them,
and their _unlocked variants, so the scatterlist based interface is
clearly named as such before further mapping types are added.
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Alistair Popple <apopple@nvidia.com>
---
drivers/accel/amdxdna/amdxdna_gem.c | 6 +--
drivers/accel/ivpu/ivpu_gem.c | 6 +--
drivers/accel/qaic/qaic_data.c | 6 +--
drivers/dma-buf/dma-buf.c | 54 +++++++++++-----------
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 4 +-
drivers/gpu/drm/armada/armada_gem.c | 16 +++----
drivers/gpu/drm/drm_prime.c | 6 +--
drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c | 8 ++--
drivers/gpu/drm/i915/gem/i915_gem_object.c | 2 +-
.../gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c | 4 +-
drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c | 4 +-
drivers/gpu/drm/tegra/gem.c | 14 +++---
drivers/gpu/drm/virtio/virtgpu_prime.c | 8 ++--
drivers/gpu/drm/xe/xe_bo.c | 16 +++----
drivers/iio/industrialio-buffer.c | 6 +--
drivers/infiniband/core/umem_dmabuf.c | 8 ++--
drivers/media/common/videobuf2/videobuf2-core.c | 2 +-
.../media/common/videobuf2/videobuf2-dma-contig.c | 8 ++--
drivers/media/common/videobuf2/videobuf2-dma-sg.c | 4 +-
.../media/platform/nvidia/tegra-vde/dmabuf-cache.c | 6 +--
drivers/misc/fastrpc.c | 6 +--
drivers/nvme/host/pci-dmabuf.c | 6 +--
drivers/usb/gadget/function/f_fs.c | 4 +-
drivers/xen/gntdev-dmabuf.c | 8 ++--
include/linux/dma-buf.h | 26 +++++------
io_uring/zcrx.c | 6 +--
net/core/devmem.c | 8 ++--
27 files changed, 126 insertions(+), 126 deletions(-)
diff --git a/drivers/accel/amdxdna/amdxdna_gem.c b/drivers/accel/amdxdna/amdxdna_gem.c
index f14484bc31ec..adee6e806eed 100644
--- a/drivers/accel/amdxdna/amdxdna_gem.c
+++ b/drivers/accel/amdxdna/amdxdna_gem.c
@@ -701,7 +701,7 @@ static struct dma_buf *amdxdna_gem_prime_export(struct drm_gem_object *gobj, int
static void amdxdna_imported_obj_free(struct amdxdna_gem_obj *abo)
{
- dma_buf_unmap_attachment_unlocked(abo->attach, abo->base.sgt, DMA_BIDIRECTIONAL);
+ dma_buf_unmap_sgt_unlocked(abo->attach, abo->base.sgt, DMA_BIDIRECTIONAL);
dma_buf_detach(abo->dma_buf, abo->attach);
dma_buf_put(abo->dma_buf);
drm_gem_object_release(to_gobj(abo));
@@ -1075,7 +1075,7 @@ amdxdna_gem_prime_import(struct drm_device *dev, struct dma_buf *dma_buf)
goto put_buf;
}
- sgt = dma_buf_map_attachment_unlocked(attach, DMA_BIDIRECTIONAL);
+ sgt = dma_buf_map_sgt_unlocked(attach, DMA_BIDIRECTIONAL);
if (IS_ERR(sgt)) {
ret = PTR_ERR(sgt);
goto fail_detach;
@@ -1096,7 +1096,7 @@ amdxdna_gem_prime_import(struct drm_device *dev, struct dma_buf *dma_buf)
return gobj;
fail_unmap:
- dma_buf_unmap_attachment_unlocked(attach, sgt, DMA_BIDIRECTIONAL);
+ dma_buf_unmap_sgt_unlocked(attach, sgt, DMA_BIDIRECTIONAL);
fail_detach:
dma_buf_detach(dma_buf, attach);
put_buf:
diff --git a/drivers/accel/ivpu/ivpu_gem.c b/drivers/accel/ivpu/ivpu_gem.c
index c521a53f89bb..276f2a04aeda 100644
--- a/drivers/accel/ivpu/ivpu_gem.c
+++ b/drivers/accel/ivpu/ivpu_gem.c
@@ -54,7 +54,7 @@ static struct sg_table *ivpu_bo_map_attachment(struct ivpu_device *vdev, struct
sgt = bo->base.sgt;
if (!sgt) {
- sgt = dma_buf_map_attachment(bo->base.base.import_attach, DMA_BIDIRECTIONAL);
+ sgt = dma_buf_map_sgt(bo->base.base.import_attach, DMA_BIDIRECTIONAL);
if (IS_ERR(sgt))
ivpu_err(vdev, "Failed to map BO in IOMMU: %ld\n", PTR_ERR(sgt));
else
@@ -158,8 +158,8 @@ static void ivpu_bo_unbind_locked(struct ivpu_bo *bo)
if (bo->base.sgt) {
if (drm_gem_is_imported(&bo->base.base)) {
- dma_buf_unmap_attachment(bo->base.base.import_attach,
- bo->base.sgt, DMA_BIDIRECTIONAL);
+ dma_buf_unmap_sgt(bo->base.base.import_attach,
+ bo->base.sgt, DMA_BIDIRECTIONAL);
} else {
dma_unmap_sgtable(vdev->drm.dev, bo->base.sgt, DMA_BIDIRECTIONAL, 0);
sg_free_table(bo->base.sgt);
diff --git a/drivers/accel/qaic/qaic_data.c b/drivers/accel/qaic/qaic_data.c
index ee35e13091b3..d65578f0368e 100644
--- a/drivers/accel/qaic/qaic_data.c
+++ b/drivers/accel/qaic/qaic_data.c
@@ -869,7 +869,7 @@ struct drm_gem_object *qaic_gem_prime_import(struct drm_device *dev, struct dma_
drm_gem_private_object_init(dev, obj, attach->dmabuf->size);
/*
- * skipping dma_buf_map_attachment() as we do not know the direction
+ * skipping dma_buf_map_sgt() as we do not know the direction
* just yet. Once the direction is known in the subsequent IOCTL to
* attach slicing, we can do it then.
*/
@@ -895,7 +895,7 @@ static int qaic_prepare_import_bo(struct qaic_bo *bo, struct qaic_attach_slice_h
struct sg_table *sgt;
int ret;
- sgt = dma_buf_map_attachment(obj->import_attach, hdr->dir);
+ sgt = dma_buf_map_sgt(obj->import_attach, hdr->dir);
if (IS_ERR(sgt)) {
ret = PTR_ERR(sgt);
return ret;
@@ -936,7 +936,7 @@ static int qaic_prepare_bo(struct qaic_device *qdev, struct qaic_bo *bo,
static void qaic_unprepare_import_bo(struct qaic_bo *bo)
{
- dma_buf_unmap_attachment(bo->base.import_attach, bo->sgt, bo->dir);
+ dma_buf_unmap_sgt(bo->base.import_attach, bo->sgt, bo->dir);
bo->sgt = NULL;
}
diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index 36cdc342627e..0dd8d0999a92 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -677,7 +677,7 @@ static struct file *dma_buf_getfile(size_t size, int flags)
*
* 3. Once the buffer is attached to all devices userspace can initiate DMA
* access to the shared buffer. In the kernel this is done by calling
- * dma_buf_map_attachment() and dma_buf_unmap_attachment().
+ * dma_buf_map_sgt() and dma_buf_unmap_sgt().
*
* 4. Once a driver is done with a shared buffer it needs to call
* dma_buf_detach() (after cleaning up any mappings) and then release the
@@ -955,8 +955,8 @@ dma_buf_pin_on_map(struct dma_buf_attachment *attach)
*
* - dma_buf_pin()
* - dma_buf_unpin()
- * - dma_buf_map_attachment()
- * - dma_buf_unmap_attachment()
+ * - dma_buf_map_sgt()
+ * - dma_buf_unmap_sgt()
* - dma_buf_vmap()
* - dma_buf_vunmap()
*
@@ -973,8 +973,8 @@ dma_buf_pin_on_map(struct dma_buf_attachment *attach)
* - dma_buf_mmap()
* - dma_buf_begin_cpu_access()
* - dma_buf_end_cpu_access()
- * - dma_buf_map_attachment_unlocked()
- * - dma_buf_unmap_attachment_unlocked()
+ * - dma_buf_map_sgt_unlocked()
+ * - dma_buf_unmap_sgt_unlocked()
* - dma_buf_vmap_unlocked()
* - dma_buf_vunmap_unlocked()
*
@@ -1165,7 +1165,7 @@ void dma_buf_unpin(struct dma_buf_attachment *attach)
EXPORT_SYMBOL_NS_GPL(dma_buf_unpin, "DMA_BUF");
/**
- * dma_buf_map_attachment - Returns the scatterlist table of the attachment;
+ * dma_buf_map_sgt - Returns the scatterlist table of the attachment;
* mapped into _device_ address space. Is a wrapper for map_dma_buf() of the
* dma_buf_ops.
* @attach: [in] attachment whose scatterlist is to be returned
@@ -1177,7 +1177,7 @@ EXPORT_SYMBOL_NS_GPL(dma_buf_unpin, "DMA_BUF");
* On success, the DMA addresses and lengths in the returned scatterlist are
* PAGE_SIZE aligned.
*
- * A mapping must be unmapped by using dma_buf_unmap_attachment(). Note that
+ * A mapping must be unmapped by using dma_buf_unmap_sgt(). Note that
* the underlying backing storage is pinned for as long as a mapping exists,
* therefore users/importers should not hold onto a mapping for undue amounts of
* time.
@@ -1185,8 +1185,8 @@ EXPORT_SYMBOL_NS_GPL(dma_buf_unpin, "DMA_BUF");
* Important: Dynamic importers must wait for the exclusive fence of the struct
* dma_resv attached to the DMA-BUF first.
*/
-struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
- enum dma_data_direction direction)
+struct sg_table *dma_buf_map_sgt(struct dma_buf_attachment *attach,
+ enum dma_data_direction direction)
{
struct sg_table *sg_table;
signed long ret;
@@ -1257,20 +1257,20 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
return sg_table;
}
-EXPORT_SYMBOL_NS_GPL(dma_buf_map_attachment, "DMA_BUF");
+EXPORT_SYMBOL_NS_GPL(dma_buf_map_sgt, "DMA_BUF");
/**
- * dma_buf_map_attachment_unlocked - Returns the scatterlist table of the attachment;
+ * dma_buf_map_sgt_unlocked - Returns the scatterlist table of the attachment;
* mapped into _device_ address space. Is a wrapper for map_dma_buf() of the
* dma_buf_ops.
* @attach: [in] attachment whose scatterlist is to be returned
* @direction: [in] direction of DMA transfer
*
- * Unlocked variant of dma_buf_map_attachment().
+ * Unlocked variant of dma_buf_map_sgt().
*/
struct sg_table *
-dma_buf_map_attachment_unlocked(struct dma_buf_attachment *attach,
- enum dma_data_direction direction)
+dma_buf_map_sgt_unlocked(struct dma_buf_attachment *attach,
+ enum dma_data_direction direction)
{
struct sg_table *sg_table;
@@ -1280,24 +1280,24 @@ dma_buf_map_attachment_unlocked(struct dma_buf_attachment *attach,
return ERR_PTR(-EINVAL);
dma_resv_lock(attach->dmabuf->resv, NULL);
- sg_table = dma_buf_map_attachment(attach, direction);
+ sg_table = dma_buf_map_sgt(attach, direction);
dma_resv_unlock(attach->dmabuf->resv);
return sg_table;
}
-EXPORT_SYMBOL_NS_GPL(dma_buf_map_attachment_unlocked, "DMA_BUF");
+EXPORT_SYMBOL_NS_GPL(dma_buf_map_sgt_unlocked, "DMA_BUF");
/**
- * dma_buf_unmap_attachment - unmaps and decreases usecount of the buffer;might
+ * dma_buf_unmap_sgt - unmaps and decreases usecount of the buffer;might
* deallocate the scatterlist associated. Is a wrapper for unmap_dma_buf() of
* dma_buf_ops.
* @attach: [in] attachment to unmap buffer from
* @sg_table: [in] scatterlist info of the buffer to unmap
* @direction: [in] direction of DMA transfer
*
- * This unmaps a DMA mapping for @attached obtained by dma_buf_map_attachment().
+ * This unmaps a DMA mapping for @attached obtained by dma_buf_map_sgt().
*/
-void dma_buf_unmap_attachment(struct dma_buf_attachment *attach,
+void dma_buf_unmap_sgt(struct dma_buf_attachment *attach,
struct sg_table *sg_table,
enum dma_data_direction direction)
{
@@ -1314,21 +1314,21 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment *attach,
if (dma_buf_pin_on_map(attach))
attach->dmabuf->ops->unpin(attach);
}
-EXPORT_SYMBOL_NS_GPL(dma_buf_unmap_attachment, "DMA_BUF");
+EXPORT_SYMBOL_NS_GPL(dma_buf_unmap_sgt, "DMA_BUF");
/**
- * dma_buf_unmap_attachment_unlocked - unmaps and decreases usecount of the buffer;might
+ * dma_buf_unmap_sgt_unlocked - unmaps and decreases usecount of the buffer;might
* deallocate the scatterlist associated. Is a wrapper for unmap_dma_buf() of
* dma_buf_ops.
* @attach: [in] attachment to unmap buffer from
* @sg_table: [in] scatterlist info of the buffer to unmap
* @direction: [in] direction of DMA transfer
*
- * Unlocked variant of dma_buf_unmap_attachment().
+ * Unlocked variant of dma_buf_unmap_sgt().
*/
-void dma_buf_unmap_attachment_unlocked(struct dma_buf_attachment *attach,
- struct sg_table *sg_table,
- enum dma_data_direction direction)
+void dma_buf_unmap_sgt_unlocked(struct dma_buf_attachment *attach,
+ struct sg_table *sg_table,
+ enum dma_data_direction direction)
{
might_sleep();
@@ -1336,10 +1336,10 @@ void dma_buf_unmap_attachment_unlocked(struct dma_buf_attachment *attach,
return;
dma_resv_lock(attach->dmabuf->resv, NULL);
- dma_buf_unmap_attachment(attach, sg_table, direction);
+ dma_buf_unmap_sgt(attach, sg_table, direction);
dma_resv_unlock(attach->dmabuf->resv);
}
-EXPORT_SYMBOL_NS_GPL(dma_buf_unmap_attachment_unlocked, "DMA_BUF");
+EXPORT_SYMBOL_NS_GPL(dma_buf_unmap_sgt_unlocked, "DMA_BUF");
/**
* dma_buf_attach_revocable - check if a DMA-buf importer implements
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index 0f86777250fc..30ec5cb9ddf5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -962,7 +962,7 @@ static int amdgpu_ttm_backend_bind(struct ttm_device *bdev,
struct sg_table *sgt;
attach = gtt->gobj->import_attach;
- sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
+ sgt = dma_buf_map_sgt(attach, DMA_BIDIRECTIONAL);
if (IS_ERR(sgt))
return PTR_ERR(sgt);
@@ -1083,7 +1083,7 @@ static void amdgpu_ttm_backend_unbind(struct ttm_device *bdev,
struct dma_buf_attachment *attach;
attach = gtt->gobj->import_attach;
- dma_buf_unmap_attachment(attach, ttm->sg, DMA_BIDIRECTIONAL);
+ dma_buf_unmap_sgt(attach, ttm->sg, DMA_BIDIRECTIONAL);
ttm->sg = NULL;
}
diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c
index da7335cbe82d..044acdef6351 100644
--- a/drivers/gpu/drm/armada/armada_gem.c
+++ b/drivers/gpu/drm/armada/armada_gem.c
@@ -67,8 +67,8 @@ void armada_gem_free_object(struct drm_gem_object *obj)
if (dobj->obj.import_attach) {
/* We only ever display imported data */
if (dobj->sgt)
- dma_buf_unmap_attachment_unlocked(dobj->obj.import_attach,
- dobj->sgt, DMA_TO_DEVICE);
+ dma_buf_unmap_sgt_unlocked(dobj->obj.import_attach,
+ dobj->sgt, DMA_TO_DEVICE);
drm_prime_gem_destroy(&dobj->obj, NULL);
}
@@ -529,7 +529,7 @@ armada_gem_prime_import(struct drm_device *dev, struct dma_buf *buf)
get_dma_buf(buf);
/*
- * Don't call dma_buf_map_attachment() here - it maps the
+ * Don't call dma_buf_map_sgt() here - it maps the
* scatterlist immediately for DMA, and this is not always
* an appropriate thing to do.
*/
@@ -540,20 +540,20 @@ int armada_gem_map_import(struct armada_gem_object *dobj)
{
int ret;
- dobj->sgt = dma_buf_map_attachment_unlocked(dobj->obj.import_attach,
- DMA_TO_DEVICE);
+ dobj->sgt = dma_buf_map_sgt_unlocked(dobj->obj.import_attach,
+ DMA_TO_DEVICE);
if (IS_ERR(dobj->sgt)) {
ret = PTR_ERR(dobj->sgt);
dobj->sgt = NULL;
- DRM_ERROR("dma_buf_map_attachment() error: %d\n", ret);
+ DRM_ERROR("dma_buf_map_sgt() error: %d\n", ret);
return ret;
}
if (dobj->sgt->nents > 1) {
- DRM_ERROR("dma_buf_map_attachment() returned an (unsupported) scattered list\n");
+ DRM_ERROR("dma_buf_map_sgt() returned an (unsupported) scattered list\n");
return -EINVAL;
}
if (sg_dma_len(dobj->sgt->sgl) < dobj->obj.size) {
- DRM_ERROR("dma_buf_map_attachment() returned a small buffer\n");
+ DRM_ERROR("dma_buf_map_sgt() returned a small buffer\n");
return -EINVAL;
}
dobj->dev_addr = sg_dma_address(dobj->sgt->sgl);
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
index fe3436d1235d..e27bda3423ed 100644
--- a/drivers/gpu/drm/drm_prime.c
+++ b/drivers/gpu/drm/drm_prime.c
@@ -993,7 +993,7 @@ struct drm_gem_object *drm_gem_prime_import_dev(struct drm_device *dev,
get_dma_buf(dma_buf);
- sgt = dma_buf_map_attachment_unlocked(attach, DMA_BIDIRECTIONAL);
+ sgt = dma_buf_map_sgt_unlocked(attach, DMA_BIDIRECTIONAL);
if (IS_ERR(sgt)) {
ret = PTR_ERR(sgt);
goto fail_detach;
@@ -1011,7 +1011,7 @@ struct drm_gem_object *drm_gem_prime_import_dev(struct drm_device *dev,
return obj;
fail_unmap:
- dma_buf_unmap_attachment_unlocked(attach, sgt, DMA_BIDIRECTIONAL);
+ dma_buf_unmap_sgt_unlocked(attach, sgt, DMA_BIDIRECTIONAL);
fail_detach:
dma_buf_detach(dma_buf, attach);
dma_buf_put(dma_buf);
@@ -1109,7 +1109,7 @@ void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg)
attach = obj->import_attach;
if (sg)
- dma_buf_unmap_attachment_unlocked(attach, sg, DMA_BIDIRECTIONAL);
+ dma_buf_unmap_sgt_unlocked(attach, sg, DMA_BIDIRECTIONAL);
dma_buf = attach->dmabuf;
dma_buf_detach(attach->dmabuf, attach);
/* remove the reference */
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
index b43d34c7d641..4ab54d2e616f 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
@@ -240,8 +240,8 @@ static int i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj)
assert_object_held(obj);
- sgt = dma_buf_map_attachment(obj->base.import_attach,
- DMA_BIDIRECTIONAL);
+ sgt = dma_buf_map_sgt(obj->base.import_attach,
+ DMA_BIDIRECTIONAL);
if (IS_ERR(sgt))
return PTR_ERR(sgt);
@@ -268,8 +268,8 @@ static int i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj)
static void i915_gem_object_put_pages_dmabuf(struct drm_i915_gem_object *obj,
struct sg_table *sgt)
{
- dma_buf_unmap_attachment(obj->base.import_attach, sgt,
- DMA_BIDIRECTIONAL);
+ dma_buf_unmap_sgt(obj->base.import_attach, sgt,
+ DMA_BIDIRECTIONAL);
}
static const struct drm_i915_gem_object_ops i915_gem_object_dmabuf_ops = {
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c
index 9e01f8b2079a..1e0aafc3643b 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
@@ -367,7 +367,7 @@ void __i915_gem_object_pages_fini(struct drm_i915_gem_object *obj)
atomic_set(&obj->mm.pages_pin_count, 0);
/*
- * dma_buf_unmap_attachment() requires reservation to be
+ * dma_buf_unmap_sgt() requires reservation to be
* locked. The imported GEM shouldn't share reservation lock
* and ttm_bo_cleanup_memtype_use() shouldn't be invoked for
* dma-buf, so it's safe to take the lock.
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
index 2fda549dd82d..af9ced05f7a8 100644
--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
@@ -293,7 +293,7 @@ static int igt_dmabuf_import_same_driver(struct drm_i915_private *i915,
goto out_import;
}
- st = dma_buf_map_attachment_unlocked(import_attach, DMA_BIDIRECTIONAL);
+ st = dma_buf_map_sgt_unlocked(import_attach, DMA_BIDIRECTIONAL);
if (IS_ERR(st)) {
err = PTR_ERR(st);
goto out_detach;
@@ -306,7 +306,7 @@ static int igt_dmabuf_import_same_driver(struct drm_i915_private *i915,
timeout = -ETIME;
}
err = timeout > 0 ? 0 : timeout;
- dma_buf_unmap_attachment_unlocked(import_attach, st, DMA_BIDIRECTIONAL);
+ dma_buf_unmap_sgt_unlocked(import_attach, st, DMA_BIDIRECTIONAL);
out_detach:
dma_buf_detach(dmabuf, import_attach);
out_import:
diff --git a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
index 30cf1cdc1aa3..afae0a56da8c 100644
--- a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
+++ b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
@@ -120,7 +120,7 @@ struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev,
get_dma_buf(dma_buf);
- sgt = dma_buf_map_attachment_unlocked(attach, DMA_TO_DEVICE);
+ sgt = dma_buf_map_sgt_unlocked(attach, DMA_TO_DEVICE);
if (IS_ERR(sgt)) {
ret = PTR_ERR(sgt);
goto fail_detach;
@@ -137,7 +137,7 @@ struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev,
return obj;
fail_unmap:
- dma_buf_unmap_attachment_unlocked(attach, sgt, DMA_TO_DEVICE);
+ dma_buf_unmap_sgt_unlocked(attach, sgt, DMA_TO_DEVICE);
fail_detach:
dma_buf_detach(dma_buf, attach);
dma_buf_put(dma_buf);
diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c
index f76af733ea79..e6aa6dae4ec8 100644
--- a/drivers/gpu/drm/tegra/gem.c
+++ b/drivers/gpu/drm/tegra/gem.c
@@ -86,7 +86,7 @@ static struct host1x_bo_mapping *tegra_bo_pin(struct device *dev, struct host1x_
goto free;
}
- map->sgt = dma_buf_map_attachment_unlocked(map->attach, direction);
+ map->sgt = dma_buf_map_sgt_unlocked(map->attach, direction);
if (IS_ERR(map->sgt)) {
dma_buf_detach(buf, map->attach);
err = PTR_ERR(map->sgt);
@@ -162,8 +162,8 @@ static struct host1x_bo_mapping *tegra_bo_pin(struct device *dev, struct host1x_
static void tegra_bo_unpin(struct host1x_bo_mapping *map)
{
if (map->attach) {
- dma_buf_unmap_attachment_unlocked(map->attach, map->sgt,
- map->direction);
+ dma_buf_unmap_sgt_unlocked(map->attach, map->sgt,
+ map->direction);
dma_buf_detach(map->attach->dmabuf, map->attach);
} else {
dma_unmap_sgtable(map->dev, map->sgt, map->direction, 0);
@@ -479,7 +479,7 @@ static struct tegra_bo *tegra_bo_import(struct drm_device *drm,
goto free;
}
- bo->sgt = dma_buf_map_attachment_unlocked(attach, DMA_TO_DEVICE);
+ bo->sgt = dma_buf_map_sgt_unlocked(attach, DMA_TO_DEVICE);
if (IS_ERR(bo->sgt)) {
err = PTR_ERR(bo->sgt);
goto detach;
@@ -499,7 +499,7 @@ static struct tegra_bo *tegra_bo_import(struct drm_device *drm,
detach:
if (!IS_ERR_OR_NULL(bo->sgt))
- dma_buf_unmap_attachment_unlocked(attach, bo->sgt, DMA_TO_DEVICE);
+ dma_buf_unmap_sgt_unlocked(attach, bo->sgt, DMA_TO_DEVICE);
dma_buf_detach(buf, attach);
dma_buf_put(buf);
@@ -520,8 +520,8 @@ void tegra_bo_free_object(struct drm_gem_object *gem)
tegra_bo_iommu_unmap(tegra, bo);
if (drm_gem_is_imported(gem)) {
- dma_buf_unmap_attachment_unlocked(gem->import_attach, bo->sgt,
- DMA_TO_DEVICE);
+ dma_buf_unmap_sgt_unlocked(gem->import_attach, bo->sgt,
+ DMA_TO_DEVICE);
dma_buf_detach(gem->import_attach->dmabuf, gem->import_attach);
}
}
diff --git a/drivers/gpu/drm/virtio/virtgpu_prime.c b/drivers/gpu/drm/virtio/virtgpu_prime.c
index ebf471044d06..a47783b47dcc 100644
--- a/drivers/gpu/drm/virtio/virtgpu_prime.c
+++ b/drivers/gpu/drm/virtio/virtgpu_prime.c
@@ -161,13 +161,13 @@ int virtgpu_dma_buf_import_sgt(struct virtio_gpu_mem_entry **ents,
if (ret <= 0)
return ret < 0 ? ret : -ETIMEDOUT;
- sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
+ sgt = dma_buf_map_sgt(attach, DMA_BIDIRECTIONAL);
if (IS_ERR(sgt))
return PTR_ERR(sgt);
*ents = kvmalloc_objs(struct virtio_gpu_mem_entry, sgt->nents);
if (!(*ents)) {
- dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
+ dma_buf_unmap_sgt(attach, sgt, DMA_BIDIRECTIONAL);
return -ENOMEM;
}
@@ -192,8 +192,8 @@ static void virtgpu_dma_buf_unmap(struct virtio_gpu_object *bo)
virtio_gpu_detach_object_fenced(bo);
if (bo->sgt)
- dma_buf_unmap_attachment(attach, bo->sgt,
- DMA_BIDIRECTIONAL);
+ dma_buf_unmap_sgt(attach, bo->sgt,
+ DMA_BIDIRECTIONAL);
bo->sgt = NULL;
}
diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c
index 12e523c61c1f..14b71d951659 100644
--- a/drivers/gpu/drm/xe/xe_bo.c
+++ b/drivers/gpu/drm/xe/xe_bo.c
@@ -869,7 +869,7 @@ static int xe_bo_move_dmabuf(struct ttm_buffer_object *ttm_bo,
ttm_bo->sg) {
dma_resv_wait_timeout(ttm_bo->base.resv, DMA_RESV_USAGE_BOOKKEEP,
false, MAX_SCHEDULE_TIMEOUT);
- dma_buf_unmap_attachment(attach, ttm_bo->sg, DMA_BIDIRECTIONAL);
+ dma_buf_unmap_sgt(attach, ttm_bo->sg, DMA_BIDIRECTIONAL);
ttm_bo->sg = NULL;
}
@@ -877,11 +877,11 @@ static int xe_bo_move_dmabuf(struct ttm_buffer_object *ttm_bo,
goto out;
if (ttm_bo->sg) {
- dma_buf_unmap_attachment(attach, ttm_bo->sg, DMA_BIDIRECTIONAL);
+ dma_buf_unmap_sgt(attach, ttm_bo->sg, DMA_BIDIRECTIONAL);
ttm_bo->sg = NULL;
}
- sg = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
+ sg = dma_buf_map_sgt(attach, DMA_BIDIRECTIONAL);
if (IS_ERR(sg))
return PTR_ERR(sg);
@@ -1750,9 +1750,9 @@ int xe_bo_dma_unmap_pinned(struct xe_bo *bo)
struct xe_ttm_tt *xe_tt = container_of(tt, typeof(*xe_tt), ttm);
if (ttm_bo->type == ttm_bo_type_sg && ttm_bo->sg) {
- dma_buf_unmap_attachment(ttm_bo->base.import_attach,
- ttm_bo->sg,
- DMA_BIDIRECTIONAL);
+ dma_buf_unmap_sgt(ttm_bo->base.import_attach,
+ ttm_bo->sg,
+ DMA_BIDIRECTIONAL);
ttm_bo->sg = NULL;
xe_tt->sg = NULL;
} else if (xe_tt->sg) {
@@ -1867,8 +1867,8 @@ static void xe_ttm_bo_delete_mem_notify(struct ttm_buffer_object *ttm_bo)
struct xe_ttm_tt *xe_tt = container_of(ttm_bo->ttm,
struct xe_ttm_tt, ttm);
- dma_buf_unmap_attachment(ttm_bo->base.import_attach, ttm_bo->sg,
- DMA_BIDIRECTIONAL);
+ dma_buf_unmap_sgt(ttm_bo->base.import_attach, ttm_bo->sg,
+ DMA_BIDIRECTIONAL);
ttm_bo->sg = NULL;
xe_tt->sg = NULL;
}
diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index 4294101810fd..4a1063e4891f 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -1593,7 +1593,7 @@ static void iio_buffer_dmabuf_release(struct kref *ref)
struct iio_buffer *buffer = priv->buffer;
struct dma_buf *dmabuf = attach->dmabuf;
- dma_buf_unmap_attachment_unlocked(attach, priv->sgt, priv->dir);
+ dma_buf_unmap_sgt_unlocked(attach, priv->sgt, priv->dir);
buffer->access->detach_dmabuf(buffer, priv->block);
@@ -1733,7 +1733,7 @@ static int iio_buffer_attach_dmabuf(struct iio_dev_buffer_pair *ib,
priv->dir = buffer->direction == IIO_BUFFER_DIRECTION_IN
? DMA_FROM_DEVICE : DMA_TO_DEVICE;
- priv->sgt = dma_buf_map_attachment(attach, priv->dir);
+ priv->sgt = dma_buf_map_sgt(attach, priv->dir);
if (IS_ERR(priv->sgt)) {
err = PTR_ERR(priv->sgt);
dev_err(&indio_dev->dev, "Unable to map attachment: %d\n", err);
@@ -1781,7 +1781,7 @@ static int iio_buffer_attach_dmabuf(struct iio_dev_buffer_pair *ib,
return 0;
err_dmabuf_unmap_attachment:
- dma_buf_unmap_attachment(attach, priv->sgt, priv->dir);
+ dma_buf_unmap_sgt(attach, priv->sgt, priv->dir);
err_resv_unlock:
dma_resv_unlock(dmabuf->resv);
err_dmabuf_detach:
diff --git a/drivers/infiniband/core/umem_dmabuf.c b/drivers/infiniband/core/umem_dmabuf.c
index 39b5564a4c35..f233fdac9a17 100644
--- a/drivers/infiniband/core/umem_dmabuf.c
+++ b/drivers/infiniband/core/umem_dmabuf.c
@@ -29,8 +29,8 @@ int ib_umem_dmabuf_map_pages(struct ib_umem_dmabuf *umem_dmabuf)
if (umem_dmabuf->sgt)
goto wait_fence;
- sgt = dma_buf_map_attachment(umem_dmabuf->attach,
- DMA_BIDIRECTIONAL);
+ sgt = dma_buf_map_sgt(umem_dmabuf->attach,
+ DMA_BIDIRECTIONAL);
if (IS_ERR(sgt))
return PTR_ERR(sgt);
@@ -106,8 +106,8 @@ void ib_umem_dmabuf_unmap_pages(struct ib_umem_dmabuf *umem_dmabuf)
umem_dmabuf->last_sg_trim = 0;
}
- dma_buf_unmap_attachment(umem_dmabuf->attach, umem_dmabuf->sgt,
- DMA_BIDIRECTIONAL);
+ dma_buf_unmap_sgt(umem_dmabuf->attach, umem_dmabuf->sgt,
+ DMA_BIDIRECTIONAL);
umem_dmabuf->sgt = NULL;
}
diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c
index b0a6084f1757..61a614074222 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -1464,7 +1464,7 @@ static int __prepare_dmabuf(struct vb2_buffer *vb)
vb->planes[plane].mem_priv = mem_priv;
/*
- * This pins the buffer(s) with dma_buf_map_attachment()). It's done
+ * This pins the buffer(s) with dma_buf_map_sgt()). It's done
* here instead just before the DMA, while queueing the buffer(s) so
* userspace knows sooner rather than later if the dma-buf map fails.
*/
diff --git a/drivers/media/common/videobuf2/videobuf2-dma-contig.c b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
index 9ce6284cd5f2..284482335c1a 100644
--- a/drivers/media/common/videobuf2/videobuf2-dma-contig.c
+++ b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
@@ -705,7 +705,7 @@ static int vb2_dc_map_dmabuf(void *mem_priv)
}
/* get the associated scatterlist for this buffer */
- sgt = dma_buf_map_attachment_unlocked(buf->db_attach, buf->dma_dir);
+ sgt = dma_buf_map_sgt_unlocked(buf->db_attach, buf->dma_dir);
if (IS_ERR(sgt)) {
pr_err("Error getting dmabuf scatterlist\n");
return -EINVAL;
@@ -716,8 +716,8 @@ static int vb2_dc_map_dmabuf(void *mem_priv)
if (contig_size < buf->size) {
pr_err("contiguous chunk is too small %lu/%lu\n",
contig_size, buf->size);
- dma_buf_unmap_attachment_unlocked(buf->db_attach, sgt,
- buf->dma_dir);
+ dma_buf_unmap_sgt_unlocked(buf->db_attach, sgt,
+ buf->dma_dir);
return -EFAULT;
}
@@ -748,7 +748,7 @@ static void vb2_dc_unmap_dmabuf(void *mem_priv)
dma_buf_vunmap_unlocked(buf->db_attach->dmabuf, &map);
buf->vaddr = NULL;
}
- dma_buf_unmap_attachment_unlocked(buf->db_attach, sgt, buf->dma_dir);
+ dma_buf_unmap_sgt_unlocked(buf->db_attach, sgt, buf->dma_dir);
buf->dma_addr = 0;
buf->dma_sgt = NULL;
diff --git a/drivers/media/common/videobuf2/videobuf2-dma-sg.c b/drivers/media/common/videobuf2/videobuf2-dma-sg.c
index b1d0695cda26..54b07e3840ac 100644
--- a/drivers/media/common/videobuf2/videobuf2-dma-sg.c
+++ b/drivers/media/common/videobuf2/videobuf2-dma-sg.c
@@ -565,7 +565,7 @@ static int vb2_dma_sg_map_dmabuf(void *mem_priv)
}
/* get the associated scatterlist for this buffer */
- sgt = dma_buf_map_attachment_unlocked(buf->db_attach, buf->dma_dir);
+ sgt = dma_buf_map_sgt_unlocked(buf->db_attach, buf->dma_dir);
if (IS_ERR(sgt)) {
pr_err("Error getting dmabuf scatterlist\n");
return -EINVAL;
@@ -597,7 +597,7 @@ static void vb2_dma_sg_unmap_dmabuf(void *mem_priv)
dma_buf_vunmap_unlocked(buf->db_attach->dmabuf, &map);
buf->vaddr = NULL;
}
- dma_buf_unmap_attachment_unlocked(buf->db_attach, sgt, buf->dma_dir);
+ dma_buf_unmap_sgt_unlocked(buf->db_attach, sgt, buf->dma_dir);
buf->dma_sgt = NULL;
}
diff --git a/drivers/media/platform/nvidia/tegra-vde/dmabuf-cache.c b/drivers/media/platform/nvidia/tegra-vde/dmabuf-cache.c
index 7752064be783..d9bac7cd855a 100644
--- a/drivers/media/platform/nvidia/tegra-vde/dmabuf-cache.c
+++ b/drivers/media/platform/nvidia/tegra-vde/dmabuf-cache.c
@@ -38,7 +38,7 @@ static void tegra_vde_release_entry(struct tegra_vde_cache_entry *entry)
if (entry->vde->domain)
tegra_vde_iommu_unmap(entry->vde, entry->iova);
- dma_buf_unmap_attachment_unlocked(entry->a, entry->sgt, entry->dma_dir);
+ dma_buf_unmap_sgt_unlocked(entry->a, entry->sgt, entry->dma_dir);
dma_buf_detach(dmabuf, entry->a);
dma_buf_put(dmabuf);
@@ -102,7 +102,7 @@ int tegra_vde_dmabuf_cache_map(struct tegra_vde *vde,
goto err_unlock;
}
- sgt = dma_buf_map_attachment_unlocked(attachment, dma_dir);
+ sgt = dma_buf_map_sgt_unlocked(attachment, dma_dir);
if (IS_ERR(sgt)) {
dev_err(dev, "Failed to get dmabufs sg_table\n");
err = PTR_ERR(sgt);
@@ -152,7 +152,7 @@ int tegra_vde_dmabuf_cache_map(struct tegra_vde *vde,
err_free:
kfree(entry);
err_unmap:
- dma_buf_unmap_attachment_unlocked(attachment, sgt, dma_dir);
+ dma_buf_unmap_sgt_unlocked(attachment, sgt, dma_dir);
err_detach:
dma_buf_detach(dmabuf, attachment);
err_unlock:
diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
index af18ff1992ee..76c8dc05fa10 100644
--- a/drivers/misc/fastrpc.c
+++ b/drivers/misc/fastrpc.c
@@ -401,8 +401,8 @@ static void fastrpc_free_map(struct kref *ref)
return;
}
}
- dma_buf_unmap_attachment_unlocked(map->attach, map->table,
- DMA_BIDIRECTIONAL);
+ dma_buf_unmap_sgt_unlocked(map->attach, map->table,
+ DMA_BIDIRECTIONAL);
dma_buf_detach(map->buf, map->attach);
dma_buf_put(map->buf);
}
@@ -911,7 +911,7 @@ static int fastrpc_map_attach(struct fastrpc_user *fl, int fd,
goto attach_err;
}
- table = dma_buf_map_attachment_unlocked(map->attach, DMA_BIDIRECTIONAL);
+ table = dma_buf_map_sgt_unlocked(map->attach, DMA_BIDIRECTIONAL);
if (IS_ERR(table)) {
err = PTR_ERR(table);
goto map_err;
diff --git a/drivers/nvme/host/pci-dmabuf.c b/drivers/nvme/host/pci-dmabuf.c
index 161e4ffa6919..fe741dc0d54a 100644
--- a/drivers/nvme/host/pci-dmabuf.c
+++ b/drivers/nvme/host/pci-dmabuf.c
@@ -41,7 +41,7 @@ static struct dma_buf_io_map *nvme_dma_buf_io_map(struct dma_buf_io_ctx *ctx)
return ERR_PTR(-ENOMEM);
map->nr_entries = nr_entries;
- sgt = dma_buf_map_attachment(attach, ctx->dir);
+ sgt = dma_buf_map_sgt(attach, ctx->dir);
if (IS_ERR(sgt)) {
ret = PTR_ERR(sgt);
sgt = NULL;
@@ -71,7 +71,7 @@ static struct dma_buf_io_map *nvme_dma_buf_io_map(struct dma_buf_io_ctx *ctx)
return &map->base;
err:
if (sgt)
- dma_buf_unmap_attachment(attach, sgt, ctx->dir);
+ dma_buf_unmap_sgt(attach, sgt, ctx->dir);
kvfree(map);
return ERR_PTR(ret);
}
@@ -84,7 +84,7 @@ static void nvme_dma_buf_io_unmap(struct dma_buf_io_ctx *ctx,
dma_resv_assert_held(ctx->dmabuf->resv);
- dma_buf_unmap_attachment(nvme_ctx->attach, map->sgt, ctx->dir);
+ dma_buf_unmap_sgt(nvme_ctx->attach, map->sgt, ctx->dir);
kvfree(map);
}
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index c64a268e98a4..2f221d0a983f 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -1365,7 +1365,7 @@ static void ffs_dmabuf_release(struct kref *ref)
struct dma_buf *dmabuf = attach->dmabuf;
pr_vdebug("FFS DMABUF release\n");
- dma_buf_unmap_attachment_unlocked(attach, priv->sgt, priv->dir);
+ dma_buf_unmap_sgt_unlocked(attach, priv->sgt, priv->dir);
dma_buf_detach(attach->dmabuf, attach);
dma_buf_put(dmabuf);
@@ -1566,7 +1566,7 @@ static int ffs_dmabuf_attach(struct file *file, int fd)
if (err)
goto err_free_priv;
- sg_table = dma_buf_map_attachment(attach, dir);
+ sg_table = dma_buf_map_sgt(attach, dir);
dma_resv_unlock(dmabuf->resv);
if (IS_ERR(sg_table)) {
diff --git a/drivers/xen/gntdev-dmabuf.c b/drivers/xen/gntdev-dmabuf.c
index df1883aca850..e07e34515421 100644
--- a/drivers/xen/gntdev-dmabuf.c
+++ b/drivers/xen/gntdev-dmabuf.c
@@ -587,7 +587,7 @@ dmabuf_imp_to_refs(struct gntdev_dmabuf_priv *priv, struct device *dev,
gntdev_dmabuf->u.imp.attach = attach;
- sgt = dma_buf_map_attachment_unlocked(attach, DMA_BIDIRECTIONAL);
+ sgt = dma_buf_map_sgt_unlocked(attach, DMA_BIDIRECTIONAL);
if (IS_ERR(sgt)) {
ret = ERR_CAST(sgt);
goto fail_detach;
@@ -650,7 +650,7 @@ dmabuf_imp_to_refs(struct gntdev_dmabuf_priv *priv, struct device *dev,
fail_end_access:
dmabuf_imp_end_foreign_access(gntdev_dmabuf->u.imp.refs, count);
fail_unmap:
- dma_buf_unmap_attachment_unlocked(attach, sgt, DMA_BIDIRECTIONAL);
+ dma_buf_unmap_sgt_unlocked(attach, sgt, DMA_BIDIRECTIONAL);
fail_detach:
dma_buf_detach(dma_buf, attach);
fail_free_obj:
@@ -700,8 +700,8 @@ static int dmabuf_imp_release(struct gntdev_dmabuf_priv *priv, u32 fd)
attach = gntdev_dmabuf->u.imp.attach;
if (gntdev_dmabuf->u.imp.sgt)
- dma_buf_unmap_attachment_unlocked(attach, gntdev_dmabuf->u.imp.sgt,
- DMA_BIDIRECTIONAL);
+ dma_buf_unmap_sgt_unlocked(attach, gntdev_dmabuf->u.imp.sgt,
+ DMA_BIDIRECTIONAL);
dma_buf = attach->dmabuf;
dma_buf_detach(attach->dmabuf, attach);
dma_buf_put(dma_buf);
diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h
index d15b2b31d3c9..cedeb8ebc99e 100644
--- a/include/linux/dma-buf.h
+++ b/include/linux/dma-buf.h
@@ -116,7 +116,7 @@ struct dma_buf_ops {
/**
* @map_dma_buf:
*
- * This is called by dma_buf_map_attachment() and is used to map a
+ * This is called by dma_buf_map_sgt() and is used to map a
* shared &dma_buf into device address space, and it is mandatory. It
* can only be called if @attach has been called successfully.
*
@@ -173,7 +173,7 @@ struct dma_buf_ops {
/**
* @unmap_dma_buf:
*
- * This is called by dma_buf_unmap_attachment() and should unmap and
+ * This is called by dma_buf_unmap_sgt() and should unmap and
* release the &sg_table allocated in @map_dma_buf, and it is mandatory.
* For static dma_buf handling this might also unpin the backing
* storage if this is the last mapping of the DMA buffer.
@@ -470,7 +470,7 @@ struct dma_buf_attach_ops {
* @peer2peer: true if the importer can handle peer resources without pages.
* @priv: exporter specific attachment data.
* @importer_ops: importer operations for this attachment, if provided
- * dma_buf_map/unmap_attachment() must be called with the dma_resv lock held.
+ * dma_buf_map/unmap_sgt() must be called with the dma_resv lock held.
* @importer_priv: importer specific attachment data.
*
* This structure holds the attachment information between the dma_buf buffer
@@ -479,8 +479,8 @@ struct dma_buf_attach_ops {
*
* An attachment is created by calling dma_buf_attach(), and released again by
* calling dma_buf_detach(). The DMA mapping itself needed to initiate a
- * transfer is created by dma_buf_map_attachment() and freed again by calling
- * dma_buf_unmap_attachment().
+ * transfer is created by dma_buf_map_sgt() and freed again by calling
+ * dma_buf_unmap_sgt().
*/
struct dma_buf_attachment {
struct dma_buf *dmabuf;
@@ -571,10 +571,10 @@ void dma_buf_fd_install(struct dma_buf *dmabuf, int fd);
struct dma_buf *dma_buf_get(int fd);
void dma_buf_put(struct dma_buf *dmabuf);
-struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *,
- enum dma_data_direction);
-void dma_buf_unmap_attachment(struct dma_buf_attachment *, struct sg_table *,
- enum dma_data_direction);
+struct sg_table *dma_buf_map_sgt(struct dma_buf_attachment *,
+ enum dma_data_direction);
+void dma_buf_unmap_sgt(struct dma_buf_attachment *, struct sg_table *,
+ enum dma_data_direction);
void dma_buf_invalidate_mappings(struct dma_buf *dma_buf);
bool dma_buf_attach_revocable(struct dma_buf_attachment *attach);
int dma_buf_begin_cpu_access(struct dma_buf *dma_buf,
@@ -582,11 +582,11 @@ int dma_buf_begin_cpu_access(struct dma_buf *dma_buf,
int dma_buf_end_cpu_access(struct dma_buf *dma_buf,
enum dma_data_direction dir);
struct sg_table *
-dma_buf_map_attachment_unlocked(struct dma_buf_attachment *attach,
+dma_buf_map_sgt_unlocked(struct dma_buf_attachment *attach,
+ enum dma_data_direction direction);
+void dma_buf_unmap_sgt_unlocked(struct dma_buf_attachment *attach,
+ struct sg_table *sg_table,
enum dma_data_direction direction);
-void dma_buf_unmap_attachment_unlocked(struct dma_buf_attachment *attach,
- struct sg_table *sg_table,
- enum dma_data_direction direction);
int dma_buf_mmap(struct dma_buf *, struct vm_area_struct *,
unsigned long);
diff --git a/io_uring/zcrx.c b/io_uring/zcrx.c
index 6d7abb1636e7..7c8ce3d2188a 100644
--- a/io_uring/zcrx.c
+++ b/io_uring/zcrx.c
@@ -132,8 +132,8 @@ static void io_unmap_dmabuf(struct io_zcrx_mem *mem)
if (!IS_ENABLED(CONFIG_DMA_SHARED_BUFFER))
return;
if (mem->sgt)
- dma_buf_unmap_attachment_unlocked(mem->attach, mem->sgt,
- DMA_FROM_DEVICE);
+ dma_buf_unmap_sgt_unlocked(mem->attach, mem->sgt,
+ DMA_FROM_DEVICE);
if (mem->attach)
dma_buf_detach(mem->dmabuf, mem->attach);
mem->sgt = NULL;
@@ -182,7 +182,7 @@ static int io_import_dmabuf(struct io_zcrx_ifq *ifq,
goto err;
}
- mem->sgt = dma_buf_map_attachment_unlocked(mem->attach, DMA_FROM_DEVICE);
+ mem->sgt = dma_buf_map_sgt_unlocked(mem->attach, DMA_FROM_DEVICE);
if (IS_ERR(mem->sgt)) {
ret = PTR_ERR(mem->sgt);
mem->sgt = NULL;
diff --git a/net/core/devmem.c b/net/core/devmem.c
index 32fafbfa1359..5a984df959f7 100644
--- a/net/core/devmem.c
+++ b/net/core/devmem.c
@@ -75,8 +75,8 @@ void __net_devmem_dmabuf_binding_free(struct work_struct *wq)
kvfree(binding->area.niovs);
dma_resv_lock(binding->dmabuf->resv, NULL);
- dma_buf_unmap_attachment(binding->attachment, binding->sgt,
- binding->direction);
+ dma_buf_unmap_sgt(binding->attachment, binding->sgt,
+ binding->direction);
dma_buf_unpin(binding->attachment);
dma_resv_unlock(binding->dmabuf->resv);
dma_buf_detach(binding->dmabuf, binding->attachment);
@@ -250,7 +250,7 @@ net_devmem_bind_dmabuf(struct net_device *dev, void *vdev,
goto err_unlock;
}
- binding->sgt = dma_buf_map_attachment(binding->attachment, direction);
+ binding->sgt = dma_buf_map_sgt(binding->attachment, direction);
if (IS_ERR(binding->sgt)) {
err = PTR_ERR(binding->sgt);
NL_SET_ERR_MSG(extack, "Failed to map dmabuf attachment");
@@ -357,7 +357,7 @@ net_devmem_bind_dmabuf(struct net_device *dev, void *vdev,
kvfree(binding->tx_vec);
err_unmap:
dma_resv_lock(dmabuf->resv, NULL);
- dma_buf_unmap_attachment(binding->attachment, binding->sgt, direction);
+ dma_buf_unmap_sgt(binding->attachment, binding->sgt, direction);
err_unpin:
dma_buf_unpin(binding->attachment);
err_unlock:
--
2.54.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH v2 02/23] dma-buf: Introduce DMA-buf mapping types
2026-11-05 6:40 [PATCH v2 00/23] DMA-buf mapping types Alistair Popple
2026-11-05 6:40 ` [PATCH v2 01/23] treewide: Rename dma_buf_(un)map_attachment() to dma_buf_(un)map_sgt() Alistair Popple
@ 2026-11-05 6:40 ` Alistair Popple
2026-11-05 6:40 ` [PATCH v2 03/23] dma-buf: Add the SGT DMA mapping type Alistair Popple
` (21 subsequent siblings)
23 siblings, 0 replies; 26+ messages in thread
From: Alistair Popple @ 2026-11-05 6:40 UTC (permalink / raw)
To: Christian König, Sumit Semwal, Thomas Hellström,
Simona Vetter, Matthew Brost, Vivek Kasireddy, Dongwon Kim,
Kevin Tian, Xu Yilun, Karl Mehltretter, Baolu Lu, Felix Kuehling,
Alex Deucher, dri-devel, intel-xe, amd-gfx, linux-media,
linaro-mm-sig, linux-rdma, iommu, Keith Busch, Jens Axboe,
Christoph Hellwig, Sagi Grimberg, linux-nvme, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Mina Almasry, netdev, Alexey Kardashevskiy, zhipingz, treding,
jhubbard, Jason Gunthorpe, Leon Romanovsky
Cc: Alistair Popple
From: Jason Gunthorpe <jgg@nvidia.com>
DMA-buf mapping types allow the importer and exporter to negotiate the
format of the map/unmap to be used during the attachment.
Currently DMA-buf only supports struct scatterlist as the attachment map
operation. This is not sufficient for all use cases as dma_addr_t is a
very specific and limited type.
With mapping types the importing driver can declare what it supports. For
example:
static const struct dma_buf_mapping_match imp_match[] = {
DMA_BUF_IMAPPING_MY_DRIVER(...),
DMA_BUF_IMAPPING_SGT(DMA_SGT_NO_P2P),
};
static const struct dma_buf_attach_ops importer_ops = {
.supported_mapping_types = imp_match,
.nr_supported_mapping_types = ARRAY_SIZE(imp_match),
...
};
attach = dma_buf_dynamic_attach(dmabuf, dev, &importer_ops, ...)
And the exporting driver can declare what it supports:
int exporter_match_mapping(struct dma_buf_match_args *args)
{
struct dma_buf_mapping_match exp_match[] = {
DMA_BUF_EMAPPING_MY_DRIVER(my_ops, dev, ...),
DMA_BUF_EMAPPING_SGT(sgt_ops),
};
return dma_buf_match_mapping(args, exp_match, ...);
}
During dma_buf_dynamic_attach() the core code records every mutually
acceptable (exporter entry, importer entry) pair in attach->matches, a
small fixed-size array in the attachment, in the exporter's order of
preference. The first entry is the default and is what
dma_buf_attach_map_type() returns; later patches let the exporter choose a different entry of the set
at pin or map time, when the buffer's placement and the other attachments
are known. Importers and exporters that list a single type see exactly one
entry.
Add the basic types:
struct dma_buf_mapping_type
Type tag and ops for each mapping type.
struct dma_buf_mapping_match
Entry in a list of importer or exporter match specifications.
The match specification can be extended by the mapping type with
unique data.
dma_buf_match_mapping() / struct dma_buf_match_args
Helper to do the matching. Called by the exporting driver
via a dma_buf_ops callback.
struct dma_buf_mapping_exp_ops
Base type for the per-mapping type exporter provided functions. This
would be the map/unmap callbacks. Each mapping type can provide its own
functions for map/unmap type operations with optimal type signatures.
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Co-developed-by: Alistair Popple <apopple@nvidia.com>
Signed-off-by: Alistair Popple <apopple@nvidia.com>
---
drivers/dma-buf/dma-buf-mapping.c | 65 +++++++++++++++++++++++++++
include/linux/dma-buf-mapping.h | 95 +++++++++++++++++++++++++++++++++++++++
include/linux/dma-buf.h | 29 ++++++++++++
3 files changed, 189 insertions(+)
diff --git a/drivers/dma-buf/dma-buf-mapping.c b/drivers/dma-buf/dma-buf-mapping.c
index 833be519e1e6..d27f02610c2a 100644
--- a/drivers/dma-buf/dma-buf-mapping.c
+++ b/drivers/dma-buf/dma-buf-mapping.c
@@ -5,6 +5,7 @@
*/
#include <linux/dma-buf-mapping.h>
#include <linux/dma-resv.h>
+#include <linux/dma-buf.h>
#include <linux/overflow.h>
#include <linux/align.h>
@@ -257,3 +258,67 @@ void dma_buf_free_sgt(struct dma_buf_attachment *attach, struct sg_table *sgt,
}
EXPORT_SYMBOL_NS_GPL(dma_buf_free_sgt, "DMA_BUF");
+
+/**
+ * dma_buf_match_mapping - Record the mapping types agreed upon by exporter
+ * and importer
+ * @args: Match arguments from attach
+ * @exp: Array of mapping types supported by the exporter, in priority order
+ * @exp_len: Number of entries in @exp
+ *
+ * Walk the exporter's list in order and, for each entry, find the first
+ * importer entry of the same type that the type's match() callback accepts.
+ * Every such pair is recorded in @args->attach->matches, so the match set
+ * preserves the exporter's priority. The first entry is the default returned
+ * by dma_buf_attach_map_type().
+ *
+ * Because the exporter list is walked in order, the exporter controls the
+ * priority of mapping types.
+ *
+ * Returns: 0 if at least one type matched, -EOPNOTSUPP if the exporter and
+ * importer have no type in common, -EINVAL if either list is empty, -E2BIG if
+ * more than DMA_BUF_MAX_MATCHES types matched, or the error a match() callback
+ * aborted the search with.
+ */
+int dma_buf_match_mapping(struct dma_buf_match_args *args,
+ const struct dma_buf_mapping_match *exp,
+ size_t exp_len)
+{
+ const struct dma_buf_mapping_match *exp_end = exp + exp_len;
+ const struct dma_buf_mapping_match *imp_end =
+ args->imp_matches + args->imp_len;
+ struct dma_buf_attachment *attach = args->attach;
+ unsigned int nr = 0;
+ int ret;
+
+ if (!exp_len || !args->imp_len)
+ return -EINVAL;
+
+ for (; exp != exp_end; exp++) {
+ const struct dma_buf_mapping_match *imp = args->imp_matches;
+
+ for (; imp != imp_end; imp++) {
+ if (exp->type != imp->type)
+ continue;
+ if (exp->type->match) {
+ ret = exp->type->match(args, exp, imp);
+ if (ret == -EOPNOTSUPP)
+ continue;
+ if (ret != 0)
+ return ret;
+ }
+ if (nr == ARRAY_SIZE(attach->matches))
+ return -E2BIG;
+ exp->type->finish_match(args, exp, imp,
+ &attach->matches[nr++]);
+ break;
+ }
+ }
+
+ if (!nr)
+ return -EOPNOTSUPP;
+
+ attach->nr_matches = nr;
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(dma_buf_match_mapping, "DMA_BUF");
diff --git a/include/linux/dma-buf-mapping.h b/include/linux/dma-buf-mapping.h
index 09bde3f748e4..28b3a65c0672 100644
--- a/include/linux/dma-buf-mapping.h
+++ b/include/linux/dma-buf-mapping.h
@@ -7,6 +7,83 @@
#define __DMA_BUF_MAPPING_H__
#include <linux/dma-buf.h>
+struct device;
+struct dma_buf;
+struct dma_buf_attachment;
+struct dma_buf_mapping_exp_ops;
+
+/* Type tag for all mapping operations */
+struct dma_buf_mapping_exp_ops {};
+
+/*
+ * Internal struct to pass arguments from the attach function to the matching
+ * function
+ */
+struct dma_buf_match_args {
+ struct dma_buf *dmabuf;
+ struct dma_buf_attachment *attach;
+ /* The importing device passed to dma_buf_dynamic_attach() */
+ struct device *dev;
+ const struct dma_buf_mapping_match *imp_matches;
+ size_t imp_len;
+};
+
+/**
+ * struct dma_buf_mapping_type - Operations for a DMA-buf mapping type
+ *
+ * Each mapping type provides a singleton instance of this struct to describe
+ * the mapping type and its operations.
+ */
+struct dma_buf_mapping_type {
+ /**
+ * @name: Human-readable name for this mapping type, used in debugfs
+ * output
+ */
+ const char *name;
+
+ /**
+ * @match:
+ *
+ * Called during attach from dma_buf_match_mapping(). &exp and &imp are
+ * single items from the importer and exporter mapping match lists.
+ * Both will have the same instance of this struct as their type member.
+ * The importing device is @args->dev; importer entries do not carry
+ * it, so they can be static tables shared by every attachment.
+ *
+ * It determines if the exporter/importer are compatible.
+ *
+ * Returns: 0 on success
+ * -EOPNOTSUPP means ignore the failure and continue
+ * Everything else aborts the search and returns the -errno
+ */
+ int (*match)(struct dma_buf_match_args *args,
+ const struct dma_buf_mapping_match *exp,
+ const struct dma_buf_mapping_match *imp);
+
+ /**
+ * @finish_match:
+ *
+ * Called by dma_buf_match_mapping() after a successful match to fill
+ * in @match, the entry being added to @args->attach->matches. The
+ * matched @exp and @imp entries are provided so the callback can copy
+ * type-specific data into it, along with @args->dev if the type needs
+ * the importing device later.
+ */
+ void (*finish_match)(struct dma_buf_match_args *args,
+ const struct dma_buf_mapping_match *exp,
+ const struct dma_buf_mapping_match *imp,
+ struct dma_buf_mapping_match *match);
+
+ /**
+ * @debugfs_dump:
+ *
+ * Optional callback to write mapping-type-specific diagnostic
+ * information about @attach to the debugfs seq_file @s.
+ */
+ void (*debugfs_dump)(struct seq_file *s,
+ struct dma_buf_attachment *attach);
+};
+
struct sg_table *dma_buf_phys_vec_to_sgt(struct dma_buf_attachment *attach,
struct p2pdma_provider *provider,
struct phys_vec *phys_vec,
@@ -14,4 +91,22 @@ struct sg_table *dma_buf_phys_vec_to_sgt(struct dma_buf_attachment *attach,
enum dma_data_direction dir);
void dma_buf_free_sgt(struct dma_buf_attachment *attach, struct sg_table *sgt,
enum dma_data_direction dir);
+
+int dma_buf_match_mapping(struct dma_buf_match_args *args,
+ const struct dma_buf_mapping_match *exp_mappings,
+ size_t exp_len);
+
+/**
+ * dma_buf_attach_map_type - The match this attachment is mapped with
+ * @attach: the attachment
+ *
+ * Returns the entry of @attach->matches in force for the attachment: the
+ * exporter's default, which is the first entry.
+ */
+static inline const struct dma_buf_mapping_match *
+dma_buf_attach_map_type(const struct dma_buf_attachment *attach)
+{
+ return &attach->matches[0];
+}
+
#endif
diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h
index cedeb8ebc99e..81bbcd420d60 100644
--- a/include/linux/dma-buf.h
+++ b/include/linux/dma-buf.h
@@ -27,6 +27,28 @@
struct device;
struct dma_buf;
struct dma_buf_attachment;
+struct dma_buf_mapping_type;
+struct dma_buf_mapping_exp_ops;
+
+/*
+ * Upper bound on the number of mapping types an attachment can record as
+ * mutually acceptable. An exporter offering more compatible types than this
+ * to one importer fails the attach with -E2BIG.
+ */
+#define DMA_BUF_MAX_MATCHES 4
+
+/*
+ * Match items are generated by the importer using the DMA_BUF_IMAPPING_*() and
+ * the exporter using the DMA_BUF_EMAPPING_*() functions. Each mapping type
+ * defines its own signature with its own data to make the match and attachment.
+ */
+struct dma_buf_mapping_match {
+ const struct dma_buf_mapping_type *type;
+ const struct dma_buf_mapping_exp_ops *exp_ops;
+ union {
+ /* Each mapping_type has unique match parameters here */
+ };
+};
/**
* struct dma_buf_ops - operations possible on struct dma_buf
@@ -472,6 +494,11 @@ struct dma_buf_attach_ops {
* @importer_ops: importer operations for this attachment, if provided
* dma_buf_map/unmap_sgt() must be called with the dma_resv lock held.
* @importer_priv: importer specific attachment data.
+ * @matches: The match set negotiated at attach time: every mapping type both
+ * sides accept, in the exporter's order of preference. The first
+ * entry is the exporter's default; dma_buf_attach_map_type()
+ * returns the entry the attachment is mapped with.
+ * @nr_matches: Number of valid entries in @matches.
*
* This structure holds the attachment information between the dma_buf buffer
* and its user device(s). The list contains one attachment struct per device
@@ -490,6 +517,8 @@ struct dma_buf_attachment {
const struct dma_buf_attach_ops *importer_ops;
void *importer_priv;
void *priv;
+ struct dma_buf_mapping_match matches[DMA_BUF_MAX_MATCHES];
+ unsigned int nr_matches;
};
/**
--
2.54.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH v2 03/23] dma-buf: Add the SGT DMA mapping type
2026-11-05 6:40 [PATCH v2 00/23] DMA-buf mapping types Alistair Popple
2026-11-05 6:40 ` [PATCH v2 01/23] treewide: Rename dma_buf_(un)map_attachment() to dma_buf_(un)map_sgt() Alistair Popple
2026-11-05 6:40 ` [PATCH v2 02/23] dma-buf: Introduce DMA-buf mapping types Alistair Popple
@ 2026-11-05 6:40 ` Alistair Popple
2026-11-05 6:40 ` [PATCH v2 04/23] dma-buf: Negotiate the mapping type in dma_buf_dynamic_attach() Alistair Popple
` (20 subsequent siblings)
23 siblings, 0 replies; 26+ messages in thread
From: Alistair Popple @ 2026-11-05 6:40 UTC (permalink / raw)
To: Christian König, Sumit Semwal, Thomas Hellström,
Simona Vetter, Matthew Brost, Vivek Kasireddy, Dongwon Kim,
Kevin Tian, Xu Yilun, Karl Mehltretter, Baolu Lu, Felix Kuehling,
Alex Deucher, dri-devel, intel-xe, amd-gfx, linux-media,
linaro-mm-sig, linux-rdma, iommu, Keith Busch, Jens Axboe,
Christoph Hellwig, Sagi Grimberg, linux-nvme, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Mina Almasry, netdev, Alexey Kardashevskiy, zhipingz, treding,
jhubbard, Jason Gunthorpe, Leon Romanovsky
Cc: Alistair Popple
From: Jason Gunthorpe <jgg@nvidia.com>
The SGT (Scatter Gather Table) DMA mapping type represents the existing
sg_table/scatterlist based DMA mapping. It provides a sg_table based
map/unmap interface that exactly matches how things work today.
dma_buf_sgt_exp_compat_match will be used in the next patch to
transparently wrap an unaware exporter with a mapping type.
The SGT type handles the allow_peer2peer flag directly through matching
logic. The importer indicates if it is willing to accept peer2peer and the
exporter indicates if it requires peer2peer. A required peer2peer exporter
will not match to an importer that does not accept peer2peer.
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Alistair Popple <apopple@nvidia.com>
---
drivers/dma-buf/dma-buf-mapping.c | 104 +++++++++++++++++++++++++++++++
include/linux/dma-buf-mapping.h | 127 ++++++++++++++++++++++++++++++++++++++
include/linux/dma-buf.h | 19 +++++-
3 files changed, 249 insertions(+), 1 deletion(-)
diff --git a/drivers/dma-buf/dma-buf-mapping.c b/drivers/dma-buf/dma-buf-mapping.c
index d27f02610c2a..4eb0ea930900 100644
--- a/drivers/dma-buf/dma-buf-mapping.c
+++ b/drivers/dma-buf/dma-buf-mapping.c
@@ -6,6 +6,7 @@
#include <linux/dma-buf-mapping.h>
#include <linux/dma-resv.h>
#include <linux/dma-buf.h>
+#include <linux/seq_file.h>
#include <linux/overflow.h>
#include <linux/align.h>
@@ -322,3 +323,106 @@ int dma_buf_match_mapping(struct dma_buf_match_args *args,
return 0;
}
EXPORT_SYMBOL_NS_GPL(dma_buf_match_mapping, "DMA_BUF");
+
+static int dma_buf_sgt_match(struct dma_buf_match_args *args,
+ const struct dma_buf_mapping_match *exp,
+ const struct dma_buf_mapping_match *imp)
+{
+ switch (exp->sgt_data.exporter_requires_p2p) {
+ case DMA_SGT_NO_P2P:
+ return 0;
+ case DMA_SGT_EXPORTER_REQUIRES_P2P:
+ if (imp->sgt_data.importer_accepts_p2p !=
+ DMA_SGT_IMPORTER_ACCEPTS_P2P)
+ return -EOPNOTSUPP;
+ return 0;
+ case DMA_SGT_EXPORTER_REQUIRES_P2P_DISTANCE:
+ if (WARN_ON(!exp->sgt_data.exporting_p2p_device) ||
+ imp->sgt_data.importer_accepts_p2p !=
+ DMA_SGT_IMPORTER_ACCEPTS_P2P)
+ return -EOPNOTSUPP;
+ /*
+ * Not verbose: failing to match P2P is normal when the
+ * exporter also offers a system memory type.
+ */
+ if (pci_p2pdma_distance(exp->sgt_data.exporting_p2p_device,
+ args->dev, false) < 0)
+ return -EOPNOTSUPP;
+ return 0;
+ }
+ return 0;
+}
+
+static inline void
+dma_buf_sgt_finish_match(struct dma_buf_match_args *args,
+ const struct dma_buf_mapping_match *exp,
+ const struct dma_buf_mapping_match *imp,
+ struct dma_buf_mapping_match *match)
+{
+ struct dma_buf_attachment *attach = args->attach;
+
+ *match = (struct dma_buf_mapping_match) {
+ .type = &dma_buf_mapping_sgt_type,
+ .exp_ops = exp->exp_ops,
+ .sgt_data = {
+ .importing_dma_device = args->dev,
+ /* exporting_p2p_device is left opaque */
+ .importer_accepts_p2p = imp->sgt_data.importer_accepts_p2p,
+ .exporter_requires_p2p = exp->sgt_data.exporter_requires_p2p,
+ },
+ };
+
+ /*
+ * Setup the SGT type variables stored in attach because importers and
+ * exporters that do not natively use mappings expect them to be there.
+ * When converting to use mappings users should use the match versions
+ * of these instead.
+ */
+ attach->dev = args->dev;
+ attach->peer2peer = match->sgt_data.importer_accepts_p2p ==
+ DMA_SGT_IMPORTER_ACCEPTS_P2P;
+}
+
+static void dma_buf_sgt_debugfs_dump(struct seq_file *s,
+ struct dma_buf_attachment *attach)
+{
+ seq_printf(s, " %s", dev_name(dma_buf_sgt_dma_device(attach)));
+}
+
+struct dma_buf_mapping_type dma_buf_mapping_sgt_type = {
+ .name = "DMA Mapped Scatter Gather Table",
+ .match = dma_buf_sgt_match,
+ .finish_match = dma_buf_sgt_finish_match,
+ .debugfs_dump = dma_buf_sgt_debugfs_dump,
+};
+EXPORT_SYMBOL_NS_GPL(dma_buf_mapping_sgt_type, "DMA_BUF");
+
+static struct sg_table *
+dma_buf_sgt_compat_map_dma_buf(struct dma_buf_attachment *attach,
+ enum dma_data_direction dir)
+{
+ return attach->dmabuf->ops->map_dma_buf(attach, dir);
+}
+
+static void dma_buf_sgt_compat_unmap_dma_buf(struct dma_buf_attachment *attach,
+ struct sg_table *sgt,
+ enum dma_data_direction dir)
+{
+ attach->dmabuf->ops->unmap_dma_buf(attach, sgt, dir);
+}
+
+/* Route the classic map/unmap ops through the exp ops for old importers */
+static const struct dma_buf_mapping_sgt_exp_ops dma_buf_sgt_compat_exp_ops = {
+ .map_dma_buf = dma_buf_sgt_compat_map_dma_buf,
+ .unmap_dma_buf = dma_buf_sgt_compat_unmap_dma_buf,
+};
+
+/*
+ * This mapping type is used for unaware exporters that do not support
+ * match_mapping(). It wraps the dma_buf ops for SGT mappings into a mapping
+ * type so aware importers can transparently work with unaware exporters. This
+ * does not require p2p because old exporters will check it through the
+ * attach->peer2peer mechanism.
+ */
+const struct dma_buf_mapping_match dma_buf_sgt_exp_compat_match =
+ DMA_BUF_EMAPPING_SGT(&dma_buf_sgt_compat_exp_ops);
diff --git a/include/linux/dma-buf-mapping.h b/include/linux/dma-buf-mapping.h
index 28b3a65c0672..69073d589e54 100644
--- a/include/linux/dma-buf-mapping.h
+++ b/include/linux/dma-buf-mapping.h
@@ -12,6 +12,24 @@ struct dma_buf;
struct dma_buf_attachment;
struct dma_buf_mapping_exp_ops;
+enum dma_sgt_requires_p2p {
+ DMA_SGT_NO_P2P = 0,
+ /*
+ * Exporter: MMIO, importer must accept P2P and pci_p2pdma_distance()
+ * from exporting_p2p_device must succeed at match time. The match runs
+ * without the dma_resv lock whenever an importer attaches, so only use
+ * this if exporting_p2p_device stays bound to its driver for as long as
+ * the dma_buf exists. Importers that are not PCI devices never match.
+ */
+ DMA_SGT_EXPORTER_REQUIRES_P2P_DISTANCE,
+ /*
+ * Exporter: MMIO, importer must accept P2P. No distance check at match;
+ * the exporter's map does its own, e.g. via dma_buf_phys_vec_to_sgt().
+ */
+ DMA_SGT_EXPORTER_REQUIRES_P2P,
+ DMA_SGT_IMPORTER_ACCEPTS_P2P,
+};
+
/* Type tag for all mapping operations */
struct dma_buf_mapping_exp_ops {};
@@ -109,4 +127,113 @@ dma_buf_attach_map_type(const struct dma_buf_attachment *attach)
return &attach->matches[0];
}
+/*
+ * DMA Mapped Scatterlist Type
+ *
+ * When this type is matched the map/unmap functions are:
+ *
+ * dma_buf_map_sgt()
+ * dma_buf_unmap_sgt()
+ *
+ * The struct sg_table returned by those functions has only the DMA portions
+ * available. The caller must not try to use the struct page * information.
+ *
+ * importing_dma_device is the device passed to dma_buf_dynamic_attach(),
+ * recorded at match time, and is passed to the DMA API to provide the
+ * dma_addr_t's.
+ */
+extern struct dma_buf_mapping_type dma_buf_mapping_sgt_type;
+
+struct dma_buf_mapping_sgt_exp_ops {
+ struct dma_buf_mapping_exp_ops ops;
+ struct sg_table *(*map_dma_buf)(struct dma_buf_attachment *attach,
+ enum dma_data_direction dir);
+ void (*unmap_dma_buf)(struct dma_buf_attachment *attach,
+ struct sg_table *sgt,
+ enum dma_data_direction dir);
+};
+
+/**
+ * dma_buf_sgt_dma_device - Return the device to use for DMA mapping
+ * @attach: sgt mapping type attachment
+ *
+ * Called by the exporter to get the struct device to pass to the DMA API
+ * during map and unmap callbacks.
+ */
+static inline struct device *
+dma_buf_sgt_dma_device(struct dma_buf_attachment *attach)
+{
+ if (dma_buf_attach_map_type(attach)->type != &dma_buf_mapping_sgt_type)
+ return NULL;
+ return dma_buf_attach_map_type(attach)->sgt_data.importing_dma_device;
+}
+
+/**
+ * dma_buf_sgt_p2p_allowed - True if MMIO memory can be used peer to peer
+ * @attach: sgt mapping type attachment
+ *
+ * Should be called by exporters, returns true if the exporter's
+ * DMA_SGT_EXPORTER_REQUIRES_P2P_DISTANCE was matched.
+ */
+static inline bool dma_buf_sgt_p2p_allowed(struct dma_buf_attachment *attach)
+{
+ if (dma_buf_attach_map_type(attach)->type != &dma_buf_mapping_sgt_type)
+ return false;
+ return dma_buf_attach_map_type(attach)->sgt_data.exporter_requires_p2p ==
+ DMA_SGT_EXPORTER_REQUIRES_P2P_DISTANCE;
+}
+
+static inline const struct dma_buf_mapping_sgt_exp_ops *
+dma_buf_get_sgt_ops(struct dma_buf_attachment *attach)
+{
+ if (dma_buf_attach_map_type(attach)->type != &dma_buf_mapping_sgt_type)
+ return NULL;
+ return container_of(dma_buf_attach_map_type(attach)->exp_ops,
+ struct dma_buf_mapping_sgt_exp_ops, ops);
+}
+
+/*
+ * Importer SGT entry. Usable in a static table: the importing device is
+ * supplied by dma_buf_dynamic_attach() and recorded in the matched entry.
+ */
+#define DMA_BUF_IMAPPING_SGT(_importer_accepts_p2p) \
+ ((struct dma_buf_mapping_match){ \
+ .type = &dma_buf_mapping_sgt_type, \
+ .sgt_data = { .importer_accepts_p2p = (_importer_accepts_p2p) } })
+#define DMA_BUF_EMAPPING_SGT(_exp_ops) \
+ ((struct dma_buf_mapping_match){ .type = &dma_buf_mapping_sgt_type, \
+ .exp_ops = &((_exp_ops)->ops) })
+
+/*
+ * Only matches if the importing device is P2P capable and the P2P subsystem
+ * says P2P is possible from p2p_device.
+ */
+static inline struct dma_buf_mapping_match
+DMA_BUF_EMAPPING_SGT_P2P(const struct dma_buf_mapping_sgt_exp_ops *exp_ops,
+ struct pci_dev *p2p_device)
+{
+ struct dma_buf_mapping_match match = DMA_BUF_EMAPPING_SGT(exp_ops);
+
+ match.sgt_data.exporter_requires_p2p =
+ DMA_SGT_EXPORTER_REQUIRES_P2P_DISTANCE;
+ match.sgt_data.exporting_p2p_device = p2p_device;
+ return match;
+}
+
+/*
+ * Only matches if the importer accepts P2P. Whether the importing device can
+ * actually reach the exporter's MMIO is left to the exporter's map, for
+ * exporters whose importers need not be PCI devices.
+ */
+static inline struct dma_buf_mapping_match
+DMA_BUF_EMAPPING_SGT_REQUIRES_P2P(const struct dma_buf_mapping_sgt_exp_ops *exp_ops)
+{
+ struct dma_buf_mapping_match match = DMA_BUF_EMAPPING_SGT(exp_ops);
+
+ match.sgt_data.exporter_requires_p2p = DMA_SGT_EXPORTER_REQUIRES_P2P;
+ return match;
+}
+
+extern const struct dma_buf_mapping_match dma_buf_sgt_exp_compat_match;
+
#endif
diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h
index 81bbcd420d60..de73f931a2f8 100644
--- a/include/linux/dma-buf.h
+++ b/include/linux/dma-buf.h
@@ -30,6 +30,7 @@ struct dma_buf_attachment;
struct dma_buf_mapping_type;
struct dma_buf_mapping_exp_ops;
+
/*
* Upper bound on the number of mapping types an attachment can record as
* mutually acceptable. An exporter offering more compatible types than this
@@ -46,7 +47,23 @@ struct dma_buf_mapping_match {
const struct dma_buf_mapping_type *type;
const struct dma_buf_mapping_exp_ops *exp_ops;
union {
- /* Each mapping_type has unique match parameters here */
+ /* For dma_buf_mapping_sgt_type */
+ struct {
+ /* Filled from the attaching device, not by importers */
+ struct device *importing_dma_device;
+ /* Only used if DMA_SGT_EXPORTER_REQUIRES_P2P_DISTANCE */
+ struct pci_dev *exporting_p2p_device;
+ /*
+ * These p2p flags are used to support the hard coded
+ * mechanism for p2p. If an exporting device knows it
+ * will put MMIO into the sgt then it should set
+ * exporter_requires_p2p. Importers should set
+ * importer_accepts_p2p unless it is known that the
+ * importing HW never supports P2P because of HW issues.
+ */
+ u8 importer_accepts_p2p;
+ u8 exporter_requires_p2p;
+ } sgt_data;
};
};
--
2.54.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH v2 04/23] dma-buf: Negotiate the mapping type in dma_buf_dynamic_attach()
2026-11-05 6:40 [PATCH v2 00/23] DMA-buf mapping types Alistair Popple
` (2 preceding siblings ...)
2026-11-05 6:40 ` [PATCH v2 03/23] dma-buf: Add the SGT DMA mapping type Alistair Popple
@ 2026-11-05 6:40 ` Alistair Popple
2026-11-05 6:40 ` [PATCH v2 05/23] dma-buf: Route SGT related actions through the attachment's mapping type Alistair Popple
` (19 subsequent siblings)
23 siblings, 0 replies; 26+ messages in thread
From: Alistair Popple @ 2026-11-05 6:40 UTC (permalink / raw)
To: Christian König, Sumit Semwal, Thomas Hellström,
Simona Vetter, Matthew Brost, Vivek Kasireddy, Dongwon Kim,
Kevin Tian, Xu Yilun, Karl Mehltretter, Baolu Lu, Felix Kuehling,
Alex Deucher, dri-devel, intel-xe, amd-gfx, linux-media,
linaro-mm-sig, linux-rdma, iommu, Keith Busch, Jens Axboe,
Christoph Hellwig, Sagi Grimberg, linux-nvme, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Mina Almasry, netdev, Alexey Kardashevskiy, zhipingz, treding,
jhubbard, Jason Gunthorpe, Leon Romanovsky
Cc: Alistair Popple
Let the importer tell the exporter which mapping types it supports when
it attaches. A new optional dma_buf_attach_ops->supported_mapping_types
table lists the importer's DMA_BUF_IMAPPING_*() entries, most preferred
first. The entries carry no device so the table is static and shared by
all of the importer's attachments; the device passed to
dma_buf_dynamic_attach() is handed to the mapping types through the match
arguments. Importers that do not provide a table, which includes every
dma_buf_attach() caller, support only the SGT type with P2P according to
allow_peer2peer, exactly as today.
dma_buf_dynamic_attach() checks if the exporter is mapping aware and calls
its ops->match_mapping() function to pick up the exporter match list and
call dma_buf_match_mapping().
If unaware it will use dma_buf_sgt_exp_compat_match as a compatibility
matchlist that uses the unaware exporter's dma_buf_ops callbacks.
The resulting match set is stored in attach->matches with the first entry,
the exporter's preferred type, returned by dma_buf_attach_map_type().
In effect dma_buf_attach_map_type() is always available and always makes
sense
regardless of what combination of aware/unaware importer/exporter is used.
The attachment's importer side (dmabuf, importer_ops, importer_priv) is
initialised before either callback runs so that exporters can consult it,
for example to recognise an importer driven by the same driver. The
dma_resv lock is not held at this point, so match_mapping() may only look
at properties that cannot change for the lifetime of the attachment.
For compatibility with unaware drivers copy the sgt matching data into the
attach->dev and peer2peer.
If the exporter sets exporter_requires_p2p then only the following are
allowed:
- importers without a supported_mapping_types table that set
importer_ops->allow_peer2peer = true
- importers whose supported_mapping_types table includes
DMA_BUF_IMAPPING_SGT(DMA_SGT_IMPORTER_ACCEPTS_P2P)
Other combinations are blocked.
Exporters that want to behave differently based on the importer's
capability can declare exporter_requires_p2p=false and check
dma_buf_attach_map_type(attach)->sgt_data.importer_accepts_p2p. Or they can
declare two
SGT exporters with different map/unmap functions.
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Alistair Popple <apopple@nvidia.com>
---
drivers/dma-buf/dma-buf.c | 62 +++++++++++++++++++++++++++++++++++++++++++----
include/linux/dma-buf.h | 46 +++++++++++++++++++++++++++++++++++
2 files changed, 103 insertions(+), 5 deletions(-)
diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index 0dd8d0999a92..1913a84d3363 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -14,6 +14,7 @@
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/dma-buf.h>
+#include <linux/dma-buf-mapping.h>
#include <linux/dma-fence.h>
#include <linux/dma-fence-unwrap.h>
#include <linux/anon_inodes.h>
@@ -714,11 +715,19 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
int ret;
if (WARN_ON(!exp_info->priv || !exp_info->ops
- || !exp_info->ops->map_dma_buf
- || !exp_info->ops->unmap_dma_buf
|| !exp_info->ops->release))
return ERR_PTR(-EINVAL);
+ if (exp_info->ops->match_mapping) {
+ if (WARN_ON(exp_info->ops->map_dma_buf ||
+ exp_info->ops->unmap_dma_buf))
+ return ERR_PTR(-EINVAL);
+ } else {
+ if (WARN_ON(!exp_info->ops->map_dma_buf ||
+ !exp_info->ops->unmap_dma_buf))
+ return ERR_PTR(-EINVAL);
+ }
+
if (WARN_ON(!exp_info->ops->pin != !exp_info->ops->unpin))
return ERR_PTR(-EINVAL);
@@ -1027,12 +1036,26 @@ dma_buf_pin_on_map(struct dma_buf_attachment *attach)
* Note that this can fail if the backing storage of @dmabuf is in a place not
* accessible to @dev, and cannot be moved to a more suitable place. This is
* indicated with the error code -EBUSY.
+ *
+ * The mapping types the importer supports come from
+ * &dma_buf_attach_ops.supported_mapping_types. Importers without it, which
+ * includes every dma_buf_attach() caller, support only the SGT type, with
+ * P2P according to &dma_buf_attach_ops.allow_peer2peer. This records the
+ * attachment's match set, i.e. the intersection of types supported by both
+ * importer and exporter, in &dma_buf_attachment.matches. Later attachments
+ * by other importers never change the set but may affect what type the
+ * exporter selects when the attachment is first mapped or pinned.
*/
struct dma_buf_attachment *
dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
const struct dma_buf_attach_ops *importer_ops,
void *importer_priv)
{
+ struct dma_buf_mapping_match default_match;
+ struct dma_buf_match_args match_args = {
+ .dmabuf = dmabuf,
+ .dev = dev,
+ };
struct dma_buf_attachment *attach;
int ret;
@@ -1043,13 +1066,42 @@ dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
if (!attach)
return ERR_PTR(-ENOMEM);
- attach->dev = dev;
attach->dmabuf = dmabuf;
- if (importer_ops)
- attach->peer2peer = importer_ops->allow_peer2peer;
attach->importer_ops = importer_ops;
attach->importer_priv = importer_priv;
+ /*
+ * The exporter's match_mapping() may look at the importer side of the
+ * attachment, so initialise it before the match.
+ */
+ match_args.attach = attach;
+ if (importer_ops && importer_ops->supported_mapping_types) {
+ if (WARN_ON(!importer_ops->nr_supported_mapping_types)) {
+ ret = -EINVAL;
+ goto err_attach;
+ }
+ match_args.imp_matches = importer_ops->supported_mapping_types;
+ match_args.imp_len = importer_ops->nr_supported_mapping_types;
+ } else {
+ default_match = DMA_BUF_IMAPPING_SGT(
+ importer_ops && importer_ops->allow_peer2peer ?
+ DMA_SGT_IMPORTER_ACCEPTS_P2P :
+ DMA_SGT_NO_P2P);
+ match_args.imp_matches = &default_match;
+ match_args.imp_len = 1;
+ }
+
+ if (dmabuf->ops->match_mapping) {
+ ret = dmabuf->ops->match_mapping(&match_args);
+ if (ret)
+ goto err_attach;
+ } else {
+ ret = dma_buf_match_mapping(&match_args,
+ &dma_buf_sgt_exp_compat_match, 1);
+ if (ret)
+ goto err_attach;
+ }
+
if (dmabuf->ops->attach) {
ret = dmabuf->ops->attach(dmabuf, attach);
if (ret)
diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h
index de73f931a2f8..ecfd9b2d2aac 100644
--- a/include/linux/dma-buf.h
+++ b/include/linux/dma-buf.h
@@ -29,6 +29,7 @@ struct dma_buf;
struct dma_buf_attachment;
struct dma_buf_mapping_type;
struct dma_buf_mapping_exp_ops;
+struct dma_buf_match_args;
/*
@@ -316,6 +317,27 @@ struct dma_buf_ops {
int (*vmap)(struct dma_buf *dmabuf, struct iosys_map *map);
void (*vunmap)(struct dma_buf *dmabuf, struct iosys_map *map);
+
+ /**
+ * @match_mapping:
+ *
+ * Called during attach, without the dma_resv lock held. Allows the
+ * exporter to build its own exporter struct dma_buf_mapping_match[]
+ * and call dma_buf_match_mapping() to record every mutually
+ * acceptable type in &dma_buf_attachment.matches in the exporter's
+ * order of preference.
+ *
+ * The match set is fixed for the lifetime of the attachment, so every
+ * input to the decision must hold for that long: either static for the
+ * dma_buf (the importer's list, PCI P2P topology, buffer creation
+ * flags) or runtime state the exporter pins until @detach, for example
+ * a runtime PM reference.
+ *
+ * It must not depend on the set of attachments or on current buffer
+ * placement as matches are static and buffer placement can change at
+ * any time until the final location is resolved during map/pin.
+ */
+ int (*match_mapping)(struct dma_buf_match_args *args);
};
/**
@@ -499,6 +521,30 @@ struct dma_buf_attach_ops {
* required behavior.
*/
void (*invalidate_mappings)(struct dma_buf_attachment *attach);
+
+ /**
+ * @supported_mapping_types: [optional] mapping types the importer
+ * can use
+ *
+ * Array of @nr_supported_mapping_types DMA_BUF_IMAPPING_*() entries
+ * the importer can use in priority order. Entries are static so can be
+ * shared by all of the importer's attachments. Any required dynamic
+ * information, such as the importing device, is passed to each type's
+ * callbacks by dma_buf_dynamic_attach() for recording in the
+ * negotiated entry.
+ *
+ * If not provided the importer supports only the SGT mapping type,
+ * accepting P2P according to @allow_peer2peer. When provided an SGT
+ * entry's DMA_SGT_IMPORTER_ACCEPTS_P2P flag takes the place of
+ * @allow_peer2peer.
+ */
+ const struct dma_buf_mapping_match *supported_mapping_types;
+
+ /**
+ * @nr_supported_mapping_types: number of entries in
+ * @supported_mapping_types
+ */
+ unsigned int nr_supported_mapping_types;
};
/**
--
2.54.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH v2 05/23] dma-buf: Route SGT related actions through the attachment's mapping type
2026-11-05 6:40 [PATCH v2 00/23] DMA-buf mapping types Alistair Popple
` (3 preceding siblings ...)
2026-11-05 6:40 ` [PATCH v2 04/23] dma-buf: Negotiate the mapping type in dma_buf_dynamic_attach() Alistair Popple
@ 2026-11-05 6:40 ` Alistair Popple
2026-11-05 6:40 ` [PATCH v2 06/23] dma-buf: Let the exporter select mapping type at pin/map Alistair Popple
` (18 subsequent siblings)
23 siblings, 0 replies; 26+ messages in thread
From: Alistair Popple @ 2026-11-05 6:40 UTC (permalink / raw)
To: Christian König, Sumit Semwal, Thomas Hellström,
Simona Vetter, Matthew Brost, Vivek Kasireddy, Dongwon Kim,
Kevin Tian, Xu Yilun, Karl Mehltretter, Baolu Lu, Felix Kuehling,
Alex Deucher, dri-devel, intel-xe, amd-gfx, linux-media,
linaro-mm-sig, linux-rdma, iommu, Keith Busch, Jens Axboe,
Christoph Hellwig, Sagi Grimberg, linux-nvme, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Mina Almasry, netdev, Alexey Kardashevskiy, zhipingz, treding,
jhubbard, Jason Gunthorpe, Leon Romanovsky
Cc: Alistair Popple
From: Jason Gunthorpe <jgg@nvidia.com>
Now that dma_buf_dynamic_attach() ensures a mapping type exists, even for
exporters and importers that don't provide it, route operations through
dma_buf_attach_map_type().
For map/unmap this will go through dma_buf_sgt_compat_map_dma_buf() which
calls the same attach->dmabuf->ops->map_dma_buf().
Move the debugfs processing unique to SGT into a callback too.
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Alistair Popple <apopple@nvidia.com>
---
drivers/dma-buf/dma-buf.c | 24 +++++++++++++++++++-----
1 file changed, 19 insertions(+), 5 deletions(-)
diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index 1913a84d3363..b3d1f0f863a5 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -1240,12 +1240,14 @@ EXPORT_SYMBOL_NS_GPL(dma_buf_unpin, "DMA_BUF");
struct sg_table *dma_buf_map_sgt(struct dma_buf_attachment *attach,
enum dma_data_direction direction)
{
+ const struct dma_buf_mapping_sgt_exp_ops *sgt_exp_ops =
+ dma_buf_get_sgt_ops(attach);
struct sg_table *sg_table;
signed long ret;
might_sleep();
- if (WARN_ON(!attach || !attach->dmabuf))
+ if (WARN_ON(!attach || !attach->dmabuf || !sgt_exp_ops))
return ERR_PTR(-EINVAL);
dma_resv_assert_held(attach->dmabuf->resv);
@@ -1261,7 +1263,7 @@ struct sg_table *dma_buf_map_sgt(struct dma_buf_attachment *attach,
return ERR_PTR(ret);
}
- sg_table = attach->dmabuf->ops->map_dma_buf(attach, direction);
+ sg_table = sgt_exp_ops->map_dma_buf(attach, direction);
if (!sg_table)
sg_table = ERR_PTR(-ENOMEM);
if (IS_ERR(sg_table))
@@ -1300,7 +1302,7 @@ struct sg_table *dma_buf_map_sgt(struct dma_buf_attachment *attach,
return sg_table;
error_unmap:
- attach->dmabuf->ops->unmap_dma_buf(attach, sg_table, direction);
+ sgt_exp_ops->unmap_dma_buf(attach, sg_table, direction);
sg_table = ERR_PTR(ret);
error_unpin:
@@ -1353,15 +1355,21 @@ void dma_buf_unmap_sgt(struct dma_buf_attachment *attach,
struct sg_table *sg_table,
enum dma_data_direction direction)
{
+ const struct dma_buf_mapping_sgt_exp_ops *sgt_exp_ops;
+
might_sleep();
if (WARN_ON(!attach || !attach->dmabuf || !sg_table))
return;
+ sgt_exp_ops = dma_buf_get_sgt_ops(attach);
+ if (WARN_ON(!sgt_exp_ops))
+ return;
+
dma_resv_assert_held(attach->dmabuf->resv);
dma_buf_unwrap_sg_table(&sg_table);
- attach->dmabuf->ops->unmap_dma_buf(attach, sg_table, direction);
+ sgt_exp_ops->unmap_dma_buf(attach, sg_table, direction);
if (dma_buf_pin_on_map(attach))
attach->dmabuf->ops->unpin(attach);
@@ -1842,7 +1850,13 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
attach_count = 0;
list_for_each_entry(attach_obj, &buf_obj->attachments, node) {
- seq_printf(s, "\t%s\n", dev_name(attach_obj->dev));
+ const struct dma_buf_mapping_type *type =
+ dma_buf_attach_map_type(attach_obj)->type;
+
+ seq_printf(s, "\t%s:", type->name);
+ if (type->debugfs_dump)
+ type->debugfs_dump(s, attach_obj);
+ seq_putc(s, '\n');
attach_count++;
}
dma_resv_unlock(buf_obj->resv);
--
2.54.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH v2 06/23] dma-buf: Let the exporter select mapping type at pin/map
2026-11-05 6:40 [PATCH v2 00/23] DMA-buf mapping types Alistair Popple
` (4 preceding siblings ...)
2026-11-05 6:40 ` [PATCH v2 05/23] dma-buf: Route SGT related actions through the attachment's mapping type Alistair Popple
@ 2026-11-05 6:40 ` Alistair Popple
2026-11-05 6:40 ` [PATCH v2 07/23] dma-buf: Add match set queries for exporter placement decisions Alistair Popple
` (17 subsequent siblings)
23 siblings, 0 replies; 26+ messages in thread
From: Alistair Popple @ 2026-11-05 6:40 UTC (permalink / raw)
To: Christian König, Sumit Semwal, Thomas Hellström,
Simona Vetter, Matthew Brost, Vivek Kasireddy, Dongwon Kim,
Kevin Tian, Xu Yilun, Karl Mehltretter, Baolu Lu, Felix Kuehling,
Alex Deucher, dri-devel, intel-xe, amd-gfx, linux-media,
linaro-mm-sig, linux-rdma, iommu, Keith Busch, Jens Axboe,
Christoph Hellwig, Sagi Grimberg, linux-nvme, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Mina Almasry, netdev, Alexey Kardashevskiy, zhipingz, treding,
jhubbard, Jason Gunthorpe, Leon Romanovsky
Cc: Alistair Popple
The match set negotiated at attach determines which types an attachment
could possibly be served with. Which one should actually be served
depends on where the buffer is and other attachments when an importer
first pins or maps. So far the first entry was used unconditionally,
even if it cannot be served to some importers.
Add dma_buf_ops.select_mapping() under dma_resv from both pin and map
paths before the type's map callback to let the exporter choose which to
serve based on the current placement and list of attachments.
The choice is recorded in attach->selected and does not call
select_mapping again across any number of unmaps and remaps, until
dma_buf_invalidate_mappings() has been delivered to the attachment.
This prevents importer remap from bouncing a buffer between placements
- the type cannot change without the exporter explicitly invalidating
first. In other words attachments that are never invalidated keep the
initially selected type for the life of the attachment.
A failed select or map establishes nothing and leaves the choice open.
Importers never select. The importer's list order is a preference the
exporter may weigh or ignore, and an importer must accept any type it
listed.
Signed-off-by: Alistair Popple <apopple@nvidia.com>
---
drivers/dma-buf/dma-buf-mapping.c | 66 +++++++++++++++++++++++-
drivers/dma-buf/dma-buf.c | 106 ++++++++++++++++++++++++++------------
include/linux/dma-buf-mapping.h | 17 ++++--
include/linux/dma-buf.h | 38 ++++++++++++++
4 files changed, 190 insertions(+), 37 deletions(-)
diff --git a/drivers/dma-buf/dma-buf-mapping.c b/drivers/dma-buf/dma-buf-mapping.c
index 4eb0ea930900..ff2dbcca23d9 100644
--- a/drivers/dma-buf/dma-buf-mapping.c
+++ b/drivers/dma-buf/dma-buf-mapping.c
@@ -271,7 +271,8 @@ EXPORT_SYMBOL_NS_GPL(dma_buf_free_sgt, "DMA_BUF");
* importer entry of the same type that the type's match() callback accepts.
* Every such pair is recorded in @args->attach->matches, so the match set
* preserves the exporter's priority. The first entry is the default returned
- * by dma_buf_attach_map_type().
+ * by dma_buf_attach_map_type() until &dma_buf_ops.select_mapping chooses
+ * otherwise at pin or map time.
*
* Because the exporter list is walked in order, the exporter controls the
* priority of mapping types.
@@ -324,6 +325,69 @@ int dma_buf_match_mapping(struct dma_buf_match_args *args,
}
EXPORT_SYMBOL_NS_GPL(dma_buf_match_mapping, "DMA_BUF");
+/**
+ * dma_buf_mapping_select - Let the exporter choose the type to map with
+ * @attach: Attachment about to be pinned or mapped
+ *
+ * Called with the dma_resv lock held by dma_buf_pin() and the map functions.
+ * The first call after attach, and after each dma_buf_invalidate_mappings(),
+ * calls &dma_buf_ops.select_mapping to pick an entry of the match set given
+ * the buffer's placement and the other live mappings. Exporters without the
+ * callback get the first entry. Every other call returns the previous choice
+ * unchanged, so the mapping type cannot change between unmap and remap without
+ * the exporter having explicitly invalidated.
+ *
+ * Returns: 0 on success or the exporter's error, typically -EBUSY when the
+ * attachment cannot be served without disturbing a mapping that cannot be
+ * invalidated.
+ */
+int dma_buf_mapping_select(struct dma_buf_attachment *attach)
+{
+ int idx = 0;
+
+ dma_resv_assert_held(attach->dmabuf->resv);
+
+ if (attach->selected)
+ return 0;
+
+ if (WARN_ON(!attach->nr_matches))
+ return -EINVAL;
+
+ if (attach->dmabuf->ops->select_mapping) {
+ idx = attach->dmabuf->ops->select_mapping(attach);
+ if (idx < 0)
+ return idx;
+ if (WARN_ON(idx >= attach->nr_matches))
+ return -EINVAL;
+ }
+
+ attach->selected_idx = idx;
+ attach->selected = true;
+ return 0;
+}
+
+/**
+ * dma_buf_mapping_unselect - Undo a selection that established nothing
+ * @attach: Attachment whose pin or map just failed
+ * @was_selected: attach->selected before the failed pin or map began
+ *
+ * A pin or map that fails after dma_buf_mapping_select() may reopen the
+ * choice only if it was the one that made it. A selection that predates the
+ * call belongs to a live pin or mapping and must survive, otherwise the next
+ * pin or map would reselect under it without an invalidate.
+ */
+void dma_buf_mapping_unselect(struct dma_buf_attachment *attach,
+ bool was_selected)
+{
+ dma_resv_assert_held(attach->dmabuf->resv);
+
+ if (was_selected)
+ return;
+
+ attach->selected = false;
+ attach->selected_idx = 0;
+}
+
static int dma_buf_sgt_match(struct dma_buf_match_args *args,
const struct dma_buf_mapping_match *exp,
const struct dma_buf_mapping_match *imp)
diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index b3d1f0f863a5..f052184da5ed 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -1182,14 +1182,22 @@ EXPORT_SYMBOL_NS_GPL(dma_buf_detach, "DMA_BUF");
int dma_buf_pin(struct dma_buf_attachment *attach)
{
struct dma_buf *dmabuf = attach->dmabuf;
+ bool selected = attach->selected;
int ret = 0;
WARN_ON(!attach->importer_ops);
dma_resv_assert_held(dmabuf->resv);
- if (dmabuf->ops->pin)
+ ret = dma_buf_mapping_select(attach);
+ if (ret)
+ return ret;
+
+ if (dmabuf->ops->pin) {
ret = dmabuf->ops->pin(attach);
+ if (ret)
+ dma_buf_mapping_unselect(attach, selected);
+ }
return ret;
}
@@ -1216,42 +1224,19 @@ void dma_buf_unpin(struct dma_buf_attachment *attach)
}
EXPORT_SYMBOL_NS_GPL(dma_buf_unpin, "DMA_BUF");
-/**
- * dma_buf_map_sgt - Returns the scatterlist table of the attachment;
- * mapped into _device_ address space. Is a wrapper for map_dma_buf() of the
- * dma_buf_ops.
- * @attach: [in] attachment whose scatterlist is to be returned
- * @direction: [in] direction of DMA transfer
- *
- * Returns sg_table containing the scatterlist to be returned; returns ERR_PTR
- * on error. May return -EINTR if it is interrupted by a signal.
- *
- * On success, the DMA addresses and lengths in the returned scatterlist are
- * PAGE_SIZE aligned.
- *
- * A mapping must be unmapped by using dma_buf_unmap_sgt(). Note that
- * the underlying backing storage is pinned for as long as a mapping exists,
- * therefore users/importers should not hold onto a mapping for undue amounts of
- * time.
- *
- * Important: Dynamic importers must wait for the exclusive fence of the struct
- * dma_resv attached to the DMA-BUF first.
- */
-struct sg_table *dma_buf_map_sgt(struct dma_buf_attachment *attach,
- enum dma_data_direction direction)
+/* The SGT type must have been selected for the attachment already */
+static struct sg_table *
+__dma_buf_map_sgt(struct dma_buf_attachment *attach,
+ enum dma_data_direction direction)
{
const struct dma_buf_mapping_sgt_exp_ops *sgt_exp_ops =
dma_buf_get_sgt_ops(attach);
struct sg_table *sg_table;
signed long ret;
- might_sleep();
-
- if (WARN_ON(!attach || !attach->dmabuf || !sgt_exp_ops))
+ if (WARN_ON(!sgt_exp_ops))
return ERR_PTR(-EINVAL);
- dma_resv_assert_held(attach->dmabuf->resv);
-
if (dma_buf_pin_on_map(attach)) {
ret = attach->dmabuf->ops->pin(attach);
/*
@@ -1311,6 +1296,53 @@ struct sg_table *dma_buf_map_sgt(struct dma_buf_attachment *attach,
return sg_table;
}
+
+/**
+ * dma_buf_map_sgt - Returns the scatterlist table of the attachment;
+ * mapped into _device_ address space. Is a wrapper for map_dma_buf() of the
+ * dma_buf_ops.
+ * @attach: [in] attachment whose scatterlist is to be returned
+ * @direction: [in] direction of DMA transfer
+ *
+ * Returns sg_table containing the scatterlist to be returned; returns ERR_PTR
+ * on error. May return -EINTR if it is interrupted by a signal.
+ *
+ * On success, the DMA addresses and lengths in the returned scatterlist are
+ * PAGE_SIZE aligned.
+ *
+ * A mapping must be unmapped by using dma_buf_unmap_sgt(). Note that
+ * the underlying backing storage is pinned for as long as a mapping exists,
+ * therefore users/importers should not hold onto a mapping for undue amounts of
+ * time.
+ *
+ * Important: Dynamic importers must wait for the exclusive fence of the struct
+ * dma_resv attached to the DMA-BUF first.
+ */
+struct sg_table *dma_buf_map_sgt(struct dma_buf_attachment *attach,
+ enum dma_data_direction direction)
+{
+ struct sg_table *sg_table;
+ bool selected;
+ int ret;
+
+ might_sleep();
+
+ if (WARN_ON(!attach || !attach->dmabuf))
+ return ERR_PTR(-EINVAL);
+
+ dma_resv_assert_held(attach->dmabuf->resv);
+
+ selected = attach->selected;
+ ret = dma_buf_mapping_select(attach);
+ if (ret)
+ return ERR_PTR(ret);
+
+ sg_table = __dma_buf_map_sgt(attach, direction);
+ if (IS_ERR(sg_table))
+ dma_buf_mapping_unselect(attach, selected);
+
+ return sg_table;
+}
EXPORT_SYMBOL_NS_GPL(dma_buf_map_sgt, "DMA_BUF");
/**
@@ -1455,6 +1487,10 @@ EXPORT_SYMBOL_NS_GPL(dma_buf_attach_revocable, "DMA_BUF");
*
* Importers are free to request a new mapping in parallel as this function
* returns.
+ *
+ * This is also the only point at which an attachment's mapping type
+ * may change after a pin/map: the core keeps the type chosen by
+ * &dma_buf_ops.select_mapping until the attachment has been invalidated here.
*/
void dma_buf_invalidate_mappings(struct dma_buf *dmabuf)
{
@@ -1462,10 +1498,14 @@ void dma_buf_invalidate_mappings(struct dma_buf *dmabuf)
dma_resv_assert_held(dmabuf->resv);
- list_for_each_entry(attach, &dmabuf->attachments, node)
- if (attach->importer_ops &&
- attach->importer_ops->invalidate_mappings)
- attach->importer_ops->invalidate_mappings(attach);
+ list_for_each_entry(attach, &dmabuf->attachments, node) {
+ if (!attach->importer_ops ||
+ !attach->importer_ops->invalidate_mappings)
+ continue;
+
+ attach->selected = false;
+ attach->importer_ops->invalidate_mappings(attach);
+ }
}
EXPORT_SYMBOL_NS_GPL(dma_buf_invalidate_mappings, "DMA_BUF");
diff --git a/include/linux/dma-buf-mapping.h b/include/linux/dma-buf-mapping.h
index 69073d589e54..0ee798a5acdd 100644
--- a/include/linux/dma-buf-mapping.h
+++ b/include/linux/dma-buf-mapping.h
@@ -118,15 +118,26 @@ int dma_buf_match_mapping(struct dma_buf_match_args *args,
* dma_buf_attach_map_type - The match this attachment is mapped with
* @attach: the attachment
*
- * Returns the entry of @attach->matches in force for the attachment: the
- * exporter's default, which is the first entry.
+ * Returns the entry of @attach->matches the attachment is mapped with: the
+ * one the exporter selected at the last pin or map, or the exporter's
+ * default, the first entry, before anything was selected. After
+ * dma_buf_invalidate_mappings() it still names the type a live mapping was
+ * made with, so a pending unmap can use it, until the next selection.
*/
static inline const struct dma_buf_mapping_match *
dma_buf_attach_map_type(const struct dma_buf_attachment *attach)
{
- return &attach->matches[0];
+ return &attach->matches[attach->selected_idx];
}
+/*
+ * Internal: Selection is made by exporters through &dma_buf_ops.select_mapping
+ * in dma_buf_pin() or map paths. Importers never call this.
+ */
+int dma_buf_mapping_select(struct dma_buf_attachment *attach);
+void dma_buf_mapping_unselect(struct dma_buf_attachment *attach,
+ bool was_selected);
+
/*
* DMA Mapped Scatterlist Type
*
diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h
index ecfd9b2d2aac..33582713a104 100644
--- a/include/linux/dma-buf.h
+++ b/include/linux/dma-buf.h
@@ -338,6 +338,32 @@ struct dma_buf_ops {
* any time until the final location is resolved during map/pin.
*/
int (*match_mapping)(struct dma_buf_match_args *args);
+
+ /**
+ * @select_mapping:
+ *
+ * Called with the dma_resv lock held from dma_buf_pin() and from the
+ * map functions, before the type's map callback, to choose which
+ * entry of &dma_buf_attachment.matches this attachment is mapped
+ * with. The exporter settles the buffer's placement here, taking all
+ * live mappings and pinned attachments into account, and returns the
+ * entry that placement can serve.
+ *
+ * The core records the choice and does not ask again until the exporter
+ * has delivered &dma_buf_attach_ops.invalidate_mappings to this
+ * attachment. The exporter must therefore keep the recorded type
+ * servable: moving the buffer somewhere the selected type cannot be
+ * produced from requires invalidating first. Attachments that cannot
+ * be invalidated keep their first choice for life.
+ *
+ * Optional. Without it the first entry of the match set, the
+ * exporter's most preferred, is used.
+ *
+ * Returns: the index into &dma_buf_attachment.matches to use, or a
+ * negative errno. -EBUSY means the attachment cannot be served without
+ * disturbing a mapping that cannot be invalidated.
+ */
+ int (*select_mapping)(struct dma_buf_attachment *attach);
};
/**
@@ -562,6 +588,16 @@ struct dma_buf_attach_ops {
* entry is the exporter's default; dma_buf_attach_map_type()
* returns the entry the attachment is mapped with.
* @nr_matches: Number of valid entries in @matches.
+ * @selected_idx: Index into @matches of the entry the attachment is mapped
+ * with, chosen by &dma_buf_ops.select_mapping at the first pin
+ * or map and kept, enforced by the core, until
+ * &dma_buf_attach_ops.invalidate_mappings is delivered to this
+ * attachment. Zero, the exporter's default, before the first
+ * selection. Still valid after an invalidate so that a pending
+ * unmap sees the type its mapping was made with.
+ * @selected: True while @selected_idx is in force, i.e. the next pin or map
+ * must not select again; cleared only by
+ * dma_buf_invalidate_mappings().
*
* This structure holds the attachment information between the dma_buf buffer
* and its user device(s). The list contains one attachment struct per device
@@ -582,6 +618,8 @@ struct dma_buf_attachment {
void *priv;
struct dma_buf_mapping_match matches[DMA_BUF_MAX_MATCHES];
unsigned int nr_matches;
+ unsigned int selected_idx;
+ bool selected;
};
/**
--
2.54.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH v2 07/23] dma-buf: Add match set queries for exporter placement decisions
2026-11-05 6:40 [PATCH v2 00/23] DMA-buf mapping types Alistair Popple
` (5 preceding siblings ...)
2026-11-05 6:40 ` [PATCH v2 06/23] dma-buf: Let the exporter select mapping type at pin/map Alistair Popple
@ 2026-11-05 6:40 ` Alistair Popple
2026-11-05 6:40 ` [PATCH v2 08/23] dma-buf: Add dma_buf_mapping_map() returning a type-tagged mapping Alistair Popple
` (16 subsequent siblings)
23 siblings, 0 replies; 26+ messages in thread
From: Alistair Popple @ 2026-11-05 6:40 UTC (permalink / raw)
To: Christian König, Sumit Semwal, Thomas Hellström,
Simona Vetter, Matthew Brost, Vivek Kasireddy, Dongwon Kim,
Kevin Tian, Xu Yilun, Karl Mehltretter, Baolu Lu, Felix Kuehling,
Alex Deucher, dri-devel, intel-xe, amd-gfx, linux-media,
linaro-mm-sig, linux-rdma, iommu, Keith Busch, Jens Axboe,
Christoph Hellwig, Sagi Grimberg, linux-nvme, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Mina Almasry, netdev, Alexey Kardashevskiy, zhipingz, treding,
jhubbard, Jason Gunthorpe, Leon Romanovsky
Cc: Alistair Popple
Exporters deciding placement in their pin path walk every attachment
to determine whether it can take P2P. With selection deferred to pin or
map an unmapped attachment only holds the exporter's default. Therefore
determining what is possible requires walking attachments.
Add dma_buf_attach_accepts() and dma_buf_attach_accepts_sgt_p2p() to
walk the match set and determine if an attachment is possible with P2P.
A future series will convert P2P into a distinct match type.
Signed-off-by: Alistair Popple <apopple@nvidia.com>
---
include/linux/dma-buf-mapping.h | 46 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 46 insertions(+)
diff --git a/include/linux/dma-buf-mapping.h b/include/linux/dma-buf-mapping.h
index 0ee798a5acdd..7140fc13dd00 100644
--- a/include/linux/dma-buf-mapping.h
+++ b/include/linux/dma-buf-mapping.h
@@ -138,6 +138,26 @@ int dma_buf_mapping_select(struct dma_buf_attachment *attach);
void dma_buf_mapping_unselect(struct dma_buf_attachment *attach,
bool was_selected);
+/**
+ * dma_buf_attach_accepts - Is @type in the attachment's match set
+ * @attach: the attachment
+ * @type: a mapping type
+ *
+ * Called by exporters deciding placement in pin or select_mapping to determine
+ * whether the importer could be served with @type.
+ */
+static inline bool
+dma_buf_attach_accepts(const struct dma_buf_attachment *attach,
+ const struct dma_buf_mapping_type *type)
+{
+ unsigned int i;
+
+ for (i = 0; i < attach->nr_matches; i++)
+ if (attach->matches[i].type == type)
+ return true;
+ return false;
+}
+
/*
* DMA Mapped Scatterlist Type
*
@@ -185,6 +205,10 @@ dma_buf_sgt_dma_device(struct dma_buf_attachment *attach)
*
* Should be called by exporters, returns true if the exporter's
* DMA_SGT_EXPORTER_REQUIRES_P2P_DISTANCE was matched.
+ *
+ * Reflects the current selection, so is only meaningful inside the
+ * exporter's pin and map callbacks. For attachments which may be unmapped use
+ * dma_buf_attach_accepts_sgt_p2p().
*/
static inline bool dma_buf_sgt_p2p_allowed(struct dma_buf_attachment *attach)
{
@@ -194,6 +218,28 @@ static inline bool dma_buf_sgt_p2p_allowed(struct dma_buf_attachment *attach)
DMA_SGT_EXPORTER_REQUIRES_P2P_DISTANCE;
}
+/**
+ * dma_buf_attach_accepts_sgt_p2p - Could this attachment take a P2P SGT?
+ * @attach: any attachment
+ *
+ * Like dma_buf_sgt_p2p_allowed() but valid for attachments that are not mapped.
+ * Instead determines if p2p is part of the current possible match set rather
+ * than the current selection. Called by exporters walking all attachments in
+ * their pin path.
+ */
+static inline bool
+dma_buf_attach_accepts_sgt_p2p(const struct dma_buf_attachment *attach)
+{
+ unsigned int i;
+
+ for (i = 0; i < attach->nr_matches; i++)
+ if (attach->matches[i].type == &dma_buf_mapping_sgt_type &&
+ attach->matches[i].sgt_data.exporter_requires_p2p ==
+ DMA_SGT_EXPORTER_REQUIRES_P2P_DISTANCE)
+ return true;
+ return false;
+}
+
static inline const struct dma_buf_mapping_sgt_exp_ops *
dma_buf_get_sgt_ops(struct dma_buf_attachment *attach)
{
--
2.54.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH v2 08/23] dma-buf: Add dma_buf_mapping_map() returning a type-tagged mapping
2026-11-05 6:40 [PATCH v2 00/23] DMA-buf mapping types Alistair Popple
` (6 preceding siblings ...)
2026-11-05 6:40 ` [PATCH v2 07/23] dma-buf: Add match set queries for exporter placement decisions Alistair Popple
@ 2026-11-05 6:40 ` Alistair Popple
2026-11-05 6:40 ` [PATCH v2 09/23] dma-buf: Allow single exporter drivers to avoid the match_mapping function Alistair Popple
` (15 subsequent siblings)
23 siblings, 0 replies; 26+ messages in thread
From: Alistair Popple @ 2026-11-05 6:40 UTC (permalink / raw)
To: Christian König, Sumit Semwal, Thomas Hellström,
Simona Vetter, Matthew Brost, Vivek Kasireddy, Dongwon Kim,
Kevin Tian, Xu Yilun, Karl Mehltretter, Baolu Lu, Felix Kuehling,
Alex Deucher, dri-devel, intel-xe, amd-gfx, linux-media,
linaro-mm-sig, linux-rdma, iommu, Keith Busch, Jens Axboe,
Christoph Hellwig, Sagi Grimberg, linux-nvme, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Mina Almasry, netdev, Alexey Kardashevskiy, zhipingz, treding,
jhubbard, Jason Gunthorpe, Leon Romanovsky
Cc: Alistair Popple
An importer that lists more than one mapping type cannot know which
type-specific map function to call, because the exporter selects the
type at map time. Create a generic entry point to determine the correct
type.
dma_buf_mapping_map() selects via dma_buf_mapping_select() and dispatches
to a map op on struct dma_buf_mapping_type. That returns a struct
dma_buf_mapping carrying the type, embedded in the type's own
result struct. dma_buf_mapping_unmap() hands it back through the type's
unmap op.
To support existing SGT importers the SGT type implements both. Its
result is struct dma_buf_sgt_mapping with the sg_table reachable through
dma_buf_sgt_mapping_table(). The sgt map body is shared with the SGT
type's map function which remains the entry point for importers listing
only SGT.
Signed-off-by: Alistair Popple <apopple@nvidia.com>
---
drivers/dma-buf/dma-buf-mapping.c | 78 +++++++++++++++++++++++++++++++++++++++
drivers/dma-buf/dma-buf.c | 33 +++++++++++++++++
include/linux/dma-buf-mapping.h | 63 +++++++++++++++++++++++++++++++
3 files changed, 174 insertions(+)
diff --git a/drivers/dma-buf/dma-buf-mapping.c b/drivers/dma-buf/dma-buf-mapping.c
index ff2dbcca23d9..264c9293438f 100644
--- a/drivers/dma-buf/dma-buf-mapping.c
+++ b/drivers/dma-buf/dma-buf-mapping.c
@@ -388,6 +388,82 @@ void dma_buf_mapping_unselect(struct dma_buf_attachment *attach,
attach->selected_idx = 0;
}
+/**
+ * dma_buf_mapping_map - Map an attachment with whichever type the exporter
+ * selects
+ * @attach: the attachment
+ * @dir: DMA direction
+ *
+ * For importers that listed more than one mapping type. The exporter picks the
+ * type from the possible matches and the result's &dma_buf_mapping.type records
+ * which was used. Must be called with the dma_resv lock held, and the lock must
+ * be held until the result has been acted on. Importers that listed a single
+ * type keep using that type's map function.
+ *
+ * Returns: a &struct dma_buf_mapping to pass to dma_buf_mapping_unmap(), or
+ * an ERR_PTR.
+ */
+struct dma_buf_mapping *dma_buf_mapping_map(struct dma_buf_attachment *attach,
+ enum dma_data_direction dir)
+{
+ const struct dma_buf_mapping_type *type;
+ struct dma_buf_mapping *mapping;
+ bool selected;
+ int ret;
+
+ might_sleep();
+
+ if (WARN_ON(!attach || !attach->dmabuf))
+ return ERR_PTR(-EINVAL);
+
+ dma_resv_assert_held(attach->dmabuf->resv);
+
+ selected = attach->selected;
+ ret = dma_buf_mapping_select(attach);
+ if (ret)
+ return ERR_PTR(ret);
+
+ type = dma_buf_attach_map_type(attach)->type;
+ if (!type->map) {
+ ret = -EOPNOTSUPP;
+ goto err_release;
+ }
+
+ mapping = type->map(attach, dir);
+ if (IS_ERR(mapping)) {
+ ret = PTR_ERR(mapping);
+ goto err_release;
+ }
+
+ return mapping;
+
+err_release:
+ dma_buf_mapping_unselect(attach, selected);
+ return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_NS_GPL(dma_buf_mapping_map, "DMA_BUF");
+
+/**
+ * dma_buf_mapping_unmap - Release a mapping from dma_buf_mapping_map()
+ * @attach: the attachment
+ * @mapping: what dma_buf_mapping_map() returned
+ * @dir: DMA direction used for the map
+ */
+void dma_buf_mapping_unmap(struct dma_buf_attachment *attach,
+ struct dma_buf_mapping *mapping,
+ enum dma_data_direction dir)
+{
+ might_sleep();
+
+ if (WARN_ON(!attach || !attach->dmabuf || !mapping))
+ return;
+
+ dma_resv_assert_held(attach->dmabuf->resv);
+
+ mapping->type->unmap(attach, mapping, dir);
+}
+EXPORT_SYMBOL_NS_GPL(dma_buf_mapping_unmap, "DMA_BUF");
+
static int dma_buf_sgt_match(struct dma_buf_match_args *args,
const struct dma_buf_mapping_match *exp,
const struct dma_buf_mapping_match *imp)
@@ -458,6 +534,8 @@ struct dma_buf_mapping_type dma_buf_mapping_sgt_type = {
.match = dma_buf_sgt_match,
.finish_match = dma_buf_sgt_finish_match,
.debugfs_dump = dma_buf_sgt_debugfs_dump,
+ .map = dma_buf_sgt_type_map,
+ .unmap = dma_buf_sgt_type_unmap,
};
EXPORT_SYMBOL_NS_GPL(dma_buf_mapping_sgt_type, "DMA_BUF");
diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index f052184da5ed..fc1e62a0b388 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -1345,6 +1345,39 @@ struct sg_table *dma_buf_map_sgt(struct dma_buf_attachment *attach,
}
EXPORT_SYMBOL_NS_GPL(dma_buf_map_sgt, "DMA_BUF");
+/* &dma_buf_mapping_type.map / .unmap for the SGT type */
+struct dma_buf_mapping *dma_buf_sgt_type_map(struct dma_buf_attachment *attach,
+ enum dma_data_direction dir)
+{
+ struct dma_buf_sgt_mapping *mapping;
+ int ret;
+
+ mapping = kzalloc_obj(*mapping);
+ if (!mapping)
+ return ERR_PTR(-ENOMEM);
+
+ mapping->base.type = &dma_buf_mapping_sgt_type;
+ mapping->sgt = __dma_buf_map_sgt(attach, dir);
+ if (IS_ERR(mapping->sgt)) {
+ ret = PTR_ERR(mapping->sgt);
+ kfree(mapping);
+ return ERR_PTR(ret);
+ }
+
+ return &mapping->base;
+}
+
+void dma_buf_sgt_type_unmap(struct dma_buf_attachment *attach,
+ struct dma_buf_mapping *base,
+ enum dma_data_direction dir)
+{
+ struct dma_buf_sgt_mapping *mapping =
+ container_of(base, struct dma_buf_sgt_mapping, base);
+
+ dma_buf_unmap_sgt(attach, mapping->sgt, dir);
+ kfree(mapping);
+}
+
/**
* dma_buf_map_sgt_unlocked - Returns the scatterlist table of the attachment;
* mapped into _device_ address space. Is a wrapper for map_dma_buf() of the
diff --git a/include/linux/dma-buf-mapping.h b/include/linux/dma-buf-mapping.h
index 7140fc13dd00..a961314dbd99 100644
--- a/include/linux/dma-buf-mapping.h
+++ b/include/linux/dma-buf-mapping.h
@@ -33,6 +33,16 @@ enum dma_sgt_requires_p2p {
/* Type tag for all mapping operations */
struct dma_buf_mapping_exp_ops {};
+/**
+ * struct dma_buf_mapping - header of a mapping made with dma_buf_mapping_map()
+ * @type: The mapping type the exporter selected. Importers that listed more
+ * than one type switch on this and use the type's accessor to get at
+ * the type-specific result embedding this header.
+ */
+struct dma_buf_mapping {
+ const struct dma_buf_mapping_type *type;
+};
+
/*
* Internal struct to pass arguments from the attach function to the matching
* function
@@ -100,8 +110,35 @@ struct dma_buf_mapping_type {
*/
void (*debugfs_dump)(struct seq_file *s,
struct dma_buf_attachment *attach);
+
+ /**
+ * @map:
+ *
+ * Produce a mapping of this type for @attach, for which this type has
+ * already been selected. Called by dma_buf_mapping_map()
+ * with the dma_resv lock held. Responsible for pin-on-map of static
+ * importers if the type supports them. Optional; a type without it
+ * can only be used through its own map functions.
+ */
+ struct dma_buf_mapping *(*map)(struct dma_buf_attachment *attach,
+ enum dma_data_direction dir);
+
+ /**
+ * @unmap:
+ *
+ * Release a mapping returned by @map.
+ */
+ void (*unmap)(struct dma_buf_attachment *attach,
+ struct dma_buf_mapping *mapping,
+ enum dma_data_direction dir);
};
+struct dma_buf_mapping *dma_buf_mapping_map(struct dma_buf_attachment *attach,
+ enum dma_data_direction dir);
+void dma_buf_mapping_unmap(struct dma_buf_attachment *attach,
+ struct dma_buf_mapping *mapping,
+ enum dma_data_direction dir);
+
struct sg_table *dma_buf_phys_vec_to_sgt(struct dma_buf_attachment *attach,
struct p2pdma_provider *provider,
struct phys_vec *phys_vec,
@@ -158,6 +195,13 @@ dma_buf_attach_accepts(const struct dma_buf_attachment *attach,
return false;
}
+/* Internal: &dma_buf_mapping_sgt_type.map / .unmap, implemented in dma-buf.c */
+struct dma_buf_mapping *dma_buf_sgt_type_map(struct dma_buf_attachment *attach,
+ enum dma_data_direction dir);
+void dma_buf_sgt_type_unmap(struct dma_buf_attachment *attach,
+ struct dma_buf_mapping *mapping,
+ enum dma_data_direction dir);
+
/*
* DMA Mapped Scatterlist Type
*
@@ -175,6 +219,25 @@ dma_buf_attach_accepts(const struct dma_buf_attachment *attach,
*/
extern struct dma_buf_mapping_type dma_buf_mapping_sgt_type;
+/**
+ * struct dma_buf_sgt_mapping - dma_buf_mapping_map() result for the SGT type
+ * @base: common header, @base.type == &dma_buf_mapping_sgt_type
+ * @sgt: the DMA mapped scatterlist, as the SGT type's own map function
+ * returns it
+ */
+struct dma_buf_sgt_mapping {
+ struct dma_buf_mapping base;
+ struct sg_table *sgt;
+};
+
+static inline struct sg_table *
+dma_buf_sgt_mapping_table(struct dma_buf_mapping *mapping)
+{
+ if (WARN_ON(mapping->type != &dma_buf_mapping_sgt_type))
+ return NULL;
+ return container_of(mapping, struct dma_buf_sgt_mapping, base)->sgt;
+}
+
struct dma_buf_mapping_sgt_exp_ops {
struct dma_buf_mapping_exp_ops ops;
struct sg_table *(*map_dma_buf)(struct dma_buf_attachment *attach,
--
2.54.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH v2 09/23] dma-buf: Allow single exporter drivers to avoid the match_mapping function
2026-11-05 6:40 [PATCH v2 00/23] DMA-buf mapping types Alistair Popple
` (7 preceding siblings ...)
2026-11-05 6:40 ` [PATCH v2 08/23] dma-buf: Add dma_buf_mapping_map() returning a type-tagged mapping Alistair Popple
@ 2026-11-05 6:40 ` Alistair Popple
2026-11-05 6:40 ` [PATCH v2 10/23] drm: Check the SGT ops for drm_gem_map_dma_buf() Alistair Popple
` (14 subsequent siblings)
23 siblings, 0 replies; 26+ messages in thread
From: Alistair Popple @ 2026-11-05 6:40 UTC (permalink / raw)
To: Christian König, Sumit Semwal, Thomas Hellström,
Simona Vetter, Matthew Brost, Vivek Kasireddy, Dongwon Kim,
Kevin Tian, Xu Yilun, Karl Mehltretter, Baolu Lu, Felix Kuehling,
Alex Deucher, dri-devel, intel-xe, amd-gfx, linux-media,
linaro-mm-sig, linux-rdma, iommu, Keith Busch, Jens Axboe,
Christoph Hellwig, Sagi Grimberg, linux-nvme, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Mina Almasry, netdev, Alexey Kardashevskiy, zhipingz, treding,
jhubbard, Jason Gunthorpe, Leon Romanovsky
Cc: Alistair Popple
From: Jason Gunthorpe <jgg@nvidia.com>
Introduce single_exporter_match into the dma_buf_ops so that single
exporter drivers can simply set it using a static initializer to use the
mapping type APIs. Provide a helper macro DMA_BUF_SIMPLE_SGT_EXP_MATCH()
that generates the initializer for simple drivers that don't use P2P.
More complex exporters, especially those with P2P, need to implement the
match_mapping call back to extract things like their DMA struct device
from the dma_buf in order to do the P2P calculations.
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Alistair Popple <apopple@nvidia.com>
---
drivers/dma-buf/dma-buf.c | 14 +++++++++++---
include/linux/dma-buf-mapping.h | 15 +++++++++++++++
include/linux/dma-buf.h | 9 +++++++++
3 files changed, 35 insertions(+), 3 deletions(-)
diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index fc1e62a0b388..70cfab4d9c49 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -718,10 +718,14 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
|| !exp_info->ops->release))
return ERR_PTR(-EINVAL);
- if (exp_info->ops->match_mapping) {
+ if (exp_info->ops->match_mapping ||
+ exp_info->ops->single_exporter_match) {
if (WARN_ON(exp_info->ops->map_dma_buf ||
exp_info->ops->unmap_dma_buf))
return ERR_PTR(-EINVAL);
+ if (WARN_ON(exp_info->ops->match_mapping &&
+ exp_info->ops->single_exporter_match))
+ return ERR_PTR(-EINVAL);
} else {
if (WARN_ON(!exp_info->ops->map_dma_buf ||
!exp_info->ops->unmap_dma_buf))
@@ -1096,8 +1100,12 @@ dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
if (ret)
goto err_attach;
} else {
- ret = dma_buf_match_mapping(&match_args,
- &dma_buf_sgt_exp_compat_match, 1);
+ const struct dma_buf_mapping_match *exp_match =
+ dmabuf->ops->single_exporter_match;
+
+ if (!exp_match)
+ exp_match = &dma_buf_sgt_exp_compat_match;
+ ret = dma_buf_match_mapping(&match_args, exp_match, 1);
if (ret)
goto err_attach;
}
diff --git a/include/linux/dma-buf-mapping.h b/include/linux/dma-buf-mapping.h
index a961314dbd99..b02eb6759d38 100644
--- a/include/linux/dma-buf-mapping.h
+++ b/include/linux/dma-buf-mapping.h
@@ -356,4 +356,19 @@ DMA_BUF_EMAPPING_SGT_REQUIRES_P2P(const struct dma_buf_mapping_sgt_exp_ops *exp_
extern const struct dma_buf_mapping_match dma_buf_sgt_exp_compat_match;
+/*
+ * dma_buf_ops initializer helper for simple drivers that use a single
+ * SGT map/unmap operation without P2P.
+ */
+#define DMA_BUF_SIMPLE_SGT_EXP_MATCH(_map, _unmap) \
+ .single_exporter_match = &((const struct dma_buf_mapping_match){ \
+ .type = &dma_buf_mapping_sgt_type, \
+ .exp_ops = &((const struct dma_buf_mapping_sgt_exp_ops){ \
+ .map_dma_buf = _map, \
+ .unmap_dma_buf = _unmap, \
+ }.ops), \
+ .sgt_data = { \
+ .exporter_requires_p2p = DMA_SGT_NO_P2P, \
+ } })
+
#endif
diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h
index 33582713a104..fc341b1257c3 100644
--- a/include/linux/dma-buf.h
+++ b/include/linux/dma-buf.h
@@ -364,6 +364,15 @@ struct dma_buf_ops {
* disturbing a mapping that cannot be invalidated.
*/
int (*select_mapping)(struct dma_buf_attachment *attach);
+
+ /**
+ * @single_exporter_match:
+ *
+ * Should only be set by the DMA_BUF_SIMPLE_*_EXP_MATCH() helper macros.
+ * Exactly one of @match_mapping or @single_exporter_match must be
+ * provided.
+ */
+ const struct dma_buf_mapping_match *single_exporter_match;
};
/**
--
2.54.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH v2 10/23] drm: Check the SGT ops for drm_gem_map_dma_buf()
2026-11-05 6:40 [PATCH v2 00/23] DMA-buf mapping types Alistair Popple
` (8 preceding siblings ...)
2026-11-05 6:40 ` [PATCH v2 09/23] dma-buf: Allow single exporter drivers to avoid the match_mapping function Alistair Popple
@ 2026-11-05 6:40 ` Alistair Popple
2026-11-05 6:40 ` [PATCH v2 11/23] dma-buf: Convert all the simple exporters to use SGT mapping type Alistair Popple
` (13 subsequent siblings)
23 siblings, 0 replies; 26+ messages in thread
From: Alistair Popple @ 2026-11-05 6:40 UTC (permalink / raw)
To: Christian König, Sumit Semwal, Thomas Hellström,
Simona Vetter, Matthew Brost, Vivek Kasireddy, Dongwon Kim,
Kevin Tian, Xu Yilun, Karl Mehltretter, Baolu Lu, Felix Kuehling,
Alex Deucher, dri-devel, intel-xe, amd-gfx, linux-media,
linaro-mm-sig, linux-rdma, iommu, Keith Busch, Jens Axboe,
Christoph Hellwig, Sagi Grimberg, linux-nvme, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Mina Almasry, netdev, Alexey Kardashevskiy, zhipingz, treding,
jhubbard, Jason Gunthorpe, Leon Romanovsky
Cc: Alistair Popple
From: Jason Gunthorpe <jgg@nvidia.com>
When the next patch converts exporters to use SGT natively, the
dma_buf->ops->map_dma_buf will become NULL. Additionally check
sgt_exp_ops to see the new location.
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Alistair Popple <apopple@nvidia.com>
---
drivers/gpu/drm/drm_prime.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
index e27bda3423ed..c5184ca602bc 100644
--- a/drivers/gpu/drm/drm_prime.c
+++ b/drivers/gpu/drm/drm_prime.c
@@ -28,6 +28,7 @@
#include <linux/export.h>
#include <linux/dma-buf.h>
+#include <linux/dma-buf-mapping.h>
#include <linux/rbtree.h>
#include <linux/module.h>
@@ -587,6 +588,18 @@ int drm_prime_handle_to_fd_ioctl(struct drm_device *dev, void *data,
* option for sharing lots of buffers for rendering.
*/
+static bool is_gem_map_dma_buf(struct dma_buf_attachment *attach)
+{
+ const struct dma_buf_mapping_sgt_exp_ops *sgt_exp_ops =
+ dma_buf_get_sgt_ops(attach);
+
+ if (attach->dmabuf->ops->map_dma_buf == drm_gem_map_dma_buf)
+ return true;
+ if (sgt_exp_ops && sgt_exp_ops->map_dma_buf == drm_gem_map_dma_buf)
+ return true;
+ return false;
+}
+
/**
* drm_gem_map_attach - dma_buf attach implementation for GEM
* @dma_buf: buffer to attach device to
@@ -608,7 +621,7 @@ int drm_gem_map_attach(struct dma_buf *dma_buf,
* drm_gem_map_dma_buf() requires obj->get_sg_table(), but drivers
* that implement their own ->map_dma_buf() do not.
*/
- if (dma_buf->ops->map_dma_buf == drm_gem_map_dma_buf &&
+ if (is_gem_map_dma_buf(attach) &&
!obj->funcs->get_sg_table)
return -ENOSYS;
--
2.54.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH v2 11/23] dma-buf: Convert all the simple exporters to use SGT mapping type
2026-11-05 6:40 [PATCH v2 00/23] DMA-buf mapping types Alistair Popple
` (9 preceding siblings ...)
2026-11-05 6:40 ` [PATCH v2 10/23] drm: Check the SGT ops for drm_gem_map_dma_buf() Alistair Popple
@ 2026-11-05 6:40 ` Alistair Popple
2026-11-05 6:40 ` [PATCH v2 12/23] drm/vmwgfx: Use match_mapping instead of dummy calls Alistair Popple
` (12 subsequent siblings)
23 siblings, 0 replies; 26+ messages in thread
From: Alistair Popple @ 2026-11-05 6:40 UTC (permalink / raw)
To: Christian König, Sumit Semwal, Thomas Hellström,
Simona Vetter, Matthew Brost, Vivek Kasireddy, Dongwon Kim,
Kevin Tian, Xu Yilun, Karl Mehltretter, Baolu Lu, Felix Kuehling,
Alex Deucher, dri-devel, intel-xe, amd-gfx, linux-media,
linaro-mm-sig, linux-rdma, iommu, Keith Busch, Jens Axboe,
Christoph Hellwig, Sagi Grimberg, linux-nvme, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Mina Almasry, netdev, Alexey Kardashevskiy, zhipingz, treding,
jhubbard, Jason Gunthorpe, Leon Romanovsky
Cc: Alistair Popple
From: Jason Gunthorpe <jgg@nvidia.com>
Update the exporters to use a SGT mapping type and the new style mapping
type API. None of these exporters do anything with attach->peer2peer or
importer_ops->allow_peer2peer and they all follow the same pattern.
Change all the places that need to get the SGT's DMA device for DMA API
use to use dma_buf_sgt_dma_device().
This is all a mechanical change of moving the map_dma_buf/unmap_dma_buf
into DMA_BUF_SIMPLE_SGT_EXP_MATCH() arguments and switching
attach->dev to dma_buf_sgt_dma_device(attach).
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Alistair Popple <apopple@nvidia.com>
---
drivers/accel/amdxdna/amdxdna_cbuf.c | 8 ++++----
drivers/accel/amdxdna/amdxdna_gem.c | 5 +++--
drivers/accel/amdxdna/amdxdna_ubuf.c | 8 ++++----
drivers/accel/ivpu/ivpu_gem_userptr.c | 11 +++++++----
drivers/dma-buf/heaps/cma_heap.c | 12 +++++++-----
drivers/dma-buf/heaps/system_heap.c | 13 ++++++++-----
drivers/dma-buf/udmabuf.c | 8 ++++----
drivers/gpu/drm/armada/armada_gem.c | 12 +++++++-----
drivers/gpu/drm/drm_prime.c | 9 +++++----
drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c | 8 +++++---
drivers/gpu/drm/i915/gem/selftests/mock_dmabuf.c | 8 ++++----
drivers/gpu/drm/msm/msm_gem_prime.c | 7 +++++--
drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c | 5 +++--
drivers/gpu/drm/panfrost/panfrost_gem.c | 13 +++++++++----
drivers/gpu/drm/panthor/panthor_gem.c | 11 +++++++----
drivers/gpu/drm/tegra/gem.c | 12 +++++++-----
drivers/gpu/drm/virtio/virtgpu_prime.c | 11 +++++++----
drivers/iommu/iommufd/selftest.c | 18 +++---------------
drivers/media/common/videobuf2/videobuf2-dma-contig.c | 15 ++++++++-------
drivers/media/common/videobuf2/videobuf2-dma-sg.c | 14 +++++++++-----
drivers/media/common/videobuf2/videobuf2-vmalloc.c | 13 ++++++++-----
drivers/misc/fastrpc.c | 12 +++++++-----
drivers/tee/tee_heap.c | 13 +++++++------
drivers/xen/gntdev-dmabuf.c | 19 +++++++++++--------
samples/vfio-mdev/mbochs.c | 10 +++++-----
sound/soc/fsl/fsl_asrc_m2m.c | 12 +++++++-----
26 files changed, 161 insertions(+), 126 deletions(-)
diff --git a/drivers/accel/amdxdna/amdxdna_cbuf.c b/drivers/accel/amdxdna/amdxdna_cbuf.c
index a504560aae98..2070a371903d 100644
--- a/drivers/accel/amdxdna/amdxdna_cbuf.c
+++ b/drivers/accel/amdxdna/amdxdna_cbuf.c
@@ -5,6 +5,7 @@
#include <drm/drm_mm.h>
#include <drm/drm_prime.h>
+#include <linux/dma-buf-mapping.h>
#include "amdxdna_cbuf.h"
#include "amdxdna_pci_drv.h"
@@ -85,7 +86,7 @@ static struct sg_table *amdxdna_cbuf_map(struct dma_buf_attachment *attach,
enum dma_data_direction direction)
{
struct amdxdna_cbuf_priv *cbuf = attach->dmabuf->priv;
- struct device *dev = attach->dev;
+ struct device *dev = dma_buf_sgt_dma_device(attach);
struct scatterlist *sgl, *sg;
int ret, n_entries, i;
struct sg_table *sgt;
@@ -140,7 +141,7 @@ static void amdxdna_cbuf_unmap(struct dma_buf_attachment *attach,
struct sg_table *sgt,
enum dma_data_direction direction)
{
- dma_unmap_resource(attach->dev, sg_dma_address(sgt->sgl),
+ dma_unmap_resource(dma_buf_sgt_dma_device(attach), sg_dma_address(sgt->sgl),
drm_prime_get_contiguous_size(sgt), direction,
DMA_ATTR_SKIP_CPU_SYNC);
sg_free_table(sgt);
@@ -210,12 +211,11 @@ static void amdxdna_cbuf_vunmap(struct dma_buf *dbuf, struct iosys_map *map)
}
static const struct dma_buf_ops amdxdna_cbuf_dmabuf_ops = {
- .map_dma_buf = amdxdna_cbuf_map,
- .unmap_dma_buf = amdxdna_cbuf_unmap,
.release = amdxdna_cbuf_release,
.mmap = amdxdna_cbuf_mmap,
.vmap = amdxdna_cbuf_vmap,
.vunmap = amdxdna_cbuf_vunmap,
+ DMA_BUF_SIMPLE_SGT_EXP_MATCH(amdxdna_cbuf_map, amdxdna_cbuf_unmap),
};
static int amdxdna_cbuf_clear(struct dma_buf *dbuf)
diff --git a/drivers/accel/amdxdna/amdxdna_gem.c b/drivers/accel/amdxdna/amdxdna_gem.c
index adee6e806eed..74b8e86638b1 100644
--- a/drivers/accel/amdxdna/amdxdna_gem.c
+++ b/drivers/accel/amdxdna/amdxdna_gem.c
@@ -11,6 +11,7 @@
#include <drm/drm_print.h>
#include <drm/gpu_scheduler.h>
#include <linux/dma-buf.h>
+#include <linux/dma-buf-mapping.h>
#include <linux/dma-direct.h>
#include <linux/iosys-map.h>
#include <linux/pagemap.h>
@@ -669,12 +670,12 @@ static int amdxdna_gem_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struc
static const struct dma_buf_ops amdxdna_dmabuf_ops = {
.attach = drm_gem_map_attach,
.detach = drm_gem_map_detach,
- .map_dma_buf = drm_gem_map_dma_buf,
- .unmap_dma_buf = drm_gem_unmap_dma_buf,
.release = drm_gem_dmabuf_release,
.mmap = amdxdna_gem_dmabuf_mmap,
.vmap = drm_gem_dmabuf_vmap,
.vunmap = drm_gem_dmabuf_vunmap,
+ DMA_BUF_SIMPLE_SGT_EXP_MATCH(drm_gem_map_dma_buf,
+ drm_gem_unmap_dma_buf),
};
static struct dma_buf *amdxdna_gem_prime_export(struct drm_gem_object *gobj, int flags)
diff --git a/drivers/accel/amdxdna/amdxdna_ubuf.c b/drivers/accel/amdxdna/amdxdna_ubuf.c
index 0e0cd69cd1fb..b81f947712e8 100644
--- a/drivers/accel/amdxdna/amdxdna_ubuf.c
+++ b/drivers/accel/amdxdna/amdxdna_ubuf.c
@@ -7,6 +7,7 @@
#include <drm/drm_device.h>
#include <drm/drm_print.h>
#include <linux/dma-buf.h>
+#include <linux/dma-buf-mapping.h>
#include <linux/overflow.h>
#include <linux/pagemap.h>
#include <linux/vmalloc.h>
@@ -36,7 +37,7 @@ static struct sg_table *amdxdna_ubuf_map(struct dma_buf_attachment *attach,
if (ret)
goto err_free_sg;
- ret = dma_map_sgtable(attach->dev, sg, direction, 0);
+ ret = dma_map_sgtable(dma_buf_sgt_dma_device(attach), sg, direction, 0);
if (ret)
goto err_free_table;
@@ -53,7 +54,7 @@ static void amdxdna_ubuf_unmap(struct dma_buf_attachment *attach,
struct sg_table *sg,
enum dma_data_direction direction)
{
- dma_unmap_sgtable(attach->dev, sg, direction, 0);
+ dma_unmap_sgtable(dma_buf_sgt_dma_device(attach), sg, direction, 0);
sg_free_table(sg);
kfree(sg);
}
@@ -70,9 +71,8 @@ static void amdxdna_ubuf_release(struct dma_buf *dbuf)
}
static const struct dma_buf_ops amdxdna_ubuf_dmabuf_ops = {
- .map_dma_buf = amdxdna_ubuf_map,
- .unmap_dma_buf = amdxdna_ubuf_unmap,
.release = amdxdna_ubuf_release,
+ DMA_BUF_SIMPLE_SGT_EXP_MATCH(amdxdna_ubuf_map, amdxdna_ubuf_unmap),
};
struct dma_buf *amdxdna_get_ubuf(struct drm_device *dev,
diff --git a/drivers/accel/ivpu/ivpu_gem_userptr.c b/drivers/accel/ivpu/ivpu_gem_userptr.c
index 7cbf3a4cdc73..7ca9d8d4f5a8 100644
--- a/drivers/accel/ivpu/ivpu_gem_userptr.c
+++ b/drivers/accel/ivpu/ivpu_gem_userptr.c
@@ -4,6 +4,7 @@
*/
#include <linux/dma-buf.h>
+#include <linux/dma-buf-mapping.h>
#include <linux/err.h>
#include <linux/highmem.h>
#include <linux/mm.h>
@@ -26,7 +27,8 @@ ivpu_gem_userptr_dmabuf_map(struct dma_buf_attachment *attachment,
struct sg_table *sgt = attachment->dmabuf->priv;
int ret;
- ret = dma_map_sgtable(attachment->dev, sgt, direction, DMA_ATTR_SKIP_CPU_SYNC);
+ ret = dma_map_sgtable(dma_buf_sgt_dma_device(attachment), sgt,
+ direction, DMA_ATTR_SKIP_CPU_SYNC);
if (ret)
return ERR_PTR(ret);
@@ -37,7 +39,8 @@ static void ivpu_gem_userptr_dmabuf_unmap(struct dma_buf_attachment *attachment,
struct sg_table *sgt,
enum dma_data_direction direction)
{
- dma_unmap_sgtable(attachment->dev, sgt, direction, DMA_ATTR_SKIP_CPU_SYNC);
+ dma_unmap_sgtable(dma_buf_sgt_dma_device(attachment), sgt, direction,
+ DMA_ATTR_SKIP_CPU_SYNC);
}
static void ivpu_gem_userptr_dmabuf_release(struct dma_buf *dma_buf)
@@ -56,9 +59,9 @@ static void ivpu_gem_userptr_dmabuf_release(struct dma_buf *dma_buf)
}
static const struct dma_buf_ops ivpu_gem_userptr_dmabuf_ops = {
- .map_dma_buf = ivpu_gem_userptr_dmabuf_map,
- .unmap_dma_buf = ivpu_gem_userptr_dmabuf_unmap,
.release = ivpu_gem_userptr_dmabuf_release,
+ DMA_BUF_SIMPLE_SGT_EXP_MATCH(ivpu_gem_userptr_dmabuf_map,
+ ivpu_gem_userptr_dmabuf_unmap),
};
static struct dma_buf *
diff --git a/drivers/dma-buf/heaps/cma_heap.c b/drivers/dma-buf/heaps/cma_heap.c
index 3fb4b946c91a..fa05c242f238 100644
--- a/drivers/dma-buf/heaps/cma_heap.c
+++ b/drivers/dma-buf/heaps/cma_heap.c
@@ -14,6 +14,7 @@
#include <linux/cma.h>
#include <linux/dma-buf.h>
+#include <linux/dma-buf-mapping.h>
#include <linux/dma-heap.h>
#include <linux/dma-map-ops.h>
#include <linux/err.h>
@@ -73,7 +74,7 @@ static int cma_heap_attach(struct dma_buf *dmabuf,
return ret;
}
- a->dev = attachment->dev;
+ a->dev = dma_buf_sgt_dma_device(attachment);
INIT_LIST_HEAD(&a->list);
a->mapped = false;
@@ -107,7 +108,8 @@ static struct sg_table *cma_heap_map_dma_buf(struct dma_buf_attachment *attachme
struct sg_table *table = &a->table;
int ret;
- ret = dma_map_sgtable(attachment->dev, table, direction, 0);
+ ret = dma_map_sgtable(dma_buf_sgt_dma_device(attachment), table,
+ direction, 0);
if (ret)
return ERR_PTR(-ENOMEM);
a->mapped = true;
@@ -121,7 +123,8 @@ static void cma_heap_unmap_dma_buf(struct dma_buf_attachment *attachment,
struct dma_heap_attachment *a = attachment->priv;
a->mapped = false;
- dma_unmap_sgtable(attachment->dev, table, direction, 0);
+ dma_unmap_sgtable(dma_buf_sgt_dma_device(attachment), table, direction,
+ 0);
}
static int cma_heap_dma_buf_begin_cpu_access(struct dma_buf *dmabuf,
@@ -268,14 +271,13 @@ static void cma_heap_dma_buf_release(struct dma_buf *dmabuf)
static const struct dma_buf_ops cma_heap_buf_ops = {
.attach = cma_heap_attach,
.detach = cma_heap_detach,
- .map_dma_buf = cma_heap_map_dma_buf,
- .unmap_dma_buf = cma_heap_unmap_dma_buf,
.begin_cpu_access = cma_heap_dma_buf_begin_cpu_access,
.end_cpu_access = cma_heap_dma_buf_end_cpu_access,
.mmap = cma_heap_mmap,
.vmap = cma_heap_vmap,
.vunmap = cma_heap_vunmap,
.release = cma_heap_dma_buf_release,
+ DMA_BUF_SIMPLE_SGT_EXP_MATCH(cma_heap_map_dma_buf, cma_heap_unmap_dma_buf),
};
static struct dma_buf *cma_heap_allocate(struct dma_heap *heap,
diff --git a/drivers/dma-buf/heaps/system_heap.c b/drivers/dma-buf/heaps/system_heap.c
index c8959eadc71d..e954238463d4 100644
--- a/drivers/dma-buf/heaps/system_heap.c
+++ b/drivers/dma-buf/heaps/system_heap.c
@@ -12,6 +12,7 @@
#include <linux/cc_platform.h>
#include <linux/dma-buf.h>
+#include <linux/dma-buf-mapping.h>
#include <linux/dma-mapping.h>
#include <linux/dma-heap.h>
#include <linux/err.h>
@@ -128,7 +129,7 @@ static int system_heap_attach(struct dma_buf *dmabuf,
return ret;
}
- a->dev = attachment->dev;
+ a->dev = dma_buf_sgt_dma_device(attachment);
INIT_LIST_HEAD(&a->list);
a->mapped = false;
a->cc_shared = buffer->cc_shared;
@@ -165,7 +166,8 @@ static struct sg_table *system_heap_map_dma_buf(struct dma_buf_attachment *attac
int ret;
attrs = cc_shared_buffer(a) ? DMA_ATTR_CC_SHARED : 0;
- ret = dma_map_sgtable(attachment->dev, table, direction, attrs);
+ ret = dma_map_sgtable(dma_buf_sgt_dma_device(attachment), table,
+ direction, attrs);
if (ret)
return ERR_PTR(ret);
@@ -180,7 +182,8 @@ static void system_heap_unmap_dma_buf(struct dma_buf_attachment *attachment,
struct dma_heap_attachment *a = attachment->priv;
a->mapped = false;
- dma_unmap_sgtable(attachment->dev, table, direction, 0);
+ dma_unmap_sgtable(dma_buf_sgt_dma_device(attachment), table, direction,
+ 0);
}
static int system_heap_dma_buf_begin_cpu_access(struct dma_buf *dmabuf,
@@ -365,14 +368,14 @@ static void system_heap_dma_buf_release(struct dma_buf *dmabuf)
static const struct dma_buf_ops system_heap_buf_ops = {
.attach = system_heap_attach,
.detach = system_heap_detach,
- .map_dma_buf = system_heap_map_dma_buf,
- .unmap_dma_buf = system_heap_unmap_dma_buf,
.begin_cpu_access = system_heap_dma_buf_begin_cpu_access,
.end_cpu_access = system_heap_dma_buf_end_cpu_access,
.mmap = system_heap_mmap,
.vmap = system_heap_vmap,
.vunmap = system_heap_vunmap,
.release = system_heap_dma_buf_release,
+ DMA_BUF_SIMPLE_SGT_EXP_MATCH(system_heap_map_dma_buf,
+ system_heap_unmap_dma_buf),
};
static struct page *alloc_largest_available(unsigned long size,
diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c
index df6dd0046242..911a3fa347b3 100644
--- a/drivers/dma-buf/udmabuf.c
+++ b/drivers/dma-buf/udmabuf.c
@@ -2,6 +2,7 @@
#include <linux/cred.h>
#include <linux/device.h>
#include <linux/dma-buf.h>
+#include <linux/dma-buf-mapping.h>
#include <linux/dma-resv.h>
#include <linux/highmem.h>
#include <linux/init.h>
@@ -168,14 +169,14 @@ static void put_sg_table(struct device *dev, struct sg_table *sg,
static struct sg_table *map_udmabuf(struct dma_buf_attachment *at,
enum dma_data_direction direction)
{
- return get_sg_table(at->dev, at->dmabuf, direction);
+ return get_sg_table(dma_buf_sgt_dma_device(at), at->dmabuf, direction);
}
static void unmap_udmabuf(struct dma_buf_attachment *at,
struct sg_table *sg,
enum dma_data_direction direction)
{
- return put_sg_table(at->dev, sg, direction);
+ return put_sg_table(dma_buf_sgt_dma_device(at), sg, direction);
}
static void unpin_all_folios(struct udmabuf *ubuf)
@@ -256,14 +257,13 @@ static int end_cpu_udmabuf(struct dma_buf *buf,
}
static const struct dma_buf_ops udmabuf_ops = {
- .map_dma_buf = map_udmabuf,
- .unmap_dma_buf = unmap_udmabuf,
.release = release_udmabuf,
.mmap = mmap_udmabuf,
.vmap = vmap_udmabuf,
.vunmap = vunmap_udmabuf,
.begin_cpu_access = begin_cpu_udmabuf,
.end_cpu_access = end_cpu_udmabuf,
+ DMA_BUF_SIMPLE_SGT_EXP_MATCH(map_udmabuf, unmap_udmabuf),
};
#define SEALS_WANTED (F_SEAL_SHRINK)
diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c
index 044acdef6351..0e34cbb7c5b2 100644
--- a/drivers/gpu/drm/armada/armada_gem.c
+++ b/drivers/gpu/drm/armada/armada_gem.c
@@ -4,6 +4,7 @@
*/
#include <linux/dma-buf.h>
+#include <linux/dma-buf-mapping.h>
#include <linux/dma-mapping.h>
#include <linux/mman.h>
#include <linux/shmem_fs.h>
@@ -387,6 +388,7 @@ static struct sg_table *
armada_gem_prime_map_dma_buf(struct dma_buf_attachment *attach,
enum dma_data_direction dir)
{
+ struct device *dma_dev = dma_buf_sgt_dma_device(attach);
struct drm_gem_object *obj = attach->dmabuf->priv;
struct armada_gem_object *dobj = drm_to_armada_gem(obj);
struct scatterlist *sg;
@@ -417,7 +419,7 @@ armada_gem_prime_map_dma_buf(struct dma_buf_attachment *attach,
sg_set_page(sg, page, PAGE_SIZE, 0);
}
- if (dma_map_sgtable(attach->dev, sgt, dir, 0))
+ if (dma_map_sgtable(dma_dev, sgt, dir, 0))
goto release;
} else if (dobj->page) {
/* Single contiguous page */
@@ -426,7 +428,7 @@ armada_gem_prime_map_dma_buf(struct dma_buf_attachment *attach,
sg_set_page(sgt->sgl, dobj->page, dobj->obj.size, 0);
- if (dma_map_sgtable(attach->dev, sgt, dir, 0))
+ if (dma_map_sgtable(dma_dev, sgt, dir, 0))
goto free_table;
} else if (dobj->linear) {
/* Single contiguous physical region - no struct page */
@@ -458,7 +460,7 @@ static void armada_gem_prime_unmap_dma_buf(struct dma_buf_attachment *attach,
int i;
if (!dobj->linear)
- dma_unmap_sgtable(attach->dev, sgt, dir, 0);
+ dma_unmap_sgtable(dma_buf_sgt_dma_device(attach), sgt, dir, 0);
if (dobj->obj.filp) {
struct scatterlist *sg;
@@ -478,10 +480,10 @@ armada_gem_dmabuf_mmap(struct dma_buf *buf, struct vm_area_struct *vma)
}
static const struct dma_buf_ops armada_gem_prime_dmabuf_ops = {
- .map_dma_buf = armada_gem_prime_map_dma_buf,
- .unmap_dma_buf = armada_gem_prime_unmap_dma_buf,
.release = drm_gem_dmabuf_release,
.mmap = armada_gem_dmabuf_mmap,
+ DMA_BUF_SIMPLE_SGT_EXP_MATCH(armada_gem_prime_map_dma_buf,
+ armada_gem_prime_unmap_dma_buf),
};
struct dma_buf *
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
index c5184ca602bc..a50ab33cd7b9 100644
--- a/drivers/gpu/drm/drm_prime.c
+++ b/drivers/gpu/drm/drm_prime.c
@@ -693,7 +693,7 @@ struct sg_table *drm_gem_map_dma_buf(struct dma_buf_attachment *attach,
if (IS_ERR(sgt))
return sgt;
- ret = dma_map_sgtable(attach->dev, sgt, dir,
+ ret = dma_map_sgtable(dma_buf_sgt_dma_device(attach), sgt, dir,
DMA_ATTR_SKIP_CPU_SYNC);
if (ret) {
sg_free_table(sgt);
@@ -720,7 +720,8 @@ void drm_gem_unmap_dma_buf(struct dma_buf_attachment *attach,
if (!sgt)
return;
- dma_unmap_sgtable(attach->dev, sgt, dir, DMA_ATTR_SKIP_CPU_SYNC);
+ dma_unmap_sgtable(dma_buf_sgt_dma_device(attach), sgt, dir,
+ DMA_ATTR_SKIP_CPU_SYNC);
sg_free_table(sgt);
kfree(sgt);
}
@@ -840,12 +841,12 @@ EXPORT_SYMBOL(drm_gem_dmabuf_mmap);
static const struct dma_buf_ops drm_gem_prime_dmabuf_ops = {
.attach = drm_gem_map_attach,
.detach = drm_gem_map_detach,
- .map_dma_buf = drm_gem_map_dma_buf,
- .unmap_dma_buf = drm_gem_unmap_dma_buf,
.release = drm_gem_dmabuf_release,
.mmap = drm_gem_dmabuf_mmap,
.vmap = drm_gem_dmabuf_vmap,
.vunmap = drm_gem_dmabuf_vunmap,
+ DMA_BUF_SIMPLE_SGT_EXP_MATCH(drm_gem_map_dma_buf,
+ drm_gem_unmap_dma_buf),
};
/**
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
index 4ab54d2e616f..5a53e281df46 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
@@ -4,6 +4,7 @@
*/
#include <linux/dma-buf.h>
+#include <linux/dma-buf-mapping.h>
#include <linux/highmem.h>
#include <linux/dma-resv.h>
#include <linux/module.h>
@@ -52,7 +53,8 @@ static struct sg_table *i915_gem_map_dma_buf(struct dma_buf_attachment *attach,
dst = sg_next(dst);
}
- ret = dma_map_sgtable(attach->dev, sgt, dir, DMA_ATTR_SKIP_CPU_SYNC);
+ ret = dma_map_sgtable(dma_buf_sgt_dma_device(attach), sgt, dir,
+ DMA_ATTR_SKIP_CPU_SYNC);
if (ret)
goto err_free_sg;
@@ -203,14 +205,14 @@ static void i915_gem_dmabuf_detach(struct dma_buf *dmabuf,
static const struct dma_buf_ops i915_dmabuf_ops = {
.attach = i915_gem_dmabuf_attach,
.detach = i915_gem_dmabuf_detach,
- .map_dma_buf = i915_gem_map_dma_buf,
- .unmap_dma_buf = drm_gem_unmap_dma_buf,
.release = drm_gem_dmabuf_release,
.mmap = i915_gem_dmabuf_mmap,
.vmap = i915_gem_dmabuf_vmap,
.vunmap = i915_gem_dmabuf_vunmap,
.begin_cpu_access = i915_gem_begin_cpu_access,
.end_cpu_access = i915_gem_end_cpu_access,
+ DMA_BUF_SIMPLE_SGT_EXP_MATCH(i915_gem_map_dma_buf,
+ drm_gem_unmap_dma_buf),
};
struct dma_buf *i915_gem_prime_export(struct drm_gem_object *gem_obj, int flags)
diff --git a/drivers/gpu/drm/i915/gem/selftests/mock_dmabuf.c b/drivers/gpu/drm/i915/gem/selftests/mock_dmabuf.c
index f2863da7f5c1..911d8f59011a 100644
--- a/drivers/gpu/drm/i915/gem/selftests/mock_dmabuf.c
+++ b/drivers/gpu/drm/i915/gem/selftests/mock_dmabuf.c
@@ -4,6 +4,7 @@
* Copyright © 2016 Intel Corporation
*/
+#include <linux/dma-buf-mapping.h>
#include <linux/vmalloc.h>
#include "mock_dmabuf.h"
@@ -29,7 +30,7 @@ static struct sg_table *mock_map_dma_buf(struct dma_buf_attachment *attachment,
sg = sg_next(sg);
}
- err = dma_map_sgtable(attachment->dev, st, dir, 0);
+ err = dma_map_sgtable(dma_buf_sgt_dma_device(attachment), st, dir, 0);
if (err)
goto err_st;
@@ -46,7 +47,7 @@ static void mock_unmap_dma_buf(struct dma_buf_attachment *attachment,
struct sg_table *st,
enum dma_data_direction dir)
{
- dma_unmap_sgtable(attachment->dev, st, dir, 0);
+ dma_unmap_sgtable(dma_buf_sgt_dma_device(attachment), st, dir, 0);
sg_free_table(st);
kfree(st);
}
@@ -88,12 +89,11 @@ static int mock_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct *vma)
}
static const struct dma_buf_ops mock_dmabuf_ops = {
- .map_dma_buf = mock_map_dma_buf,
- .unmap_dma_buf = mock_unmap_dma_buf,
.release = mock_dmabuf_release,
.mmap = mock_dmabuf_mmap,
.vmap = mock_dmabuf_vmap,
.vunmap = mock_dmabuf_vunmap,
+ DMA_BUF_SIMPLE_SGT_EXP_MATCH(mock_map_dma_buf, mock_unmap_dma_buf),
};
static struct dma_buf *mock_dmabuf(int npages)
diff --git a/drivers/gpu/drm/msm/msm_gem_prime.c b/drivers/gpu/drm/msm/msm_gem_prime.c
index e1e74e9b7e6a..b6aae3c85250 100644
--- a/drivers/gpu/drm/msm/msm_gem_prime.c
+++ b/drivers/gpu/drm/msm/msm_gem_prime.c
@@ -5,6 +5,7 @@
*/
#include <linux/dma-buf.h>
+#include <linux/dma-buf-mapping.h>
#include <drm/drm_drv.h>
#include <drm/drm_prime.h>
@@ -54,12 +55,12 @@ static void msm_gem_dmabuf_release(struct dma_buf *dma_buf)
static const struct dma_buf_ops msm_gem_prime_dmabuf_ops = {
.attach = drm_gem_map_attach,
.detach = drm_gem_map_detach,
- .map_dma_buf = drm_gem_map_dma_buf,
- .unmap_dma_buf = drm_gem_unmap_dma_buf,
.release = msm_gem_dmabuf_release,
.mmap = drm_gem_dmabuf_mmap,
.vmap = drm_gem_dmabuf_vmap,
.vunmap = drm_gem_dmabuf_vunmap,
+ DMA_BUF_SIMPLE_SGT_EXP_MATCH(drm_gem_map_dma_buf,
+ drm_gem_unmap_dma_buf),
};
struct drm_gem_object *msm_gem_prime_import(struct drm_device *dev,
@@ -125,3 +126,5 @@ void msm_gem_prime_unpin(struct drm_gem_object *obj)
msm_gem_unpin_pages_locked(obj);
}
+
+MODULE_IMPORT_NS("DMA_BUF");
diff --git a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
index afae0a56da8c..0628a054f17a 100644
--- a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
+++ b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
@@ -5,6 +5,7 @@
*/
#include <linux/dma-buf.h>
+#include <linux/dma-buf-mapping.h>
#include <linux/highmem.h>
#include <drm/drm_prime.h>
@@ -69,12 +70,12 @@ static int omap_gem_dmabuf_mmap(struct dma_buf *buffer,
}
static const struct dma_buf_ops omap_dmabuf_ops = {
- .map_dma_buf = omap_gem_map_dma_buf,
- .unmap_dma_buf = omap_gem_unmap_dma_buf,
.release = drm_gem_dmabuf_release,
.begin_cpu_access = omap_gem_dmabuf_begin_cpu_access,
.end_cpu_access = omap_gem_dmabuf_end_cpu_access,
.mmap = omap_gem_dmabuf_mmap,
+ DMA_BUF_SIMPLE_SGT_EXP_MATCH(omap_gem_map_dma_buf,
+ omap_gem_unmap_dma_buf),
};
struct dma_buf *omap_gem_prime_export(struct drm_gem_object *obj, int flags)
diff --git a/drivers/gpu/drm/panfrost/panfrost_gem.c b/drivers/gpu/drm/panfrost/panfrost_gem.c
index 518f24549b9d..d7c3dd9a631e 100644
--- a/drivers/gpu/drm/panfrost/panfrost_gem.c
+++ b/drivers/gpu/drm/panfrost/panfrost_gem.c
@@ -6,6 +6,7 @@
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/dma-buf.h>
+#include <linux/dma-buf-mapping.h>
#include <linux/dma-mapping.h>
#include <drm/panfrost_drm.h>
@@ -23,6 +24,8 @@ MODULE_PARM_DESC(transparent_hugepage, "Use a dedicated tmpfs mount point with T
#define panfrost_transparent_hugepage false
#endif
+MODULE_IMPORT_NS("DMA_BUF");
+
int panfrost_gem_init(struct panfrost_device *pfdev)
{
if (panfrost_transparent_hugepage) {
@@ -330,7 +333,8 @@ panfrost_gem_prime_begin_cpu_access(struct dma_buf *dma_buf,
struct sg_table *sgt = attach->priv;
if (sgt)
- dma_sync_sgtable_for_cpu(attach->dev, sgt, dir);
+ dma_sync_sgtable_for_cpu(dma_buf_sgt_dma_device(attach),
+ sgt, dir);
}
dma_resv_unlock(obj->resv);
@@ -351,7 +355,8 @@ panfrost_gem_prime_end_cpu_access(struct dma_buf *dma_buf,
struct sg_table *sgt = attach->priv;
if (sgt)
- dma_sync_sgtable_for_device(attach->dev, sgt, dir);
+ dma_sync_sgtable_for_device(dma_buf_sgt_dma_device(attach),
+ sgt, dir);
}
if (shmem->vaddr)
@@ -367,14 +372,14 @@ panfrost_gem_prime_end_cpu_access(struct dma_buf *dma_buf,
static const struct dma_buf_ops panfrost_dma_buf_ops = {
.attach = drm_gem_map_attach,
.detach = drm_gem_map_detach,
- .map_dma_buf = panfrost_gem_prime_map_dma_buf,
- .unmap_dma_buf = panfrost_gem_prime_unmap_dma_buf,
.release = drm_gem_dmabuf_release,
.mmap = drm_gem_dmabuf_mmap,
.vmap = drm_gem_dmabuf_vmap,
.vunmap = drm_gem_dmabuf_vunmap,
.begin_cpu_access = panfrost_gem_prime_begin_cpu_access,
.end_cpu_access = panfrost_gem_prime_end_cpu_access,
+ DMA_BUF_SIMPLE_SGT_EXP_MATCH(panfrost_gem_prime_map_dma_buf,
+ panfrost_gem_prime_unmap_dma_buf),
};
static struct dma_buf *
diff --git a/drivers/gpu/drm/panthor/panthor_gem.c b/drivers/gpu/drm/panthor/panthor_gem.c
index 22b57ab6f929..56c7e724a6c7 100644
--- a/drivers/gpu/drm/panthor/panthor_gem.c
+++ b/drivers/gpu/drm/panthor/panthor_gem.c
@@ -7,6 +7,7 @@
#include <linux/cleanup.h>
#include <linux/debugfs.h>
#include <linux/dma-buf.h>
+#include <linux/dma-buf-mapping.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/slab.h>
@@ -512,7 +513,8 @@ panthor_gem_prime_begin_cpu_access(struct dma_buf *dma_buf,
struct sg_table *sgt = attach->priv;
if (sgt)
- dma_sync_sgtable_for_cpu(attach->dev, sgt, dir);
+ dma_sync_sgtable_for_cpu(dma_buf_sgt_dma_device(attach),
+ sgt, dir);
}
dma_resv_unlock(obj->resv);
@@ -533,7 +535,8 @@ panthor_gem_prime_end_cpu_access(struct dma_buf *dma_buf,
struct sg_table *sgt = attach->priv;
if (sgt)
- dma_sync_sgtable_for_device(attach->dev, sgt, dir);
+ dma_sync_sgtable_for_device(dma_buf_sgt_dma_device(attach),
+ sgt, dir);
}
if (bo->cmap.vaddr)
@@ -549,14 +552,14 @@ panthor_gem_prime_end_cpu_access(struct dma_buf *dma_buf,
static const struct dma_buf_ops panthor_dma_buf_ops = {
.attach = drm_gem_map_attach,
.detach = drm_gem_map_detach,
- .map_dma_buf = panthor_gem_prime_map_dma_buf,
- .unmap_dma_buf = panthor_gem_prime_unmap_dma_buf,
.release = drm_gem_dmabuf_release,
.mmap = drm_gem_dmabuf_mmap,
.vmap = drm_gem_dmabuf_vmap,
.vunmap = drm_gem_dmabuf_vunmap,
.begin_cpu_access = panthor_gem_prime_begin_cpu_access,
.end_cpu_access = panthor_gem_prime_end_cpu_access,
+ DMA_BUF_SIMPLE_SGT_EXP_MATCH(panthor_gem_prime_map_dma_buf,
+ panthor_gem_prime_unmap_dma_buf),
};
static struct dma_buf *
diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c
index e6aa6dae4ec8..faff826848bd 100644
--- a/drivers/gpu/drm/tegra/gem.c
+++ b/drivers/gpu/drm/tegra/gem.c
@@ -11,6 +11,7 @@
*/
#include <linux/dma-buf.h>
+#include <linux/dma-buf-mapping.h>
#include <linux/iommu.h>
#include <linux/module.h>
#include <linux/pagemap.h>
@@ -630,6 +631,7 @@ static struct sg_table *
tegra_gem_prime_map_dma_buf(struct dma_buf_attachment *attach,
enum dma_data_direction dir)
{
+ struct device *dma_dev = dma_buf_sgt_dma_device(attach);
struct drm_gem_object *gem = attach->dmabuf->priv;
struct tegra_bo *bo = to_tegra_bo(gem);
struct sg_table *sgt;
@@ -643,12 +645,12 @@ tegra_gem_prime_map_dma_buf(struct dma_buf_attachment *attach,
0, gem->size, GFP_KERNEL) < 0)
goto free;
} else {
- if (dma_get_sgtable(attach->dev, sgt, bo->vaddr, bo->iova,
+ if (dma_get_sgtable(dma_dev, sgt, bo->vaddr, bo->iova,
gem->size) < 0)
goto free;
}
- if (dma_map_sgtable(attach->dev, sgt, dir, 0))
+ if (dma_map_sgtable(dma_dev, sgt, dir, 0))
goto free;
return sgt;
@@ -667,7 +669,7 @@ static void tegra_gem_prime_unmap_dma_buf(struct dma_buf_attachment *attach,
struct tegra_bo *bo = to_tegra_bo(gem);
if (bo->pages)
- dma_unmap_sgtable(attach->dev, sgt, dir, 0);
+ dma_unmap_sgtable(dma_buf_sgt_dma_device(attach), sgt, dir, 0);
sg_free_table(sgt);
kfree(sgt);
@@ -740,14 +742,14 @@ static void tegra_gem_prime_vunmap(struct dma_buf *buf, struct iosys_map *map)
}
static const struct dma_buf_ops tegra_gem_prime_dmabuf_ops = {
- .map_dma_buf = tegra_gem_prime_map_dma_buf,
- .unmap_dma_buf = tegra_gem_prime_unmap_dma_buf,
.release = tegra_gem_prime_release,
.begin_cpu_access = tegra_gem_prime_begin_cpu_access,
.end_cpu_access = tegra_gem_prime_end_cpu_access,
.mmap = tegra_gem_prime_mmap,
.vmap = tegra_gem_prime_vmap,
.vunmap = tegra_gem_prime_vunmap,
+ DMA_BUF_SIMPLE_SGT_EXP_MATCH(tegra_gem_prime_map_dma_buf,
+ tegra_gem_prime_unmap_dma_buf),
};
struct dma_buf *tegra_gem_prime_export(struct drm_gem_object *gem,
diff --git a/drivers/gpu/drm/virtio/virtgpu_prime.c b/drivers/gpu/drm/virtio/virtgpu_prime.c
index a47783b47dcc..fd6943e8a40a 100644
--- a/drivers/gpu/drm/virtio/virtgpu_prime.c
+++ b/drivers/gpu/drm/virtio/virtgpu_prime.c
@@ -24,6 +24,7 @@
#include <drm/drm_prime.h>
#include <drm/drm_print.h>
+#include <linux/dma-buf-mapping.h>
#include <linux/virtio_dma_buf.h>
#include "virtgpu_drv.h"
@@ -54,7 +55,8 @@ virtgpu_gem_map_dma_buf(struct dma_buf_attachment *attach,
struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(obj);
if (virtio_gpu_is_vram(bo))
- return virtio_gpu_vram_map_dma_buf(bo, attach->dev, dir);
+ return virtio_gpu_vram_map_dma_buf(
+ bo, dma_buf_sgt_dma_device(attach), dir);
return drm_gem_map_dma_buf(attach, dir);
}
@@ -67,7 +69,8 @@ static void virtgpu_gem_unmap_dma_buf(struct dma_buf_attachment *attach,
struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(obj);
if (virtio_gpu_is_vram(bo)) {
- virtio_gpu_vram_unmap_dma_buf(attach->dev, sgt, dir);
+ virtio_gpu_vram_unmap_dma_buf(dma_buf_sgt_dma_device(attach),
+ sgt, dir);
return;
}
@@ -78,12 +81,12 @@ static const struct virtio_dma_buf_ops virtgpu_dmabuf_ops = {
.ops = {
.attach = virtio_dma_buf_attach,
.detach = drm_gem_map_detach,
- .map_dma_buf = virtgpu_gem_map_dma_buf,
- .unmap_dma_buf = virtgpu_gem_unmap_dma_buf,
.release = drm_gem_dmabuf_release,
.mmap = drm_gem_dmabuf_mmap,
.vmap = drm_gem_dmabuf_vmap,
.vunmap = drm_gem_dmabuf_vunmap,
+ DMA_BUF_SIMPLE_SGT_EXP_MATCH(virtgpu_gem_map_dma_buf,
+ virtgpu_gem_unmap_dma_buf),
},
.device_attach = drm_gem_map_attach,
.get_uuid = virtgpu_virtio_get_uuid,
diff --git a/drivers/iommu/iommufd/selftest.c b/drivers/iommu/iommufd/selftest.c
index 25387969ab75..77b7d962cf17 100644
--- a/drivers/iommu/iommufd/selftest.c
+++ b/drivers/iommu/iommufd/selftest.c
@@ -6,6 +6,7 @@
#include <linux/anon_inodes.h>
#include <linux/debugfs.h>
#include <linux/dma-buf.h>
+#include <linux/dma-buf-mapping.h>
#include <linux/dma-resv.h>
#include <linux/fault-inject.h>
#include <linux/file.h>
@@ -1959,17 +1960,6 @@ struct iommufd_test_dma_buf {
bool revoked;
};
-static int iommufd_test_dma_buf_attach(struct dma_buf *dmabuf,
- struct dma_buf_attachment *attachment)
-{
- return 0;
-}
-
-static void iommufd_test_dma_buf_detach(struct dma_buf *dmabuf,
- struct dma_buf_attachment *attachment)
-{
-}
-
static struct sg_table *
iommufd_test_dma_buf_map(struct dma_buf_attachment *attachment,
enum dma_data_direction dir)
@@ -1992,11 +1982,9 @@ static void iommufd_test_dma_buf_release(struct dma_buf *dmabuf)
}
static const struct dma_buf_ops iommufd_test_dmabuf_ops = {
- .attach = iommufd_test_dma_buf_attach,
- .detach = iommufd_test_dma_buf_detach,
- .map_dma_buf = iommufd_test_dma_buf_map,
.release = iommufd_test_dma_buf_release,
- .unmap_dma_buf = iommufd_test_dma_buf_unmap,
+ DMA_BUF_SIMPLE_SGT_EXP_MATCH(iommufd_test_dma_buf_map,
+ iommufd_test_dma_buf_unmap),
};
int iommufd_test_dma_buf_iommufd_map(struct dma_buf_attachment *attachment,
diff --git a/drivers/media/common/videobuf2/videobuf2-dma-contig.c b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
index 284482335c1a..039ff95ac4db 100644
--- a/drivers/media/common/videobuf2/videobuf2-dma-contig.c
+++ b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
@@ -11,6 +11,7 @@
*/
#include <linux/dma-buf.h>
+#include <linux/dma-buf-mapping.h>
#include <linux/module.h>
#include <linux/refcount.h>
#include <linux/scatterlist.h>
@@ -372,8 +373,8 @@ static void vb2_dc_dmabuf_ops_detach(struct dma_buf *dbuf,
* memory locations do not require any explicit cache
* maintenance prior or after being used by the device.
*/
- dma_unmap_sgtable(db_attach->dev, sgt, attach->dma_dir,
- DMA_ATTR_SKIP_CPU_SYNC);
+ dma_unmap_sgtable(dma_buf_sgt_dma_device(db_attach), sgt,
+ attach->dma_dir, DMA_ATTR_SKIP_CPU_SYNC);
sg_free_table(sgt);
kfree(attach);
db_attach->priv = NULL;
@@ -392,8 +393,8 @@ static struct sg_table *vb2_dc_dmabuf_ops_map(
/* release any previous cache */
if (attach->dma_dir != DMA_NONE) {
- dma_unmap_sgtable(db_attach->dev, sgt, attach->dma_dir,
- DMA_ATTR_SKIP_CPU_SYNC);
+ dma_unmap_sgtable(dma_buf_sgt_dma_device(db_attach), sgt,
+ attach->dma_dir, DMA_ATTR_SKIP_CPU_SYNC);
attach->dma_dir = DMA_NONE;
}
@@ -401,7 +402,7 @@ static struct sg_table *vb2_dc_dmabuf_ops_map(
* mapping to the client with new direction, no cache sync
* required see comment in vb2_dc_dmabuf_ops_detach()
*/
- if (dma_map_sgtable(db_attach->dev, sgt, dma_dir,
+ if (dma_map_sgtable(dma_buf_sgt_dma_device(db_attach), sgt, dma_dir,
DMA_ATTR_SKIP_CPU_SYNC)) {
pr_err("failed to map scatterlist\n");
return ERR_PTR(-EIO);
@@ -462,13 +463,13 @@ static int vb2_dc_dmabuf_ops_mmap(struct dma_buf *dbuf,
static const struct dma_buf_ops vb2_dc_dmabuf_ops = {
.attach = vb2_dc_dmabuf_ops_attach,
.detach = vb2_dc_dmabuf_ops_detach,
- .map_dma_buf = vb2_dc_dmabuf_ops_map,
- .unmap_dma_buf = vb2_dc_dmabuf_ops_unmap,
.begin_cpu_access = vb2_dc_dmabuf_ops_begin_cpu_access,
.end_cpu_access = vb2_dc_dmabuf_ops_end_cpu_access,
.vmap = vb2_dc_dmabuf_ops_vmap,
.mmap = vb2_dc_dmabuf_ops_mmap,
.release = vb2_dc_dmabuf_ops_release,
+ DMA_BUF_SIMPLE_SGT_EXP_MATCH(vb2_dc_dmabuf_ops_map,
+ vb2_dc_dmabuf_ops_unmap),
};
static struct sg_table *vb2_dc_get_base_sgt(struct vb2_dc_buf *buf)
diff --git a/drivers/media/common/videobuf2/videobuf2-dma-sg.c b/drivers/media/common/videobuf2/videobuf2-dma-sg.c
index 54b07e3840ac..5a201062ff5b 100644
--- a/drivers/media/common/videobuf2/videobuf2-dma-sg.c
+++ b/drivers/media/common/videobuf2/videobuf2-dma-sg.c
@@ -10,6 +10,7 @@
* the Free Software Foundation.
*/
+#include <linux/dma-buf-mapping.h>
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/refcount.h>
@@ -417,7 +418,8 @@ static void vb2_dma_sg_dmabuf_ops_detach(struct dma_buf *dbuf,
/* release the scatterlist cache */
if (attach->dma_dir != DMA_NONE)
- dma_unmap_sgtable(db_attach->dev, sgt, attach->dma_dir, 0);
+ dma_unmap_sgtable(dma_buf_sgt_dma_device(db_attach), sgt,
+ attach->dma_dir, 0);
sg_free_table(sgt);
kfree(attach);
db_attach->priv = NULL;
@@ -436,12 +438,14 @@ static struct sg_table *vb2_dma_sg_dmabuf_ops_map(
/* release any previous cache */
if (attach->dma_dir != DMA_NONE) {
- dma_unmap_sgtable(db_attach->dev, sgt, attach->dma_dir, 0);
+ dma_unmap_sgtable(dma_buf_sgt_dma_device(db_attach), sgt,
+ attach->dma_dir, 0);
attach->dma_dir = DMA_NONE;
}
/* mapping to the client with new direction */
- if (dma_map_sgtable(db_attach->dev, sgt, dma_dir, 0)) {
+ if (dma_map_sgtable(dma_buf_sgt_dma_device(db_attach), sgt, dma_dir,
+ 0)) {
pr_err("failed to map scatterlist\n");
return ERR_PTR(-EIO);
}
@@ -510,13 +514,13 @@ static int vb2_dma_sg_dmabuf_ops_mmap(struct dma_buf *dbuf,
static const struct dma_buf_ops vb2_dma_sg_dmabuf_ops = {
.attach = vb2_dma_sg_dmabuf_ops_attach,
.detach = vb2_dma_sg_dmabuf_ops_detach,
- .map_dma_buf = vb2_dma_sg_dmabuf_ops_map,
- .unmap_dma_buf = vb2_dma_sg_dmabuf_ops_unmap,
.begin_cpu_access = vb2_dma_sg_dmabuf_ops_begin_cpu_access,
.end_cpu_access = vb2_dma_sg_dmabuf_ops_end_cpu_access,
.vmap = vb2_dma_sg_dmabuf_ops_vmap,
.mmap = vb2_dma_sg_dmabuf_ops_mmap,
.release = vb2_dma_sg_dmabuf_ops_release,
+ DMA_BUF_SIMPLE_SGT_EXP_MATCH(vb2_dma_sg_dmabuf_ops_map,
+ vb2_dma_sg_dmabuf_ops_unmap),
};
static struct dma_buf *vb2_dma_sg_get_dmabuf(struct vb2_buffer *vb,
diff --git a/drivers/media/common/videobuf2/videobuf2-vmalloc.c b/drivers/media/common/videobuf2/videobuf2-vmalloc.c
index 63f023696f3e..d79acf83286a 100644
--- a/drivers/media/common/videobuf2/videobuf2-vmalloc.c
+++ b/drivers/media/common/videobuf2/videobuf2-vmalloc.c
@@ -10,6 +10,7 @@
* the Free Software Foundation.
*/
+#include <linux/dma-buf-mapping.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/mm.h>
@@ -261,7 +262,8 @@ static void vb2_vmalloc_dmabuf_ops_detach(struct dma_buf *dbuf,
/* release the scatterlist cache */
if (attach->dma_dir != DMA_NONE)
- dma_unmap_sgtable(db_attach->dev, sgt, attach->dma_dir, 0);
+ dma_unmap_sgtable(dma_buf_sgt_dma_device(db_attach), sgt,
+ attach->dma_dir, 0);
sg_free_table(sgt);
kfree(attach);
db_attach->priv = NULL;
@@ -270,6 +272,7 @@ static void vb2_vmalloc_dmabuf_ops_detach(struct dma_buf *dbuf,
static struct sg_table *vb2_vmalloc_dmabuf_ops_map(
struct dma_buf_attachment *db_attach, enum dma_data_direction dma_dir)
{
+ struct device *dma_dev = dma_buf_sgt_dma_device(db_attach);
struct vb2_vmalloc_attachment *attach = db_attach->priv;
struct sg_table *sgt;
@@ -280,12 +283,12 @@ static struct sg_table *vb2_vmalloc_dmabuf_ops_map(
/* release any previous cache */
if (attach->dma_dir != DMA_NONE) {
- dma_unmap_sgtable(db_attach->dev, sgt, attach->dma_dir, 0);
+ dma_unmap_sgtable(dma_dev, sgt, attach->dma_dir, 0);
attach->dma_dir = DMA_NONE;
}
/* mapping to the client with new direction */
- if (dma_map_sgtable(db_attach->dev, sgt, dma_dir, 0)) {
+ if (dma_map_sgtable(dma_dev, sgt, dma_dir, 0)) {
pr_err("failed to map scatterlist\n");
return ERR_PTR(-EIO);
}
@@ -326,11 +329,11 @@ static int vb2_vmalloc_dmabuf_ops_mmap(struct dma_buf *dbuf,
static const struct dma_buf_ops vb2_vmalloc_dmabuf_ops = {
.attach = vb2_vmalloc_dmabuf_ops_attach,
.detach = vb2_vmalloc_dmabuf_ops_detach,
- .map_dma_buf = vb2_vmalloc_dmabuf_ops_map,
- .unmap_dma_buf = vb2_vmalloc_dmabuf_ops_unmap,
.vmap = vb2_vmalloc_dmabuf_ops_vmap,
.mmap = vb2_vmalloc_dmabuf_ops_mmap,
.release = vb2_vmalloc_dmabuf_ops_release,
+ DMA_BUF_SIMPLE_SGT_EXP_MATCH(vb2_vmalloc_dmabuf_ops_map,
+ vb2_vmalloc_dmabuf_ops_unmap),
};
static struct dma_buf *vb2_vmalloc_get_dmabuf(struct vb2_buffer *vb,
diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
index 76c8dc05fa10..cbe53144e79b 100644
--- a/drivers/misc/fastrpc.c
+++ b/drivers/misc/fastrpc.c
@@ -5,6 +5,7 @@
#include <linux/completion.h>
#include <linux/device.h>
#include <linux/dma-buf.h>
+#include <linux/dma-buf-mapping.h>
#include <linux/dma-mapping.h>
#include <linux/dma-resv.h>
#include <linux/idr.h>
@@ -780,7 +781,8 @@ fastrpc_map_dma_buf(struct dma_buf_attachment *attachment,
table = &a->sgt;
- ret = dma_map_sgtable(attachment->dev, table, dir, 0);
+ ret = dma_map_sgtable(dma_buf_sgt_dma_device(attachment), table, dir,
+ 0);
if (ret)
table = ERR_PTR(ret);
return table;
@@ -790,7 +792,7 @@ static void fastrpc_unmap_dma_buf(struct dma_buf_attachment *attach,
struct sg_table *table,
enum dma_data_direction dir)
{
- dma_unmap_sgtable(attach->dev, table, dir, 0);
+ dma_unmap_sgtable(dma_buf_sgt_dma_device(attach), table, dir, 0);
}
static void fastrpc_release(struct dma_buf *dmabuf)
@@ -820,7 +822,7 @@ static int fastrpc_dma_buf_attach(struct dma_buf *dmabuf,
return -EINVAL;
}
- a->dev = attachment->dev;
+ a->dev = dma_buf_sgt_dma_device(attachment);
INIT_LIST_HEAD(&a->node);
attachment->priv = a;
@@ -868,11 +870,11 @@ static int fastrpc_mmap(struct dma_buf *dmabuf,
static const struct dma_buf_ops fastrpc_dma_buf_ops = {
.attach = fastrpc_dma_buf_attach,
.detach = fastrpc_dma_buf_detatch,
- .map_dma_buf = fastrpc_map_dma_buf,
- .unmap_dma_buf = fastrpc_unmap_dma_buf,
.mmap = fastrpc_mmap,
.vmap = fastrpc_vmap,
.release = fastrpc_release,
+ DMA_BUF_SIMPLE_SGT_EXP_MATCH(fastrpc_map_dma_buf,
+ fastrpc_unmap_dma_buf),
};
static dma_addr_t fastrpc_compute_dma_addr(struct fastrpc_user *fl, dma_addr_t sg_dma_addr)
diff --git a/drivers/tee/tee_heap.c b/drivers/tee/tee_heap.c
index 007c00156520..099b153087a3 100644
--- a/drivers/tee/tee_heap.c
+++ b/drivers/tee/tee_heap.c
@@ -4,6 +4,7 @@
*/
#include <linux/dma-buf.h>
+#include <linux/dma-buf-mapping.h>
#include <linux/dma-heap.h>
#include <linux/genalloc.h>
#include <linux/module.h>
@@ -104,7 +105,7 @@ static int tee_heap_attach(struct dma_buf *dmabuf,
return ret;
}
- a->dev = attachment->dev;
+ a->dev = dma_buf_sgt_dma_device(attachment);
attachment->priv = a;
return 0;
@@ -126,8 +127,8 @@ tee_heap_map_dma_buf(struct dma_buf_attachment *attachment,
struct tee_heap_attachment *a = attachment->priv;
int ret;
- ret = dma_map_sgtable(attachment->dev, &a->table, direction,
- DMA_ATTR_SKIP_CPU_SYNC);
+ ret = dma_map_sgtable(dma_buf_sgt_dma_device(attachment), &a->table,
+ direction, DMA_ATTR_SKIP_CPU_SYNC);
if (ret)
return ERR_PTR(ret);
@@ -142,7 +143,7 @@ static void tee_heap_unmap_dma_buf(struct dma_buf_attachment *attachment,
WARN_ON(&a->table != table);
- dma_unmap_sgtable(attachment->dev, table, direction,
+ dma_unmap_sgtable(dma_buf_sgt_dma_device(attachment), table, direction,
DMA_ATTR_SKIP_CPU_SYNC);
}
@@ -160,9 +161,9 @@ static void tee_heap_buf_free(struct dma_buf *dmabuf)
static const struct dma_buf_ops tee_heap_buf_ops = {
.attach = tee_heap_attach,
.detach = tee_heap_detach,
- .map_dma_buf = tee_heap_map_dma_buf,
- .unmap_dma_buf = tee_heap_unmap_dma_buf,
.release = tee_heap_buf_free,
+ DMA_BUF_SIMPLE_SGT_EXP_MATCH(tee_heap_map_dma_buf,
+ tee_heap_unmap_dma_buf),
};
static struct dma_buf *tee_dma_heap_alloc(struct dma_heap *heap,
diff --git a/drivers/xen/gntdev-dmabuf.c b/drivers/xen/gntdev-dmabuf.c
index e07e34515421..27cb179efc15 100644
--- a/drivers/xen/gntdev-dmabuf.c
+++ b/drivers/xen/gntdev-dmabuf.c
@@ -11,6 +11,7 @@
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/dma-buf.h>
+#include <linux/dma-buf-mapping.h>
#include <linux/dma-direct.h>
#include <linux/slab.h>
#include <linux/types.h>
@@ -243,9 +244,10 @@ static void dmabuf_exp_ops_detach(struct dma_buf *dma_buf,
if (sgt) {
if (gntdev_dmabuf_attach->dir != DMA_NONE)
- dma_unmap_sgtable(attach->dev, sgt,
- gntdev_dmabuf_attach->dir,
- DMA_ATTR_SKIP_CPU_SYNC);
+ dma_unmap_sgtable(
+ dma_buf_sgt_dma_device(attach), sgt,
+ gntdev_dmabuf_attach->dir,
+ DMA_ATTR_SKIP_CPU_SYNC);
sg_free_table(sgt);
}
@@ -259,12 +261,13 @@ static struct sg_table *
dmabuf_exp_ops_map_dma_buf(struct dma_buf_attachment *attach,
enum dma_data_direction dir)
{
+ struct device *dma_dev = dma_buf_sgt_dma_device(attach);
struct gntdev_dmabuf_attachment *gntdev_dmabuf_attach = attach->priv;
struct gntdev_dmabuf *gntdev_dmabuf = attach->dmabuf->priv;
struct sg_table *sgt;
pr_debug("Mapping %d pages for dev %p\n", gntdev_dmabuf->nr_pages,
- attach->dev);
+ dma_dev);
if (dir == DMA_NONE || !gntdev_dmabuf_attach)
return ERR_PTR(-EINVAL);
@@ -283,7 +286,7 @@ dmabuf_exp_ops_map_dma_buf(struct dma_buf_attachment *attach,
sgt = dmabuf_pages_to_sgt(gntdev_dmabuf->pages,
gntdev_dmabuf->nr_pages);
if (!IS_ERR(sgt)) {
- if (dma_map_sgtable(attach->dev, sgt, dir,
+ if (dma_map_sgtable(dma_dev, sgt, dir,
DMA_ATTR_SKIP_CPU_SYNC)) {
sg_free_table(sgt);
kfree(sgt);
@@ -294,7 +297,7 @@ dmabuf_exp_ops_map_dma_buf(struct dma_buf_attachment *attach,
}
}
if (IS_ERR(sgt))
- pr_debug("Failed to map sg table for dev %p\n", attach->dev);
+ pr_debug("Failed to map sg table for dev %p\n", dma_dev);
return sgt;
}
@@ -340,9 +343,9 @@ static void dmabuf_exp_ops_release(struct dma_buf *dma_buf)
static const struct dma_buf_ops dmabuf_exp_ops = {
.attach = dmabuf_exp_ops_attach,
.detach = dmabuf_exp_ops_detach,
- .map_dma_buf = dmabuf_exp_ops_map_dma_buf,
- .unmap_dma_buf = dmabuf_exp_ops_unmap_dma_buf,
.release = dmabuf_exp_ops_release,
+ DMA_BUF_SIMPLE_SGT_EXP_MATCH(dmabuf_exp_ops_map_dma_buf,
+ dmabuf_exp_ops_unmap_dma_buf),
};
struct gntdev_dmabuf_export_args {
diff --git a/samples/vfio-mdev/mbochs.c b/samples/vfio-mdev/mbochs.c
index 64ea19253ee3..c2eaa14b9ddd 100644
--- a/samples/vfio-mdev/mbochs.c
+++ b/samples/vfio-mdev/mbochs.c
@@ -32,6 +32,7 @@
#include <linux/pci.h>
#include <linux/dma-buf.h>
#include <linux/highmem.h>
+#include <linux/dma-buf-mapping.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_rect.h>
#include <drm/drm_modeset_lock.h>
@@ -872,7 +873,7 @@ static struct sg_table *mbochs_map_dmabuf(struct dma_buf_attachment *at,
if (sg_alloc_table_from_pages(sg, dmabuf->pages, dmabuf->pagecount,
0, dmabuf->mode.size, GFP_KERNEL) < 0)
goto err2;
- if (dma_map_sgtable(at->dev, sg, direction, 0))
+ if (dma_map_sgtable(dma_buf_sgt_dma_device(at), sg, direction, 0))
goto err3;
return sg;
@@ -894,7 +895,7 @@ static void mbochs_unmap_dmabuf(struct dma_buf_attachment *at,
dev_dbg(dev, "%s: %d\n", __func__, dmabuf->id);
- dma_unmap_sgtable(at->dev, sg, direction, 0);
+ dma_unmap_sgtable(dma_buf_sgt_dma_device(at), sg, direction, 0);
sg_free_table(sg);
kfree(sg);
}
@@ -918,11 +919,10 @@ static void mbochs_release_dmabuf(struct dma_buf *buf)
mutex_unlock(&mdev_state->ops_lock);
}
-static struct dma_buf_ops mbochs_dmabuf_ops = {
- .map_dma_buf = mbochs_map_dmabuf,
- .unmap_dma_buf = mbochs_unmap_dmabuf,
+static const struct dma_buf_ops mbochs_dmabuf_ops = {
.release = mbochs_release_dmabuf,
.mmap = mbochs_mmap_dmabuf,
+ DMA_BUF_SIMPLE_SGT_EXP_MATCH(mbochs_map_dmabuf, mbochs_unmap_dmabuf),
};
static struct mbochs_dmabuf *mbochs_dmabuf_alloc(struct mdev_state *mdev_state,
diff --git a/sound/soc/fsl/fsl_asrc_m2m.c b/sound/soc/fsl/fsl_asrc_m2m.c
index 58101ce07c9f..ef5a0d7639ed 100644
--- a/sound/soc/fsl/fsl_asrc_m2m.c
+++ b/sound/soc/fsl/fsl_asrc_m2m.c
@@ -7,6 +7,7 @@
#include <linux/dma/imx-dma.h>
#include <linux/dma-buf.h>
+#include <linux/dma-buf-mapping.h>
#include <linux/dma-mapping.h>
#include <linux/pm_runtime.h>
#include <sound/asound.h>
@@ -417,6 +418,7 @@ static int fsl_asrc_m2m_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
static struct sg_table *fsl_asrc_m2m_map_dma_buf(struct dma_buf_attachment *attachment,
enum dma_data_direction direction)
{
+ struct device *dma_dev = dma_buf_sgt_dma_device(attachment);
struct snd_dma_buffer *dmab = attachment->dmabuf->priv;
struct sg_table *sgt;
@@ -424,10 +426,10 @@ static struct sg_table *fsl_asrc_m2m_map_dma_buf(struct dma_buf_attachment *atta
if (!sgt)
return NULL;
- if (dma_get_sgtable(attachment->dev, sgt, dmab->area, dmab->addr, dmab->bytes) < 0)
+ if (dma_get_sgtable(dma_dev, sgt, dmab->area, dmab->addr, dmab->bytes) < 0)
goto free;
- if (dma_map_sgtable(attachment->dev, sgt, direction, 0))
+ if (dma_map_sgtable(dma_dev, sgt, direction, 0))
goto free;
return sgt;
@@ -442,7 +444,7 @@ static void fsl_asrc_m2m_unmap_dma_buf(struct dma_buf_attachment *attachment,
struct sg_table *table,
enum dma_data_direction direction)
{
- dma_unmap_sgtable(attachment->dev, table, direction, 0);
+ dma_unmap_sgtable(dma_buf_sgt_dma_device(attachment), table, direction, 0);
}
static void fsl_asrc_m2m_release(struct dma_buf *dmabuf)
@@ -452,9 +454,9 @@ static void fsl_asrc_m2m_release(struct dma_buf *dmabuf)
static const struct dma_buf_ops fsl_asrc_m2m_dma_buf_ops = {
.mmap = fsl_asrc_m2m_mmap,
- .map_dma_buf = fsl_asrc_m2m_map_dma_buf,
- .unmap_dma_buf = fsl_asrc_m2m_unmap_dma_buf,
.release = fsl_asrc_m2m_release,
+ DMA_BUF_SIMPLE_SGT_EXP_MATCH(fsl_asrc_m2m_map_dma_buf,
+ fsl_asrc_m2m_unmap_dma_buf),
};
static int fsl_asrc_m2m_comp_task_create(struct snd_compr_stream *stream,
--
2.54.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH v2 12/23] drm/vmwgfx: Use match_mapping instead of dummy calls
2026-11-05 6:40 [PATCH v2 00/23] DMA-buf mapping types Alistair Popple
` (10 preceding siblings ...)
2026-11-05 6:40 ` [PATCH v2 11/23] dma-buf: Convert all the simple exporters to use SGT mapping type Alistair Popple
@ 2026-11-05 6:40 ` Alistair Popple
2026-11-05 6:40 ` [PATCH v2 13/23] accel/habanalabs: Use the SGT_P2P mapping type Alistair Popple
` (11 subsequent siblings)
23 siblings, 0 replies; 26+ messages in thread
From: Alistair Popple @ 2026-11-05 6:40 UTC (permalink / raw)
To: Christian König, Sumit Semwal, Thomas Hellström,
Simona Vetter, Matthew Brost, Vivek Kasireddy, Dongwon Kim,
Kevin Tian, Xu Yilun, Karl Mehltretter, Baolu Lu, Felix Kuehling,
Alex Deucher, dri-devel, intel-xe, amd-gfx, linux-media,
linaro-mm-sig, linux-rdma, iommu, Keith Busch, Jens Axboe,
Christoph Hellwig, Sagi Grimberg, linux-nvme, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Mina Almasry, netdev, Alexey Kardashevskiy, zhipingz, treding,
jhubbard, Jason Gunthorpe, Leon Romanovsky
Cc: Alistair Popple
From: Jason Gunthorpe <jgg@nvidia.com>
vmwgfx is creating a DMA-buf that cannot be attached by providing
always fail functions for dma_buf_ops.
The attach/detach callbacks are already optional inside DMA-buf, but
dma_buf_export() is checking for non-null map/unmap callbacks.
Instead use the mapping type interface and provide an always fail
match_mapping(). Remove the unused SGT and attach/detach functions, they
can never be called if match_mapping() fails.
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Alistair Popple <apopple@nvidia.com>
---
drivers/gpu/drm/vmwgfx/vmwgfx_prime.c | 32 +++++---------------------------
1 file changed, 5 insertions(+), 27 deletions(-)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_prime.c b/drivers/gpu/drm/vmwgfx/vmwgfx_prime.c
index 598b90ac7590..90e4342a378d 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_prime.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_prime.c
@@ -35,41 +35,19 @@
#include "vmwgfx_bo.h"
#include "ttm_object.h"
#include <linux/dma-buf.h>
+#include <linux/dma-buf-mapping.h>
/*
- * DMA-BUF attach- and mapping methods. No need to implement
- * these until we have other virtual devices use them.
+ * No need to implement these until we have other virtual devices use them.
*/
-
-static int vmw_prime_map_attach(struct dma_buf *dma_buf,
- struct dma_buf_attachment *attach)
-{
- return -ENOSYS;
-}
-
-static void vmw_prime_map_detach(struct dma_buf *dma_buf,
- struct dma_buf_attachment *attach)
-{
-}
-
-static struct sg_table *vmw_prime_map_dma_buf(struct dma_buf_attachment *attach,
- enum dma_data_direction dir)
-{
- return ERR_PTR(-ENOSYS);
-}
-
-static void vmw_prime_unmap_dma_buf(struct dma_buf_attachment *attach,
- struct sg_table *sgb,
- enum dma_data_direction dir)
+static int vmw_prime_match_mapping(struct dma_buf_match_args *args)
{
+ return -EOPNOTSUPP;
}
const struct dma_buf_ops vmw_prime_dmabuf_ops = {
- .attach = vmw_prime_map_attach,
- .detach = vmw_prime_map_detach,
- .map_dma_buf = vmw_prime_map_dma_buf,
- .unmap_dma_buf = vmw_prime_unmap_dma_buf,
.release = NULL,
+ .match_mapping = vmw_prime_match_mapping,
};
int vmw_prime_fd_to_handle(struct drm_device *dev,
--
2.54.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH v2 13/23] accel/habanalabs: Use the SGT_P2P mapping type
2026-11-05 6:40 [PATCH v2 00/23] DMA-buf mapping types Alistair Popple
` (11 preceding siblings ...)
2026-11-05 6:40 ` [PATCH v2 12/23] drm/vmwgfx: Use match_mapping instead of dummy calls Alistair Popple
@ 2026-11-05 6:40 ` Alistair Popple
2026-11-05 6:40 ` [PATCH v2 14/23] drm/xe/dma-buf: Use the SGT " Alistair Popple
` (10 subsequent siblings)
23 siblings, 0 replies; 26+ messages in thread
From: Alistair Popple @ 2026-11-05 6:40 UTC (permalink / raw)
To: Christian König, Sumit Semwal, Thomas Hellström,
Simona Vetter, Matthew Brost, Vivek Kasireddy, Dongwon Kim,
Kevin Tian, Xu Yilun, Karl Mehltretter, Baolu Lu, Felix Kuehling,
Alex Deucher, dri-devel, intel-xe, amd-gfx, linux-media,
linaro-mm-sig, linux-rdma, iommu, Keith Busch, Jens Axboe,
Christoph Hellwig, Sagi Grimberg, linux-nvme, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Mina Almasry, netdev, Alexey Kardashevskiy, zhipingz, treding,
jhubbard, Jason Gunthorpe, Leon Romanovsky
Cc: Alistair Popple
From: Jason Gunthorpe <jgg@nvidia.com>
habana has special code to check pci_p2pdma_distance() and rejects any
importer that cannot do P2P DMA to its MMIO.
Convert this directly to a SGT_P2P match which does the same check
inside the matching logic.
Someday this should be converted to use dma_buf_phys_vec_to_sgt() which
does the P2P checking correctly, for both direct and IOMMU based cases,
instead of this hack.
Remove the now empty attach function.
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Alistair Popple <apopple@nvidia.com>
---
drivers/accel/habanalabs/common/memory.c | 54 ++++++++++++++------------------
1 file changed, 24 insertions(+), 30 deletions(-)
diff --git a/drivers/accel/habanalabs/common/memory.c b/drivers/accel/habanalabs/common/memory.c
index 361cff577381..6745af1328c1 100644
--- a/drivers/accel/habanalabs/common/memory.c
+++ b/drivers/accel/habanalabs/common/memory.c
@@ -9,10 +9,10 @@
#include "habanalabs.h"
#include "../include/hw_ip/mmu/mmu_general.h"
+#include <linux/dma-buf-mapping.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
-#include <linux/pci-p2pdma.h>
MODULE_IMPORT_NS("DMA_BUF");
@@ -1704,23 +1704,6 @@ static struct sg_table *alloc_sgt_from_device_pages(struct hl_device *hdev, u64
return ERR_PTR(rc);
}
-static int hl_dmabuf_attach(struct dma_buf *dmabuf,
- struct dma_buf_attachment *attachment)
-{
- struct hl_dmabuf_priv *hl_dmabuf;
- struct hl_device *hdev;
- int rc;
-
- hl_dmabuf = dmabuf->priv;
- hdev = hl_dmabuf->ctx->hdev;
-
- rc = pci_p2pdma_distance(hdev->pdev, attachment->dev, true);
-
- if (rc < 0)
- attachment->peer2peer = false;
- return 0;
-}
-
static struct sg_table *hl_map_dmabuf(struct dma_buf_attachment *attachment,
enum dma_data_direction dir)
{
@@ -1734,11 +1717,6 @@ static struct sg_table *hl_map_dmabuf(struct dma_buf_attachment *attachment,
hl_dmabuf = dma_buf->priv;
hdev = hl_dmabuf->ctx->hdev;
- if (!attachment->peer2peer) {
- dev_dbg(hdev->dev, "Failed to map dmabuf because p2p is disabled\n");
- return ERR_PTR(-EPERM);
- }
-
exported_size = hl_dmabuf->dmabuf->size;
offset = hl_dmabuf->offset;
phys_pg_pack = hl_dmabuf->phys_pg_pack;
@@ -1753,8 +1731,10 @@ static struct sg_table *hl_map_dmabuf(struct dma_buf_attachment *attachment,
page_size = hl_dmabuf->dmabuf->size;
}
- sgt = alloc_sgt_from_device_pages(hdev, pages, npages, page_size, exported_size, offset,
- attachment->dev, dir);
+ sgt = alloc_sgt_from_device_pages(hdev, pages, npages, page_size,
+ exported_size, offset,
+ dma_buf_sgt_dma_device(attachment),
+ dir);
if (IS_ERR(sgt))
dev_err(hdev->dev, "failed (%ld) to initialize sgt for dmabuf\n", PTR_ERR(sgt));
@@ -1776,9 +1756,9 @@ static void hl_unmap_dmabuf(struct dma_buf_attachment *attachment,
* a sync of the memory to the CPU's cache, as it never resided inside that cache.
*/
for_each_sgtable_dma_sg(sgt, sg, i)
- dma_unmap_resource(attachment->dev, sg_dma_address(sg),
- sg_dma_len(sg), dir,
- DMA_ATTR_SKIP_CPU_SYNC);
+ dma_unmap_resource(dma_buf_sgt_dma_device(attachment),
+ sg_dma_address(sg), sg_dma_len(sg), dir,
+ DMA_ATTR_SKIP_CPU_SYNC);
/* Need to restore orig_nents because sg_free_table use that field */
sgt->orig_nents = sgt->nents;
@@ -1848,11 +1828,25 @@ static void hl_release_dmabuf(struct dma_buf *dmabuf)
kfree(hl_dmabuf);
}
-static const struct dma_buf_ops habanalabs_dmabuf_ops = {
- .attach = hl_dmabuf_attach,
+static const struct dma_buf_mapping_sgt_exp_ops hl_dma_buf_sgt_ops = {
.map_dma_buf = hl_map_dmabuf,
.unmap_dma_buf = hl_unmap_dmabuf,
+};
+
+static int hl_match_mapping(struct dma_buf_match_args *args)
+{
+ struct hl_dmabuf_priv *hl_dmabuf = args->dmabuf->priv;
+ struct dma_buf_mapping_match sgt_match[] = {
+ DMA_BUF_EMAPPING_SGT_P2P(&hl_dma_buf_sgt_ops,
+ hl_dmabuf->ctx->hdev->pdev),
+ };
+
+ return dma_buf_match_mapping(args, sgt_match, ARRAY_SIZE(sgt_match));
+}
+
+static const struct dma_buf_ops habanalabs_dmabuf_ops = {
.release = hl_release_dmabuf,
+ .match_mapping = hl_match_mapping,
};
static int export_dmabuf(struct hl_ctx *ctx,
--
2.54.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH v2 14/23] drm/xe/dma-buf: Use the SGT mapping type
2026-11-05 6:40 [PATCH v2 00/23] DMA-buf mapping types Alistair Popple
` (12 preceding siblings ...)
2026-11-05 6:40 ` [PATCH v2 13/23] accel/habanalabs: Use the SGT_P2P mapping type Alistair Popple
@ 2026-11-05 6:40 ` Alistair Popple
2026-11-05 6:40 ` [PATCH v2 15/23] drm/amdgpu: " Alistair Popple
` (9 subsequent siblings)
23 siblings, 0 replies; 26+ messages in thread
From: Alistair Popple @ 2026-11-05 6:40 UTC (permalink / raw)
To: Christian König, Sumit Semwal, Thomas Hellström,
Simona Vetter, Matthew Brost, Vivek Kasireddy, Dongwon Kim,
Kevin Tian, Xu Yilun, Karl Mehltretter, Baolu Lu, Felix Kuehling,
Alex Deucher, dri-devel, intel-xe, amd-gfx, linux-media,
linaro-mm-sig, linux-rdma, iommu, Keith Busch, Jens Axboe,
Christoph Hellwig, Sagi Grimberg, linux-nvme, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Mina Almasry, netdev, Alexey Kardashevskiy, zhipingz, treding,
jhubbard, Jason Gunthorpe, Leon Romanovsky
Cc: Alistair Popple
From: Jason Gunthorpe <jgg@nvidia.com>
Like habana, xe wants to check pci_p2pdma_distance(), but unlike
habana, it can migrate to system memory and support non-p2p DMAs as well.
Add two exporter SGT mapping types, one that matches P2P and one that
matches all of the non-p2p. The pin and map code will force migrate if
the non-p2p one is matched.
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Alistair Popple <apopple@nvidia.com>
---
drivers/gpu/drm/xe/xe_dma_buf.c | 79 +++++++++++++++++++++--------------------
1 file changed, 41 insertions(+), 38 deletions(-)
diff --git a/drivers/gpu/drm/xe/xe_dma_buf.c b/drivers/gpu/drm/xe/xe_dma_buf.c
index 6a85b292dee7..f9bdfe7ee2c7 100644
--- a/drivers/gpu/drm/xe/xe_dma_buf.c
+++ b/drivers/gpu/drm/xe/xe_dma_buf.c
@@ -7,8 +7,7 @@
#include <kunit/test.h>
#include <linux/dma-buf.h>
-#include <linux/dynamic_debug.h>
-#include <linux/pci-p2pdma.h>
+#include <linux/dma-buf-mapping.h>
#include <drm/drm_device.h>
#include <drm/drm_prime.h>
@@ -23,33 +22,10 @@
MODULE_IMPORT_NS("DMA_BUF");
-#if defined(CONFIG_DYNAMIC_DEBUG) || \
- (defined(CONFIG_DYNAMIC_DEBUG_CORE) && defined(DYNAMIC_DEBUG_MODULE))
-static void xe_ddebug_flip_bool(const struct _ddebug *desc, bool *flag)
-{
- *flag = true;
-}
-
-#define xe_dma_buf_p2p_debug_flip(flag) \
- _dynamic_func_call("xe dma-buf p2p debug", xe_ddebug_flip_bool, flag)
-#else
-#define xe_dma_buf_p2p_debug_flip(flag) do { } while (0)
-#endif
-
static int xe_dma_buf_attach(struct dma_buf *dmabuf,
struct dma_buf_attachment *attach)
{
struct drm_gem_object *obj = attach->dmabuf->priv;
- bool verbose_p2p_dist = drm_debug_enabled(DRM_UT_DRIVER);
-
- xe_dma_buf_p2p_debug_flip(&verbose_p2p_dist);
-
- if (attach->peer2peer &&
- pci_p2pdma_distance(to_pci_dev(obj->dev->dev), attach->dev, verbose_p2p_dist) < 0)
- attach->peer2peer = false;
-
- if (!attach->peer2peer && !xe_bo_can_migrate(gem_to_xe_bo(obj), XE_PL_TT))
- return -EOPNOTSUPP;
xe_pm_runtime_get(to_xe_device(obj->dev));
return 0;
@@ -70,13 +46,16 @@ static int xe_dma_buf_pin(struct dma_buf_attachment *attach)
struct xe_bo *bo = gem_to_xe_bo(obj);
struct xe_device *xe = xe_bo_device(bo);
struct drm_exec *exec = XE_VALIDATION_UNSUPPORTED;
- bool allow_vram = true;
+ bool allow_vram = dma_buf_sgt_p2p_allowed(attach);
int ret;
- list_for_each_entry(attach, &dmabuf->attachments, node) {
- if (!attach->peer2peer) {
- allow_vram = false;
- break;
+ if (allow_vram) {
+ /* Other attachments may be unmapped: ask what they accept */
+ list_for_each_entry(attach, &dmabuf->attachments, node) {
+ if (!dma_buf_attach_accepts_sgt_p2p(attach)) {
+ allow_vram = false;
+ break;
+ }
}
}
@@ -114,6 +93,8 @@ static void xe_dma_buf_unpin(struct dma_buf_attachment *attach)
static struct sg_table *xe_dma_buf_map(struct dma_buf_attachment *attach,
enum dma_data_direction dir)
{
+ struct device *dma_dev = dma_buf_sgt_dma_device(attach);
+ bool peer2peer = dma_buf_sgt_p2p_allowed(attach);
struct dma_buf *dma_buf = attach->dmabuf;
struct drm_gem_object *obj = dma_buf->priv;
struct xe_bo *bo = gem_to_xe_bo(obj);
@@ -124,11 +105,11 @@ static struct sg_table *xe_dma_buf_map(struct dma_buf_attachment *attach,
if (xe_bo_is_purged(bo))
return ERR_PTR(-ENOENT);
- if (!attach->peer2peer && !xe_bo_can_migrate(bo, XE_PL_TT))
+ if (!peer2peer && !xe_bo_can_migrate(bo, XE_PL_TT))
return ERR_PTR(-EOPNOTSUPP);
if (!xe_bo_is_pinned(bo)) {
- if (!attach->peer2peer)
+ if (!peer2peer)
r = xe_bo_migrate(bo, XE_PL_TT, NULL, exec);
else
r = xe_bo_validate(bo, NULL, false, exec);
@@ -144,7 +125,7 @@ static struct sg_table *xe_dma_buf_map(struct dma_buf_attachment *attach,
if (IS_ERR(sgt))
return sgt;
- if (dma_map_sgtable(attach->dev, sgt, dir,
+ if (dma_map_sgtable(dma_dev, sgt, dir,
DMA_ATTR_SKIP_CPU_SYNC))
goto error_free;
break;
@@ -153,7 +134,7 @@ static struct sg_table *xe_dma_buf_map(struct dma_buf_attachment *attach,
case XE_PL_VRAM1:
r = xe_ttm_vram_mgr_alloc_sgt(xe_bo_device(bo),
bo->ttm.resource, 0,
- bo->ttm.base.size, attach->dev,
+ bo->ttm.base.size, dma_dev,
dir, &sgt);
if (r)
return ERR_PTR(r);
@@ -174,12 +155,14 @@ static void xe_dma_buf_unmap(struct dma_buf_attachment *attach,
struct sg_table *sgt,
enum dma_data_direction dir)
{
+ struct device *dma_dev = dma_buf_sgt_dma_device(attach);
+
if (sg_page(sgt->sgl)) {
- dma_unmap_sgtable(attach->dev, sgt, dir, 0);
+ dma_unmap_sgtable(dma_dev, sgt, dir, 0);
sg_free_table(sgt);
kfree(sgt);
} else {
- xe_ttm_vram_mgr_free_sgt(attach->dev, dir, sgt);
+ xe_ttm_vram_mgr_free_sgt(dma_dev, dir, sgt);
}
}
@@ -225,18 +208,38 @@ static void xe_dma_buf_release(struct dma_buf *dmabuf)
drm_gem_dmabuf_release(dmabuf);
}
+static const struct dma_buf_mapping_sgt_exp_ops xe_dma_buf_sgt_ops = {
+ .map_dma_buf = xe_dma_buf_map,
+ .unmap_dma_buf = xe_dma_buf_unmap,
+};
+
+static int xe_dma_buf_match_mapping(struct dma_buf_match_args *args)
+{
+ struct drm_gem_object *obj = args->dmabuf->priv;
+ struct dma_buf_mapping_match sgt_match[2];
+ unsigned int num_match = 0;
+
+ sgt_match[num_match++] = DMA_BUF_EMAPPING_SGT_P2P(
+ &xe_dma_buf_sgt_ops, to_pci_dev(obj->dev->dev));
+
+ if (xe_bo_can_migrate(gem_to_xe_bo(obj), XE_PL_TT))
+ sgt_match[num_match++] =
+ DMA_BUF_EMAPPING_SGT(&xe_dma_buf_sgt_ops);
+
+ return dma_buf_match_mapping(args, sgt_match, num_match);
+}
+
static const struct dma_buf_ops xe_dmabuf_ops = {
.attach = xe_dma_buf_attach,
.detach = xe_dma_buf_detach,
.pin = xe_dma_buf_pin,
.unpin = xe_dma_buf_unpin,
- .map_dma_buf = xe_dma_buf_map,
- .unmap_dma_buf = xe_dma_buf_unmap,
.release = xe_dma_buf_release,
.begin_cpu_access = xe_dma_buf_begin_cpu_access,
.mmap = drm_gem_dmabuf_mmap,
.vmap = drm_gem_dmabuf_vmap,
.vunmap = drm_gem_dmabuf_vunmap,
+ .match_mapping = xe_dma_buf_match_mapping,
};
struct dma_buf *xe_gem_prime_export(struct drm_gem_object *obj, int flags)
--
2.54.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH v2 15/23] drm/amdgpu: Use the SGT mapping type
2026-11-05 6:40 [PATCH v2 00/23] DMA-buf mapping types Alistair Popple
` (13 preceding siblings ...)
2026-11-05 6:40 ` [PATCH v2 14/23] drm/xe/dma-buf: Use the SGT " Alistair Popple
@ 2026-11-05 6:40 ` Alistair Popple
2026-11-05 6:40 ` [PATCH v2 16/23] vfio/pci: Change the DMA-buf exporter to use mapping_type Alistair Popple
` (8 subsequent siblings)
23 siblings, 0 replies; 26+ messages in thread
From: Alistair Popple @ 2026-11-05 6:40 UTC (permalink / raw)
To: Christian König, Sumit Semwal, Thomas Hellström,
Simona Vetter, Matthew Brost, Vivek Kasireddy, Dongwon Kim,
Kevin Tian, Xu Yilun, Karl Mehltretter, Baolu Lu, Felix Kuehling,
Alex Deucher, dri-devel, intel-xe, amd-gfx, linux-media,
linaro-mm-sig, linux-rdma, iommu, Keith Busch, Jens Axboe,
Christoph Hellwig, Sagi Grimberg, linux-nvme, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Mina Almasry, netdev, Alexey Kardashevskiy, zhipingz, treding,
jhubbard, Jason Gunthorpe, Leon Romanovsky
Cc: Alistair Popple
From: Jason Gunthorpe <jgg@nvidia.com>
Similar to xe, amdgpu wants to check pci_p2pdma_distance(), and
only needs that if peer2peer can be supported by the GPU. It can migrate to
system memory and support non-p2p DMA as well.
Further it supports a private non-PCI XGMI path. For now hack this on top
of a SGT type, but eventually this is likely better off as its own mapping
type.
Add two exporter SGT mapping types, one that matches P2P and one that
matches all of the non-p2p. The pin and map code will force migrate if
the non-p2p one is matched.
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Alistair Popple <apopple@nvidia.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 136 ++++++++++++++++++----------
1 file changed, 90 insertions(+), 46 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
index bbe518757907..edb74e2f4e26 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
@@ -41,6 +41,7 @@
#include <drm/amdgpu_drm.h>
#include <drm/ttm/ttm_tt.h>
#include <linux/dma-buf.h>
+#include <linux/dma-buf-mapping.h>
#include <linux/dma-fence-array.h>
#include <linux/pci-p2pdma.h>
#include <linux/pm_runtime.h>
@@ -79,43 +80,11 @@ static struct amdgpu_device *dma_buf_attach_adev(struct dma_buf_attachment *atta
static int amdgpu_dma_buf_attach(struct dma_buf *dmabuf,
struct dma_buf_attachment *attach)
{
- struct amdgpu_device *attach_adev = dma_buf_attach_adev(attach);
struct drm_gem_object *obj = dmabuf->priv;
struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
int r;
- /*
- * Disable peer-to-peer access for DCC-enabled VRAM surfaces on GFX12+.
- * Such buffers cannot be safely accessed over P2P due to device-local
- * compression metadata. Fallback to system-memory path instead.
- * Device supports GFX12 (GC 12.x or newer)
- * BO was created with the AMDGPU_GEM_CREATE_GFX12_DCC flag
- *
- */
- if (amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(12, 0, 0) &&
- bo->flags & AMDGPU_GEM_CREATE_GFX12_DCC)
- attach->peer2peer = false;
-
- if (!amdgpu_dmabuf_is_xgmi_accessible(attach_adev, bo) &&
- pci_p2pdma_distance(adev->pdev, attach->dev, false) < 0)
- attach->peer2peer = false;
-
- /*
- * Only allow P2P while the exporter is active, and keep it active
- * until detach. With runtime PM disabled take a plain reference so
- * the put in detach stays balanced.
- */
- if (attach->peer2peer) {
- struct device *dev = adev_to_drm(adev)->dev;
- int ret = pm_runtime_get_if_active(dev);
-
- if (!ret)
- attach->peer2peer = false;
- else if (ret < 0)
- pm_runtime_get_noresume(dev);
- }
-
r = dma_resv_lock(bo->tbo.base.resv, NULL);
if (r)
goto err_pm_put;
@@ -127,7 +96,8 @@ static int amdgpu_dma_buf_attach(struct dma_buf *dmabuf,
return 0;
err_pm_put:
- if (attach->peer2peer)
+ /* Drop the reference taken in amdgpu_dma_buf_match_mapping() */
+ if (dma_buf_attach_accepts_sgt_p2p(attach))
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
return r;
}
@@ -138,7 +108,7 @@ static int amdgpu_dma_buf_attach(struct dma_buf *dmabuf,
* @dmabuf: DMA-buf where we remove the attachment from
* @attach: the attachment to remove
*
- * Drop the runtime PM reference taken in amdgpu_dma_buf_attach().
+ * Drop the runtime PM reference taken in amdgpu_dma_buf_match_mapping().
*/
static void amdgpu_dma_buf_detach(struct dma_buf *dmabuf,
struct dma_buf_attachment *attach)
@@ -147,7 +117,7 @@ static void amdgpu_dma_buf_detach(struct dma_buf *dmabuf,
struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
- if (attach->peer2peer)
+ if (dma_buf_attach_accepts_sgt_p2p(attach))
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
}
@@ -175,7 +145,7 @@ static int amdgpu_dma_buf_pin(struct dma_buf_attachment *attach)
* notiers are enabled.
*/
list_for_each_entry(attach, &dmabuf->attachments, node)
- if (!attach->peer2peer)
+ if (!dma_buf_attach_accepts_sgt_p2p(attach))
domains &= ~AMDGPU_GEM_DOMAIN_VRAM;
if (domains & AMDGPU_GEM_DOMAIN_VRAM)
@@ -218,6 +188,7 @@ static void amdgpu_dma_buf_unpin(struct dma_buf_attachment *attach)
static struct sg_table *amdgpu_dma_buf_map(struct dma_buf_attachment *attach,
enum dma_data_direction dir)
{
+ struct device *dma_dev = dma_buf_sgt_dma_device(attach);
struct dma_buf *dma_buf = attach->dmabuf;
struct drm_gem_object *obj = dma_buf->priv;
struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
@@ -231,7 +202,7 @@ static struct sg_table *amdgpu_dma_buf_map(struct dma_buf_attachment *attach,
unsigned int domains = AMDGPU_GEM_DOMAIN_GTT;
if (bo->preferred_domains & AMDGPU_GEM_DOMAIN_VRAM &&
- attach->peer2peer) {
+ dma_buf_sgt_p2p_allowed(attach)) {
bo->flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
domains |= AMDGPU_GEM_DOMAIN_VRAM;
}
@@ -249,7 +220,7 @@ static struct sg_table *amdgpu_dma_buf_map(struct dma_buf_attachment *attach,
if (IS_ERR(sgt))
return sgt;
- if (dma_map_sgtable(attach->dev, sgt, dir,
+ if (dma_map_sgtable(dma_dev, sgt, dir,
DMA_ATTR_SKIP_CPU_SYNC))
goto error_free;
break;
@@ -261,7 +232,7 @@ static struct sg_table *amdgpu_dma_buf_map(struct dma_buf_attachment *attach,
return ERR_PTR(-EINVAL);
r = amdgpu_vram_mgr_alloc_sgt(adev, bo->tbo.resource, 0,
- bo->tbo.base.size, attach->dev,
+ bo->tbo.base.size, dma_dev,
dir, &sgt);
if (r)
return ERR_PTR(r);
@@ -269,7 +240,7 @@ static struct sg_table *amdgpu_dma_buf_map(struct dma_buf_attachment *attach,
case AMDGPU_PL_MMIO_REMAP:
r = amdgpu_ttm_mmio_remap_alloc_sgt(adev, bo->tbo.resource,
- attach->dev, dir, &sgt);
+ dma_dev, dir, &sgt);
if (r)
return ERR_PTR(r);
break;
@@ -299,21 +270,22 @@ static void amdgpu_dma_buf_unmap(struct dma_buf_attachment *attach,
struct sg_table *sgt,
enum dma_data_direction dir)
{
+ struct device *dma_dev = dma_buf_sgt_dma_device(attach);
struct drm_gem_object *obj = attach->dmabuf->priv;
struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
if (bo->tbo.resource &&
bo->tbo.resource->mem_type == AMDGPU_PL_MMIO_REMAP) {
- amdgpu_ttm_mmio_remap_free_sgt(attach->dev, dir, sgt);
+ amdgpu_ttm_mmio_remap_free_sgt(dma_dev, dir, sgt);
return;
}
if (sg_page(sgt->sgl)) {
- dma_unmap_sgtable(attach->dev, sgt, dir, 0);
+ dma_unmap_sgtable(dma_dev, sgt, dir, 0);
sg_free_table(sgt);
kfree(sgt);
} else {
- amdgpu_vram_mgr_free_sgt(attach->dev, dir, sgt);
+ amdgpu_vram_mgr_free_sgt(dma_dev, dir, sgt);
}
}
@@ -388,18 +360,90 @@ static void amdgpu_dma_buf_vunmap(struct dma_buf *dma_buf, struct iosys_map *map
amdgpu_bo_unpin(bo);
}
+static const struct dma_buf_mapping_sgt_exp_ops amdgpu_dma_buf_sgt_ops = {
+ .map_dma_buf = amdgpu_dma_buf_map,
+ .unmap_dma_buf = amdgpu_dma_buf_unmap,
+};
+
+static int amdgpu_dma_buf_match_mapping(struct dma_buf_match_args *args)
+{
+ struct dma_buf_attachment *attach = args->attach;
+ struct drm_gem_object *obj = args->dmabuf->priv;
+ struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
+ struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
+ struct device *dev = adev_to_drm(adev)->dev;
+ struct dma_buf_mapping_match sgt_match[2];
+ unsigned int num_match = 0;
+ bool peer2peer = true;
+ int ret;
+
+ /*
+ * Disable peer-to-peer access for DCC-enabled VRAM surfaces on GFX12+.
+ * Such buffers cannot be safely accessed over P2P due to device-local
+ * compression metadata. Fallback to system-memory path instead.
+ * Device supports GFX12 (GC 12.x or newer)
+ * BO was created with the AMDGPU_GEM_CREATE_GFX12_DCC flag
+ *
+ */
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(12, 0, 0) &&
+ bo->flags & AMDGPU_GEM_CREATE_GFX12_DCC)
+ peer2peer = false;
+
+ /*
+ * Only allow P2P while the exporter is active, and keep it active
+ * until detach. With runtime PM disabled take a plain reference so
+ * the put in detach stays balanced.
+ */
+ if (peer2peer) {
+ ret = pm_runtime_get_if_active(dev);
+ if (!ret)
+ peer2peer = false;
+ else if (ret < 0)
+ pm_runtime_get_noresume(dev);
+ }
+
+ if (peer2peer)
+ sgt_match[num_match++] = DMA_BUF_EMAPPING_SGT_P2P(
+ &amdgpu_dma_buf_sgt_ops, adev->pdev);
+ sgt_match[num_match++] = DMA_BUF_EMAPPING_SGT(&amdgpu_dma_buf_sgt_ops);
+
+ ret = dma_buf_match_mapping(args, sgt_match, num_match);
+ if (ret)
+ goto err_pm_put;
+
+ /*
+ * If the transfer will use XGMI then force a P2P match: the importer
+ * reaches VRAM over XGMI, so the BO may stay there even though PCIe
+ * P2P did not match. Rewrite the recorded match set entry, which is
+ * what dma_buf_mapping_select() picks from at pin or map time.
+ */
+ if (peer2peer && !dma_buf_attach_accepts_sgt_p2p(attach) &&
+ amdgpu_dmabuf_is_xgmi_accessible(dma_buf_attach_adev(attach), bo))
+ attach->matches[0].sgt_data.exporter_requires_p2p =
+ DMA_SGT_EXPORTER_REQUIRES_P2P_DISTANCE;
+
+ /* The PM reference is only needed while P2P is actually possible. */
+ if (peer2peer && !dma_buf_attach_accepts_sgt_p2p(attach))
+ pm_runtime_put_autosuspend(dev);
+ return 0;
+
+err_pm_put:
+ if (peer2peer)
+ pm_runtime_put_autosuspend(dev);
+ return ret;
+}
+
const struct dma_buf_ops amdgpu_dmabuf_ops = {
.attach = amdgpu_dma_buf_attach,
.detach = amdgpu_dma_buf_detach,
.pin = amdgpu_dma_buf_pin,
.unpin = amdgpu_dma_buf_unpin,
- .map_dma_buf = amdgpu_dma_buf_map,
- .unmap_dma_buf = amdgpu_dma_buf_unmap,
.release = drm_gem_dmabuf_release,
.begin_cpu_access = amdgpu_dma_buf_begin_cpu_access,
.mmap = drm_gem_dmabuf_mmap,
.vmap = amdgpu_dma_buf_vmap,
.vunmap = amdgpu_dma_buf_vunmap,
+ .match_mapping = amdgpu_dma_buf_match_mapping,
};
/**
@@ -635,7 +679,7 @@ struct drm_gem_object *amdgpu_gem_prime_import(struct drm_device *dev,
* budget normally, so drop AMDGPU_GEM_CREATE_PREEMPTIBLE again. The
* BO is not published yet, so clearing the flag here is race-free.
*/
- if (!attach->peer2peer)
+ if (!dma_buf_attach_accepts_sgt_p2p(attach))
gem_to_amdgpu_bo(obj)->flags &= ~AMDGPU_GEM_CREATE_PREEMPTIBLE;
get_dma_buf(dma_buf);
--
2.54.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH v2 16/23] vfio/pci: Change the DMA-buf exporter to use mapping_type
2026-11-05 6:40 [PATCH v2 00/23] DMA-buf mapping types Alistair Popple
` (14 preceding siblings ...)
2026-11-05 6:40 ` [PATCH v2 15/23] drm/amdgpu: " Alistair Popple
@ 2026-11-05 6:40 ` Alistair Popple
2026-11-05 6:40 ` [PATCH v2 17/23] RDMA/uverbs: Use the SGT_P2P mapping type Alistair Popple
` (7 subsequent siblings)
23 siblings, 0 replies; 26+ messages in thread
From: Alistair Popple @ 2026-11-05 6:40 UTC (permalink / raw)
To: Christian König, Sumit Semwal, Thomas Hellström,
Simona Vetter, Matthew Brost, Vivek Kasireddy, Dongwon Kim,
Kevin Tian, Xu Yilun, Karl Mehltretter, Baolu Lu, Felix Kuehling,
Alex Deucher, dri-devel, intel-xe, amd-gfx, linux-media,
linaro-mm-sig, linux-rdma, iommu, Keith Busch, Jens Axboe,
Christoph Hellwig, Sagi Grimberg, linux-nvme, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Mina Almasry, netdev, Alexey Kardashevskiy, zhipingz, treding,
jhubbard, Jason Gunthorpe, Leon Romanovsky
Cc: Alistair Popple
From: Jason Gunthorpe <jgg@nvidia.com>
Simple conversion to add a match_mapping() callback that offers an
exporter SGT mapping type. Later patches will add a physical address
exporter so go straight to adding the match_mapping() function.
The check for attachment->peer2peer is replaced with setting
exporter_requires_p2p=true. VFIO always uses MMIO memory.
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Alistair Popple <apopple@nvidia.com>
---
drivers/vfio/pci/vfio_pci_dmabuf.c | 26 +++++++++++++++++++++-----
1 file changed, 21 insertions(+), 5 deletions(-)
diff --git a/drivers/vfio/pci/vfio_pci_dmabuf.c b/drivers/vfio/pci/vfio_pci_dmabuf.c
index c16f460c01d6..ebbdbcc6ecbf 100644
--- a/drivers/vfio/pci/vfio_pci_dmabuf.c
+++ b/drivers/vfio/pci/vfio_pci_dmabuf.c
@@ -27,9 +27,6 @@ static int vfio_pci_dma_buf_attach(struct dma_buf *dmabuf,
{
struct vfio_pci_dma_buf *priv = dmabuf->priv;
- if (!attachment->peer2peer)
- return -EOPNOTSUPP;
-
if (priv->revoked)
return -ENODEV;
@@ -99,11 +96,30 @@ static void vfio_pci_dma_buf_release(struct dma_buf *dmabuf)
kfree(priv);
}
-static const struct dma_buf_ops vfio_pci_dmabuf_ops = {
- .attach = vfio_pci_dma_buf_attach,
+static const struct dma_buf_mapping_sgt_exp_ops vfio_pci_dma_buf_sgt_ops = {
.map_dma_buf = vfio_pci_dma_buf_map,
.unmap_dma_buf = vfio_pci_dma_buf_unmap,
+};
+
+static int vfio_pci_dma_buf_match_mapping(struct dma_buf_match_args *args)
+{
+ struct dma_buf_mapping_match sgt_match[1];
+
+ /*
+ * MMIO, so the importer must accept P2P, but it need not be a PCI
+ * device: iommufd attaches with its own non-PCI device and programs
+ * physical addresses. Reachability is checked when mapping, by
+ * dma_buf_phys_vec_to_sgt().
+ */
+ sgt_match[0] = DMA_BUF_EMAPPING_SGT_REQUIRES_P2P(&vfio_pci_dma_buf_sgt_ops);
+
+ return dma_buf_match_mapping(args, sgt_match, ARRAY_SIZE(sgt_match));
+}
+
+static const struct dma_buf_ops vfio_pci_dmabuf_ops = {
+ .attach = vfio_pci_dma_buf_attach,
.release = vfio_pci_dma_buf_release,
+ .match_mapping = vfio_pci_dma_buf_match_mapping,
};
/*
--
2.54.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH v2 17/23] RDMA/uverbs: Use the SGT_P2P mapping type
2026-11-05 6:40 [PATCH v2 00/23] DMA-buf mapping types Alistair Popple
` (15 preceding siblings ...)
2026-11-05 6:40 ` [PATCH v2 16/23] vfio/pci: Change the DMA-buf exporter to use mapping_type Alistair Popple
@ 2026-11-05 6:40 ` Alistair Popple
2026-11-05 6:40 ` [PATCH v2 18/23] dma-buf: Update dma_buf_phys_vec_to_sgt() to use the SGT " Alistair Popple
` (6 subsequent siblings)
23 siblings, 0 replies; 26+ messages in thread
From: Alistair Popple @ 2026-11-05 6:40 UTC (permalink / raw)
To: Christian König, Sumit Semwal, Thomas Hellström,
Simona Vetter, Matthew Brost, Vivek Kasireddy, Dongwon Kim,
Kevin Tian, Xu Yilun, Karl Mehltretter, Baolu Lu, Felix Kuehling,
Alex Deucher, dri-devel, intel-xe, amd-gfx, linux-media,
linaro-mm-sig, linux-rdma, iommu, Keith Busch, Jens Axboe,
Christoph Hellwig, Sagi Grimberg, linux-nvme, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Mina Almasry, netdev, Alexey Kardashevskiy, zhipingz, treding,
jhubbard, Jason Gunthorpe, Leon Romanovsky
Cc: Alistair Popple
From: Jason Gunthorpe <jgg@nvidia.com>
Very similar to habana, except the rejection of unsupported
pci_p2p_dma_distance() is done inside map not attach via
dma_buf_phys_vec_to_sgt().
Convert this directly to a SGT_P2P match which will prevent matching if
dma_buf_phys_vec_to_sgt() would fail.
Remove the now empty attach function.
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Alistair Popple <apopple@nvidia.com>
---
drivers/infiniband/core/uverbs_std_types_dmabuf.c | 30 ++++++++++++++---------
1 file changed, 19 insertions(+), 11 deletions(-)
diff --git a/drivers/infiniband/core/uverbs_std_types_dmabuf.c b/drivers/infiniband/core/uverbs_std_types_dmabuf.c
index 8d8c997a4883..0bae578c3d78 100644
--- a/drivers/infiniband/core/uverbs_std_types_dmabuf.c
+++ b/drivers/infiniband/core/uverbs_std_types_dmabuf.c
@@ -12,15 +12,6 @@
MODULE_IMPORT_NS("DMA_BUF");
-static int uverbs_dmabuf_attach(struct dma_buf *dmabuf,
- struct dma_buf_attachment *attachment)
-{
- if (!attachment->peer2peer)
- return -EOPNOTSUPP;
-
- return 0;
-}
-
static struct sg_table *
uverbs_dmabuf_map(struct dma_buf_attachment *attachment,
enum dma_data_direction dir)
@@ -95,13 +86,30 @@ static void uverbs_dmabuf_release(struct dma_buf *dmabuf)
uverbs_uobject_put(&priv->uobj);
}
-static const struct dma_buf_ops uverbs_dmabuf_ops = {
- .attach = uverbs_dmabuf_attach,
+static const struct dma_buf_mapping_sgt_exp_ops uverbs_dma_buf_sgt_ops = {
.map_dma_buf = uverbs_dmabuf_map,
.unmap_dma_buf = uverbs_dmabuf_unmap,
+};
+
+static int uverbs_dmabuf_match_mapping(struct dma_buf_match_args *args)
+{
+ struct dma_buf_mapping_match sgt_match[1];
+
+ /*
+ * MMIO, so the importer must accept P2P. The provider is only valid
+ * under the dma_resv lock while not revoked, so the distance check is
+ * left to dma_buf_phys_vec_to_sgt() at map time, as before.
+ */
+ sgt_match[0] = DMA_BUF_EMAPPING_SGT_REQUIRES_P2P(&uverbs_dma_buf_sgt_ops);
+
+ return dma_buf_match_mapping(args, sgt_match, ARRAY_SIZE(sgt_match));
+}
+
+static const struct dma_buf_ops uverbs_dmabuf_ops = {
.pin = uverbs_dmabuf_pin,
.unpin = uverbs_dmabuf_unpin,
.release = uverbs_dmabuf_release,
+ .match_mapping = uverbs_dmabuf_match_mapping,
};
static int UVERBS_HANDLER(UVERBS_METHOD_DMABUF_ALLOC)(
--
2.54.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH v2 18/23] dma-buf: Update dma_buf_phys_vec_to_sgt() to use the SGT mapping type
2026-11-05 6:40 [PATCH v2 00/23] DMA-buf mapping types Alistair Popple
` (16 preceding siblings ...)
2026-11-05 6:40 ` [PATCH v2 17/23] RDMA/uverbs: Use the SGT_P2P mapping type Alistair Popple
@ 2026-11-05 6:40 ` Alistair Popple
2026-11-05 6:40 ` [PATCH v2 19/23] iio: buffer: convert " Alistair Popple
` (5 subsequent siblings)
23 siblings, 0 replies; 26+ messages in thread
From: Alistair Popple @ 2026-11-05 6:40 UTC (permalink / raw)
To: Christian König, Sumit Semwal, Thomas Hellström,
Simona Vetter, Matthew Brost, Vivek Kasireddy, Dongwon Kim,
Kevin Tian, Xu Yilun, Karl Mehltretter, Baolu Lu, Felix Kuehling,
Alex Deucher, dri-devel, intel-xe, amd-gfx, linux-media,
linaro-mm-sig, linux-rdma, iommu, Keith Busch, Jens Axboe,
Christoph Hellwig, Sagi Grimberg, linux-nvme, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Mina Almasry, netdev, Alexey Kardashevskiy, zhipingz, treding,
jhubbard, Jason Gunthorpe, Leon Romanovsky
Cc: Alistair Popple
From: Jason Gunthorpe <jgg@nvidia.com>
These helpers only work when matched to a SGT mapping type, call
dma_buf_sgt_dma_device() to get the DMA device.
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Alistair Popple <apopple@nvidia.com>
---
drivers/dma-buf/dma-buf-mapping.c | 22 ++++++++++++----------
1 file changed, 12 insertions(+), 10 deletions(-)
diff --git a/drivers/dma-buf/dma-buf-mapping.c b/drivers/dma-buf/dma-buf-mapping.c
index 264c9293438f..ea5762a73730 100644
--- a/drivers/dma-buf/dma-buf-mapping.c
+++ b/drivers/dma-buf/dma-buf-mapping.c
@@ -105,6 +105,7 @@ struct sg_table *dma_buf_phys_vec_to_sgt(struct dma_buf_attachment *attach,
size_t nr_ranges, size_t size,
enum dma_data_direction dir)
{
+ struct device *dma_dev = dma_buf_sgt_dma_device(attach);
struct dma_buf_dma *dma;
struct scatterlist *sgl;
size_t mapped_len = 0;
@@ -123,7 +124,7 @@ struct sg_table *dma_buf_phys_vec_to_sgt(struct dma_buf_attachment *attach,
if (!dma)
return ERR_PTR(-ENOMEM);
- switch (pci_p2pdma_map_type(provider, attach->dev)) {
+ switch (pci_p2pdma_map_type(provider, dma_dev)) {
case PCI_P2PDMA_MAP_BUS_ADDR:
/*
* There is no need in IOVA at all for this flow.
@@ -136,7 +137,7 @@ struct sg_table *dma_buf_phys_vec_to_sgt(struct dma_buf_attachment *attach,
goto err_free_dma;
}
- dma_iova_try_alloc(attach->dev, dma->state, 0, size);
+ dma_iova_try_alloc(dma_dev, dma->state, 0, size);
break;
default:
ret = -EINVAL;
@@ -157,7 +158,7 @@ struct sg_table *dma_buf_phys_vec_to_sgt(struct dma_buf_attachment *attach,
addr = pci_p2pdma_bus_addr_map(provider,
phys_vec[i].paddr);
} else if (dma_use_iova(dma->state)) {
- ret = dma_iova_link(attach->dev, dma->state,
+ ret = dma_iova_link(dma_dev, dma->state,
phys_vec[i].paddr, 0,
phys_vec[i].len, dir,
DMA_ATTR_MMIO);
@@ -166,10 +167,10 @@ struct sg_table *dma_buf_phys_vec_to_sgt(struct dma_buf_attachment *attach,
mapped_len += phys_vec[i].len;
} else {
- addr = dma_map_phys(attach->dev, phys_vec[i].paddr,
+ addr = dma_map_phys(dma_dev, phys_vec[i].paddr,
phys_vec[i].len, dir,
DMA_ATTR_MMIO);
- ret = dma_mapping_error(attach->dev, addr);
+ ret = dma_mapping_error(dma_dev, addr);
if (ret)
goto err_unmap_dma;
}
@@ -180,7 +181,7 @@ struct sg_table *dma_buf_phys_vec_to_sgt(struct dma_buf_attachment *attach,
if (dma->state && dma_use_iova(dma->state)) {
WARN_ON_ONCE(mapped_len != size);
- ret = dma_iova_sync(attach->dev, dma->state, 0, mapped_len);
+ ret = dma_iova_sync(dma_dev, dma->state, 0, mapped_len);
if (ret)
goto err_unmap_dma;
@@ -207,11 +208,11 @@ struct sg_table *dma_buf_phys_vec_to_sgt(struct dma_buf_attachment *attach,
if (!i || !dma->state) {
; /* Do nothing */
} else if (dma_use_iova(dma->state)) {
- dma_iova_destroy(attach->dev, dma->state, mapped_len, dir,
+ dma_iova_destroy(dma_dev, dma->state, mapped_len, dir,
DMA_ATTR_MMIO);
} else {
for_each_sgtable_dma_sg(&dma->sgt, sgl, i)
- dma_unmap_phys(attach->dev, sg_dma_address(sgl),
+ dma_unmap_phys(dma_dev, sg_dma_address(sgl),
sg_dma_len(sgl), dir, DMA_ATTR_MMIO);
}
sg_free_table(&dma->sgt);
@@ -236,6 +237,7 @@ void dma_buf_free_sgt(struct dma_buf_attachment *attach, struct sg_table *sgt,
enum dma_data_direction dir)
{
struct dma_buf_dma *dma = container_of(sgt, struct dma_buf_dma, sgt);
+ struct device *dma_dev = dma_buf_sgt_dma_device(attach);
int i;
dma_resv_assert_held(attach->dmabuf->resv);
@@ -243,13 +245,13 @@ void dma_buf_free_sgt(struct dma_buf_attachment *attach, struct sg_table *sgt,
if (!dma->state) {
; /* Do nothing */
} else if (dma_use_iova(dma->state)) {
- dma_iova_destroy(attach->dev, dma->state, dma->size, dir,
+ dma_iova_destroy(dma_dev, dma->state, dma->size, dir,
DMA_ATTR_MMIO);
} else {
struct scatterlist *sgl;
for_each_sgtable_dma_sg(sgt, sgl, i)
- dma_unmap_phys(attach->dev, sg_dma_address(sgl),
+ dma_unmap_phys(dma_dev, sg_dma_address(sgl),
sg_dma_len(sgl), dir, DMA_ATTR_MMIO);
}
--
2.54.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH v2 19/23] iio: buffer: convert to use the SGT mapping type
2026-11-05 6:40 [PATCH v2 00/23] DMA-buf mapping types Alistair Popple
` (17 preceding siblings ...)
2026-11-05 6:40 ` [PATCH v2 18/23] dma-buf: Update dma_buf_phys_vec_to_sgt() to use the SGT " Alistair Popple
@ 2026-11-05 6:40 ` Alistair Popple
2026-11-05 6:40 ` [PATCH v2 20/23] functionfs: " Alistair Popple
` (4 subsequent siblings)
23 siblings, 0 replies; 26+ messages in thread
From: Alistair Popple @ 2026-11-05 6:40 UTC (permalink / raw)
To: Christian König, Sumit Semwal, Thomas Hellström,
Simona Vetter, Matthew Brost, Vivek Kasireddy, Dongwon Kim,
Kevin Tian, Xu Yilun, Karl Mehltretter, Baolu Lu, Felix Kuehling,
Alex Deucher, dri-devel, intel-xe, amd-gfx, linux-media,
linaro-mm-sig, linux-rdma, iommu, Keith Busch, Jens Axboe,
Christoph Hellwig, Sagi Grimberg, linux-nvme, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Mina Almasry, netdev, Alexey Kardashevskiy, zhipingz, treding,
jhubbard, Jason Gunthorpe, Leon Romanovsky
Cc: Alistair Popple
From: Jason Gunthorpe <jgg@nvidia.com>
These importer helper functions should call dma_buf_sgt_dma_device() as
they are always working with SGTs.
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Alistair Popple <apopple@nvidia.com>
---
drivers/iio/industrialio-buffer.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index 4a1063e4891f..f907fb6ca936 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -16,6 +16,7 @@
#include <linux/export.h>
#include <linux/device.h>
#include <linux/dma-buf.h>
+#include <linux/dma-buf-mapping.h>
#include <linux/dma-fence.h>
#include <linux/dma-resv.h>
#include <linux/file.h>
@@ -1676,7 +1677,7 @@ iio_buffer_find_attachment(struct iio_dev_buffer_pair *ib,
guard(mutex)(&buffer->dmabufs_mutex);
list_for_each_entry(priv, &buffer->dmabufs, entry) {
- if (priv->attach->dev == dma_dev
+ if (dma_buf_sgt_dma_device(priv->attach) == dma_dev
&& priv->attach->dmabuf == dmabuf) {
attach = priv->attach;
break;
@@ -1760,7 +1761,7 @@ static int iio_buffer_attach_dmabuf(struct iio_dev_buffer_pair *ib,
* combo. If we do, refuse to attach.
*/
list_for_each_entry(each, &buffer->dmabufs, entry) {
- if (each->attach->dev == dma_dev
+ if (dma_buf_sgt_dma_device(each->attach) == dma_dev
&& each->attach->dmabuf == dmabuf) {
/*
* We unlocked the reservation object, so going through
@@ -1814,7 +1815,7 @@ static int iio_buffer_detach_dmabuf(struct iio_dev_buffer_pair *ib,
guard(mutex)(&buffer->dmabufs_mutex);
list_for_each_entry(priv, &buffer->dmabufs, entry) {
- if (priv->attach->dev == dma_dev
+ if (dma_buf_sgt_dma_device(priv->attach) == dma_dev
&& priv->attach->dmabuf == dmabuf) {
list_del(&priv->entry);
--
2.54.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH v2 20/23] functionfs: convert to use the SGT mapping type
2026-11-05 6:40 [PATCH v2 00/23] DMA-buf mapping types Alistair Popple
` (18 preceding siblings ...)
2026-11-05 6:40 ` [PATCH v2 19/23] iio: buffer: convert " Alistair Popple
@ 2026-11-05 6:40 ` Alistair Popple
2026-11-05 6:40 ` [PATCH v2 21/23] dma-buf: Remove unused SGT stuff from the common structures Alistair Popple
` (3 subsequent siblings)
23 siblings, 0 replies; 26+ messages in thread
From: Alistair Popple @ 2026-11-05 6:40 UTC (permalink / raw)
To: Christian König, Sumit Semwal, Thomas Hellström,
Simona Vetter, Matthew Brost, Vivek Kasireddy, Dongwon Kim,
Kevin Tian, Xu Yilun, Karl Mehltretter, Baolu Lu, Felix Kuehling,
Alex Deucher, dri-devel, intel-xe, amd-gfx, linux-media,
linaro-mm-sig, linux-rdma, iommu, Keith Busch, Jens Axboe,
Christoph Hellwig, Sagi Grimberg, linux-nvme, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Mina Almasry, netdev, Alexey Kardashevskiy, zhipingz, treding,
jhubbard, Jason Gunthorpe, Leon Romanovsky
Cc: Alistair Popple
From: Jason Gunthorpe <jgg@nvidia.com>
These importer helper functions should call dma_buf_sgt_dma_device() as
they are always working with SGTs.
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Alistair Popple <apopple@nvidia.com>
---
drivers/usb/gadget/function/f_fs.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index 2f221d0a983f..1efadf2c0f73 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -16,6 +16,7 @@
#include <linux/blkdev.h>
#include <linux/dma-buf.h>
+#include <linux/dma-buf-mapping.h>
#include <linux/dma-fence.h>
#include <linux/dma-resv.h>
#include <linux/pagemap.h>
@@ -1514,7 +1515,7 @@ ffs_dmabuf_find_attachment(struct ffs_epfile *epfile, struct dma_buf *dmabuf)
mutex_lock(&epfile->dmabufs_mutex);
list_for_each_entry(priv, &epfile->dmabufs, entry) {
- if (priv->attach->dev == dev
+ if (dma_buf_sgt_dma_device(priv->attach) == dev
&& priv->attach->dmabuf == dmabuf) {
attach = priv->attach;
break;
@@ -1616,7 +1617,7 @@ static int ffs_dmabuf_detach(struct file *file, int fd)
mutex_lock(&epfile->dmabufs_mutex);
list_for_each_entry_safe(priv, tmp, &epfile->dmabufs, entry) {
- if (priv->attach->dev == dev
+ if (dma_buf_sgt_dma_device(priv->attach) == dev
&& priv->attach->dmabuf == dmabuf) {
/* Cancel any pending transfer */
spin_lock_irq(&ffs->eps_lock);
--
2.54.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH v2 21/23] dma-buf: Remove unused SGT stuff from the common structures
2026-11-05 6:40 [PATCH v2 00/23] DMA-buf mapping types Alistair Popple
` (19 preceding siblings ...)
2026-11-05 6:40 ` [PATCH v2 20/23] functionfs: " Alistair Popple
@ 2026-11-05 6:40 ` Alistair Popple
2026-11-05 6:40 ` [PATCH v2 22/23] dma-buf: Add kunit tests for mapping type Alistair Popple
` (2 subsequent siblings)
23 siblings, 0 replies; 26+ messages in thread
From: Alistair Popple @ 2026-11-05 6:40 UTC (permalink / raw)
To: Christian König, Sumit Semwal, Thomas Hellström,
Simona Vetter, Matthew Brost, Vivek Kasireddy, Dongwon Kim,
Kevin Tian, Xu Yilun, Karl Mehltretter, Baolu Lu, Felix Kuehling,
Alex Deucher, dri-devel, intel-xe, amd-gfx, linux-media,
linaro-mm-sig, linux-rdma, iommu, Keith Busch, Jens Axboe,
Christoph Hellwig, Sagi Grimberg, linux-nvme, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Mina Almasry, netdev, Alexey Kardashevskiy, zhipingz, treding,
jhubbard, Jason Gunthorpe, Leon Romanovsky
Cc: Alistair Popple
From: Jason Gunthorpe <jgg@nvidia.com>
Now that all exporters are converted these compatibility things can be
removed:
dma_buf_ops: map_dma_buf/unmap_dma_buf
Moved to dma_buf_mapping_sgt_exp_ops
dma_buf_attachment: dev
Moved to the match set entry's sgt_data.importing_dma_device,
accessed via dma_buf_sgt_dma_device()
dma_buf_attachment: peer2peer
Moved to the match set entry's sgt_data.exporter_requires_p2p,
accessed via dma_buf_sgt_p2p_allowed()
dma_buf_sgt_exp_compat_match: No compatibility exporters anymore
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Alistair Popple <apopple@nvidia.com>
---
drivers/dma-buf/dma-buf-mapping.c | 42 ----------------------
drivers/dma-buf/dma-buf.c | 27 ++++-----------
drivers/gpu/drm/drm_prime.c | 2 --
include/linux/dma-buf-mapping.h | 67 +++++++++++++++++++++++++++++++++--
include/linux/dma-buf.h | 73 ---------------------------------------
include/trace/events/dma_buf.h | 2 +-
6 files changed, 73 insertions(+), 140 deletions(-)
diff --git a/drivers/dma-buf/dma-buf-mapping.c b/drivers/dma-buf/dma-buf-mapping.c
index ea5762a73730..3854e6052947 100644
--- a/drivers/dma-buf/dma-buf-mapping.c
+++ b/drivers/dma-buf/dma-buf-mapping.c
@@ -501,8 +501,6 @@ dma_buf_sgt_finish_match(struct dma_buf_match_args *args,
const struct dma_buf_mapping_match *imp,
struct dma_buf_mapping_match *match)
{
- struct dma_buf_attachment *attach = args->attach;
-
*match = (struct dma_buf_mapping_match) {
.type = &dma_buf_mapping_sgt_type,
.exp_ops = exp->exp_ops,
@@ -513,16 +511,6 @@ dma_buf_sgt_finish_match(struct dma_buf_match_args *args,
.exporter_requires_p2p = exp->sgt_data.exporter_requires_p2p,
},
};
-
- /*
- * Setup the SGT type variables stored in attach because importers and
- * exporters that do not natively use mappings expect them to be there.
- * When converting to use mappings users should use the match versions
- * of these instead.
- */
- attach->dev = args->dev;
- attach->peer2peer = match->sgt_data.importer_accepts_p2p ==
- DMA_SGT_IMPORTER_ACCEPTS_P2P;
}
static void dma_buf_sgt_debugfs_dump(struct seq_file *s,
@@ -540,33 +528,3 @@ struct dma_buf_mapping_type dma_buf_mapping_sgt_type = {
.unmap = dma_buf_sgt_type_unmap,
};
EXPORT_SYMBOL_NS_GPL(dma_buf_mapping_sgt_type, "DMA_BUF");
-
-static struct sg_table *
-dma_buf_sgt_compat_map_dma_buf(struct dma_buf_attachment *attach,
- enum dma_data_direction dir)
-{
- return attach->dmabuf->ops->map_dma_buf(attach, dir);
-}
-
-static void dma_buf_sgt_compat_unmap_dma_buf(struct dma_buf_attachment *attach,
- struct sg_table *sgt,
- enum dma_data_direction dir)
-{
- attach->dmabuf->ops->unmap_dma_buf(attach, sgt, dir);
-}
-
-/* Route the classic map/unmap ops through the exp ops for old importers */
-static const struct dma_buf_mapping_sgt_exp_ops dma_buf_sgt_compat_exp_ops = {
- .map_dma_buf = dma_buf_sgt_compat_map_dma_buf,
- .unmap_dma_buf = dma_buf_sgt_compat_unmap_dma_buf,
-};
-
-/*
- * This mapping type is used for unaware exporters that do not support
- * match_mapping(). It wraps the dma_buf ops for SGT mappings into a mapping
- * type so aware importers can transparently work with unaware exporters. This
- * does not require p2p because old exporters will check it through the
- * attach->peer2peer mechanism.
- */
-const struct dma_buf_mapping_match dma_buf_sgt_exp_compat_match =
- DMA_BUF_EMAPPING_SGT(&dma_buf_sgt_compat_exp_ops);
diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index 70cfab4d9c49..112ffd3a5234 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -718,19 +718,9 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
|| !exp_info->ops->release))
return ERR_PTR(-EINVAL);
- if (exp_info->ops->match_mapping ||
- exp_info->ops->single_exporter_match) {
- if (WARN_ON(exp_info->ops->map_dma_buf ||
- exp_info->ops->unmap_dma_buf))
- return ERR_PTR(-EINVAL);
- if (WARN_ON(exp_info->ops->match_mapping &&
- exp_info->ops->single_exporter_match))
- return ERR_PTR(-EINVAL);
- } else {
- if (WARN_ON(!exp_info->ops->map_dma_buf ||
- !exp_info->ops->unmap_dma_buf))
- return ERR_PTR(-EINVAL);
- }
+ if (WARN_ON(!exp_info->ops->match_mapping &&
+ !exp_info->ops->single_exporter_match))
+ return ERR_PTR(-EINVAL);
if (WARN_ON(!exp_info->ops->pin != !exp_info->ops->unpin))
return ERR_PTR(-EINVAL);
@@ -1100,12 +1090,8 @@ dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
if (ret)
goto err_attach;
} else {
- const struct dma_buf_mapping_match *exp_match =
- dmabuf->ops->single_exporter_match;
-
- if (!exp_match)
- exp_match = &dma_buf_sgt_exp_compat_match;
- ret = dma_buf_match_mapping(&match_args, exp_match, 1);
+ ret = dma_buf_match_mapping(
+ &match_args, dmabuf->ops->single_exporter_match, 1);
if (ret)
goto err_attach;
}
@@ -1167,7 +1153,8 @@ void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach)
dmabuf->ops->detach(dmabuf, attach);
DMA_BUF_TRACE(trace_dma_buf_detach, dmabuf, attach,
- dma_buf_attachment_is_dynamic(attach), attach->dev);
+ dma_buf_attachment_is_dynamic(attach),
+ dma_buf_sgt_dma_device(attach));
kfree(attach);
}
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
index a50ab33cd7b9..c8bd285ed7f6 100644
--- a/drivers/gpu/drm/drm_prime.c
+++ b/drivers/gpu/drm/drm_prime.c
@@ -593,8 +593,6 @@ static bool is_gem_map_dma_buf(struct dma_buf_attachment *attach)
const struct dma_buf_mapping_sgt_exp_ops *sgt_exp_ops =
dma_buf_get_sgt_ops(attach);
- if (attach->dmabuf->ops->map_dma_buf == drm_gem_map_dma_buf)
- return true;
if (sgt_exp_ops && sgt_exp_ops->map_dma_buf == drm_gem_map_dma_buf)
return true;
return false;
diff --git a/include/linux/dma-buf-mapping.h b/include/linux/dma-buf-mapping.h
index b02eb6759d38..c134324db345 100644
--- a/include/linux/dma-buf-mapping.h
+++ b/include/linux/dma-buf-mapping.h
@@ -240,8 +240,73 @@ dma_buf_sgt_mapping_table(struct dma_buf_mapping *mapping)
struct dma_buf_mapping_sgt_exp_ops {
struct dma_buf_mapping_exp_ops ops;
+
+ /**
+ * @map_dma_buf:
+ *
+ * This is called by dma_buf_map_sgt() and is used to map a
+ * shared &dma_buf into device address space, and it is mandatory. It
+ * can only be called if @attach has been called successfully.
+ *
+ * This call may sleep, e.g. when the backing storage first needs to be
+ * allocated, or moved to a location suitable for all currently attached
+ * devices.
+ *
+ * Note that any specific buffer attributes required for this function
+ * should get added to device_dma_parameters accessible via
+ * &device.dma_params from the &dma_buf_attachment. The @attach callback
+ * should also check these constraints.
+ *
+ * If this is being called for the first time, the exporter can now
+ * choose to scan through the list of attachments for this buffer,
+ * collate the requirements of the attached devices, and choose an
+ * appropriate backing storage for the buffer.
+ *
+ * Based on enum dma_data_direction, it might be possible to have
+ * multiple users accessing at the same time (for reading, maybe), or
+ * any other kind of sharing that the exporter might wish to make
+ * available to buffer-users.
+ *
+ * This is always called with the dmabuf->resv object locked when
+ * the dynamic_mapping flag is true.
+ *
+ * Note that for non-dynamic exporters the driver must guarantee that
+ * that the memory is available for use and cleared of any old data by
+ * the time this function returns. Drivers which pipeline their buffer
+ * moves internally must wait for all moves and clears to complete.
+ * Dynamic exporters do not need to follow this rule: For non-dynamic
+ * importers the buffer is already pinned through @pin, which has the
+ * same requirements. Dynamic importers otoh are required to obey the
+ * dma_resv fences.
+ *
+ * Returns:
+ *
+ * A &sg_table scatter list of the backing storage of the DMA buffer,
+ * already mapped into the device address space of the &device attached
+ * with the provided &dma_buf_attachment. The addresses and lengths in
+ * the scatter list are PAGE_SIZE aligned.
+ *
+ * On failure, returns a negative error value wrapped into a pointer.
+ * May also return -EINTR when a signal was received while being
+ * blocked.
+ *
+ * Note that exporters should not try to cache the scatter list, or
+ * return the same one for multiple calls. Caching is done either by the
+ * DMA-BUF code (for non-dynamic importers) or the importer. Ownership
+ * of the scatter list is transferred to the caller, and returned by
+ * @unmap_dma_buf.
+ */
struct sg_table *(*map_dma_buf)(struct dma_buf_attachment *attach,
enum dma_data_direction dir);
+
+ /**
+ * @unmap_dma_buf:
+ *
+ * This is called by dma_buf_unmap_sgt() and should unmap and
+ * release the &sg_table allocated in @map_dma_buf, and it is mandatory.
+ * For static dma_buf handling this might also unpin the backing
+ * storage if this is the last mapping of the DMA buffer.
+ */
void (*unmap_dma_buf)(struct dma_buf_attachment *attach,
struct sg_table *sgt,
enum dma_data_direction dir);
@@ -354,8 +419,6 @@ DMA_BUF_EMAPPING_SGT_REQUIRES_P2P(const struct dma_buf_mapping_sgt_exp_ops *exp_
return match;
}
-extern const struct dma_buf_mapping_match dma_buf_sgt_exp_compat_match;
-
/*
* dma_buf_ops initializer helper for simple drivers that use a single
* SGT map/unmap operation without P2P.
diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h
index fc341b1257c3..8b27725c7dc9 100644
--- a/include/linux/dma-buf.h
+++ b/include/linux/dma-buf.h
@@ -153,75 +153,6 @@ struct dma_buf_ops {
*/
void (*unpin)(struct dma_buf_attachment *attach);
- /**
- * @map_dma_buf:
- *
- * This is called by dma_buf_map_sgt() and is used to map a
- * shared &dma_buf into device address space, and it is mandatory. It
- * can only be called if @attach has been called successfully.
- *
- * This call may sleep, e.g. when the backing storage first needs to be
- * allocated, or moved to a location suitable for all currently attached
- * devices.
- *
- * Note that any specific buffer attributes required for this function
- * should get added to device_dma_parameters accessible via
- * &device.dma_params from the &dma_buf_attachment. The @attach callback
- * should also check these constraints.
- *
- * If this is being called for the first time, the exporter can now
- * choose to scan through the list of attachments for this buffer,
- * collate the requirements of the attached devices, and choose an
- * appropriate backing storage for the buffer.
- *
- * Based on enum dma_data_direction, it might be possible to have
- * multiple users accessing at the same time (for reading, maybe), or
- * any other kind of sharing that the exporter might wish to make
- * available to buffer-users.
- *
- * This is always called with the dmabuf->resv object locked when
- * the dynamic_mapping flag is true.
- *
- * Note that for non-dynamic exporters the driver must guarantee that
- * that the memory is available for use and cleared of any old data by
- * the time this function returns. Drivers which pipeline their buffer
- * moves internally must wait for all moves and clears to complete.
- * Dynamic exporters do not need to follow this rule: For non-dynamic
- * importers the buffer is already pinned through @pin, which has the
- * same requirements. Dynamic importers otoh are required to obey the
- * dma_resv fences.
- *
- * Returns:
- *
- * A &sg_table scatter list of the backing storage of the DMA buffer,
- * already mapped into the device address space of the &device attached
- * with the provided &dma_buf_attachment. The addresses and lengths in
- * the scatter list are PAGE_SIZE aligned.
- *
- * On failure, returns a negative error value wrapped into a pointer.
- * May also return -EINTR when a signal was received while being
- * blocked.
- *
- * Note that exporters should not try to cache the scatter list, or
- * return the same one for multiple calls. Caching is done either by the
- * DMA-BUF code (for non-dynamic importers) or the importer. Ownership
- * of the scatter list is transferred to the caller, and returned by
- * @unmap_dma_buf.
- */
- struct sg_table * (*map_dma_buf)(struct dma_buf_attachment *,
- enum dma_data_direction);
- /**
- * @unmap_dma_buf:
- *
- * This is called by dma_buf_unmap_sgt() and should unmap and
- * release the &sg_table allocated in @map_dma_buf, and it is mandatory.
- * For static dma_buf handling this might also unpin the backing
- * storage if this is the last mapping of the DMA buffer.
- */
- void (*unmap_dma_buf)(struct dma_buf_attachment *,
- struct sg_table *,
- enum dma_data_direction);
-
/* TODO: Add try_map_dma_buf version, to return immed with -EBUSY
* if the call would block.
*/
@@ -585,9 +516,7 @@ struct dma_buf_attach_ops {
/**
* struct dma_buf_attachment - holds device-buffer attachment data
* @dmabuf: buffer for this attachment.
- * @dev: device attached to the buffer.
* @node: list of dma_buf_attachment, protected by dma_resv lock of the dmabuf.
- * @peer2peer: true if the importer can handle peer resources without pages.
* @priv: exporter specific attachment data.
* @importer_ops: importer operations for this attachment, if provided
* dma_buf_map/unmap_sgt() must be called with the dma_resv lock held.
@@ -619,9 +548,7 @@ struct dma_buf_attach_ops {
*/
struct dma_buf_attachment {
struct dma_buf *dmabuf;
- struct device *dev;
struct list_head node;
- bool peer2peer;
const struct dma_buf_attach_ops *importer_ops;
void *importer_priv;
void *priv;
diff --git a/include/trace/events/dma_buf.h b/include/trace/events/dma_buf.h
index 3bb88d05bcc8..13d3a82856b6 100644
--- a/include/trace/events/dma_buf.h
+++ b/include/trace/events/dma_buf.h
@@ -40,7 +40,7 @@ DECLARE_EVENT_CLASS(dma_buf_attach_dev,
TP_ARGS(dmabuf, attach, is_dynamic, dev),
TP_STRUCT__entry(
- __string( dev_name, dev_name(dev))
+ __string( dev_name, dev ? dev_name(dev) : "none")
__string( exp_name, dmabuf->exp_name)
__field( size_t, size)
__field( ino_t, ino)
--
2.54.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH v2 22/23] dma-buf: Add kunit tests for mapping type
2026-11-05 6:40 [PATCH v2 00/23] DMA-buf mapping types Alistair Popple
` (20 preceding siblings ...)
2026-11-05 6:40 ` [PATCH v2 21/23] dma-buf: Remove unused SGT stuff from the common structures Alistair Popple
@ 2026-11-05 6:40 ` Alistair Popple
2026-11-05 6:40 ` [PATCH v2 23/23] dma-buf: Add kunit tests for mapping type selection Alistair Popple
2026-11-05 16:18 ` [PATCH v2 00/23] DMA-buf mapping types Maarten Lankhorst
23 siblings, 0 replies; 26+ messages in thread
From: Alistair Popple @ 2026-11-05 6:40 UTC (permalink / raw)
To: Christian König, Sumit Semwal, Thomas Hellström,
Simona Vetter, Matthew Brost, Vivek Kasireddy, Dongwon Kim,
Kevin Tian, Xu Yilun, Karl Mehltretter, Baolu Lu, Felix Kuehling,
Alex Deucher, dri-devel, intel-xe, amd-gfx, linux-media,
linaro-mm-sig, linux-rdma, iommu, Keith Busch, Jens Axboe,
Christoph Hellwig, Sagi Grimberg, linux-nvme, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Mina Almasry, netdev, Alexey Kardashevskiy, zhipingz, treding,
jhubbard, Jason Gunthorpe, Leon Romanovsky
Cc: Alistair Popple
From: Jason Gunthorpe <jgg@nvidia.com>
Some basic coverage of common flows:
- Check dma_buf_match_mapping()'s rules. These choices effectively
become driver facing API and it would be a pain to change them later
- Test the dma_bug_sgt attachment flow to see that the new wrappers work
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Alistair Popple <apopple@nvidia.com>
---
drivers/dma-buf/Makefile | 1 +
drivers/dma-buf/st-dma-mapping.c | 403 +++++++++++++++++++++++++++++++++++++++
2 files changed, 404 insertions(+)
diff --git a/drivers/dma-buf/Makefile b/drivers/dma-buf/Makefile
index 523731b0f83e..02745fca8b88 100644
--- a/drivers/dma-buf/Makefile
+++ b/drivers/dma-buf/Makefile
@@ -11,6 +11,7 @@ dmabuf_kunit-y := \
st-dma-fence.o \
st-dma-fence-chain.o \
st-dma-fence-unwrap.o \
+ st-dma-mapping.o \
st-dma-resv.o
obj-$(CONFIG_DMABUF_KUNIT_TEST) += dmabuf_kunit.o
diff --git a/drivers/dma-buf/st-dma-mapping.c b/drivers/dma-buf/st-dma-mapping.c
new file mode 100644
index 000000000000..cbfa99aeb0ff
--- /dev/null
+++ b/drivers/dma-buf/st-dma-mapping.c
@@ -0,0 +1,403 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * KUnit tests for dma_buf_match_mapping()
+ */
+
+#include <kunit/device.h>
+#include <kunit/test.h>
+#include <linux/dma-buf.h>
+#include <linux/dma-buf-mapping.h>
+#include <linux/errno.h>
+
+/* Mock tracking state -- reset before each test */
+static bool mock_match_called;
+static const struct dma_buf_mapping_match *mock_match_exp_arg;
+static const struct dma_buf_mapping_match *mock_match_imp_arg;
+static struct device *mock_match_dev_arg;
+static int mock_match_ret;
+
+static bool mock_finish_called;
+static const struct dma_buf_match_args *mock_finish_args_arg;
+static const struct dma_buf_mapping_match *mock_finish_exp_arg;
+static const struct dma_buf_mapping_match *mock_finish_imp_arg;
+
+static int reset_mock_state(struct kunit *test)
+{
+ mock_match_called = false;
+ mock_match_exp_arg = NULL;
+ mock_match_imp_arg = NULL;
+ mock_match_dev_arg = NULL;
+ mock_match_ret = 0;
+ mock_finish_called = false;
+ mock_finish_args_arg = NULL;
+ mock_finish_exp_arg = NULL;
+ mock_finish_imp_arg = NULL;
+ return 0;
+}
+
+static int mock_match(struct dma_buf_match_args *args,
+ const struct dma_buf_mapping_match *exp,
+ const struct dma_buf_mapping_match *imp)
+{
+ mock_match_called = true;
+ mock_match_exp_arg = exp;
+ mock_match_imp_arg = imp;
+ mock_match_dev_arg = args->dev;
+ return mock_match_ret;
+}
+
+static void mock_finish_match(struct dma_buf_match_args *args,
+ const struct dma_buf_mapping_match *exp,
+ const struct dma_buf_mapping_match *imp,
+ struct dma_buf_mapping_match *match)
+{
+ mock_finish_called = true;
+ mock_finish_args_arg = args;
+ mock_finish_exp_arg = exp;
+ mock_finish_imp_arg = imp;
+
+ *match = (struct dma_buf_mapping_match){
+ .type = exp->type,
+ .exp_ops = exp->exp_ops,
+ };
+}
+
+/* Type with both match and finish_match callbacks */
+static struct dma_buf_mapping_type mock_type_a = {
+ .name = "mock_type_a",
+ .match = mock_match,
+ .finish_match = mock_finish_match,
+};
+
+/* Second type -- distinct pointer identity from A */
+static struct dma_buf_mapping_type mock_type_b = {
+ .name = "mock_type_b",
+ .match = mock_match,
+ .finish_match = mock_finish_match,
+};
+
+static void test_match_fail(struct kunit *test)
+{
+ struct dma_buf_mapping_match matches[] = { { .type = &mock_type_a } };
+ struct dma_buf_mapping_match exp[] = { { .type = &mock_type_b } };
+ struct dma_buf_attachment attach = {};
+ struct dma_buf_match_args args = {
+ .attach = &attach,
+ .imp_matches = matches,
+ .imp_len = ARRAY_SIZE(matches),
+ };
+
+ /* Zero-length exporter array returns -EINVAL */
+ KUNIT_EXPECT_EQ(test, dma_buf_match_mapping(&args, NULL, 0), -EINVAL);
+ KUNIT_EXPECT_FALSE(test, mock_match_called);
+ KUNIT_EXPECT_FALSE(test, mock_finish_called);
+
+ /* Zero-length importer array returns -EINVAL */
+ args = (struct dma_buf_match_args){ .attach = &attach };
+ KUNIT_EXPECT_EQ(test,
+ dma_buf_match_mapping(&args, matches,
+ ARRAY_SIZE(matches)),
+ -EINVAL);
+ KUNIT_EXPECT_FALSE(test, mock_match_called);
+ KUNIT_EXPECT_FALSE(test, mock_finish_called);
+
+ /* Different types produce no match */
+ args.imp_matches = matches;
+ args.imp_len = ARRAY_SIZE(matches);
+ KUNIT_EXPECT_EQ(test,
+ dma_buf_match_mapping(&args, exp, ARRAY_SIZE(exp)),
+ -EOPNOTSUPP);
+ KUNIT_EXPECT_FALSE(test, mock_match_called);
+ KUNIT_EXPECT_FALSE(test, mock_finish_called);
+}
+
+/* When type->match() is NULL same types always match */
+static void test_match_no_match_callback(struct kunit *test)
+{
+ static struct dma_buf_mapping_type mock_type_no_match = {
+ .name = "mock_type_no_match",
+ .finish_match = mock_finish_match,
+ };
+ struct dma_buf_mapping_match matches[] = {
+ { .type = &mock_type_no_match }
+ };
+ struct dma_buf_attachment attach = {};
+ struct dma_buf_match_args args = {
+ .attach = &attach,
+ .imp_matches = matches,
+ .imp_len = ARRAY_SIZE(matches),
+ };
+
+ KUNIT_EXPECT_EQ(
+ test,
+ dma_buf_match_mapping(&args, matches, ARRAY_SIZE(matches)), 0);
+ KUNIT_EXPECT_FALSE(test, mock_match_called);
+ KUNIT_EXPECT_TRUE(test, mock_finish_called);
+ KUNIT_EXPECT_PTR_EQ(test, mock_finish_args_arg, &args);
+ KUNIT_EXPECT_PTR_EQ(test, mock_finish_exp_arg, &matches[0]);
+ KUNIT_EXPECT_PTR_EQ(test, mock_finish_imp_arg, &matches[0]);
+}
+
+static void test_match_callback_returns(struct kunit *test)
+{
+ struct dma_buf_mapping_match matches[] = { { .type = &mock_type_a } };
+ struct dma_buf_attachment attach = {};
+ struct dma_buf_match_args args = {
+ .attach = &attach,
+ .imp_matches = matches,
+ .imp_len = ARRAY_SIZE(matches),
+ };
+
+ /* type->match() returns -EOPNOTSUPP. Skips to next */
+ mock_match_ret = -EOPNOTSUPP;
+ KUNIT_EXPECT_EQ(test,
+ dma_buf_match_mapping(&args, matches,
+ ARRAY_SIZE(matches)),
+ -EOPNOTSUPP);
+ KUNIT_EXPECT_TRUE(test, mock_match_called);
+ KUNIT_EXPECT_FALSE(test, mock_finish_called);
+
+ /* type->match() returns an error code. Stops immediately, returns code */
+ mock_match_ret = -ENOMEM;
+ KUNIT_EXPECT_EQ(test,
+ dma_buf_match_mapping(&args, matches,
+ ARRAY_SIZE(matches)),
+ -ENOMEM);
+ KUNIT_EXPECT_TRUE(test, mock_match_called);
+ KUNIT_EXPECT_FALSE(test, mock_finish_called);
+}
+
+/*
+ * The match set records every compatible pair, in the exporter's order. The
+ * first entry is the default selection.
+ */
+static void test_match_exporter_priority(struct kunit *test)
+{
+ struct dma_buf_mapping_match exp1[2] = {
+ { .type = &mock_type_a },
+ { .type = &mock_type_b },
+ };
+ struct dma_buf_mapping_match exp2[] = { { .type = &mock_type_b } };
+ struct dma_buf_mapping_match imp[2] = {
+ { .type = &mock_type_a },
+ { .type = &mock_type_b },
+ };
+ struct dma_buf_attachment attach = {};
+ struct dma_buf_match_args args = {
+ .attach = &attach,
+ .imp_matches = imp,
+ .imp_len = ARRAY_SIZE(imp),
+ };
+
+ /* Both match, exporter order preserved, first is the default */
+ KUNIT_EXPECT_EQ(
+ test, dma_buf_match_mapping(&args, exp1, ARRAY_SIZE(exp1)), 0);
+ KUNIT_ASSERT_EQ(test, attach.nr_matches, 2);
+ KUNIT_EXPECT_PTR_EQ(test, attach.matches[0].type, &mock_type_a);
+ KUNIT_EXPECT_PTR_EQ(test, attach.matches[1].type, &mock_type_b);
+ KUNIT_EXPECT_PTR_EQ(test, dma_buf_attach_map_type(&attach)->type,
+ &mock_type_a);
+
+ /* Only the second importer type is offered */
+ KUNIT_EXPECT_EQ(
+ test, dma_buf_match_mapping(&args, exp2, ARRAY_SIZE(exp2)), 0);
+ KUNIT_ASSERT_EQ(test, attach.nr_matches, 1);
+ KUNIT_EXPECT_PTR_EQ(test, attach.matches[0].type, &mock_type_b);
+ KUNIT_EXPECT_PTR_EQ(test, dma_buf_attach_map_type(&attach)->type,
+ &mock_type_b);
+ KUNIT_EXPECT_PTR_EQ(test, mock_finish_imp_arg, &imp[1]);
+}
+
+/* The exporter's order wins over the importer's */
+static void test_match_importer_priority(struct kunit *test)
+{
+ struct dma_buf_mapping_match exp[] = {
+ { .type = &mock_type_a },
+ { .type = &mock_type_b },
+ };
+ struct dma_buf_mapping_match imp1[] = { { .type = &mock_type_b } };
+ struct dma_buf_mapping_match imp2[] = {
+ { .type = &mock_type_b },
+ { .type = &mock_type_a },
+ };
+ struct dma_buf_attachment attach = {};
+ struct dma_buf_match_args args = {
+ .attach = &attach,
+ .imp_matches = imp1,
+ .imp_len = ARRAY_SIZE(imp1),
+ };
+
+ /* Single importer type */
+ KUNIT_EXPECT_EQ(test,
+ dma_buf_match_mapping(&args, exp, ARRAY_SIZE(exp)), 0);
+ KUNIT_ASSERT_EQ(test, attach.nr_matches, 1);
+ KUNIT_EXPECT_PTR_EQ(test, attach.matches[0].type, &mock_type_b);
+ KUNIT_EXPECT_PTR_EQ(test, mock_finish_imp_arg, &imp1[0]);
+
+ /* Importer prefers B, exporter prefers A: A is the default */
+ args.imp_matches = imp2;
+ args.imp_len = ARRAY_SIZE(imp2);
+ KUNIT_EXPECT_EQ(test,
+ dma_buf_match_mapping(&args, exp, ARRAY_SIZE(exp)), 0);
+ KUNIT_ASSERT_EQ(test, attach.nr_matches, 2);
+ KUNIT_EXPECT_PTR_EQ(test, attach.matches[0].type, &mock_type_a);
+ KUNIT_EXPECT_PTR_EQ(test, attach.matches[1].type, &mock_type_b);
+ KUNIT_EXPECT_PTR_EQ(test, dma_buf_attach_map_type(&attach)->type,
+ &mock_type_a);
+}
+
+static void mock_dmabuf_release(struct dma_buf *dmabuf)
+{
+}
+
+static struct sg_table *mock_map_dma_buf(struct dma_buf_attachment *attach,
+ enum dma_data_direction dir)
+{
+ return ERR_PTR(-ENODEV);
+}
+
+static void mock_unmap_dma_buf(struct dma_buf_attachment *attach,
+ struct sg_table *sgt,
+ enum dma_data_direction dir)
+{
+}
+
+static const struct dma_buf_mapping_sgt_exp_ops mock_sgt_ops = {
+ .map_dma_buf = mock_map_dma_buf,
+ .unmap_dma_buf = mock_unmap_dma_buf,
+};
+
+static const struct dma_buf_ops mock_dmabuf_simple_sgt_ops = {
+ .release = mock_dmabuf_release,
+ DMA_BUF_SIMPLE_SGT_EXP_MATCH(mock_map_dma_buf, mock_unmap_dma_buf),
+};
+
+static int mock_dmabuf_match_mapping(struct dma_buf_match_args *args)
+{
+ struct dma_buf_mapping_match sgt_match[2];
+ unsigned int num_match = 0;
+
+ sgt_match[num_match++] =
+ (struct dma_buf_mapping_match){ .type = &mock_type_a };
+
+ sgt_match[num_match++] = DMA_BUF_EMAPPING_SGT(&mock_sgt_ops);
+
+ return dma_buf_match_mapping(args, sgt_match, ARRAY_SIZE(sgt_match));
+}
+
+static const struct dma_buf_ops mock_dmabuf_two_exp_ops = {
+ .release = mock_dmabuf_release,
+ .match_mapping = mock_dmabuf_match_mapping,
+};
+
+struct dma_exporter {
+ const struct dma_buf_ops *ops;
+ const char *desc;
+};
+
+static struct dma_buf *mock_dmabuf_export(const struct dma_buf_ops *ops)
+{
+ DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
+
+ exp_info.ops = ops;
+ exp_info.size = PAGE_SIZE;
+ exp_info.priv = ERR_PTR(-EINVAL);
+ return dma_buf_export(&exp_info);
+}
+
+/*
+ * Check that a simple SGT exporter with single_exporter_match works with
+ * dma_buf_attach()
+ */
+static void test_sgt_attach(struct kunit *test)
+{
+ const struct dma_exporter *param = test->param_value;
+ struct dma_buf *dmabuf;
+ struct dma_buf_attachment *attach;
+ struct device *dev;
+
+ dev = kunit_device_register(test, "dma-buf-test");
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
+
+ dmabuf = mock_dmabuf_export(param->ops);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dmabuf);
+
+ attach = dma_buf_attach(dmabuf, dev);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, attach);
+
+ KUNIT_EXPECT_PTR_EQ(test, dma_buf_attach_map_type(attach)->type,
+ &dma_buf_mapping_sgt_type);
+ KUNIT_EXPECT_PTR_EQ(test, dma_buf_sgt_dma_device(attach), dev);
+ KUNIT_EXPECT_FALSE(test, dma_buf_sgt_p2p_allowed(attach));
+
+ dma_buf_detach(dmabuf, attach);
+ dma_buf_put(dmabuf);
+}
+
+static void mock_move_notify(struct dma_buf_attachment *attach)
+{
+}
+
+/*
+ * Mock importer: declares a dma_buf_attach_ops whose supported_mapping_types
+ * table is whatever the test put in @_matches.
+ */
+#define MOCK_IMPORTER_OPS(_name, _matches) \
+ const struct dma_buf_attach_ops _name = { \
+ .invalidate_mappings = &mock_move_notify, \
+ .supported_mapping_types = (_matches), \
+ .nr_supported_mapping_types = ARRAY_SIZE(_matches), \
+ }
+
+/* Check a dynamic attach with a non-sgt mapping type */
+static void test_mock_attach(struct kunit *test)
+{
+ struct dma_buf_mapping_match imp[] = { { .type = &mock_type_a } };
+ MOCK_IMPORTER_OPS(importer_ops, imp);
+ struct dma_buf *dmabuf;
+ struct dma_buf_attachment *attach;
+ struct device *dev;
+
+ dev = kunit_device_register(test, "dma-buf-test");
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
+
+ dmabuf = mock_dmabuf_export(&mock_dmabuf_two_exp_ops);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dmabuf);
+
+ attach = dma_buf_dynamic_attach(dmabuf, dev, &importer_ops, NULL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, attach);
+
+ KUNIT_EXPECT_PTR_EQ(test, dma_buf_attach_map_type(attach)->type,
+ &mock_type_a);
+ KUNIT_EXPECT_PTR_EQ(test, mock_match_dev_arg, dev);
+
+ dma_buf_detach(dmabuf, attach);
+ dma_buf_put(dmabuf);
+}
+
+static const struct dma_exporter dma_exporter_params[] = {
+ { &mock_dmabuf_simple_sgt_ops, "simple_sgt" },
+ { &mock_dmabuf_two_exp_ops, "two_exp" },
+};
+KUNIT_ARRAY_PARAM_DESC(dma_exporter, dma_exporter_params, desc);
+
+static struct kunit_case dma_mapping_cases[] = {
+ KUNIT_CASE(test_match_fail),
+ KUNIT_CASE(test_match_no_match_callback),
+ KUNIT_CASE(test_match_callback_returns),
+ KUNIT_CASE(test_match_exporter_priority),
+ KUNIT_CASE(test_match_importer_priority),
+ KUNIT_CASE_PARAM(test_sgt_attach, dma_exporter_gen_params),
+ KUNIT_CASE(test_mock_attach),
+ {}
+};
+
+static struct kunit_suite dma_mapping_test_suite = {
+ .name = "dma-buf-mapping",
+ .init = reset_mock_state,
+ .test_cases = dma_mapping_cases,
+};
+
+kunit_test_suite(dma_mapping_test_suite);
+
+MODULE_IMPORT_NS("DMA_BUF");
--
2.54.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH v2 23/23] dma-buf: Add kunit tests for mapping type selection
2026-11-05 6:40 [PATCH v2 00/23] DMA-buf mapping types Alistair Popple
` (21 preceding siblings ...)
2026-11-05 6:40 ` [PATCH v2 22/23] dma-buf: Add kunit tests for mapping type Alistair Popple
@ 2026-11-05 6:40 ` Alistair Popple
2026-11-05 16:18 ` [PATCH v2 00/23] DMA-buf mapping types Maarten Lankhorst
23 siblings, 0 replies; 26+ messages in thread
From: Alistair Popple @ 2026-11-05 6:40 UTC (permalink / raw)
To: Christian König, Sumit Semwal, Thomas Hellström,
Simona Vetter, Matthew Brost, Vivek Kasireddy, Dongwon Kim,
Kevin Tian, Xu Yilun, Karl Mehltretter, Baolu Lu, Felix Kuehling,
Alex Deucher, dri-devel, intel-xe, amd-gfx, linux-media,
linaro-mm-sig, linux-rdma, iommu, Keith Busch, Jens Axboe,
Christoph Hellwig, Sagi Grimberg, linux-nvme, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Mina Almasry, netdev, Alexey Kardashevskiy, zhipingz, treding,
jhubbard, Jason Gunthorpe, Leon Romanovsky
Cc: Alistair Popple
Add an offer list and a select_mapping() callback to the mock exporter
along with map/unmap for the two mock types.
Adds tests for the exporter/importer contract.
- test_match_set_is_final: a later importer attaching, even one the
exporter answers differently, does not change an existing
attachment's match set or default. Later attachments influence what
the exporter selects at pin and map time, not previous attachments.
- test_select_at_map: the exporter chooses a non-default entry
at the first map and the result is tagged with it. A pin taken
under the live mapping inherits the type and the choice survives
unmap/remap even though the exporter would answer differently. Only
dma_buf_invalidate_mappings() allows the exporter to make a different
selection. An -EBUSY from selection leaves nothing established.
- test_select_at_pin: pin selects, and the choice survives map, unmap
and unpin so a pinned importer that is never invalidated keeps its
first type for the life of the import.
Signed-off-by: Alistair Popple <apopple@nvidia.com>
---
drivers/dma-buf/st-dma-mapping.c | 493 +++++++++++++++++++++++++++++++++++++++
1 file changed, 493 insertions(+)
diff --git a/drivers/dma-buf/st-dma-mapping.c b/drivers/dma-buf/st-dma-mapping.c
index cbfa99aeb0ff..11010731150a 100644
--- a/drivers/dma-buf/st-dma-mapping.c
+++ b/drivers/dma-buf/st-dma-mapping.c
@@ -7,6 +7,7 @@
#include <kunit/test.h>
#include <linux/dma-buf.h>
#include <linux/dma-buf-mapping.h>
+#include <linux/dma-resv.h>
#include <linux/errno.h>
/* Mock tracking state -- reset before each test */
@@ -21,6 +22,19 @@ static const struct dma_buf_match_args *mock_finish_args_arg;
static const struct dma_buf_mapping_match *mock_finish_exp_arg;
static const struct dma_buf_mapping_match *mock_finish_imp_arg;
+/* Mapping types the configurable mock exporter currently offers */
+static const struct dma_buf_mapping_match *mock_exp_offer;
+static size_t mock_exp_offer_len;
+
+/* Which match set entry the selecting mock exporter picks, or an error */
+static int mock_select_idx;
+static int mock_select_err;
+
+/* Failure injection for the mock types' map and the mock exporter's pin */
+static int mock_map_err;
+static int mock_pin_err;
+static int mock_pin_count;
+
static int reset_mock_state(struct kunit *test)
{
mock_match_called = false;
@@ -32,6 +46,13 @@ static int reset_mock_state(struct kunit *test)
mock_finish_args_arg = NULL;
mock_finish_exp_arg = NULL;
mock_finish_imp_arg = NULL;
+ mock_exp_offer = NULL;
+ mock_exp_offer_len = 0;
+ mock_select_idx = 0;
+ mock_select_err = 0;
+ mock_map_err = 0;
+ mock_pin_err = 0;
+ mock_pin_count = 0;
return 0;
}
@@ -370,11 +391,478 @@ static void test_mock_attach(struct kunit *test)
KUNIT_EXPECT_PTR_EQ(test, dma_buf_attach_map_type(attach)->type,
&mock_type_a);
KUNIT_EXPECT_PTR_EQ(test, mock_match_dev_arg, dev);
+ KUNIT_EXPECT_PTR_EQ(test, mock_match_dev_arg, dev);
dma_buf_detach(dmabuf, attach);
dma_buf_put(dmabuf);
}
+static int mock_dmabuf_offer_match_mapping(struct dma_buf_match_args *args)
+{
+ return dma_buf_match_mapping(args, mock_exp_offer, mock_exp_offer_len);
+}
+
+static const struct dma_buf_ops mock_dmabuf_offer_ops = {
+ .release = mock_dmabuf_release,
+ .match_mapping = mock_dmabuf_offer_match_mapping,
+};
+
+/*
+ * The match set is final once attached. A later importer attaching, even one
+ * the exporter answers differently, must not change an existing attachment.
+ *
+ * Later attachments influence what the exporter selects at pin or map time,
+ * not what was previously negotiated.
+ */
+static void test_match_set_is_final(struct kunit *test)
+{
+ static const struct dma_buf_mapping_match offer_ab[] = {
+ { .type = &mock_type_a },
+ { .type = &mock_type_b },
+ };
+ static const struct dma_buf_mapping_match offer_b[] = {
+ { .type = &mock_type_b },
+ };
+ struct dma_buf_mapping_match imp1[] = {
+ { .type = &mock_type_a },
+ { .type = &mock_type_b },
+ };
+ struct dma_buf_mapping_match imp2[] = { { .type = &mock_type_b } };
+ MOCK_IMPORTER_OPS(importer1_ops, imp1);
+ MOCK_IMPORTER_OPS(importer2_ops, imp2);
+ struct dma_buf_attachment *attach1, *attach2;
+ struct dma_buf *dmabuf;
+ struct device *dev;
+
+ dev = kunit_device_register(test, "dma-buf-test");
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
+
+ dmabuf = mock_dmabuf_export(&mock_dmabuf_offer_ops);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dmabuf);
+
+ mock_exp_offer = offer_ab;
+ mock_exp_offer_len = ARRAY_SIZE(offer_ab);
+ attach1 = dma_buf_dynamic_attach(dmabuf, dev, &importer1_ops, NULL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, attach1);
+ KUNIT_ASSERT_EQ(test, attach1->nr_matches, 2);
+ KUNIT_EXPECT_PTR_EQ(test, dma_buf_attach_map_type(attach1)->type,
+ &mock_type_a);
+
+ /* Exporter's answer for new importers changes; attach1 does not */
+ mock_exp_offer = offer_b;
+ mock_exp_offer_len = ARRAY_SIZE(offer_b);
+ attach2 = dma_buf_dynamic_attach(dmabuf, dev, &importer2_ops, NULL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, attach2);
+ KUNIT_ASSERT_EQ(test, attach2->nr_matches, 1);
+ KUNIT_EXPECT_PTR_EQ(test, dma_buf_attach_map_type(attach2)->type,
+ &mock_type_b);
+ KUNIT_EXPECT_EQ(test, attach1->nr_matches, 2);
+ KUNIT_EXPECT_PTR_EQ(test, dma_buf_attach_map_type(attach1)->type,
+ &mock_type_a);
+
+ dma_buf_detach(dmabuf, attach2);
+ KUNIT_EXPECT_EQ(test, attach1->nr_matches, 2);
+ KUNIT_EXPECT_PTR_EQ(test, dma_buf_attach_map_type(attach1)->type,
+ &mock_type_a);
+
+ dma_buf_detach(dmabuf, attach1);
+ dma_buf_put(dmabuf);
+}
+
+/* Mock mapping result for the generic map path */
+struct mock_mapping {
+ struct dma_buf_mapping base;
+ const struct dma_buf_mapping_type *made_by;
+};
+
+static struct dma_buf_mapping *mock_type_map(struct dma_buf_attachment *attach,
+ enum dma_data_direction dir)
+{
+ struct mock_mapping *m;
+
+ if (mock_map_err)
+ return ERR_PTR(mock_map_err);
+ m = kzalloc_obj(*m);
+ if (!m)
+ return ERR_PTR(-ENOMEM);
+ m->base.type = dma_buf_attach_map_type(attach)->type;
+ m->made_by = dma_buf_attach_map_type(attach)->type;
+ return &m->base;
+}
+
+static void mock_type_unmap(struct dma_buf_attachment *attach,
+ struct dma_buf_mapping *mapping,
+ enum dma_data_direction dir)
+{
+ kfree(container_of(mapping, struct mock_mapping, base));
+}
+
+/* Exporter choosing the match set entry the test asks for */
+static int mock_dmabuf_select_mapping(struct dma_buf_attachment *attach)
+{
+ if (mock_select_err)
+ return mock_select_err;
+ return mock_select_idx;
+}
+
+static int mock_dmabuf_pin(struct dma_buf_attachment *attach)
+{
+ if (mock_pin_err)
+ return mock_pin_err;
+ mock_pin_count++;
+ return 0;
+}
+
+static void mock_dmabuf_unpin(struct dma_buf_attachment *attach)
+{
+ mock_pin_count--;
+}
+
+static const struct dma_buf_ops mock_dmabuf_select_ops = {
+ .release = mock_dmabuf_release,
+ .match_mapping = mock_dmabuf_offer_match_mapping,
+ .select_mapping = mock_dmabuf_select_mapping,
+ .pin = mock_dmabuf_pin,
+ .unpin = mock_dmabuf_unpin,
+};
+
+/*
+ * Exporter decides type at first map from the match set. The result is tagged
+ * with it and the core holds the choice across unmap/remap until the attachment
+ * has been explicitly invalidated.
+ */
+static void test_select_at_map(struct kunit *test)
+{
+ static const struct dma_buf_mapping_match offer_ab[] = {
+ { .type = &mock_type_a },
+ { .type = &mock_type_b },
+ };
+ struct dma_buf_mapping_match imp[] = {
+ { .type = &mock_type_a },
+ { .type = &mock_type_b },
+ };
+ MOCK_IMPORTER_OPS(importer_ops, imp);
+ struct dma_buf_attachment *attach;
+ struct dma_buf_mapping *mapping;
+ struct dma_buf *dmabuf;
+ struct device *dev;
+
+ mock_type_a.map = mock_type_map;
+ mock_type_a.unmap = mock_type_unmap;
+ mock_type_b.map = mock_type_map;
+ mock_type_b.unmap = mock_type_unmap;
+
+ dev = kunit_device_register(test, "dma-buf-test");
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
+
+ dmabuf = mock_dmabuf_export(&mock_dmabuf_select_ops);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dmabuf);
+
+ mock_exp_offer = offer_ab;
+ mock_exp_offer_len = ARRAY_SIZE(offer_ab);
+ attach = dma_buf_dynamic_attach(dmabuf, dev, &importer_ops, NULL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, attach);
+ KUNIT_EXPECT_FALSE(test, attach->selected);
+ KUNIT_EXPECT_PTR_EQ(test, dma_buf_attach_map_type(attach)->type,
+ &mock_type_a);
+
+ dma_resv_lock(dmabuf->resv, NULL);
+
+ /* Exporter picks the second entry (mock_type_b) */
+ mock_select_idx = 1;
+ mapping = dma_buf_mapping_map(attach, DMA_BIDIRECTIONAL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, mapping);
+ KUNIT_EXPECT_PTR_EQ(test, mapping->type, &mock_type_b);
+ KUNIT_EXPECT_PTR_EQ(test, dma_buf_attach_map_type(attach)->type,
+ &mock_type_b);
+ KUNIT_EXPECT_TRUE(test, attach->selected);
+
+ /* A pin taken whilst mapping is live gets the same type */
+ mock_select_idx = 0;
+ KUNIT_EXPECT_EQ(test, dma_buf_pin(attach), 0);
+ KUNIT_EXPECT_PTR_EQ(test, dma_buf_attach_map_type(attach)->type,
+ &mock_type_b);
+ dma_buf_unpin(attach);
+
+ dma_buf_mapping_unmap(attach, mapping, DMA_BIDIRECTIONAL);
+
+ /*
+ * Unmapped the exporter would now pick A, but no invalidate has
+ * happened so remap must get B again to avoid ping-ponging.
+ */
+ KUNIT_EXPECT_TRUE(test, attach->selected);
+ mapping = dma_buf_mapping_map(attach, DMA_BIDIRECTIONAL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, mapping);
+ KUNIT_EXPECT_PTR_EQ(test, mapping->type, &mock_type_b);
+ dma_buf_mapping_unmap(attach, mapping, DMA_BIDIRECTIONAL);
+
+ /* Only an explicit invalidation allows the type to change */
+ dma_buf_invalidate_mappings(dmabuf);
+ KUNIT_EXPECT_FALSE(test, attach->selected);
+ /* The selection is kept for a pending unmap until the next one */
+ KUNIT_EXPECT_PTR_EQ(test, dma_buf_attach_map_type(attach)->type,
+ &mock_type_b);
+
+ mapping = dma_buf_mapping_map(attach, DMA_BIDIRECTIONAL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, mapping);
+ KUNIT_EXPECT_PTR_EQ(test, mapping->type, &mock_type_a);
+ dma_buf_mapping_unmap(attach, mapping, DMA_BIDIRECTIONAL);
+
+ /* Exporter cannot serve this importer right now */
+ dma_buf_invalidate_mappings(dmabuf);
+ mock_select_err = -EBUSY;
+ mapping = dma_buf_mapping_map(attach, DMA_BIDIRECTIONAL);
+ KUNIT_EXPECT_EQ(test, PTR_ERR(mapping), -EBUSY);
+ KUNIT_EXPECT_FALSE(test, attach->selected);
+ mock_select_err = 0;
+
+ dma_resv_unlock(dmabuf->resv);
+
+ dma_buf_detach(dmabuf, attach);
+ dma_buf_put(dmabuf);
+
+ mock_type_a.map = NULL;
+ mock_type_a.unmap = NULL;
+ mock_type_b.map = NULL;
+ mock_type_b.unmap = NULL;
+}
+
+/*
+ * Pin selects too and the choice survives map, unmap and unpin. A pinned
+ * importer that is never invalidated keeps its first type for the life of the
+ * attachment.
+ */
+static void test_select_at_pin(struct kunit *test)
+{
+ static const struct dma_buf_mapping_match offer_ab[] = {
+ { .type = &mock_type_a },
+ { .type = &mock_type_b },
+ };
+ struct dma_buf_mapping_match imp[] = {
+ { .type = &mock_type_a },
+ { .type = &mock_type_b },
+ };
+ MOCK_IMPORTER_OPS(importer_ops, imp);
+ struct dma_buf_attachment *attach;
+ struct dma_buf_mapping *mapping;
+ struct dma_buf *dmabuf;
+ struct device *dev;
+
+ mock_type_a.map = mock_type_map;
+ mock_type_a.unmap = mock_type_unmap;
+ mock_type_b.map = mock_type_map;
+ mock_type_b.unmap = mock_type_unmap;
+
+ dev = kunit_device_register(test, "dma-buf-test");
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
+
+ dmabuf = mock_dmabuf_export(&mock_dmabuf_select_ops);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dmabuf);
+
+ mock_exp_offer = offer_ab;
+ mock_exp_offer_len = ARRAY_SIZE(offer_ab);
+ attach = dma_buf_dynamic_attach(dmabuf, dev, &importer_ops, NULL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, attach);
+
+ dma_resv_lock(dmabuf->resv, NULL);
+
+ mock_select_idx = 1;
+ KUNIT_EXPECT_EQ(test, dma_buf_pin(attach), 0);
+ KUNIT_EXPECT_TRUE(test, attach->selected);
+ KUNIT_EXPECT_PTR_EQ(test, dma_buf_attach_map_type(attach)->type,
+ &mock_type_b);
+
+ /* Map after pin uses the pinned type regardless of the exporter now */
+ mock_select_idx = 0;
+ mapping = dma_buf_mapping_map(attach, DMA_BIDIRECTIONAL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, mapping);
+ KUNIT_EXPECT_PTR_EQ(test, mapping->type, &mock_type_b);
+ dma_buf_mapping_unmap(attach, mapping, DMA_BIDIRECTIONAL);
+
+ KUNIT_EXPECT_PTR_EQ(test, dma_buf_attach_map_type(attach)->type,
+ &mock_type_b);
+
+ dma_buf_unpin(attach);
+ KUNIT_EXPECT_TRUE(test, attach->selected);
+ KUNIT_EXPECT_PTR_EQ(test, dma_buf_attach_map_type(attach)->type,
+ &mock_type_b);
+
+ dma_resv_unlock(dmabuf->resv);
+
+ dma_buf_detach(dmabuf, attach);
+ dma_buf_put(dmabuf);
+
+ mock_type_a.map = NULL;
+ mock_type_a.unmap = NULL;
+ mock_type_b.map = NULL;
+ mock_type_b.unmap = NULL;
+}
+
+/*
+ * A failed pin or map may only undo a selection it made itself. One made by
+ * an earlier pin or map belongs to that pin or mapping and must survive,
+ * otherwise the retry reselects under it without an invalidate. Reproduced
+ * by Karl Mehltretter against the posted series: pin selects B, map fails,
+ * retry selects A with the pin still held.
+ */
+static void test_select_survives_failed_map(struct kunit *test)
+{
+ static const struct dma_buf_mapping_match offer_ab[] = {
+ { .type = &mock_type_a },
+ { .type = &mock_type_b },
+ };
+ struct dma_buf_mapping_match imp[] = {
+ { .type = &mock_type_a },
+ { .type = &mock_type_b },
+ };
+ MOCK_IMPORTER_OPS(importer_ops, imp);
+ struct dma_buf_attachment *attach;
+ struct dma_buf_mapping *mapping;
+ struct dma_buf *dmabuf;
+ struct device *dev;
+
+ mock_type_a.map = mock_type_map;
+ mock_type_a.unmap = mock_type_unmap;
+ mock_type_b.map = mock_type_map;
+ mock_type_b.unmap = mock_type_unmap;
+
+ dev = kunit_device_register(test, "dma-buf-test");
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
+
+ dmabuf = mock_dmabuf_export(&mock_dmabuf_select_ops);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dmabuf);
+
+ mock_exp_offer = offer_ab;
+ mock_exp_offer_len = ARRAY_SIZE(offer_ab);
+ attach = dma_buf_dynamic_attach(dmabuf, dev, &importer_ops, NULL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, attach);
+
+ dma_resv_lock(dmabuf->resv, NULL);
+
+ /* A map that selected and then failed leaves nothing behind */
+ mock_select_idx = 1;
+ mock_map_err = -EIO;
+ mapping = dma_buf_mapping_map(attach, DMA_BIDIRECTIONAL);
+ KUNIT_EXPECT_EQ(test, PTR_ERR(mapping), -EIO);
+ KUNIT_EXPECT_FALSE(test, attach->selected);
+ KUNIT_EXPECT_PTR_EQ(test, dma_buf_attach_map_type(attach)->type,
+ &mock_type_a);
+ mock_map_err = 0;
+
+ /* Pin selects B and holds it */
+ KUNIT_EXPECT_EQ(test, dma_buf_pin(attach), 0);
+ KUNIT_EXPECT_TRUE(test, attach->selected);
+ KUNIT_EXPECT_PTR_EQ(test, dma_buf_attach_map_type(attach)->type,
+ &mock_type_b);
+ KUNIT_EXPECT_EQ(test, mock_pin_count, 1);
+
+ /* A map failing under that pin must not reopen the choice */
+ mock_select_idx = 0;
+ mock_map_err = -EIO;
+ mapping = dma_buf_mapping_map(attach, DMA_BIDIRECTIONAL);
+ KUNIT_EXPECT_EQ(test, PTR_ERR(mapping), -EIO);
+ KUNIT_EXPECT_TRUE(test, attach->selected);
+ KUNIT_EXPECT_PTR_EQ(test, dma_buf_attach_map_type(attach)->type,
+ &mock_type_b);
+ KUNIT_EXPECT_EQ(test, mock_pin_count, 1);
+ mock_map_err = 0;
+
+ /* The retry gets the pinned type, whatever the exporter answers now */
+ mapping = dma_buf_mapping_map(attach, DMA_BIDIRECTIONAL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, mapping);
+ KUNIT_EXPECT_PTR_EQ(test, mapping->type, &mock_type_b);
+ dma_buf_mapping_unmap(attach, mapping, DMA_BIDIRECTIONAL);
+
+ dma_buf_unpin(attach);
+ KUNIT_EXPECT_EQ(test, mock_pin_count, 0);
+
+ dma_resv_unlock(dmabuf->resv);
+
+ dma_buf_detach(dmabuf, attach);
+ dma_buf_put(dmabuf);
+
+ mock_type_a.map = NULL;
+ mock_type_a.unmap = NULL;
+ mock_type_b.map = NULL;
+ mock_type_b.unmap = NULL;
+}
+
+/*
+ * The same rule for a failing exporter pin: a pin that selected and then
+ * failed leaves nothing behind, one that failed under an existing mapping
+ * leaves the mapping's selection alone.
+ */
+static void test_select_after_failed_pin(struct kunit *test)
+{
+ static const struct dma_buf_mapping_match offer_ab[] = {
+ { .type = &mock_type_a },
+ { .type = &mock_type_b },
+ };
+ struct dma_buf_mapping_match imp[] = {
+ { .type = &mock_type_a },
+ { .type = &mock_type_b },
+ };
+ MOCK_IMPORTER_OPS(importer_ops, imp);
+ struct dma_buf_attachment *attach;
+ struct dma_buf_mapping *mapping;
+ struct dma_buf *dmabuf;
+ struct device *dev;
+
+ mock_type_a.map = mock_type_map;
+ mock_type_a.unmap = mock_type_unmap;
+ mock_type_b.map = mock_type_map;
+ mock_type_b.unmap = mock_type_unmap;
+
+ dev = kunit_device_register(test, "dma-buf-test");
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
+
+ dmabuf = mock_dmabuf_export(&mock_dmabuf_select_ops);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dmabuf);
+
+ mock_exp_offer = offer_ab;
+ mock_exp_offer_len = ARRAY_SIZE(offer_ab);
+ attach = dma_buf_dynamic_attach(dmabuf, dev, &importer_ops, NULL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, attach);
+
+ dma_resv_lock(dmabuf->resv, NULL);
+
+ /* First pin selects B but the exporter cannot pin: nothing is kept */
+ mock_select_idx = 1;
+ mock_pin_err = -ENOSPC;
+ KUNIT_EXPECT_EQ(test, dma_buf_pin(attach), -ENOSPC);
+ KUNIT_EXPECT_FALSE(test, attach->selected);
+ KUNIT_EXPECT_PTR_EQ(test, dma_buf_attach_map_type(attach)->type,
+ &mock_type_a);
+ KUNIT_EXPECT_EQ(test, mock_pin_count, 0);
+ mock_pin_err = 0;
+
+ /* A live mapping selects A */
+ mock_select_idx = 0;
+ mapping = dma_buf_mapping_map(attach, DMA_BIDIRECTIONAL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, mapping);
+ KUNIT_EXPECT_PTR_EQ(test, mapping->type, &mock_type_a);
+
+ /* A pin failing under it leaves that selection in place */
+ mock_select_idx = 1;
+ mock_pin_err = -ENOSPC;
+ KUNIT_EXPECT_EQ(test, dma_buf_pin(attach), -ENOSPC);
+ KUNIT_EXPECT_TRUE(test, attach->selected);
+ KUNIT_EXPECT_PTR_EQ(test, dma_buf_attach_map_type(attach)->type,
+ &mock_type_a);
+ mock_pin_err = 0;
+
+ dma_buf_mapping_unmap(attach, mapping, DMA_BIDIRECTIONAL);
+ dma_resv_unlock(dmabuf->resv);
+
+ dma_buf_detach(dmabuf, attach);
+ dma_buf_put(dmabuf);
+
+ mock_type_a.map = NULL;
+ mock_type_a.unmap = NULL;
+ mock_type_b.map = NULL;
+ mock_type_b.unmap = NULL;
+}
+
static const struct dma_exporter dma_exporter_params[] = {
{ &mock_dmabuf_simple_sgt_ops, "simple_sgt" },
{ &mock_dmabuf_two_exp_ops, "two_exp" },
@@ -389,6 +877,11 @@ static struct kunit_case dma_mapping_cases[] = {
KUNIT_CASE(test_match_importer_priority),
KUNIT_CASE_PARAM(test_sgt_attach, dma_exporter_gen_params),
KUNIT_CASE(test_mock_attach),
+ KUNIT_CASE(test_match_set_is_final),
+ KUNIT_CASE(test_select_at_map),
+ KUNIT_CASE(test_select_at_pin),
+ KUNIT_CASE(test_select_survives_failed_map),
+ KUNIT_CASE(test_select_after_failed_pin),
{}
};
--
2.54.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* Re: [PATCH v2 01/23] treewide: Rename dma_buf_(un)map_attachment() to dma_buf_(un)map_sgt()
2026-11-05 6:40 ` [PATCH v2 01/23] treewide: Rename dma_buf_(un)map_attachment() to dma_buf_(un)map_sgt() Alistair Popple
@ 2026-11-05 9:55 ` Christian König
0 siblings, 0 replies; 26+ messages in thread
From: Christian König @ 2026-11-05 9:55 UTC (permalink / raw)
To: Alistair Popple, Sumit Semwal, Thomas Hellström,
Simona Vetter, Matthew Brost, Vivek Kasireddy, Dongwon Kim,
Kevin Tian, Xu Yilun, Karl Mehltretter, Baolu Lu, Felix Kuehling,
Alex Deucher, dri-devel, intel-xe, amd-gfx, linux-media,
linaro-mm-sig, linux-rdma, iommu, Keith Busch, Jens Axboe,
Christoph Hellwig, Sagi Grimberg, linux-nvme, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Mina Almasry, netdev, Alexey Kardashevskiy, zhipingz, treding,
jhubbard, Jason Gunthorpe, Leon Romanovsky
On 11/5/26 07:40, Alistair Popple wrote:
> From: Jason Gunthorpe <jgg@nvidia.com>
>
> These map and unmap functions only work with SGT importers. Rename them,
> and their _unlocked variants, so the scatterlist based interface is
> clearly named as such before further mapping types are added.
>
> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
> Signed-off-by: Alistair Popple <apopple@nvidia.com>
Acked-by: Christian König <christian.koenig@amd.com>
If nobody objects by the end of the week I'm going to push this to drm-misc-next.
Regards,
Christian.
> ---
> drivers/accel/amdxdna/amdxdna_gem.c | 6 +--
> drivers/accel/ivpu/ivpu_gem.c | 6 +--
> drivers/accel/qaic/qaic_data.c | 6 +--
> drivers/dma-buf/dma-buf.c | 54 +++++++++++-----------
> drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 4 +-
> drivers/gpu/drm/armada/armada_gem.c | 16 +++----
> drivers/gpu/drm/drm_prime.c | 6 +--
> drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c | 8 ++--
> drivers/gpu/drm/i915/gem/i915_gem_object.c | 2 +-
> .../gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c | 4 +-
> drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c | 4 +-
> drivers/gpu/drm/tegra/gem.c | 14 +++---
> drivers/gpu/drm/virtio/virtgpu_prime.c | 8 ++--
> drivers/gpu/drm/xe/xe_bo.c | 16 +++----
> drivers/iio/industrialio-buffer.c | 6 +--
> drivers/infiniband/core/umem_dmabuf.c | 8 ++--
> drivers/media/common/videobuf2/videobuf2-core.c | 2 +-
> .../media/common/videobuf2/videobuf2-dma-contig.c | 8 ++--
> drivers/media/common/videobuf2/videobuf2-dma-sg.c | 4 +-
> .../media/platform/nvidia/tegra-vde/dmabuf-cache.c | 6 +--
> drivers/misc/fastrpc.c | 6 +--
> drivers/nvme/host/pci-dmabuf.c | 6 +--
> drivers/usb/gadget/function/f_fs.c | 4 +-
> drivers/xen/gntdev-dmabuf.c | 8 ++--
> include/linux/dma-buf.h | 26 +++++------
> io_uring/zcrx.c | 6 +--
> net/core/devmem.c | 8 ++--
> 27 files changed, 126 insertions(+), 126 deletions(-)
>
> diff --git a/drivers/accel/amdxdna/amdxdna_gem.c b/drivers/accel/amdxdna/amdxdna_gem.c
> index f14484bc31ec..adee6e806eed 100644
> --- a/drivers/accel/amdxdna/amdxdna_gem.c
> +++ b/drivers/accel/amdxdna/amdxdna_gem.c
> @@ -701,7 +701,7 @@ static struct dma_buf *amdxdna_gem_prime_export(struct drm_gem_object *gobj, int
>
> static void amdxdna_imported_obj_free(struct amdxdna_gem_obj *abo)
> {
> - dma_buf_unmap_attachment_unlocked(abo->attach, abo->base.sgt, DMA_BIDIRECTIONAL);
> + dma_buf_unmap_sgt_unlocked(abo->attach, abo->base.sgt, DMA_BIDIRECTIONAL);
> dma_buf_detach(abo->dma_buf, abo->attach);
> dma_buf_put(abo->dma_buf);
> drm_gem_object_release(to_gobj(abo));
> @@ -1075,7 +1075,7 @@ amdxdna_gem_prime_import(struct drm_device *dev, struct dma_buf *dma_buf)
> goto put_buf;
> }
>
> - sgt = dma_buf_map_attachment_unlocked(attach, DMA_BIDIRECTIONAL);
> + sgt = dma_buf_map_sgt_unlocked(attach, DMA_BIDIRECTIONAL);
> if (IS_ERR(sgt)) {
> ret = PTR_ERR(sgt);
> goto fail_detach;
> @@ -1096,7 +1096,7 @@ amdxdna_gem_prime_import(struct drm_device *dev, struct dma_buf *dma_buf)
> return gobj;
>
> fail_unmap:
> - dma_buf_unmap_attachment_unlocked(attach, sgt, DMA_BIDIRECTIONAL);
> + dma_buf_unmap_sgt_unlocked(attach, sgt, DMA_BIDIRECTIONAL);
> fail_detach:
> dma_buf_detach(dma_buf, attach);
> put_buf:
> diff --git a/drivers/accel/ivpu/ivpu_gem.c b/drivers/accel/ivpu/ivpu_gem.c
> index c521a53f89bb..276f2a04aeda 100644
> --- a/drivers/accel/ivpu/ivpu_gem.c
> +++ b/drivers/accel/ivpu/ivpu_gem.c
> @@ -54,7 +54,7 @@ static struct sg_table *ivpu_bo_map_attachment(struct ivpu_device *vdev, struct
>
> sgt = bo->base.sgt;
> if (!sgt) {
> - sgt = dma_buf_map_attachment(bo->base.base.import_attach, DMA_BIDIRECTIONAL);
> + sgt = dma_buf_map_sgt(bo->base.base.import_attach, DMA_BIDIRECTIONAL);
> if (IS_ERR(sgt))
> ivpu_err(vdev, "Failed to map BO in IOMMU: %ld\n", PTR_ERR(sgt));
> else
> @@ -158,8 +158,8 @@ static void ivpu_bo_unbind_locked(struct ivpu_bo *bo)
>
> if (bo->base.sgt) {
> if (drm_gem_is_imported(&bo->base.base)) {
> - dma_buf_unmap_attachment(bo->base.base.import_attach,
> - bo->base.sgt, DMA_BIDIRECTIONAL);
> + dma_buf_unmap_sgt(bo->base.base.import_attach,
> + bo->base.sgt, DMA_BIDIRECTIONAL);
> } else {
> dma_unmap_sgtable(vdev->drm.dev, bo->base.sgt, DMA_BIDIRECTIONAL, 0);
> sg_free_table(bo->base.sgt);
> diff --git a/drivers/accel/qaic/qaic_data.c b/drivers/accel/qaic/qaic_data.c
> index ee35e13091b3..d65578f0368e 100644
> --- a/drivers/accel/qaic/qaic_data.c
> +++ b/drivers/accel/qaic/qaic_data.c
> @@ -869,7 +869,7 @@ struct drm_gem_object *qaic_gem_prime_import(struct drm_device *dev, struct dma_
>
> drm_gem_private_object_init(dev, obj, attach->dmabuf->size);
> /*
> - * skipping dma_buf_map_attachment() as we do not know the direction
> + * skipping dma_buf_map_sgt() as we do not know the direction
> * just yet. Once the direction is known in the subsequent IOCTL to
> * attach slicing, we can do it then.
> */
> @@ -895,7 +895,7 @@ static int qaic_prepare_import_bo(struct qaic_bo *bo, struct qaic_attach_slice_h
> struct sg_table *sgt;
> int ret;
>
> - sgt = dma_buf_map_attachment(obj->import_attach, hdr->dir);
> + sgt = dma_buf_map_sgt(obj->import_attach, hdr->dir);
> if (IS_ERR(sgt)) {
> ret = PTR_ERR(sgt);
> return ret;
> @@ -936,7 +936,7 @@ static int qaic_prepare_bo(struct qaic_device *qdev, struct qaic_bo *bo,
>
> static void qaic_unprepare_import_bo(struct qaic_bo *bo)
> {
> - dma_buf_unmap_attachment(bo->base.import_attach, bo->sgt, bo->dir);
> + dma_buf_unmap_sgt(bo->base.import_attach, bo->sgt, bo->dir);
> bo->sgt = NULL;
> }
>
> diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
> index 36cdc342627e..0dd8d0999a92 100644
> --- a/drivers/dma-buf/dma-buf.c
> +++ b/drivers/dma-buf/dma-buf.c
> @@ -677,7 +677,7 @@ static struct file *dma_buf_getfile(size_t size, int flags)
> *
> * 3. Once the buffer is attached to all devices userspace can initiate DMA
> * access to the shared buffer. In the kernel this is done by calling
> - * dma_buf_map_attachment() and dma_buf_unmap_attachment().
> + * dma_buf_map_sgt() and dma_buf_unmap_sgt().
> *
> * 4. Once a driver is done with a shared buffer it needs to call
> * dma_buf_detach() (after cleaning up any mappings) and then release the
> @@ -955,8 +955,8 @@ dma_buf_pin_on_map(struct dma_buf_attachment *attach)
> *
> * - dma_buf_pin()
> * - dma_buf_unpin()
> - * - dma_buf_map_attachment()
> - * - dma_buf_unmap_attachment()
> + * - dma_buf_map_sgt()
> + * - dma_buf_unmap_sgt()
> * - dma_buf_vmap()
> * - dma_buf_vunmap()
> *
> @@ -973,8 +973,8 @@ dma_buf_pin_on_map(struct dma_buf_attachment *attach)
> * - dma_buf_mmap()
> * - dma_buf_begin_cpu_access()
> * - dma_buf_end_cpu_access()
> - * - dma_buf_map_attachment_unlocked()
> - * - dma_buf_unmap_attachment_unlocked()
> + * - dma_buf_map_sgt_unlocked()
> + * - dma_buf_unmap_sgt_unlocked()
> * - dma_buf_vmap_unlocked()
> * - dma_buf_vunmap_unlocked()
> *
> @@ -1165,7 +1165,7 @@ void dma_buf_unpin(struct dma_buf_attachment *attach)
> EXPORT_SYMBOL_NS_GPL(dma_buf_unpin, "DMA_BUF");
>
> /**
> - * dma_buf_map_attachment - Returns the scatterlist table of the attachment;
> + * dma_buf_map_sgt - Returns the scatterlist table of the attachment;
> * mapped into _device_ address space. Is a wrapper for map_dma_buf() of the
> * dma_buf_ops.
> * @attach: [in] attachment whose scatterlist is to be returned
> @@ -1177,7 +1177,7 @@ EXPORT_SYMBOL_NS_GPL(dma_buf_unpin, "DMA_BUF");
> * On success, the DMA addresses and lengths in the returned scatterlist are
> * PAGE_SIZE aligned.
> *
> - * A mapping must be unmapped by using dma_buf_unmap_attachment(). Note that
> + * A mapping must be unmapped by using dma_buf_unmap_sgt(). Note that
> * the underlying backing storage is pinned for as long as a mapping exists,
> * therefore users/importers should not hold onto a mapping for undue amounts of
> * time.
> @@ -1185,8 +1185,8 @@ EXPORT_SYMBOL_NS_GPL(dma_buf_unpin, "DMA_BUF");
> * Important: Dynamic importers must wait for the exclusive fence of the struct
> * dma_resv attached to the DMA-BUF first.
> */
> -struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
> - enum dma_data_direction direction)
> +struct sg_table *dma_buf_map_sgt(struct dma_buf_attachment *attach,
> + enum dma_data_direction direction)
> {
> struct sg_table *sg_table;
> signed long ret;
> @@ -1257,20 +1257,20 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
>
> return sg_table;
> }
> -EXPORT_SYMBOL_NS_GPL(dma_buf_map_attachment, "DMA_BUF");
> +EXPORT_SYMBOL_NS_GPL(dma_buf_map_sgt, "DMA_BUF");
>
> /**
> - * dma_buf_map_attachment_unlocked - Returns the scatterlist table of the attachment;
> + * dma_buf_map_sgt_unlocked - Returns the scatterlist table of the attachment;
> * mapped into _device_ address space. Is a wrapper for map_dma_buf() of the
> * dma_buf_ops.
> * @attach: [in] attachment whose scatterlist is to be returned
> * @direction: [in] direction of DMA transfer
> *
> - * Unlocked variant of dma_buf_map_attachment().
> + * Unlocked variant of dma_buf_map_sgt().
> */
> struct sg_table *
> -dma_buf_map_attachment_unlocked(struct dma_buf_attachment *attach,
> - enum dma_data_direction direction)
> +dma_buf_map_sgt_unlocked(struct dma_buf_attachment *attach,
> + enum dma_data_direction direction)
> {
> struct sg_table *sg_table;
>
> @@ -1280,24 +1280,24 @@ dma_buf_map_attachment_unlocked(struct dma_buf_attachment *attach,
> return ERR_PTR(-EINVAL);
>
> dma_resv_lock(attach->dmabuf->resv, NULL);
> - sg_table = dma_buf_map_attachment(attach, direction);
> + sg_table = dma_buf_map_sgt(attach, direction);
> dma_resv_unlock(attach->dmabuf->resv);
>
> return sg_table;
> }
> -EXPORT_SYMBOL_NS_GPL(dma_buf_map_attachment_unlocked, "DMA_BUF");
> +EXPORT_SYMBOL_NS_GPL(dma_buf_map_sgt_unlocked, "DMA_BUF");
>
> /**
> - * dma_buf_unmap_attachment - unmaps and decreases usecount of the buffer;might
> + * dma_buf_unmap_sgt - unmaps and decreases usecount of the buffer;might
> * deallocate the scatterlist associated. Is a wrapper for unmap_dma_buf() of
> * dma_buf_ops.
> * @attach: [in] attachment to unmap buffer from
> * @sg_table: [in] scatterlist info of the buffer to unmap
> * @direction: [in] direction of DMA transfer
> *
> - * This unmaps a DMA mapping for @attached obtained by dma_buf_map_attachment().
> + * This unmaps a DMA mapping for @attached obtained by dma_buf_map_sgt().
> */
> -void dma_buf_unmap_attachment(struct dma_buf_attachment *attach,
> +void dma_buf_unmap_sgt(struct dma_buf_attachment *attach,
> struct sg_table *sg_table,
> enum dma_data_direction direction)
> {
> @@ -1314,21 +1314,21 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment *attach,
> if (dma_buf_pin_on_map(attach))
> attach->dmabuf->ops->unpin(attach);
> }
> -EXPORT_SYMBOL_NS_GPL(dma_buf_unmap_attachment, "DMA_BUF");
> +EXPORT_SYMBOL_NS_GPL(dma_buf_unmap_sgt, "DMA_BUF");
>
> /**
> - * dma_buf_unmap_attachment_unlocked - unmaps and decreases usecount of the buffer;might
> + * dma_buf_unmap_sgt_unlocked - unmaps and decreases usecount of the buffer;might
> * deallocate the scatterlist associated. Is a wrapper for unmap_dma_buf() of
> * dma_buf_ops.
> * @attach: [in] attachment to unmap buffer from
> * @sg_table: [in] scatterlist info of the buffer to unmap
> * @direction: [in] direction of DMA transfer
> *
> - * Unlocked variant of dma_buf_unmap_attachment().
> + * Unlocked variant of dma_buf_unmap_sgt().
> */
> -void dma_buf_unmap_attachment_unlocked(struct dma_buf_attachment *attach,
> - struct sg_table *sg_table,
> - enum dma_data_direction direction)
> +void dma_buf_unmap_sgt_unlocked(struct dma_buf_attachment *attach,
> + struct sg_table *sg_table,
> + enum dma_data_direction direction)
> {
> might_sleep();
>
> @@ -1336,10 +1336,10 @@ void dma_buf_unmap_attachment_unlocked(struct dma_buf_attachment *attach,
> return;
>
> dma_resv_lock(attach->dmabuf->resv, NULL);
> - dma_buf_unmap_attachment(attach, sg_table, direction);
> + dma_buf_unmap_sgt(attach, sg_table, direction);
> dma_resv_unlock(attach->dmabuf->resv);
> }
> -EXPORT_SYMBOL_NS_GPL(dma_buf_unmap_attachment_unlocked, "DMA_BUF");
> +EXPORT_SYMBOL_NS_GPL(dma_buf_unmap_sgt_unlocked, "DMA_BUF");
>
> /**
> * dma_buf_attach_revocable - check if a DMA-buf importer implements
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
> index 0f86777250fc..30ec5cb9ddf5 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
> @@ -962,7 +962,7 @@ static int amdgpu_ttm_backend_bind(struct ttm_device *bdev,
> struct sg_table *sgt;
>
> attach = gtt->gobj->import_attach;
> - sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
> + sgt = dma_buf_map_sgt(attach, DMA_BIDIRECTIONAL);
> if (IS_ERR(sgt))
> return PTR_ERR(sgt);
>
> @@ -1083,7 +1083,7 @@ static void amdgpu_ttm_backend_unbind(struct ttm_device *bdev,
> struct dma_buf_attachment *attach;
>
> attach = gtt->gobj->import_attach;
> - dma_buf_unmap_attachment(attach, ttm->sg, DMA_BIDIRECTIONAL);
> + dma_buf_unmap_sgt(attach, ttm->sg, DMA_BIDIRECTIONAL);
> ttm->sg = NULL;
> }
>
> diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c
> index da7335cbe82d..044acdef6351 100644
> --- a/drivers/gpu/drm/armada/armada_gem.c
> +++ b/drivers/gpu/drm/armada/armada_gem.c
> @@ -67,8 +67,8 @@ void armada_gem_free_object(struct drm_gem_object *obj)
> if (dobj->obj.import_attach) {
> /* We only ever display imported data */
> if (dobj->sgt)
> - dma_buf_unmap_attachment_unlocked(dobj->obj.import_attach,
> - dobj->sgt, DMA_TO_DEVICE);
> + dma_buf_unmap_sgt_unlocked(dobj->obj.import_attach,
> + dobj->sgt, DMA_TO_DEVICE);
> drm_prime_gem_destroy(&dobj->obj, NULL);
> }
>
> @@ -529,7 +529,7 @@ armada_gem_prime_import(struct drm_device *dev, struct dma_buf *buf)
> get_dma_buf(buf);
>
> /*
> - * Don't call dma_buf_map_attachment() here - it maps the
> + * Don't call dma_buf_map_sgt() here - it maps the
> * scatterlist immediately for DMA, and this is not always
> * an appropriate thing to do.
> */
> @@ -540,20 +540,20 @@ int armada_gem_map_import(struct armada_gem_object *dobj)
> {
> int ret;
>
> - dobj->sgt = dma_buf_map_attachment_unlocked(dobj->obj.import_attach,
> - DMA_TO_DEVICE);
> + dobj->sgt = dma_buf_map_sgt_unlocked(dobj->obj.import_attach,
> + DMA_TO_DEVICE);
> if (IS_ERR(dobj->sgt)) {
> ret = PTR_ERR(dobj->sgt);
> dobj->sgt = NULL;
> - DRM_ERROR("dma_buf_map_attachment() error: %d\n", ret);
> + DRM_ERROR("dma_buf_map_sgt() error: %d\n", ret);
> return ret;
> }
> if (dobj->sgt->nents > 1) {
> - DRM_ERROR("dma_buf_map_attachment() returned an (unsupported) scattered list\n");
> + DRM_ERROR("dma_buf_map_sgt() returned an (unsupported) scattered list\n");
> return -EINVAL;
> }
> if (sg_dma_len(dobj->sgt->sgl) < dobj->obj.size) {
> - DRM_ERROR("dma_buf_map_attachment() returned a small buffer\n");
> + DRM_ERROR("dma_buf_map_sgt() returned a small buffer\n");
> return -EINVAL;
> }
> dobj->dev_addr = sg_dma_address(dobj->sgt->sgl);
> diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
> index fe3436d1235d..e27bda3423ed 100644
> --- a/drivers/gpu/drm/drm_prime.c
> +++ b/drivers/gpu/drm/drm_prime.c
> @@ -993,7 +993,7 @@ struct drm_gem_object *drm_gem_prime_import_dev(struct drm_device *dev,
>
> get_dma_buf(dma_buf);
>
> - sgt = dma_buf_map_attachment_unlocked(attach, DMA_BIDIRECTIONAL);
> + sgt = dma_buf_map_sgt_unlocked(attach, DMA_BIDIRECTIONAL);
> if (IS_ERR(sgt)) {
> ret = PTR_ERR(sgt);
> goto fail_detach;
> @@ -1011,7 +1011,7 @@ struct drm_gem_object *drm_gem_prime_import_dev(struct drm_device *dev,
> return obj;
>
> fail_unmap:
> - dma_buf_unmap_attachment_unlocked(attach, sgt, DMA_BIDIRECTIONAL);
> + dma_buf_unmap_sgt_unlocked(attach, sgt, DMA_BIDIRECTIONAL);
> fail_detach:
> dma_buf_detach(dma_buf, attach);
> dma_buf_put(dma_buf);
> @@ -1109,7 +1109,7 @@ void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg)
>
> attach = obj->import_attach;
> if (sg)
> - dma_buf_unmap_attachment_unlocked(attach, sg, DMA_BIDIRECTIONAL);
> + dma_buf_unmap_sgt_unlocked(attach, sg, DMA_BIDIRECTIONAL);
> dma_buf = attach->dmabuf;
> dma_buf_detach(attach->dmabuf, attach);
> /* remove the reference */
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
> index b43d34c7d641..4ab54d2e616f 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
> @@ -240,8 +240,8 @@ static int i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj)
>
> assert_object_held(obj);
>
> - sgt = dma_buf_map_attachment(obj->base.import_attach,
> - DMA_BIDIRECTIONAL);
> + sgt = dma_buf_map_sgt(obj->base.import_attach,
> + DMA_BIDIRECTIONAL);
> if (IS_ERR(sgt))
> return PTR_ERR(sgt);
>
> @@ -268,8 +268,8 @@ static int i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj)
> static void i915_gem_object_put_pages_dmabuf(struct drm_i915_gem_object *obj,
> struct sg_table *sgt)
> {
> - dma_buf_unmap_attachment(obj->base.import_attach, sgt,
> - DMA_BIDIRECTIONAL);
> + dma_buf_unmap_sgt(obj->base.import_attach, sgt,
> + DMA_BIDIRECTIONAL);
> }
>
> static const struct drm_i915_gem_object_ops i915_gem_object_dmabuf_ops = {
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c
> index 9e01f8b2079a..1e0aafc3643b 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
> @@ -367,7 +367,7 @@ void __i915_gem_object_pages_fini(struct drm_i915_gem_object *obj)
> atomic_set(&obj->mm.pages_pin_count, 0);
>
> /*
> - * dma_buf_unmap_attachment() requires reservation to be
> + * dma_buf_unmap_sgt() requires reservation to be
> * locked. The imported GEM shouldn't share reservation lock
> * and ttm_bo_cleanup_memtype_use() shouldn't be invoked for
> * dma-buf, so it's safe to take the lock.
> diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
> index 2fda549dd82d..af9ced05f7a8 100644
> --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
> +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
> @@ -293,7 +293,7 @@ static int igt_dmabuf_import_same_driver(struct drm_i915_private *i915,
> goto out_import;
> }
>
> - st = dma_buf_map_attachment_unlocked(import_attach, DMA_BIDIRECTIONAL);
> + st = dma_buf_map_sgt_unlocked(import_attach, DMA_BIDIRECTIONAL);
> if (IS_ERR(st)) {
> err = PTR_ERR(st);
> goto out_detach;
> @@ -306,7 +306,7 @@ static int igt_dmabuf_import_same_driver(struct drm_i915_private *i915,
> timeout = -ETIME;
> }
> err = timeout > 0 ? 0 : timeout;
> - dma_buf_unmap_attachment_unlocked(import_attach, st, DMA_BIDIRECTIONAL);
> + dma_buf_unmap_sgt_unlocked(import_attach, st, DMA_BIDIRECTIONAL);
> out_detach:
> dma_buf_detach(dmabuf, import_attach);
> out_import:
> diff --git a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
> index 30cf1cdc1aa3..afae0a56da8c 100644
> --- a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
> +++ b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
> @@ -120,7 +120,7 @@ struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev,
>
> get_dma_buf(dma_buf);
>
> - sgt = dma_buf_map_attachment_unlocked(attach, DMA_TO_DEVICE);
> + sgt = dma_buf_map_sgt_unlocked(attach, DMA_TO_DEVICE);
> if (IS_ERR(sgt)) {
> ret = PTR_ERR(sgt);
> goto fail_detach;
> @@ -137,7 +137,7 @@ struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev,
> return obj;
>
> fail_unmap:
> - dma_buf_unmap_attachment_unlocked(attach, sgt, DMA_TO_DEVICE);
> + dma_buf_unmap_sgt_unlocked(attach, sgt, DMA_TO_DEVICE);
> fail_detach:
> dma_buf_detach(dma_buf, attach);
> dma_buf_put(dma_buf);
> diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c
> index f76af733ea79..e6aa6dae4ec8 100644
> --- a/drivers/gpu/drm/tegra/gem.c
> +++ b/drivers/gpu/drm/tegra/gem.c
> @@ -86,7 +86,7 @@ static struct host1x_bo_mapping *tegra_bo_pin(struct device *dev, struct host1x_
> goto free;
> }
>
> - map->sgt = dma_buf_map_attachment_unlocked(map->attach, direction);
> + map->sgt = dma_buf_map_sgt_unlocked(map->attach, direction);
> if (IS_ERR(map->sgt)) {
> dma_buf_detach(buf, map->attach);
> err = PTR_ERR(map->sgt);
> @@ -162,8 +162,8 @@ static struct host1x_bo_mapping *tegra_bo_pin(struct device *dev, struct host1x_
> static void tegra_bo_unpin(struct host1x_bo_mapping *map)
> {
> if (map->attach) {
> - dma_buf_unmap_attachment_unlocked(map->attach, map->sgt,
> - map->direction);
> + dma_buf_unmap_sgt_unlocked(map->attach, map->sgt,
> + map->direction);
> dma_buf_detach(map->attach->dmabuf, map->attach);
> } else {
> dma_unmap_sgtable(map->dev, map->sgt, map->direction, 0);
> @@ -479,7 +479,7 @@ static struct tegra_bo *tegra_bo_import(struct drm_device *drm,
> goto free;
> }
>
> - bo->sgt = dma_buf_map_attachment_unlocked(attach, DMA_TO_DEVICE);
> + bo->sgt = dma_buf_map_sgt_unlocked(attach, DMA_TO_DEVICE);
> if (IS_ERR(bo->sgt)) {
> err = PTR_ERR(bo->sgt);
> goto detach;
> @@ -499,7 +499,7 @@ static struct tegra_bo *tegra_bo_import(struct drm_device *drm,
>
> detach:
> if (!IS_ERR_OR_NULL(bo->sgt))
> - dma_buf_unmap_attachment_unlocked(attach, bo->sgt, DMA_TO_DEVICE);
> + dma_buf_unmap_sgt_unlocked(attach, bo->sgt, DMA_TO_DEVICE);
>
> dma_buf_detach(buf, attach);
> dma_buf_put(buf);
> @@ -520,8 +520,8 @@ void tegra_bo_free_object(struct drm_gem_object *gem)
> tegra_bo_iommu_unmap(tegra, bo);
>
> if (drm_gem_is_imported(gem)) {
> - dma_buf_unmap_attachment_unlocked(gem->import_attach, bo->sgt,
> - DMA_TO_DEVICE);
> + dma_buf_unmap_sgt_unlocked(gem->import_attach, bo->sgt,
> + DMA_TO_DEVICE);
> dma_buf_detach(gem->import_attach->dmabuf, gem->import_attach);
> }
> }
> diff --git a/drivers/gpu/drm/virtio/virtgpu_prime.c b/drivers/gpu/drm/virtio/virtgpu_prime.c
> index ebf471044d06..a47783b47dcc 100644
> --- a/drivers/gpu/drm/virtio/virtgpu_prime.c
> +++ b/drivers/gpu/drm/virtio/virtgpu_prime.c
> @@ -161,13 +161,13 @@ int virtgpu_dma_buf_import_sgt(struct virtio_gpu_mem_entry **ents,
> if (ret <= 0)
> return ret < 0 ? ret : -ETIMEDOUT;
>
> - sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
> + sgt = dma_buf_map_sgt(attach, DMA_BIDIRECTIONAL);
> if (IS_ERR(sgt))
> return PTR_ERR(sgt);
>
> *ents = kvmalloc_objs(struct virtio_gpu_mem_entry, sgt->nents);
> if (!(*ents)) {
> - dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
> + dma_buf_unmap_sgt(attach, sgt, DMA_BIDIRECTIONAL);
> return -ENOMEM;
> }
>
> @@ -192,8 +192,8 @@ static void virtgpu_dma_buf_unmap(struct virtio_gpu_object *bo)
> virtio_gpu_detach_object_fenced(bo);
>
> if (bo->sgt)
> - dma_buf_unmap_attachment(attach, bo->sgt,
> - DMA_BIDIRECTIONAL);
> + dma_buf_unmap_sgt(attach, bo->sgt,
> + DMA_BIDIRECTIONAL);
>
> bo->sgt = NULL;
> }
> diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c
> index 12e523c61c1f..14b71d951659 100644
> --- a/drivers/gpu/drm/xe/xe_bo.c
> +++ b/drivers/gpu/drm/xe/xe_bo.c
> @@ -869,7 +869,7 @@ static int xe_bo_move_dmabuf(struct ttm_buffer_object *ttm_bo,
> ttm_bo->sg) {
> dma_resv_wait_timeout(ttm_bo->base.resv, DMA_RESV_USAGE_BOOKKEEP,
> false, MAX_SCHEDULE_TIMEOUT);
> - dma_buf_unmap_attachment(attach, ttm_bo->sg, DMA_BIDIRECTIONAL);
> + dma_buf_unmap_sgt(attach, ttm_bo->sg, DMA_BIDIRECTIONAL);
> ttm_bo->sg = NULL;
> }
>
> @@ -877,11 +877,11 @@ static int xe_bo_move_dmabuf(struct ttm_buffer_object *ttm_bo,
> goto out;
>
> if (ttm_bo->sg) {
> - dma_buf_unmap_attachment(attach, ttm_bo->sg, DMA_BIDIRECTIONAL);
> + dma_buf_unmap_sgt(attach, ttm_bo->sg, DMA_BIDIRECTIONAL);
> ttm_bo->sg = NULL;
> }
>
> - sg = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
> + sg = dma_buf_map_sgt(attach, DMA_BIDIRECTIONAL);
> if (IS_ERR(sg))
> return PTR_ERR(sg);
>
> @@ -1750,9 +1750,9 @@ int xe_bo_dma_unmap_pinned(struct xe_bo *bo)
> struct xe_ttm_tt *xe_tt = container_of(tt, typeof(*xe_tt), ttm);
>
> if (ttm_bo->type == ttm_bo_type_sg && ttm_bo->sg) {
> - dma_buf_unmap_attachment(ttm_bo->base.import_attach,
> - ttm_bo->sg,
> - DMA_BIDIRECTIONAL);
> + dma_buf_unmap_sgt(ttm_bo->base.import_attach,
> + ttm_bo->sg,
> + DMA_BIDIRECTIONAL);
> ttm_bo->sg = NULL;
> xe_tt->sg = NULL;
> } else if (xe_tt->sg) {
> @@ -1867,8 +1867,8 @@ static void xe_ttm_bo_delete_mem_notify(struct ttm_buffer_object *ttm_bo)
> struct xe_ttm_tt *xe_tt = container_of(ttm_bo->ttm,
> struct xe_ttm_tt, ttm);
>
> - dma_buf_unmap_attachment(ttm_bo->base.import_attach, ttm_bo->sg,
> - DMA_BIDIRECTIONAL);
> + dma_buf_unmap_sgt(ttm_bo->base.import_attach, ttm_bo->sg,
> + DMA_BIDIRECTIONAL);
> ttm_bo->sg = NULL;
> xe_tt->sg = NULL;
> }
> diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
> index 4294101810fd..4a1063e4891f 100644
> --- a/drivers/iio/industrialio-buffer.c
> +++ b/drivers/iio/industrialio-buffer.c
> @@ -1593,7 +1593,7 @@ static void iio_buffer_dmabuf_release(struct kref *ref)
> struct iio_buffer *buffer = priv->buffer;
> struct dma_buf *dmabuf = attach->dmabuf;
>
> - dma_buf_unmap_attachment_unlocked(attach, priv->sgt, priv->dir);
> + dma_buf_unmap_sgt_unlocked(attach, priv->sgt, priv->dir);
>
> buffer->access->detach_dmabuf(buffer, priv->block);
>
> @@ -1733,7 +1733,7 @@ static int iio_buffer_attach_dmabuf(struct iio_dev_buffer_pair *ib,
> priv->dir = buffer->direction == IIO_BUFFER_DIRECTION_IN
> ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
>
> - priv->sgt = dma_buf_map_attachment(attach, priv->dir);
> + priv->sgt = dma_buf_map_sgt(attach, priv->dir);
> if (IS_ERR(priv->sgt)) {
> err = PTR_ERR(priv->sgt);
> dev_err(&indio_dev->dev, "Unable to map attachment: %d\n", err);
> @@ -1781,7 +1781,7 @@ static int iio_buffer_attach_dmabuf(struct iio_dev_buffer_pair *ib,
> return 0;
>
> err_dmabuf_unmap_attachment:
> - dma_buf_unmap_attachment(attach, priv->sgt, priv->dir);
> + dma_buf_unmap_sgt(attach, priv->sgt, priv->dir);
> err_resv_unlock:
> dma_resv_unlock(dmabuf->resv);
> err_dmabuf_detach:
> diff --git a/drivers/infiniband/core/umem_dmabuf.c b/drivers/infiniband/core/umem_dmabuf.c
> index 39b5564a4c35..f233fdac9a17 100644
> --- a/drivers/infiniband/core/umem_dmabuf.c
> +++ b/drivers/infiniband/core/umem_dmabuf.c
> @@ -29,8 +29,8 @@ int ib_umem_dmabuf_map_pages(struct ib_umem_dmabuf *umem_dmabuf)
> if (umem_dmabuf->sgt)
> goto wait_fence;
>
> - sgt = dma_buf_map_attachment(umem_dmabuf->attach,
> - DMA_BIDIRECTIONAL);
> + sgt = dma_buf_map_sgt(umem_dmabuf->attach,
> + DMA_BIDIRECTIONAL);
> if (IS_ERR(sgt))
> return PTR_ERR(sgt);
>
> @@ -106,8 +106,8 @@ void ib_umem_dmabuf_unmap_pages(struct ib_umem_dmabuf *umem_dmabuf)
> umem_dmabuf->last_sg_trim = 0;
> }
>
> - dma_buf_unmap_attachment(umem_dmabuf->attach, umem_dmabuf->sgt,
> - DMA_BIDIRECTIONAL);
> + dma_buf_unmap_sgt(umem_dmabuf->attach, umem_dmabuf->sgt,
> + DMA_BIDIRECTIONAL);
>
> umem_dmabuf->sgt = NULL;
> }
> diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c
> index b0a6084f1757..61a614074222 100644
> --- a/drivers/media/common/videobuf2/videobuf2-core.c
> +++ b/drivers/media/common/videobuf2/videobuf2-core.c
> @@ -1464,7 +1464,7 @@ static int __prepare_dmabuf(struct vb2_buffer *vb)
> vb->planes[plane].mem_priv = mem_priv;
>
> /*
> - * This pins the buffer(s) with dma_buf_map_attachment()). It's done
> + * This pins the buffer(s) with dma_buf_map_sgt()). It's done
> * here instead just before the DMA, while queueing the buffer(s) so
> * userspace knows sooner rather than later if the dma-buf map fails.
> */
> diff --git a/drivers/media/common/videobuf2/videobuf2-dma-contig.c b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
> index 9ce6284cd5f2..284482335c1a 100644
> --- a/drivers/media/common/videobuf2/videobuf2-dma-contig.c
> +++ b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
> @@ -705,7 +705,7 @@ static int vb2_dc_map_dmabuf(void *mem_priv)
> }
>
> /* get the associated scatterlist for this buffer */
> - sgt = dma_buf_map_attachment_unlocked(buf->db_attach, buf->dma_dir);
> + sgt = dma_buf_map_sgt_unlocked(buf->db_attach, buf->dma_dir);
> if (IS_ERR(sgt)) {
> pr_err("Error getting dmabuf scatterlist\n");
> return -EINVAL;
> @@ -716,8 +716,8 @@ static int vb2_dc_map_dmabuf(void *mem_priv)
> if (contig_size < buf->size) {
> pr_err("contiguous chunk is too small %lu/%lu\n",
> contig_size, buf->size);
> - dma_buf_unmap_attachment_unlocked(buf->db_attach, sgt,
> - buf->dma_dir);
> + dma_buf_unmap_sgt_unlocked(buf->db_attach, sgt,
> + buf->dma_dir);
> return -EFAULT;
> }
>
> @@ -748,7 +748,7 @@ static void vb2_dc_unmap_dmabuf(void *mem_priv)
> dma_buf_vunmap_unlocked(buf->db_attach->dmabuf, &map);
> buf->vaddr = NULL;
> }
> - dma_buf_unmap_attachment_unlocked(buf->db_attach, sgt, buf->dma_dir);
> + dma_buf_unmap_sgt_unlocked(buf->db_attach, sgt, buf->dma_dir);
>
> buf->dma_addr = 0;
> buf->dma_sgt = NULL;
> diff --git a/drivers/media/common/videobuf2/videobuf2-dma-sg.c b/drivers/media/common/videobuf2/videobuf2-dma-sg.c
> index b1d0695cda26..54b07e3840ac 100644
> --- a/drivers/media/common/videobuf2/videobuf2-dma-sg.c
> +++ b/drivers/media/common/videobuf2/videobuf2-dma-sg.c
> @@ -565,7 +565,7 @@ static int vb2_dma_sg_map_dmabuf(void *mem_priv)
> }
>
> /* get the associated scatterlist for this buffer */
> - sgt = dma_buf_map_attachment_unlocked(buf->db_attach, buf->dma_dir);
> + sgt = dma_buf_map_sgt_unlocked(buf->db_attach, buf->dma_dir);
> if (IS_ERR(sgt)) {
> pr_err("Error getting dmabuf scatterlist\n");
> return -EINVAL;
> @@ -597,7 +597,7 @@ static void vb2_dma_sg_unmap_dmabuf(void *mem_priv)
> dma_buf_vunmap_unlocked(buf->db_attach->dmabuf, &map);
> buf->vaddr = NULL;
> }
> - dma_buf_unmap_attachment_unlocked(buf->db_attach, sgt, buf->dma_dir);
> + dma_buf_unmap_sgt_unlocked(buf->db_attach, sgt, buf->dma_dir);
>
> buf->dma_sgt = NULL;
> }
> diff --git a/drivers/media/platform/nvidia/tegra-vde/dmabuf-cache.c b/drivers/media/platform/nvidia/tegra-vde/dmabuf-cache.c
> index 7752064be783..d9bac7cd855a 100644
> --- a/drivers/media/platform/nvidia/tegra-vde/dmabuf-cache.c
> +++ b/drivers/media/platform/nvidia/tegra-vde/dmabuf-cache.c
> @@ -38,7 +38,7 @@ static void tegra_vde_release_entry(struct tegra_vde_cache_entry *entry)
> if (entry->vde->domain)
> tegra_vde_iommu_unmap(entry->vde, entry->iova);
>
> - dma_buf_unmap_attachment_unlocked(entry->a, entry->sgt, entry->dma_dir);
> + dma_buf_unmap_sgt_unlocked(entry->a, entry->sgt, entry->dma_dir);
> dma_buf_detach(dmabuf, entry->a);
> dma_buf_put(dmabuf);
>
> @@ -102,7 +102,7 @@ int tegra_vde_dmabuf_cache_map(struct tegra_vde *vde,
> goto err_unlock;
> }
>
> - sgt = dma_buf_map_attachment_unlocked(attachment, dma_dir);
> + sgt = dma_buf_map_sgt_unlocked(attachment, dma_dir);
> if (IS_ERR(sgt)) {
> dev_err(dev, "Failed to get dmabufs sg_table\n");
> err = PTR_ERR(sgt);
> @@ -152,7 +152,7 @@ int tegra_vde_dmabuf_cache_map(struct tegra_vde *vde,
> err_free:
> kfree(entry);
> err_unmap:
> - dma_buf_unmap_attachment_unlocked(attachment, sgt, dma_dir);
> + dma_buf_unmap_sgt_unlocked(attachment, sgt, dma_dir);
> err_detach:
> dma_buf_detach(dmabuf, attachment);
> err_unlock:
> diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
> index af18ff1992ee..76c8dc05fa10 100644
> --- a/drivers/misc/fastrpc.c
> +++ b/drivers/misc/fastrpc.c
> @@ -401,8 +401,8 @@ static void fastrpc_free_map(struct kref *ref)
> return;
> }
> }
> - dma_buf_unmap_attachment_unlocked(map->attach, map->table,
> - DMA_BIDIRECTIONAL);
> + dma_buf_unmap_sgt_unlocked(map->attach, map->table,
> + DMA_BIDIRECTIONAL);
> dma_buf_detach(map->buf, map->attach);
> dma_buf_put(map->buf);
> }
> @@ -911,7 +911,7 @@ static int fastrpc_map_attach(struct fastrpc_user *fl, int fd,
> goto attach_err;
> }
>
> - table = dma_buf_map_attachment_unlocked(map->attach, DMA_BIDIRECTIONAL);
> + table = dma_buf_map_sgt_unlocked(map->attach, DMA_BIDIRECTIONAL);
> if (IS_ERR(table)) {
> err = PTR_ERR(table);
> goto map_err;
> diff --git a/drivers/nvme/host/pci-dmabuf.c b/drivers/nvme/host/pci-dmabuf.c
> index 161e4ffa6919..fe741dc0d54a 100644
> --- a/drivers/nvme/host/pci-dmabuf.c
> +++ b/drivers/nvme/host/pci-dmabuf.c
> @@ -41,7 +41,7 @@ static struct dma_buf_io_map *nvme_dma_buf_io_map(struct dma_buf_io_ctx *ctx)
> return ERR_PTR(-ENOMEM);
> map->nr_entries = nr_entries;
>
> - sgt = dma_buf_map_attachment(attach, ctx->dir);
> + sgt = dma_buf_map_sgt(attach, ctx->dir);
> if (IS_ERR(sgt)) {
> ret = PTR_ERR(sgt);
> sgt = NULL;
> @@ -71,7 +71,7 @@ static struct dma_buf_io_map *nvme_dma_buf_io_map(struct dma_buf_io_ctx *ctx)
> return &map->base;
> err:
> if (sgt)
> - dma_buf_unmap_attachment(attach, sgt, ctx->dir);
> + dma_buf_unmap_sgt(attach, sgt, ctx->dir);
> kvfree(map);
> return ERR_PTR(ret);
> }
> @@ -84,7 +84,7 @@ static void nvme_dma_buf_io_unmap(struct dma_buf_io_ctx *ctx,
>
> dma_resv_assert_held(ctx->dmabuf->resv);
>
> - dma_buf_unmap_attachment(nvme_ctx->attach, map->sgt, ctx->dir);
> + dma_buf_unmap_sgt(nvme_ctx->attach, map->sgt, ctx->dir);
> kvfree(map);
> }
>
> diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
> index c64a268e98a4..2f221d0a983f 100644
> --- a/drivers/usb/gadget/function/f_fs.c
> +++ b/drivers/usb/gadget/function/f_fs.c
> @@ -1365,7 +1365,7 @@ static void ffs_dmabuf_release(struct kref *ref)
> struct dma_buf *dmabuf = attach->dmabuf;
>
> pr_vdebug("FFS DMABUF release\n");
> - dma_buf_unmap_attachment_unlocked(attach, priv->sgt, priv->dir);
> + dma_buf_unmap_sgt_unlocked(attach, priv->sgt, priv->dir);
>
> dma_buf_detach(attach->dmabuf, attach);
> dma_buf_put(dmabuf);
> @@ -1566,7 +1566,7 @@ static int ffs_dmabuf_attach(struct file *file, int fd)
> if (err)
> goto err_free_priv;
>
> - sg_table = dma_buf_map_attachment(attach, dir);
> + sg_table = dma_buf_map_sgt(attach, dir);
> dma_resv_unlock(dmabuf->resv);
>
> if (IS_ERR(sg_table)) {
> diff --git a/drivers/xen/gntdev-dmabuf.c b/drivers/xen/gntdev-dmabuf.c
> index df1883aca850..e07e34515421 100644
> --- a/drivers/xen/gntdev-dmabuf.c
> +++ b/drivers/xen/gntdev-dmabuf.c
> @@ -587,7 +587,7 @@ dmabuf_imp_to_refs(struct gntdev_dmabuf_priv *priv, struct device *dev,
>
> gntdev_dmabuf->u.imp.attach = attach;
>
> - sgt = dma_buf_map_attachment_unlocked(attach, DMA_BIDIRECTIONAL);
> + sgt = dma_buf_map_sgt_unlocked(attach, DMA_BIDIRECTIONAL);
> if (IS_ERR(sgt)) {
> ret = ERR_CAST(sgt);
> goto fail_detach;
> @@ -650,7 +650,7 @@ dmabuf_imp_to_refs(struct gntdev_dmabuf_priv *priv, struct device *dev,
> fail_end_access:
> dmabuf_imp_end_foreign_access(gntdev_dmabuf->u.imp.refs, count);
> fail_unmap:
> - dma_buf_unmap_attachment_unlocked(attach, sgt, DMA_BIDIRECTIONAL);
> + dma_buf_unmap_sgt_unlocked(attach, sgt, DMA_BIDIRECTIONAL);
> fail_detach:
> dma_buf_detach(dma_buf, attach);
> fail_free_obj:
> @@ -700,8 +700,8 @@ static int dmabuf_imp_release(struct gntdev_dmabuf_priv *priv, u32 fd)
> attach = gntdev_dmabuf->u.imp.attach;
>
> if (gntdev_dmabuf->u.imp.sgt)
> - dma_buf_unmap_attachment_unlocked(attach, gntdev_dmabuf->u.imp.sgt,
> - DMA_BIDIRECTIONAL);
> + dma_buf_unmap_sgt_unlocked(attach, gntdev_dmabuf->u.imp.sgt,
> + DMA_BIDIRECTIONAL);
> dma_buf = attach->dmabuf;
> dma_buf_detach(attach->dmabuf, attach);
> dma_buf_put(dma_buf);
> diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h
> index d15b2b31d3c9..cedeb8ebc99e 100644
> --- a/include/linux/dma-buf.h
> +++ b/include/linux/dma-buf.h
> @@ -116,7 +116,7 @@ struct dma_buf_ops {
> /**
> * @map_dma_buf:
> *
> - * This is called by dma_buf_map_attachment() and is used to map a
> + * This is called by dma_buf_map_sgt() and is used to map a
> * shared &dma_buf into device address space, and it is mandatory. It
> * can only be called if @attach has been called successfully.
> *
> @@ -173,7 +173,7 @@ struct dma_buf_ops {
> /**
> * @unmap_dma_buf:
> *
> - * This is called by dma_buf_unmap_attachment() and should unmap and
> + * This is called by dma_buf_unmap_sgt() and should unmap and
> * release the &sg_table allocated in @map_dma_buf, and it is mandatory.
> * For static dma_buf handling this might also unpin the backing
> * storage if this is the last mapping of the DMA buffer.
> @@ -470,7 +470,7 @@ struct dma_buf_attach_ops {
> * @peer2peer: true if the importer can handle peer resources without pages.
> * @priv: exporter specific attachment data.
> * @importer_ops: importer operations for this attachment, if provided
> - * dma_buf_map/unmap_attachment() must be called with the dma_resv lock held.
> + * dma_buf_map/unmap_sgt() must be called with the dma_resv lock held.
> * @importer_priv: importer specific attachment data.
> *
> * This structure holds the attachment information between the dma_buf buffer
> @@ -479,8 +479,8 @@ struct dma_buf_attach_ops {
> *
> * An attachment is created by calling dma_buf_attach(), and released again by
> * calling dma_buf_detach(). The DMA mapping itself needed to initiate a
> - * transfer is created by dma_buf_map_attachment() and freed again by calling
> - * dma_buf_unmap_attachment().
> + * transfer is created by dma_buf_map_sgt() and freed again by calling
> + * dma_buf_unmap_sgt().
> */
> struct dma_buf_attachment {
> struct dma_buf *dmabuf;
> @@ -571,10 +571,10 @@ void dma_buf_fd_install(struct dma_buf *dmabuf, int fd);
> struct dma_buf *dma_buf_get(int fd);
> void dma_buf_put(struct dma_buf *dmabuf);
>
> -struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *,
> - enum dma_data_direction);
> -void dma_buf_unmap_attachment(struct dma_buf_attachment *, struct sg_table *,
> - enum dma_data_direction);
> +struct sg_table *dma_buf_map_sgt(struct dma_buf_attachment *,
> + enum dma_data_direction);
> +void dma_buf_unmap_sgt(struct dma_buf_attachment *, struct sg_table *,
> + enum dma_data_direction);
> void dma_buf_invalidate_mappings(struct dma_buf *dma_buf);
> bool dma_buf_attach_revocable(struct dma_buf_attachment *attach);
> int dma_buf_begin_cpu_access(struct dma_buf *dma_buf,
> @@ -582,11 +582,11 @@ int dma_buf_begin_cpu_access(struct dma_buf *dma_buf,
> int dma_buf_end_cpu_access(struct dma_buf *dma_buf,
> enum dma_data_direction dir);
> struct sg_table *
> -dma_buf_map_attachment_unlocked(struct dma_buf_attachment *attach,
> +dma_buf_map_sgt_unlocked(struct dma_buf_attachment *attach,
> + enum dma_data_direction direction);
> +void dma_buf_unmap_sgt_unlocked(struct dma_buf_attachment *attach,
> + struct sg_table *sg_table,
> enum dma_data_direction direction);
> -void dma_buf_unmap_attachment_unlocked(struct dma_buf_attachment *attach,
> - struct sg_table *sg_table,
> - enum dma_data_direction direction);
>
> int dma_buf_mmap(struct dma_buf *, struct vm_area_struct *,
> unsigned long);
> diff --git a/io_uring/zcrx.c b/io_uring/zcrx.c
> index 6d7abb1636e7..7c8ce3d2188a 100644
> --- a/io_uring/zcrx.c
> +++ b/io_uring/zcrx.c
> @@ -132,8 +132,8 @@ static void io_unmap_dmabuf(struct io_zcrx_mem *mem)
> if (!IS_ENABLED(CONFIG_DMA_SHARED_BUFFER))
> return;
> if (mem->sgt)
> - dma_buf_unmap_attachment_unlocked(mem->attach, mem->sgt,
> - DMA_FROM_DEVICE);
> + dma_buf_unmap_sgt_unlocked(mem->attach, mem->sgt,
> + DMA_FROM_DEVICE);
> if (mem->attach)
> dma_buf_detach(mem->dmabuf, mem->attach);
> mem->sgt = NULL;
> @@ -182,7 +182,7 @@ static int io_import_dmabuf(struct io_zcrx_ifq *ifq,
> goto err;
> }
>
> - mem->sgt = dma_buf_map_attachment_unlocked(mem->attach, DMA_FROM_DEVICE);
> + mem->sgt = dma_buf_map_sgt_unlocked(mem->attach, DMA_FROM_DEVICE);
> if (IS_ERR(mem->sgt)) {
> ret = PTR_ERR(mem->sgt);
> mem->sgt = NULL;
> diff --git a/net/core/devmem.c b/net/core/devmem.c
> index 32fafbfa1359..5a984df959f7 100644
> --- a/net/core/devmem.c
> +++ b/net/core/devmem.c
> @@ -75,8 +75,8 @@ void __net_devmem_dmabuf_binding_free(struct work_struct *wq)
>
> kvfree(binding->area.niovs);
> dma_resv_lock(binding->dmabuf->resv, NULL);
> - dma_buf_unmap_attachment(binding->attachment, binding->sgt,
> - binding->direction);
> + dma_buf_unmap_sgt(binding->attachment, binding->sgt,
> + binding->direction);
> dma_buf_unpin(binding->attachment);
> dma_resv_unlock(binding->dmabuf->resv);
> dma_buf_detach(binding->dmabuf, binding->attachment);
> @@ -250,7 +250,7 @@ net_devmem_bind_dmabuf(struct net_device *dev, void *vdev,
> goto err_unlock;
> }
>
> - binding->sgt = dma_buf_map_attachment(binding->attachment, direction);
> + binding->sgt = dma_buf_map_sgt(binding->attachment, direction);
> if (IS_ERR(binding->sgt)) {
> err = PTR_ERR(binding->sgt);
> NL_SET_ERR_MSG(extack, "Failed to map dmabuf attachment");
> @@ -357,7 +357,7 @@ net_devmem_bind_dmabuf(struct net_device *dev, void *vdev,
> kvfree(binding->tx_vec);
> err_unmap:
> dma_resv_lock(dmabuf->resv, NULL);
> - dma_buf_unmap_attachment(binding->attachment, binding->sgt, direction);
> + dma_buf_unmap_sgt(binding->attachment, binding->sgt, direction);
> err_unpin:
> dma_buf_unpin(binding->attachment);
> err_unlock:
>
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH v2 00/23] DMA-buf mapping types
2026-11-05 6:40 [PATCH v2 00/23] DMA-buf mapping types Alistair Popple
` (22 preceding siblings ...)
2026-11-05 6:40 ` [PATCH v2 23/23] dma-buf: Add kunit tests for mapping type selection Alistair Popple
@ 2026-11-05 16:18 ` Maarten Lankhorst
23 siblings, 0 replies; 26+ messages in thread
From: Maarten Lankhorst @ 2026-11-05 16:18 UTC (permalink / raw)
To: Alistair Popple, Christian König, Sumit Semwal,
Thomas Hellström, Simona Vetter, Matthew Brost,
Vivek Kasireddy, Dongwon Kim, Kevin Tian, Xu Yilun,
Karl Mehltretter, Baolu Lu, Felix Kuehling, Alex Deucher,
dri-devel, intel-xe, amd-gfx, linux-media, linaro-mm-sig,
linux-rdma, iommu, Keith Busch, Jens Axboe, Christoph Hellwig,
Sagi Grimberg, linux-nvme, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Mina Almasry, netdev,
Alexey Kardashevskiy, zhipingz, treding, jhubbard,
Jason Gunthorpe, Leon Romanovsky
For the whole series:
Acked-by: Maarten Lankhorst <dev@lankhorst.se>
Great to see the non-sgt mapping types finally being a first class option in dma-buf.
On 11/5/26 07:40, Alistair Popple wrote:
> This is v2 of the DMA-buf mapping types series [1]. It keeps the framework
> and the SGT conversions from the RFC but defers the final mapping type
> selection until the first pin/map of the buffer.
>
> At pin/map the exporter chooses one of the types matched, taking the other
> attachments and the buffer's placement into account. That choice is held by the
> core until the exporter explicitly invalidates the attachment. This ensures
> unmap/remap cannot cause buffer movement and ping/pong.
>
> Future work will build on top of this series to add an iommufd importer type
> per the plan in [2], separate out PCIe P2P as its own mapping type and convert
> XGMI to an exclusive mapping type.
>
> Why mapping types
> -----------------
>
> Since its introduction, DMA-buf has only supported using scatterlist for
> the exporter and importer to exchange address information. This is not
> sufficient for all use cases as dma_addr_t is a very specific and limited
> type that should not be abused for things unrelated to the DMA API.
>
> There are several motivations for addressing this now:
> 1) VFIO to IOMMUFD and KVM requires a physical address, not a dma_addr_t
> scatterlist, it cannot be represented in the scatterlist structure
> 2) xe vGPU requires the host driver to accept a DMABUF from VFIO of its
> own VF and convert it into an internal VRAM address on the PF
> 3) We are starting to look at replacement datastructures for
> scatterlist
> 4) Ideas around UALink/etc are suggesting not using the DMA API
> 5) Private interconnects, such as XGMI, are forced to work around this using
> driver-specific hacks.
>
> None of these can be achieved using scatterlist. This series introduces a
> "mapping type" mechanism allowing dma-buf to negotiate compatibility between
> different types and support alternate mapping options. See the description of
> patch 2 for more details.
>
> Selecting mapping type
> ----------------------
>
> Importers and exporters list possible mapping types with the exporter
> responsible for selecting the final type at pin/map time under the dma_resv
> lock. A matching phase at attachment time eliminates types which statically
> cannot be supported for a given exporter/importer.
>
> This was done in response to review comments on the RFC. Karl found that the
> RFC's match callback ran on an uninitialised attachment [3]. Christian noted
> that the final decision has to be made under the dma_resv lock before a
> mapping is created, not at attach [4], and Thomas proposed the three steps
> followed here: agree the possible types at attach, select at map, hold the
> selection until invalidate_mappings() [5]. Christian also noted that remaps
> must not change type or placement as that makes buffers ping/pong [6].
>
> The dma-buf core enforces that last point by calling select_mapping() only on
> the first pin/map after attach or after an invalidate. The pin/map type can
> therefore only change once the exporter has explicitly invalidated the mapping.
>
> Future work
> -----------
>
> This series stops at the SGT type so that the framework and the
> attach/pin/map contract can be reviewed on their own. I already have
> proof-of-concept conversions of both PCIe P2P (building on Thomas's work [7])
> and XGMI to separate mapping types. If those would be helpful for reviewing
> this series let me know and I will post them.
>
> Alternatively this series could be split up with patches 1-9 & 22-23 adding the
> general framework and the rest adding the conversions later.
>
> Further work, per [2], is an iommufd importer type to replace the private
> vfio/iommufd interface and allow other DMA-bufs to be imported into iommufd.
>
> Testing
> -------
>
> - KUnit dma-buf-mapping suite (patches 22 and 23) passes.
> - Every patch compile-tested with a config enabling all converted drivers.
>
> Changes since v1 [9]
> --------------------
>
> - Rebased onto v7.4-rc1. The rename also covers the new nvme-pci DMA-buf
> importer and devmem's switch to pinning. xe's dynamic-debug knob for the
> p2pdma distance check (3bc497a40178) is dropped, since the check is now
> done by the core at match time, and amdgpu's PREEMPT-domain import
> decision (78cdd96ab497) asks the negotiated match set instead of
> attach->peer2peer.
> - The dma_buf_map_attachment()/dma_buf_unmap_attachment() rename is now the
> first patch, squashed into one, and uses the shorter dma_buf_map_sgt() and
> dma_buf_unmap_sgt() names (Christian [9]).
> - Dropped dma_buf_mapping_attach() and the dma_buf_sgt_attach() /
> dma_buf_sgt_dynamic_attach() renames. Importers that support more than
> the SGT type list them in a static dma_buf_attach_ops
> ->supported_mapping_types table. The importing device is passed to the
> mapping types through the match arguments rather than stored in each
> entry. dma_buf_attach() and dma_buf_dynamic_attach() are unchanged for
> everyone else (Christian [9]).
> - The selected type is an index into the attachment's match set, read
> through dma_buf_attach_map_type(), instead of a copy in attach->map_type.
> finish_match() fills the match set entry directly and select_mapping()
> returns the index.
> - A failed pin or map only undoes a selection it made itself, so a map
> failing under a held pin keeps the pinned type and a failed first pin
> leaves the attachment unselected; KUnit tests for both (Karl [10]).
> - dma_buf_match_mapping() returns -EOPNOTSUPP when the two sides have no
> type in common, keeping -EINVAL for an empty list, which restores the
> error xe's own tests expect (Sashiko).
> - New DMA_SGT_EXPORTER_REQUIRES_P2P flavour that requires a P2P capable
> importer without a pci_p2pdma_distance() check at match time, used by
> vfio and uverbs so iommufd's non-PCI device can still attach and so no
> pci_dev is dereferenced outside the dma_resv lock (Sashiko).
> - The SGT P2P distance check is quiet, as it was in xe and amdgpu before
> the conversion (Sashiko).
> - Fixed a NULL importer_ops dereference in dma_buf_dynamic_attach() and the
> NULL check order in dma_buf_unmap_sgt() (Sashiko).
> - Signed-off-by added to every patch (Jason). Patch 4 is now authored by me
> with Jason as co-developer, as little of the original remains.
> - Not addressed: the Tegra fault with CONFIG_DMABUF_DEBUG that Karl
> reported [12] is a pre-existing Tegra bug being fixed separately.
>
> Changes since RFC v1 [1]
> ------------------------
>
> - Dropped the PAL type and its vfio/iommufd users (RFC 21-25).
> - Rebased onto v7.3-rc5: move_notify is now invalidate_mappings,
> CONFIG_DMABUF_MOVE_NOTIFY is gone, new amdxdna/panfrost/panthor
> exporters converted, kzalloc_obj().
> - Patch 1 records the whole match set in a fixed-size array in the
> attachment; patch 3 initialises the attachment before match_mapping()
> (Karl); patch 15 holds a pci_dev reference instead of asserting the resv
> lock (Baolu).
> - New patches 5, 6 and 7: exporter selection at pin/map with core-enforced
> stickiness, match set queries, and dma_buf_mapping_map()/unmap().
> - xe and amdgpu conversions written against the final API; amdgpu's XGMI
> override rewrites the recorded match set entry.
> - New patch 26 with KUnit tests for the selection contract.
>
> [1] https://lore.kernel.org/all/0-v1-b5cab63049c0+191af-dmabuf_map_type_jgg@nvidia.com/
> [2] https://lore.kernel.org/all/20260422150000.GK3199414@nvidia.com/
> [3] https://lore.kernel.org/all/20261016202653.97339-1-kmehltretter@gmail.com/
> [4] https://lore.kernel.org/all/d08a26ed-ded7-4447-bf7b-88597ee7df0e@amd.com/
> [5] https://lore.kernel.org/all/8d4cb20b70ac4c3f36d8d631769757158af2ac8e.camel@linux.intel.com/
> [6] https://lore.kernel.org/all/7b4dc988-5dbd-40e4-b17a-47b6eaf4bf81@amd.com/
> [7] https://gitlab.freedesktop.org/thomash/xe-vibe/-/commit/7452df0fc858a7dc5ccac0e2037852cb7ab64d61
> [8] https://lore.kernel.org/all/20261026053623.202642-1-apopple@nvidia.com/
> [9] https://lore.kernel.org/all/3151a820-c583-4968-8440-673a9e390446@amd.com/
> [10] https://lore.kernel.org/all/7193d384-5e28-4f85-8004-1dc9318d5c1c@amd.com/
> [11] https://lore.kernel.org/all/at8IQZ34wkHQ_5PL@gmail.com/
> [12] https://lore.kernel.org/all/auAIO0y09SXk34CN@gmail.com/
>
> ---
> Alistair Popple (5):
> dma-buf: Negotiate the mapping type in dma_buf_dynamic_attach()
> dma-buf: Let the exporter select mapping type at pin/map
> dma-buf: Add match set queries for exporter placement decisions
> dma-buf: Add dma_buf_mapping_map() returning a type-tagged mapping
> dma-buf: Add kunit tests for mapping type selection
>
> Jason Gunthorpe (18):
> treewide: Rename dma_buf_(un)map_attachment() to dma_buf_(un)map_sgt()
> dma-buf: Introduce DMA-buf mapping types
> dma-buf: Add the SGT DMA mapping type
> dma-buf: Route SGT related actions through the attachment's mapping type
> dma-buf: Allow single exporter drivers to avoid the match_mapping function
> drm: Check the SGT ops for drm_gem_map_dma_buf()
> dma-buf: Convert all the simple exporters to use SGT mapping type
> drm/vmwgfx: Use match_mapping instead of dummy calls
> accel/habanalabs: Use the SGT_P2P mapping type
> drm/xe/dma-buf: Use the SGT mapping type
> drm/amdgpu: Use the SGT mapping type
> vfio/pci: Change the DMA-buf exporter to use mapping_type
> RDMA/uverbs: Use the SGT_P2P mapping type
> dma-buf: Update dma_buf_phys_vec_to_sgt() to use the SGT mapping type
> iio: buffer: convert to use the SGT mapping type
> functionfs: convert to use the SGT mapping type
> dma-buf: Remove unused SGT stuff from the common structures
> dma-buf: Add kunit tests for mapping type
>
> drivers/accel/amdxdna/amdxdna_cbuf.c | 8 +-
> drivers/accel/amdxdna/amdxdna_gem.c | 11 +-
> drivers/accel/amdxdna/amdxdna_ubuf.c | 8 +-
> drivers/accel/habanalabs/common/memory.c | 54 +-
> drivers/accel/ivpu/ivpu_gem.c | 6 +-
> drivers/accel/ivpu/ivpu_gem_userptr.c | 11 +-
> drivers/accel/qaic/qaic_data.c | 6 +-
> drivers/dma-buf/Makefile | 1 +
> drivers/dma-buf/dma-buf-mapping.c | 291 ++++++-
> drivers/dma-buf/dma-buf.c | 266 ++++--
> drivers/dma-buf/heaps/cma_heap.c | 12 +-
> drivers/dma-buf/heaps/system_heap.c | 13 +-
> drivers/dma-buf/st-dma-mapping.c | 896 +++++++++++++++++++++
> drivers/dma-buf/udmabuf.c | 8 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 136 ++--
> drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 4 +-
> drivers/gpu/drm/armada/armada_gem.c | 28 +-
> drivers/gpu/drm/drm_prime.c | 28 +-
> drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c | 16 +-
> drivers/gpu/drm/i915/gem/i915_gem_object.c | 2 +-
> .../gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c | 4 +-
> drivers/gpu/drm/i915/gem/selftests/mock_dmabuf.c | 8 +-
> drivers/gpu/drm/msm/msm_gem_prime.c | 7 +-
> drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c | 9 +-
> drivers/gpu/drm/panfrost/panfrost_gem.c | 13 +-
> drivers/gpu/drm/panthor/panthor_gem.c | 11 +-
> drivers/gpu/drm/tegra/gem.c | 26 +-
> drivers/gpu/drm/virtio/virtgpu_prime.c | 19 +-
> drivers/gpu/drm/vmwgfx/vmwgfx_prime.c | 32 +-
> drivers/gpu/drm/xe/xe_bo.c | 16 +-
> drivers/gpu/drm/xe/xe_dma_buf.c | 79 +-
> drivers/iio/industrialio-buffer.c | 13 +-
> drivers/infiniband/core/umem_dmabuf.c | 8 +-
> drivers/infiniband/core/uverbs_std_types_dmabuf.c | 30 +-
> drivers/iommu/iommufd/selftest.c | 18 +-
> drivers/media/common/videobuf2/videobuf2-core.c | 2 +-
> .../media/common/videobuf2/videobuf2-dma-contig.c | 23 +-
> drivers/media/common/videobuf2/videobuf2-dma-sg.c | 18 +-
> drivers/media/common/videobuf2/videobuf2-vmalloc.c | 13 +-
> .../media/platform/nvidia/tegra-vde/dmabuf-cache.c | 6 +-
> drivers/misc/fastrpc.c | 18 +-
> drivers/nvme/host/pci-dmabuf.c | 6 +-
> drivers/tee/tee_heap.c | 13 +-
> drivers/usb/gadget/function/f_fs.c | 9 +-
> drivers/vfio/pci/vfio_pci_dmabuf.c | 26 +-
> drivers/xen/gntdev-dmabuf.c | 27 +-
> include/linux/dma-buf-mapping.h | 420 ++++++++++
> include/linux/dma-buf.h | 234 ++++--
> include/trace/events/dma_buf.h | 2 +-
> io_uring/zcrx.c | 6 +-
> net/core/devmem.c | 8 +-
> samples/vfio-mdev/mbochs.c | 10 +-
> sound/soc/fsl/fsl_asrc_m2m.c | 12 +-
> 53 files changed, 2415 insertions(+), 536 deletions(-)
> ---
> base-commit: 6628e7d4c6b25c8d18f1345e3a20d21829aae7e4
> change-id: 20261105-dma_mapping_type_v4-f71180b977e8
>
> Best regards,
> --
> Alistair Popple <apopple@nvidia.com>
>
^ permalink raw reply [flat|nested] 26+ messages in thread
end of thread, other threads:[~2026-11-05 16:17 UTC | newest]
Thread overview: 26+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-05 6:40 [PATCH v2 00/23] DMA-buf mapping types Alistair Popple
2026-11-05 6:40 ` [PATCH v2 01/23] treewide: Rename dma_buf_(un)map_attachment() to dma_buf_(un)map_sgt() Alistair Popple
2026-11-05 9:55 ` Christian König
2026-11-05 6:40 ` [PATCH v2 02/23] dma-buf: Introduce DMA-buf mapping types Alistair Popple
2026-11-05 6:40 ` [PATCH v2 03/23] dma-buf: Add the SGT DMA mapping type Alistair Popple
2026-11-05 6:40 ` [PATCH v2 04/23] dma-buf: Negotiate the mapping type in dma_buf_dynamic_attach() Alistair Popple
2026-11-05 6:40 ` [PATCH v2 05/23] dma-buf: Route SGT related actions through the attachment's mapping type Alistair Popple
2026-11-05 6:40 ` [PATCH v2 06/23] dma-buf: Let the exporter select mapping type at pin/map Alistair Popple
2026-11-05 6:40 ` [PATCH v2 07/23] dma-buf: Add match set queries for exporter placement decisions Alistair Popple
2026-11-05 6:40 ` [PATCH v2 08/23] dma-buf: Add dma_buf_mapping_map() returning a type-tagged mapping Alistair Popple
2026-11-05 6:40 ` [PATCH v2 09/23] dma-buf: Allow single exporter drivers to avoid the match_mapping function Alistair Popple
2026-11-05 6:40 ` [PATCH v2 10/23] drm: Check the SGT ops for drm_gem_map_dma_buf() Alistair Popple
2026-11-05 6:40 ` [PATCH v2 11/23] dma-buf: Convert all the simple exporters to use SGT mapping type Alistair Popple
2026-11-05 6:40 ` [PATCH v2 12/23] drm/vmwgfx: Use match_mapping instead of dummy calls Alistair Popple
2026-11-05 6:40 ` [PATCH v2 13/23] accel/habanalabs: Use the SGT_P2P mapping type Alistair Popple
2026-11-05 6:40 ` [PATCH v2 14/23] drm/xe/dma-buf: Use the SGT " Alistair Popple
2026-11-05 6:40 ` [PATCH v2 15/23] drm/amdgpu: " Alistair Popple
2026-11-05 6:40 ` [PATCH v2 16/23] vfio/pci: Change the DMA-buf exporter to use mapping_type Alistair Popple
2026-11-05 6:40 ` [PATCH v2 17/23] RDMA/uverbs: Use the SGT_P2P mapping type Alistair Popple
2026-11-05 6:40 ` [PATCH v2 18/23] dma-buf: Update dma_buf_phys_vec_to_sgt() to use the SGT " Alistair Popple
2026-11-05 6:40 ` [PATCH v2 19/23] iio: buffer: convert " Alistair Popple
2026-11-05 6:40 ` [PATCH v2 20/23] functionfs: " Alistair Popple
2026-11-05 6:40 ` [PATCH v2 21/23] dma-buf: Remove unused SGT stuff from the common structures Alistair Popple
2026-11-05 6:40 ` [PATCH v2 22/23] dma-buf: Add kunit tests for mapping type Alistair Popple
2026-11-05 6:40 ` [PATCH v2 23/23] dma-buf: Add kunit tests for mapping type selection Alistair Popple
2026-11-05 16:18 ` [PATCH v2 00/23] DMA-buf mapping types Maarten Lankhorst
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox