aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorIlia Levi <ilia.levi@intel.com>2026-09-08 17:50:52 +0100
committerRodrigo Vivi <rodrigo.vivi@intel.com>2026-09-14 09:09:01 -0400
commitde40d31275cd57408ff1fdd97ea117a3f8c50cc5 (patch)
tree67fc14ce8ae528dea91c432d2764e8b5f97c5d49
parentdrm/xe/mmio_gem: Revoke drm_vma_node on xe_mmio_gem destroy (diff)
drm/xe/mmio_gem: cache the dummy page per object
Currently, when the fault handler provides a dummy page, it allocates a new one on every invocation and ties its lifetime to the drm_device via drmm_add_action_or_reset(). Concurrent faults after hot-unplug therefore accumulate pages that persist until device teardown. Cache a single dummy page in the xe_mmio_gem object and use dma_resv lock to protect its allocation. Free it with the object. v2: use dma_resv lock to protect the allocation (Matt Auld) Assisted-by: GitHub-Copilot:claude-opus-4.6 Signed-off-by: Ilia Levi <ilia.levi@intel.com> Reviewed-by: Matthew Auld <matthew.auld@intel.com> Signed-off-by: Matthew Auld <matthew.auld@intel.com> Link: https://patch.msgid.link/20260908165046.1393557-15-matthew.auld@intel.com (cherry picked from commit 8bf6213f9831e46313af4722a1ee6db1b7596378) Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
-rw-r--r--drivers/gpu/drm/xe/xe_mmio_gem.c27
1 files changed, 16 insertions, 11 deletions
diff --git a/drivers/gpu/drm/xe/xe_mmio_gem.c b/drivers/gpu/drm/xe/xe_mmio_gem.c
index 3c42d8358c7d..970b1e2f4981 100644
--- a/drivers/gpu/drm/xe/xe_mmio_gem.c
+++ b/drivers/gpu/drm/xe/xe_mmio_gem.c
@@ -5,9 +5,9 @@
#include "xe_mmio_gem.h"
+#include <linux/dma-resv.h>
#include <drm/drm_drv.h>
#include <drm/drm_gem.h>
-#include <drm/drm_managed.h>
#include "xe_device_types.h"
@@ -37,6 +37,7 @@ static vm_fault_t xe_mmio_gem_vm_fault(struct vm_fault *);
struct xe_mmio_gem {
struct drm_gem_object base;
phys_addr_t phys_addr;
+ struct page *dummy_page; /* protected by the GEM's dma_resv */
};
static int xe_mmio_gem_vm_may_split(struct vm_area_struct *area, unsigned long addr)
@@ -131,6 +132,8 @@ static void xe_mmio_gem_free(struct drm_gem_object *base)
{
struct xe_mmio_gem *obj = to_xe_mmio_gem(base);
+ if (obj->dummy_page)
+ __free_page(obj->dummy_page);
drm_gem_object_release(base);
kfree(obj);
}
@@ -169,27 +172,29 @@ static int xe_mmio_gem_mmap(struct drm_gem_object *base, struct vm_area_struct *
return 0;
}
-static void xe_mmio_gem_release_dummy_page(struct drm_device *dev, void *res)
+static int alloc_dummy_page_if_needed(struct drm_gem_object *base)
{
- __free_page((struct page *)res);
+ struct xe_mmio_gem *obj = to_xe_mmio_gem(base);
+
+ dma_resv_lock(base->resv, NULL);
+ if (!obj->dummy_page)
+ obj->dummy_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+ dma_resv_unlock(base->resv);
+
+ return obj->dummy_page ? 0 : -ENOMEM;
}
static vm_fault_t xe_mmio_gem_vm_fault_dummy_page(struct vm_fault *vmf)
{
struct vm_area_struct *vma = vmf->vma;
struct drm_gem_object *base = vma->vm_private_data;
- struct drm_device *dev = base->dev;
- struct page *page;
+ struct xe_mmio_gem *obj = to_xe_mmio_gem(base);
unsigned long pfn;
- page = alloc_page(GFP_KERNEL | __GFP_ZERO);
- if (!page)
- return VM_FAULT_OOM;
-
- if (drmm_add_action_or_reset(dev, xe_mmio_gem_release_dummy_page, page))
+ if (alloc_dummy_page_if_needed(base))
return VM_FAULT_OOM;
- pfn = page_to_pfn(page);
+ pfn = page_to_pfn(obj->dummy_page);
return vmf_insert_pfn_prot(vma, vmf->address, pfn,
vm_get_page_prot(vma->vm_flags));