mirror of
https://github.com/torvalds/linux.git
synced 2026-09-24 06:24:02 +02:00
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>
This commit is contained in:
parent
37fcbd7b2f
commit
de40d31275
|
|
@ -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)
|
||||
if (alloc_dummy_page_if_needed(base))
|
||||
return VM_FAULT_OOM;
|
||||
|
||||
if (drmm_add_action_or_reset(dev, xe_mmio_gem_release_dummy_page, page))
|
||||
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));
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user