On Tue, Nov 11, 2025 at 05:44:04PM +0100, Thomas Hellström wrote: > Mimic the dma-buf method using dma_[map|unmap]_resource to map > for pcie-p2p dma. > > There's an ongoing area of work upstream to sort out how this best > should be done. One method proposed is to add an additional > pci_p2p_dma_pagemap aliasing the device_private pagemap and use > the corresponding pci_p2p_dma_pagemap page as input for > dma_map_page(). However, that would incur double the amount of > memory and latency to set up the drm_pagemap and given the huge > amount of memory present on modern GPUs, that would really not work. > Hence the simple approach used in this patch. > > v2: > - Simplify xe_page_to_pcie(). (Matt Brost) > > Signed-off-by: Thomas Hellström <[email protected]>
Reviewed-by: Matthew Brost <[email protected]> > --- > drivers/gpu/drm/xe/xe_svm.c | 34 +++++++++++++++++++++++++++++++--- > drivers/gpu/drm/xe/xe_svm.h | 1 + > 2 files changed, 32 insertions(+), 3 deletions(-) > > diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c > index c0b17b548a00..86d7b0882b60 100644 > --- a/drivers/gpu/drm/xe/xe_svm.c > +++ b/drivers/gpu/drm/xe/xe_svm.c > @@ -3,6 +3,8 @@ > * Copyright © 2024 Intel Corporation > */ > > +#include <linux/pci-p2pdma.h> > + > #include <drm/drm_drv.h> > #include <drm/drm_managed.h> > #include <drm/drm_pagemap.h> > @@ -441,6 +443,14 @@ static u64 xe_page_to_dpa(struct page *page) > return dpa; > } > > +static u64 xe_page_to_pcie(struct page *page) > +{ > + struct xe_pagemap *xpagemap = xe_page_to_pagemap(page); > + struct xe_vram_region *vr = xe_pagemap_to_vr(xpagemap); > + > + return xe_page_to_dpa(page) - vr->dpa_base + vr->io_start; > +} > + > enum xe_svm_copy_dir { > XE_SVM_COPY_TO_VRAM, > XE_SVM_COPY_TO_SRAM, > @@ -792,7 +802,10 @@ static bool xe_has_interconnect(struct drm_pagemap_peer > *peer1, > struct device *dev1 = xe_peer_to_dev(peer1); > struct device *dev2 = xe_peer_to_dev(peer2); > > - return dev1 == dev2; > + if (dev1 == dev2) > + return true; > + > + return pci_p2pdma_distance(to_pci_dev(dev1), dev2, true) >= 0; > } > > static DRM_PAGEMAP_OWNER_LIST_DEFINE(xe_owner_list); > @@ -1552,13 +1565,27 @@ xe_drm_pagemap_device_map(struct drm_pagemap > *dpagemap, > addr = xe_page_to_dpa(page); > prot = XE_INTERCONNECT_VRAM; > } else { > - addr = DMA_MAPPING_ERROR; > - prot = 0; > + addr = dma_map_resource(dev, > + xe_page_to_pcie(page), > + PAGE_SIZE << order, dir, > + DMA_ATTR_SKIP_CPU_SYNC); > + prot = XE_INTERCONNECT_P2P; > } > > return drm_pagemap_addr_encode(addr, prot, order, dir); > } > > +static void xe_drm_pagemap_device_unmap(struct drm_pagemap *dpagemap, > + struct device *dev, > + struct drm_pagemap_addr addr) > +{ > + if (addr.proto != XE_INTERCONNECT_P2P) > + return; > + > + dma_unmap_resource(dev, addr.addr, PAGE_SIZE << addr.order, > + addr.dir, DMA_ATTR_SKIP_CPU_SYNC); > +} > + > static void xe_pagemap_destroy_work(struct work_struct *work) > { > struct xe_pagemap *xpagemap = container_of(work, typeof(*xpagemap), > destroy_work); > @@ -1595,6 +1622,7 @@ static void xe_pagemap_destroy(struct drm_pagemap > *dpagemap, bool from_atomic_or > > static const struct drm_pagemap_ops xe_drm_pagemap_ops = { > .device_map = xe_drm_pagemap_device_map, > + .device_unmap = xe_drm_pagemap_device_unmap, > .populate_mm = xe_drm_pagemap_populate_mm, > .destroy = xe_pagemap_destroy, > }; > diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h > index 60eae01a4220..64971c9b2a1a 100644 > --- a/drivers/gpu/drm/xe/xe_svm.h > +++ b/drivers/gpu/drm/xe/xe_svm.h > @@ -13,6 +13,7 @@ > #include <drm/drm_pagemap_util.h> > > #define XE_INTERCONNECT_VRAM DRM_INTERCONNECT_DRIVER > +#define XE_INTERCONNECT_P2P (XE_INTERCONNECT_VRAM + 1) > > struct drm_device; > struct drm_file; > -- > 2.51.1 >
