summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/xe
diff options
context:
space:
mode:
authorHonglei Huang <honghuan@amd.com>2026-06-30 18:21:23 +0800
committerMatthew Brost <matthew.brost@intel.com>2026-07-09 04:12:42 -0700
commitba40db36971a59f197b41219e8ffc6ce9998df82 (patch)
treedf3fc2dcfcbcbfa8ae4c5b4272ca383f92433251 /drivers/gpu/drm/xe
parent671b7825dbfe9ea6e3ad3001003aeee0df48d1b5 (diff)
downloadlinux-next-ba40db36971a59f197b41219e8ffc6ce9998df82.tar.gz
linux-next-ba40db36971a59f197b41219e8ffc6ce9998df82.zip
drm/gpusvm: split MM state flags out of drm_gpusvm_pages_flags
drm_gpusvm_pages_flags currently mixes two status: - MM / virtual-address state: whether the range has been (partially) unmapped by the Linux MM, these follow the lifetime of the VMA and are a single per VA range fact. - Device mapping state: has_devmem_pages and has_dma_mapping, which describe the current page mapping status held by device itself. Keeping both on the pages object blurs the semantics of the abstraction of pages and VA range. So move the MM state flags onto the range, and keep drm_gpusvm_pages_flags strictly for mapping state. - Introduce drm_gpusvm_range_flags { migrate_devmem, unmapped, partial_unmap } on drm_gpusvm_range. - Shrink drm_gpusvm_pages_flags to just has_devmem_pages and has_dma_mapping. Side effect: drivers now need to check the unmap flags in the driver itself to avoid handling the unmapped pages. Mirror that bit onto drm_gpusvm_pages so the framework can still short circuit drm_gpusvm_get_pages() under the notifier lock, and make drm_gpusvm_range_set_unmapped() propagate it to the backing pages. This follows Matt's review fixup for the v0 series; see the Link below. Like drm_gpusvm_pages_flags, drm_gpusvm_range_flags unions its bits with a u16 __flags member. Build the new value in a local copy and publish it with a single WRITE_ONCE() on __flags, and have the lockless readers use READ_ONCE(), so concurrent bitfield access stays data-race free and KCSAN quiet. Suggested-by: Matthew Brost <matthew.brost@intel.com> Reviewed-by: Matthew Brost <matthew.brost@intel.com> Link: https://gitlab.freedesktop.org/mbrost/xe-kernel-driver-svn-perf-6-15-2025/-/commit/623f6a50c037d9e44f6c9fbe6859a0ba7ad50177 Signed-off-by: Honglei Huang <honghuan@amd.com> Signed-off-by: Matthew Brost <matthew.brost@intel.com> Link: https://patch.msgid.link/20260630102127.392396-2-honghuan@amd.com
Diffstat (limited to 'drivers/gpu/drm/xe')
-rw-r--r--drivers/gpu/drm/xe/xe_svm.c22
1 files changed, 17 insertions, 5 deletions
diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c
index e0f0c23d172d..28a5d95945c3 100644
--- a/drivers/gpu/drm/xe/xe_svm.c
+++ b/drivers/gpu/drm/xe/xe_svm.c
@@ -134,7 +134,8 @@ xe_svm_garbage_collector_add_range(struct xe_vm *vm, struct xe_svm_range *range,
range_debug(range, "GARBAGE COLLECTOR ADD");
- drm_gpusvm_range_set_unmapped(&range->base, mmu_range);
+ drm_gpusvm_range_set_unmapped(&range->base, &range->base.pages, 1,
+ mmu_range);
spin_lock(&vm->svm.garbage_collector.lock);
if (list_empty(&range->garbage_collector_link))
@@ -166,7 +167,7 @@ xe_svm_range_notifier_event_begin(struct xe_vm *vm, struct drm_gpusvm_range *r,
range_debug(range, "NOTIFIER");
/* Skip if already unmapped or if no binding exist */
- if (range->base.pages.flags.unmapped || !range->tile_present)
+ if (range->base.flags.unmapped || !range->tile_present)
return 0;
range_debug(range, "NOTIFIER - EXECUTE");
@@ -1135,8 +1136,12 @@ bool xe_svm_range_needs_migrate_to_vram(struct xe_svm_range *range, struct xe_vm
{
struct xe_vm *vm = range_to_vm(&range->base);
u64 range_size = xe_svm_range_size(range);
+ struct drm_gpusvm_range_flags flags = {
+ /* READ_ONCE pairs with WRITE_ONCE in drm_gpusvm_range_set_unmapped() */
+ .__flags = READ_ONCE(range->base.flags.__flags),
+ };
- if (!range->base.pages.flags.migrate_devmem || !dpagemap)
+ if (!flags.migrate_devmem || !dpagemap)
return false;
xe_assert(vm->xe, IS_DGFX(vm->xe));
@@ -1220,6 +1225,7 @@ static int __xe_svm_handle_pagefault(struct xe_vm *vm, struct xe_vma *vma,
struct xe_validation_ctx vctx;
struct drm_exec exec;
struct xe_svm_range *range;
+ struct drm_gpusvm_range_flags range_flags;
struct dma_fence *fence;
struct drm_pagemap *dpagemap;
struct xe_tile *tile = gt_to_tile(gt);
@@ -1248,7 +1254,9 @@ retry:
xe_svm_range_fault_count_stats_incr(gt, range);
- if (ctx.devmem_only && !range->base.pages.flags.migrate_devmem)
+ /* READ_ONCE pairs with WRITE_ONCE in drm_gpusvm_range_set_unmapped() */
+ range_flags.__flags = READ_ONCE(range->base.flags.__flags);
+ if (ctx.devmem_only && !range_flags.migrate_devmem)
return -EACCES;
if (xe_svm_range_is_valid(range, tile, ctx.devmem_only, dpagemap)) {
@@ -1620,8 +1628,12 @@ int xe_svm_alloc_vram(struct xe_svm_range *range, const struct drm_gpusvm_ctx *c
struct xe_device *xe = vm->xe;
int err, retries = 1;
bool write_locked = false;
+ struct drm_gpusvm_range_flags flags = {
+ /* READ_ONCE pairs with WRITE_ONCE in drm_gpusvm_range_set_unmapped() */
+ .__flags = READ_ONCE(range->base.flags.__flags),
+ };
- xe_assert(range_to_vm(&range->base)->xe, range->base.pages.flags.migrate_devmem);
+ xe_assert(range_to_vm(&range->base)->xe, flags.migrate_devmem);
range_debug(range, "ALLOCATE VRAM");
migration_state = drm_gpusvm_scan_mm(&range->base,