summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorHonglei Huang <honghuan@amd.com>2026-07-01 14:27:59 +0800
committerMatthew Brost <matthew.brost@intel.com>2026-07-14 09:27:31 -0700
commitea2f9985aa4adeef89e9523be295633bb3d0874a (patch)
treec83dd5d9a578ec7078a43e708698b25dfd6f5f1c /drivers
parent0bc7c196f3ab855da0879283ba633c4c51ddfd81 (diff)
downloadlinux-next-ea2f9985aa4adeef89e9523be295633bb3d0874a.tar.gz
linux-next-ea2f9985aa4adeef89e9523be295633bb3d0874a.zip
drm/gpusvm: do not route system pages to device_unmap() on IOVA unmap
In a mixed range: ctx->allow_mixed dpagemap is not NULL while some entries are system pages. The unmap loop used: dma_unmap_page(...); else if (dpagemap && dpagemap->ops->device_unmap) dpagemap->ops->device_unmap(...); When use_iova is true the first condition is false for system pages, so they fall through to device_unmap() and a system DMA address is handed to the device specific unmap callback, risking invalid accesses or state corruption. Key the branch off addr->proto instead: system pages only need an explicit dma_unmap_page() in the non IOVA case, IOVA system pages are already torn down by the single dma_iova_destroy(), and only genuine device pages reach device_unmap(). This issue was found by Sashiko AI review. Fixes: 37ad039fb367 ("drm/gpusvm: Use dma-map IOVA alloc, link, and sync API in GPU SVM") Cc: stable@vger.kernel.org Reviewed-by: Matthew Brost <matthew.brost@intel.com> Signed-off-by: Honglei Huang <honghuan@amd.com> Signed-off-by: Matthew Brost <matthew.brost@intel.com> Link: https://patch.msgid.link/20260701062800.409248-3-honghuan@amd.com
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/drm_gpusvm.c18
1 files changed, 12 insertions, 6 deletions
diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c
index 3145d55cd860..44bb19658dd6 100644
--- a/drivers/gpu/drm/drm_gpusvm.c
+++ b/drivers/gpu/drm/drm_gpusvm.c
@@ -1163,12 +1163,18 @@ static void __drm_gpusvm_unmap_pages(struct drm_gpusvm *gpusvm,
for (i = 0, j = 0; i < npages; j++) {
struct drm_pagemap_addr *addr = &svm_pages->dma_addr[j];
- if (!use_iova && addr->proto == DRM_INTERCONNECT_SYSTEM)
- dma_unmap_page(dev,
- addr->addr,
- PAGE_SIZE << addr->order,
- addr->dir);
- else if (dpagemap && dpagemap->ops->device_unmap)
+ if (addr->proto == DRM_INTERCONNECT_SYSTEM) {
+ /*
+ * Linked IOVA pages were already torn down by
+ * the dma_iova_unlink()/dma_iova_free() above;
+ * only the non-IOVA mappings need unmap here.
+ */
+ if (!use_iova)
+ dma_unmap_page(dev,
+ addr->addr,
+ PAGE_SIZE << addr->order,
+ addr->dir);
+ } else if (dpagemap && dpagemap->ops->device_unmap)
dpagemap->ops->device_unmap(dpagemap,
dev, addr);
i += 1 << addr->order;