Link:
https://gitlab.freedesktop.org/mbrost/xe-kernel-driver-svn-perf-6-15-2025/-/commit/623f6a50c037d9e44f6c9fbe6859a0ba7ad50177
Signed-off-by: Honglei Huang <[email protected]>
---
drivers/gpu/drm/drm_gpusvm.c | 21 ++++++++++++++++++---
drivers/gpu/drm/xe/xe_svm.c | 11 ++++++-----
include/drm/drm_gpusvm.h | 30 +++++++++++++++++++++++++-----
3 files changed, 49 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c
index 958cb605aed..df900553f21 100644
--- a/drivers/gpu/drm/drm_gpusvm.c
+++ b/drivers/gpu/drm/drm_gpusvm.c
@@ -641,7 +641,7 @@ drm_gpusvm_range_alloc(struct drm_gpusvm *gpusvm,
range->itree.last = ALIGN(fault_addr + 1, chunk_size) - 1;
INIT_LIST_HEAD(&range->entry);
range->pages.notifier_seq = LONG_MAX;
- range->pages.flags.migrate_devmem = migrate_devmem ? 1 : 0;
+ range->flags.migrate_devmem = migrate_devmem ? 1 : 0;
return range;
}
@@ -1784,20 +1784,35 @@ EXPORT_SYMBOL_GPL(drm_gpusvm_has_mapping);
/**
* drm_gpusvm_range_set_unmapped() - Mark a GPU SVM range as unmapped
* @range: Pointer to the GPU SVM range structure.
+ * @pages: Pointer to the GPU SVM pages structure(s).
+ * @pages_count: Number of GPU SVM pages structure(s) passed in.
* @mmu_range: Pointer to the MMU notifier range structure.
*
* This function marks a GPU SVM range as unmapped and sets the partial_unmap
flag
* if the range partially falls within the provided MMU notifier range.
*/
void drm_gpusvm_range_set_unmapped(struct drm_gpusvm_range *range,
+ struct drm_gpusvm_pages *pages,
+ unsigned int pages_count,
const struct mmu_notifier_range *mmu_range)
{
+ unsigned int i;
+
lockdep_assert_held_write(&range->gpusvm->notifier_lock);
- range->pages.flags.unmapped = true;
+ range->flags.unmapped = true;
+ for (i = 0; i < pages_count; ++i) {
+ struct drm_gpusvm_pages_flags flags = {
+ .__flags = pages[i].flags.__flags,
+ };
+
+ flags.unmapped = true;
+ /* WRITE_ONCE pairs with READ_ONCE for opportunistic checks */
+ WRITE_ONCE(pages[i].flags.__flags, flags.__flags);
+ }
if (drm_gpusvm_range_start(range) < mmu_range->start ||
drm_gpusvm_range_end(range) > mmu_range->end)
- range->pages.flags.partial_unmap = true;
+ range->flags.partial_unmap = true;
}
EXPORT_SYMBOL_GPL(drm_gpusvm_range_set_unmapped);
diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c
index e1651e70c8f..63da149f3b7 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");
@@ -1136,7 +1137,7 @@ 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);
- if (!range->base.pages.flags.migrate_devmem || !dpagemap)
+ if (!range->base.flags.migrate_devmem || !dpagemap)
return false;
xe_assert(vm->xe, IS_DGFX(vm->xe));
@@ -1248,7 +1249,7 @@ static int __xe_svm_handle_pagefault(struct xe_vm *vm,
struct xe_vma *vma,
xe_svm_range_fault_count_stats_incr(gt, range);
- if (ctx.devmem_only && !range->base.pages.flags.migrate_devmem) {
+ if (ctx.devmem_only && !range->base.flags.migrate_devmem) {
err = -EACCES;
goto out;
}
@@ -1623,7 +1624,7 @@ int xe_svm_alloc_vram(struct xe_svm_range *range, const
struct drm_gpusvm_ctx *c
int err, retries = 1;
bool write_locked = false;
- xe_assert(range_to_vm(&range->base)->xe, range->base.pages.flags.migrate_devmem);
+ xe_assert(range_to_vm(&range->base)->xe,
range->base.flags.migrate_devmem);
range_debug(range, "ALLOCATE VRAM");
migration_state = drm_gpusvm_scan_mm(&range->base,
diff --git a/include/drm/drm_gpusvm.h b/include/drm/drm_gpusvm.h
index 8a4d7134a9a..251a7266a73 100644
--- a/include/drm/drm_gpusvm.h
+++ b/include/drm/drm_gpusvm.h
@@ -109,9 +109,7 @@ struct drm_gpusvm_notifier {
/**
* struct drm_gpusvm_pages_flags - Structure representing a GPU SVM pages
flags
*
- * @migrate_devmem: Flag indicating whether the pages can be migrated to
device memory
* @unmapped: Flag indicating if the pages has been unmapped
- * @partial_unmap: Flag indicating if the pages has been partially unmapped
* @has_devmem_pages: Flag indicating if the pages has devmem pages
* @has_dma_mapping: Flag indicating if the pages has a DMA mapping
* @__flags: Flags for pages in u16 form (used for READ_ONCE)
@@ -119,11 +117,8 @@ struct drm_gpusvm_notifier {
struct drm_gpusvm_pages_flags {
union {
struct {
- /* All flags below must be set upon creation */
- u16 migrate_devmem : 1;
/* All flags below must be set / cleared under notifier
lock */
u16 unmapped : 1;
- u16 partial_unmap : 1;
u16 has_devmem_pages : 1;
u16 has_dma_mapping : 1;
};
@@ -151,6 +146,27 @@ struct drm_gpusvm_pages {
struct drm_gpusvm_pages_flags flags;
};
+/**
+ * struct drm_gpusvm_range_flags - Range-level GPU SVM flags
+ *
+ * @migrate_devmem: Flag indicating whether the range can be migrated to
device memory
+ * @unmapped: Flag indicating if the range has been unmapped
+ * @partial_unmap: Flag indicating if the range has been partially unmapped
+ * @__flags: All flags in u16 form (used for READ_ONCE)
+ */
+struct drm_gpusvm_range_flags {
+ union {
+ struct {
+ /* All flags below must be set upon creation */
+ u16 migrate_devmem : 1;
+ /* All flags below must be set / cleared under notifier
lock */
+ u16 unmapped : 1;
+ u16 partial_unmap : 1;
+ };
+ u16 __flags;
+ };
+};
+
/**
* struct drm_gpusvm_range - Structure representing a GPU SVM range
*
@@ -160,6 +176,7 @@ struct drm_gpusvm_pages {
* @itree: Interval tree node for the range (inserted in GPU SVM notifier)
* @entry: List entry to fast interval tree traversal
* @pages: The pages for this range.
+ * @flags: Flags for range see &struct drm_gpusvm_range_flags
*
* This structure represents a GPU SVM range used for tracking memory ranges
* mapped in a DRM device.
@@ -171,6 +188,7 @@ struct drm_gpusvm_range {
struct interval_tree_node itree;
struct list_head entry;
struct drm_gpusvm_pages pages;
+ struct drm_gpusvm_range_flags flags;
};
/**
@@ -310,6 +328,8 @@ drm_gpusvm_range_find(struct drm_gpusvm_notifier *notifier,
unsigned long start,
unsigned long end);
void drm_gpusvm_range_set_unmapped(struct drm_gpusvm_range *range,
+ struct drm_gpusvm_pages *pages,
+ unsigned int pages_count,
const struct mmu_notifier_range *mmu_range);
int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
--
2.34.1