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
None of these can sanely be achieved using scatterlist.
Introduce a new mechanism called "mapping types" which allows DMA-buf to
work with more map/unmap options than scatterlist. Each mapping type
encompasses a full set of functions and data unique to itself. The core
code provides a match-making system to select the best type offered by the
exporter and importer to be the active mapping type for the attachment.
Everything related to scatterlist is moved into a DMA-buf SGT mapping
type, and into the "dma_buf_sgt_*" namespace for clarity. Existing
exporters are moved over to explicitly declare SGT mapping types and
importers are adjusted to use the dma_buf_sgt_* named importer helpers.
Mapping types are designed to be extendable, a driver can declare its own
mapping type for its internal private interconnect and use that without
having to adjust the core code.
The new attachment sequence starts with the importing driver declaring
what mapping types it can accept:
struct dma_buf_mapping_match imp_match[] = {
DMA_BUF_IMAPPING_MY_DRIVER(dev, ...),
DMA_BUF_IMAPPING_SGT(dev, false),
};
attach = dma_buf_mapping_attach(dmabuf, imp_match, ...)
Most drivers will do this via a dma_buf_sgt_*attach() helper.
The exporting driver can then declare what mapping types it can supply:
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, dev, false),
DMA_BUF_EMAPPING_PAL(PAL_ops),
};
return dma_buf_match_mapping(args, exp_match, ...);
}
Most drivers will do this via a helper:
static const struct dma_buf_ops ops = {
DMA_BUF_SIMPLE_SGT_EXP_MATCH(map_func, unmap_func)
};
During dma_buf_mapping_attach() the core code will select a mutual match
between the importer and exporter and record it as the active match in
the attach->map_type.
Each mapping type has its own types/function calls for
mapping/unmapping, and storage in the attach->map_type for its
information. As such each mapping type can offer function signatures
and data that exactly matches its needs.
This series goes through a sequence of:
1) Introduce the basic mapping type framework and the main components of
the SGT mapping type
2) Automatically make all existing exporters and importers use core
generated SGT mapping types so every attachment has a SGT mapping type
3) Convert all exporter drivers to natively create a SGT mapping type
4) Move all dma_buf_* functions and types that are related to SGT into
dma_buf_sgt_*
5) Remove all the now-unused items that have been moved into SGT specific
structures.
6) Demonstrate adding a new Physical Address List alongside SGT.
Due to the high number of files touched I would expect this to be broken
into phases, but this shows the entire picture.
This is on github: https://github.com/jgunthorpe/linux/commits/dmabuf_map_type
It is a followup to the discussion here:
https://lore.kernel.org/dri-devel/20251027044712.1676175-1-vivek.kasireddy@…
Jason Gunthorpe (26):
dma-buf: Introduce DMA-buf mapping types
dma-buf: Add the SGT DMA mapping type
dma-buf: Add dma_buf_mapping_attach()
dma-buf: Route SGT related actions through attach->map_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 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
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
treewide: Rename dma_buf_map_attachment(_unlocked) to dma_buf_sgt_
treewide: Rename dma_buf_unmap_attachment(_unlocked) to dma_buf_sgt_*
treewide: Rename dma_buf_attach() to dma_buf_sgt_attach()
treewide: Rename dma_buf_dynamic_attach() to
dma_buf_sgt_dynamic_attach()
dma-buf: Add the Physical Address List DMA mapping type
vfio/pci: Add physical address list support to DMABUF
iommufd: Use the PAL mapping type instead of a vfio function
iommufd: Support DMA-bufs with multiple physical ranges
iommufd/selftest: Check multi-phys DMA-buf scenarios
dma-buf: Add kunit tests for mapping type
Documentation/gpu/todo.rst | 2 +-
drivers/accel/amdxdna/amdxdna_gem.c | 14 +-
drivers/accel/amdxdna/amdxdna_ubuf.c | 10 +-
drivers/accel/habanalabs/common/memory.c | 54 ++-
drivers/accel/ivpu/ivpu_gem.c | 10 +-
drivers/accel/ivpu/ivpu_gem_userptr.c | 11 +-
drivers/accel/qaic/qaic_data.c | 8 +-
drivers/dma-buf/Makefile | 1 +
drivers/dma-buf/dma-buf-mapping.c | 186 ++++++++-
drivers/dma-buf/dma-buf.c | 180 ++++++---
drivers/dma-buf/heaps/cma_heap.c | 12 +-
drivers/dma-buf/heaps/system_heap.c | 13 +-
drivers/dma-buf/st-dma-mapping.c | 373 ++++++++++++++++++
drivers/dma-buf/udmabuf.c | 8 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 98 +++--
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 6 +-
drivers/gpu/drm/armada/armada_gem.c | 33 +-
drivers/gpu/drm/drm_gem_shmem_helper.c | 2 +-
drivers/gpu/drm/drm_prime.c | 31 +-
drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c | 18 +-
drivers/gpu/drm/i915/gem/i915_gem_object.c | 2 +-
.../drm/i915/gem/selftests/i915_gem_dmabuf.c | 8 +-
.../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 | 11 +-
drivers/gpu/drm/tegra/gem.c | 33 +-
drivers/gpu/drm/virtio/virtgpu_prime.c | 23 +-
drivers/gpu/drm/vmwgfx/vmwgfx_prime.c | 32 +-
drivers/gpu/drm/xe/xe_bo.c | 18 +-
drivers/gpu/drm/xe/xe_dma_buf.c | 61 +--
drivers/iio/industrialio-buffer.c | 15 +-
drivers/infiniband/core/umem_dmabuf.c | 15 +-
drivers/iommu/iommufd/io_pagetable.h | 4 +-
drivers/iommu/iommufd/iommufd_private.h | 8 -
drivers/iommu/iommufd/iommufd_test.h | 7 +
drivers/iommu/iommufd/pages.c | 85 ++--
drivers/iommu/iommufd/selftest.c | 177 ++++++---
.../media/common/videobuf2/videobuf2-core.c | 2 +-
.../common/videobuf2/videobuf2-dma-contig.c | 26 +-
.../media/common/videobuf2/videobuf2-dma-sg.c | 21 +-
.../common/videobuf2/videobuf2-vmalloc.c | 13 +-
.../platform/nvidia/tegra-vde/dmabuf-cache.c | 9 +-
drivers/misc/fastrpc.c | 21 +-
drivers/tee/tee_heap.c | 13 +-
drivers/usb/gadget/function/f_fs.c | 11 +-
drivers/vfio/pci/vfio_pci_dmabuf.c | 79 ++--
drivers/xen/gntdev-dmabuf.c | 29 +-
include/linux/dma-buf-mapping.h | 297 ++++++++++++++
include/linux/dma-buf.h | 168 ++++----
io_uring/zcrx.c | 9 +-
net/core/devmem.c | 14 +-
samples/vfio-mdev/mbochs.c | 10 +-
sound/soc/fsl/fsl_asrc_m2m.c | 12 +-
tools/testing/selftests/iommu/iommufd.c | 43 ++
tools/testing/selftests/iommu/iommufd_utils.h | 17 +
55 files changed, 1764 insertions(+), 614 deletions(-)
create mode 100644 drivers/dma-buf/st-dma-mapping.c
base-commit: c63e5a50e1dd291cd95b04291b028fdcaba4c534
--
2.43.0
Hi,
These patches fix two issues in the drm/drm_crtc driver. Initially I
was hitting the BUG_ON() in a scenario as explained in the commit
message of what is now the second patch in this series.
After posting, sashiko.dev noticed another issue, that was previously
masked by the now-removed BUG_ON(). Since we can't have a loud BUG() be
replaced with silent data corruption or worse, I've also added a patch
to address this issue highlighted by sashiko.dev. I believe its
observation and analysis to be correct.
Cheers,
Andre'
Signed-off-by: André Draszik <andre.draszik(a)linaro.org>
---
Changes in v3:
- Philipp:
- patch 1: update kerneldoc, add Fixes:
- patch 2: shorten commit message
- explicitly Cc: stable
- collect tag
- Link to v2: https://lore.kernel.org/r/20260708-linux-drm_crtc_fix2-v2-0-cf72be75d75a@li…
Changes in v2:
- add new patch 1 to address sashiko observation
- original patch 1 becomes patch 2
- patch 2:
- don't turn fence_to_crtc() into macro (Jani, Philipp)
- update commit message to include reference to deprecated use of BUG
- Link to v1: https://lore.kernel.org/r/20260618-linux-drm_crtc_fix2-v1-1-c03e77b36f34@li…
---
André Draszik (2):
drm/drm_crtc: ensure dma_fence_ops remain valid during device unbind
drm/drm_crtc: fix race with dma_fence_signal() in ::get_driver_name()
drivers/gpu/drm/drm_crtc.c | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)
---
base-commit: 0718283ab28bc3907e10b61a6b4be6fefa1cbb2f
change-id: 20260618-linux-drm_crtc_fix2-23a7c354a412
Best regards,
--
André Draszik <andre.draszik(a)linaro.org>
DMA-buf lets an exporter pin, move or revoke the backing storage under
an importer, and which of the three applies is decided by the optional
callbacks each side implements and by whether dma_buf_pin() succeeds.
Nothing in Documentation/ describes that, and the single reference to
the mechanism still names move_notify(), removed in v7.1.
Thanks
Signed-off-by: Leon Romanovsky <leonro(a)nvidia.com>
---
Leon Romanovsky (2):
PCI/P2PDMA: Update DMABUF lifecycle docs after move_notify() rename
dma-buf: Document how exporters and importers agree on mapping lifetime
Documentation/driver-api/dma-buf.rst | 6 +++
Documentation/driver-api/pci/p2pdma.rst | 6 ++-
drivers/dma-buf/dma-buf.c | 85 ++++++++++++++++++++++++++++++++-
3 files changed, 94 insertions(+), 3 deletions(-)
---
base-commit: 8049741ac93acd3a590dac070e12571fddf0e294
change-id: 20260820-document-dma-buf-3f8b41e32f57
Best regards,
--
Leon Romanovsky <leonro(a)nvidia.com>
On 8/28/26 10:31, SHANMUGAM, SRINIVASAN wrote:
> AMD General
>
>> -----Original Message-----
>> From: Koenig, Christian <Christian.Koenig(a)amd.com>
>> Sent: Friday, August 28, 2026 1:48 PM
>> To: SHANMUGAM, SRINIVASAN <SRINIVASAN.SHANMUGAM(a)amd.com>;
>> Matthew Brost <matthew.brost(a)intel.com>
>> Cc: Deucher, Alexander <Alexander.Deucher(a)amd.com>; Maarten Lankhorst
>> <maarten.lankhorst(a)linux.intel.com>; Maxime Ripard <mripard(a)kernel.org>;
>> Thomas Zimmermann <tzimmermann(a)suse.de>; David Airlie
>> <airlied(a)gmail.com>; Simona Vetter <simona(a)ffwll.ch>; Sumit Semwal
>> <sumit.semwal(a)linaro.org>; Thomas Hellström
>> <thomas.hellstrom(a)linux.intel.com>; dri-devel(a)lists.freedesktop.org; intel-
>> xe(a)lists.freedesktop.org; linux-media(a)vger.kernel.org; linaro-mm-
>> sig(a)lists.linaro.org; linux-kernel(a)vger.kernel.org; amd-gfx(a)lists.freedesktop.org
>> Subject: Re: [PATCH v4 1/2] drm: Add common drm_user_fence helper
>>
>> On 8/28/26 10:06, SHANMUGAM, SRINIVASAN wrote:
>> ...
>>>>> +/**
>>>>> + * struct drm_user_fence - embeddable DRM user fence
>>>>> + *
>>>>> + * Drivers embed this in their own structure and implement
>>>>> + * &drm_user_fence_ops. Call drm_user_fence_init() at creation and
>>>>> + * drm_user_fence_add_callback() to arm on a dma-fence.
>>>>> + * Call drm_user_fence_cancel_sync() before driver teardown.
>>>>> + */
>>>>> +struct drm_user_fence {
>>>>
>>>> Should this common layer be split into two distinct concepts?
>>>>
>>>> - drm_work_fence: 90% of what is here, minus the kthread_use_mm() and
>>>> mm-related code.
>>>> - drm_user_fence: a subclass of drm_work_fence that adds the
>>>> kthread_use_mm() and mm-related code.
>>>>
>>>> I suggest this because I was thinking about it the other day (I
>>>> forget the exact
>>>> context) and reconsidered a pattern where a fence signals and then I
>>>> need a worker because some work must be done outside of IRQ context.
>>>> A user fence is one example, since copy_to_user() can fault, which is
>>>> not allowed in IRQ context. At various times in Xe we've had multiple
>>>> patterns like this, although at the moment user fences are probably
>>>> the only case that requires it. If we looked across DRM as a whole, I suspect
>> we'd find this pattern open-coded in a number of places.
>>>>
>>>> Yes, drm_user_fence would be a very thin layer on top of
>>>> drm_work_fence, but I still see value in the split.
>>>
>>> Hi Matt,
>>>
>>> Thanks for the review and for being supportive of the idea.
>>>
>>> The split into drm_work_fence (general fence-to-workqueue pattern) and
>>> drm_user_fence (subclass adding kthread_use_mm) makes sense. I'll
>>> restructure v5 as follows:
>>>
>>> drm_work_fence: kref, work_struct, dma_fence_cb, stored fence ref,
>>> wq, ops — add_callback, cancel, cancel_sync
>>
>> Yeah, this pattern came up so often that I already considered adding it to the core
>> dma_fence framework.
>
> Hi Christian,
>
> Thanks for the feedback.
>
> On dma_fence_work: would you prefer I place the generic fence-to-work
> helper directly in the core dma_fence framework (drivers/dma-buf/),
> or is starting with drm_work_fence in DRM and promoting it later also
> acceptable?
Maybe ask AI to search for use cases. If you find something outside of drivers/gpu/drm then please place it under drivers/dma-buf.
If you don't find any existing use case drivers/gpu/drm should do as well.
Thanks,
Christian.
>
> I'll add the value comparison logic and will add a clear note that this cannot be
> used to implement dma_fence_ops.
>
> Thanks,
> Srini
On 8/28/26 10:06, SHANMUGAM, SRINIVASAN wrote:
...
>>> +/**
>>> + * struct drm_user_fence - embeddable DRM user fence
>>> + *
>>> + * Drivers embed this in their own structure and implement
>>> + * &drm_user_fence_ops. Call drm_user_fence_init() at creation and
>>> + * drm_user_fence_add_callback() to arm on a dma-fence.
>>> + * Call drm_user_fence_cancel_sync() before driver teardown.
>>> + */
>>> +struct drm_user_fence {
>>
>> Should this common layer be split into two distinct concepts?
>>
>> - drm_work_fence: 90% of what is here, minus the kthread_use_mm() and
>> mm-related code.
>> - drm_user_fence: a subclass of drm_work_fence that adds the
>> kthread_use_mm() and mm-related code.
>>
>> I suggest this because I was thinking about it the other day (I forget the exact
>> context) and reconsidered a pattern where a fence signals and then I need a worker
>> because some work must be done outside of IRQ context. A user fence is one
>> example, since copy_to_user() can fault, which is not allowed in IRQ context. At
>> various times in Xe we've had multiple patterns like this, although at the moment
>> user fences are probably the only case that requires it. If we looked across DRM as
>> a whole, I suspect we'd find this pattern open-coded in a number of places.
>>
>> Yes, drm_user_fence would be a very thin layer on top of drm_work_fence, but I still
>> see value in the split.
>
> Hi Matt,
>
> Thanks for the review and for being supportive of the idea.
>
> The split into drm_work_fence (general fence-to-workqueue pattern) and
> drm_user_fence (subclass adding kthread_use_mm) makes sense. I'll
> restructure v5 as follows:
>
> drm_work_fence: kref, work_struct, dma_fence_cb, stored fence ref,
> wq, ops — add_callback, cancel, cancel_sync
Yeah, this pattern came up so often that I already considered adding it to the core dma_fence framework.
So if you feel really brave make that a dma_fence_work helper. If I'm not completely mistaken AI should be able to find quite a number of use cases for that already.
>
> drm_user_fence: embeds drm_work_fence, adds mm_struct and the
> kthread_use_mm/mmput boilerplate, thin wrappers
>
> XE will continue to use drm_user_fence. For AMDGPU, The long-term
> per-signal filtering approach (reading the fence value via copy_from_user
> before signaling) will use drm_user_fence — further validating both
> layers of the split.
It would be really nice if we could move those compare functionality (>, <, !=, == etc...) XE has for the user value into the drm_user_fence handling as well.
We also need to add a heck of documentation that while this is able to consume dma_fences it *CAN'T* be used to implement dma_fence_ops. I had more than enough headache because of that.
Regards,
Christian.
>
> Regarding the CI failure — the root cause was a missing trailing newline
> at the end of xe_sync_types.h which caused the kunit build to fail with
> "unterminated #ifndef". I've set up kunit locally and confirmed the fix:
>
> Testing complete. Ran 588 tests: passed: 570, skipped: 18
> Elapsed time: 22.916s total, 3.949s configuring, 18.350s building,
> 0.601s running
>
> The 18 skipped tests require Intel hardware — expected. The CI fix will
> be included in v5 along with the drm_work_fence restructuring.
>
> Thanks,
> Srini
>
>>
>> Matt
On 8/13/26 09:46, Taimuraz Kaitmazov wrote:
> amdxdna_gem_obj_vmap() takes whatever dma_buf_vmap() returns and only
> rejects a NULL vaddr. iosys_map is discriminated by is_iomem, so an
> exporter answering with an I/O mapping leaves a void __iomem pointer in
> abo->mem.kva, which amdxdna_cmd_set_error() memsets and memcpys through.
>
> amdxdna_drm_va_tbl takes a dmabuf_fd, so such a BO can be any exporter's
> buffer. amdgpu cannot reach this: its .pin forces GTT for a non peer to
> peer attachment like ours. An exporter on drm_gem_prime_dmabuf_ops has
> no .pin, and drm_gem_ttm_vmap() answers iomem for a VRAM resident
> object, so an NPU paired with nouveau or radeon does.
>
> Refuse the mapping. vmw_gem_vmap() does the same; unlike that one this
> path is reachable from an unprivileged ioctl, so it does not warn.
>
> Signed-off-by: Taimuraz Kaitmazov <taimuraz(a)kaitmazov.com>
> ---
> drivers/accel/amdxdna/amdxdna_gem.c | 10 ++++++++--
> 1 file changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/accel/amdxdna/amdxdna_gem.c b/drivers/accel/amdxdna/amdxdna_gem.c
> index 1f190b319bb..b66ec9e4828 100644
> --- a/drivers/accel/amdxdna/amdxdna_gem.c
> +++ b/drivers/accel/amdxdna/amdxdna_gem.c
> @@ -683,10 +683,16 @@ static int amdxdna_gem_obj_vmap(struct drm_gem_object *obj, struct iosys_map *ma
>
> dma_resv_assert_held(obj->resv);
>
> - if (is_import_bo(abo))
> + if (is_import_bo(abo)) {
> ret = dma_buf_vmap(abo->dma_buf, map);
> - else
> + /* Callers use mem.kva as an ordinary kernel address. */
> + if (!ret && map->is_iomem) {
> + dma_buf_vunmap(abo->dma_buf, map);
> + return -EOPNOTSUPP;
> + }
Thanks for the fix. The 'is_iomem' check should be moved to
amdxdna_gem_vmap() to cover all the cases.
Lizhi
> + } else {
> ret = drm_gem_shmem_object_vmap(obj, map);
> + }
> if (ret)
> return ret;
> if (!map->vaddr)
On Tue, Aug 25, 2026 at 03:10:28PM +0200, David Hildenbrand (Arm) wrote:
> >> As the saying goes, it's hard to teach old dogs new tricks, but in the end
> >> taking care of two dogs is likely harder than only a single dog? :)
> >
> > Or it's better to train a unmatured hunting dog than to teach a pet dog,
> > how to hunt, for better hunting, even though the pet dog might
> > eventually become able to.
>
> I'm not sure whether "pet dog" is the right analogy to lockdep in that scenario,
> though ;)
Ah. Okay. I will be careful in using terms.
I wanted to tell DEPT has its strength, lockdep has its own, and they
are different.
Byungchul
>
> --
> Cheers,
>
> David