MADVISE_AUTORESET notifiers are only needed while the VMA is
CPU-only. After the first GPU fault, later unmaps follow the
normal SVM path.

Add an active flag so GPU-touched VMAs stop queueing autoreset
work. Broader notifiers from split VMAs may still remain active,
but the worker rechecks cpu_autoreset_active under vm->lock
before resetting attrs.

v2:
  - Use plain bool active; callback reads it lockless. (Matt)
  - Use wq check and mt_for_each in deactivate path. (Matt)
  - Add lockdep_assert_held_write(&vm->lock) to xe_vm_madvise_gpu_touch().

v3:
  - Deactivate only exact-match notifiers to preserve split siblings.
  - Use READ_ONCE/WRITE_ONCE for notifier->active since the MMU notifier
    callback reads it locklessly.

Cc: Matthew Brost <[email protected]>
Cc: Thomas Hellström <[email protected]>
Cc: Himal Prasad Ghimiray <[email protected]>
Signed-off-by: Arvind Yadav <[email protected]>
---
 drivers/gpu/drm/xe/xe_pagefault.c  |  5 +++-
 drivers/gpu/drm/xe/xe_svm.c        |  1 +
 drivers/gpu/drm/xe/xe_vm_madvise.c | 47 +++++++++++++++++++++++++++++-
 drivers/gpu/drm/xe/xe_vm_madvise.h |  1 +
 drivers/gpu/drm/xe/xe_vm_types.h   |  7 +++++
 5 files changed, 59 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_pagefault.c 
b/drivers/gpu/drm/xe/xe_pagefault.c
index f64d3df08261..442a4fcad0c0 100644
--- a/drivers/gpu/drm/xe/xe_pagefault.c
+++ b/drivers/gpu/drm/xe/xe_pagefault.c
@@ -19,6 +19,7 @@
 #include "xe_svm.h"
 #include "xe_trace_bo.h"
 #include "xe_vm.h"
+#include "xe_vm_madvise.h"
 
 /**
  * DOC: Xe page faults
@@ -222,8 +223,10 @@ static int xe_pagefault_service(struct xe_pagefault *pf)
 
                /* First successful GPU fault ends CPU-only state. */
                if (vma && xe_vma_is_cpu_addr_mirror(vma) &&
-                   xe_vma_has_cpu_autoreset_active(vma))
+                   xe_vma_has_cpu_autoreset_active(vma)) {
                        xe_vma_gpu_touch(vma);
+                       xe_vm_madvise_gpu_touch(vm, vma);
+               }
        }
        up_write(&vm->lock);
        xe_vm_put(vm);
diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c
index e1651e70c8f0..b58857668d48 100644
--- a/drivers/gpu/drm/xe/xe_svm.c
+++ b/drivers/gpu/drm/xe/xe_svm.c
@@ -24,6 +24,7 @@
 #include "xe_vm.h"
 #include "xe_vm_types.h"
 #include "xe_vram_types.h"
+#include "xe_vm_madvise.h"
 
 /* Identifies subclasses of struct drm_pagemap_peer */
 #define XE_PEER_PAGEMAP ((void *)0ul)
diff --git a/drivers/gpu/drm/xe/xe_vm_madvise.c 
b/drivers/gpu/drm/xe/xe_vm_madvise.c
index c2abe712598a..6c42ce8e3f52 100644
--- a/drivers/gpu/drm/xe/xe_vm_madvise.c
+++ b/drivers/gpu/drm/xe/xe_vm_madvise.c
@@ -948,7 +948,7 @@ static bool xe_madvise_notifier_callback(struct 
mmu_interval_notifier *mni,
        struct xe_vm *vm = notifier->vm;
        u64 adj_start, adj_end;
 
-       if (range->event != MMU_NOTIFY_UNMAP)
+       if (range->event != MMU_NOTIFY_UNMAP || !READ_ONCE(notifier->active))
                return true;
 
        if (!mmu_notifier_range_blockable(range))
@@ -1057,6 +1057,7 @@ xe_madvise_notifier_alloc(struct xe_vm *vm, u64 start, 
u64 end)
        notifier->vma_start = start;
        notifier->vma_end = end;
        INIT_LIST_HEAD(&notifier->link);
+       WRITE_ONCE(notifier->active, true);
        spin_lock_init(&notifier->work_lock);
        notifier->work_pending = false;
        INIT_WORK(&notifier->work, xe_madvise_work_func);
@@ -1186,6 +1187,7 @@ int xe_vm_madvise_register_notifier_range(struct xe_vm 
*vm, u64 start, u64 end)
        /* Dedup by stored range; tree slots can be fragmented by partial 
overlap. */
        list_for_each_entry(existing, &vm->svm.madvise_notifier_list, link) {
                if (xe_madvise_notifier_exact(existing, start, end)) {
+                       WRITE_ONCE(existing->active, true);
                        err = 0;
                        goto unlock_remove_new;
                }
@@ -1236,3 +1238,46 @@ int xe_vm_madvise_register_notifier_range(struct xe_vm 
*vm, u64 start, u64 end)
 
        return err;
 }
+
+/**
+ * xe_vm_deactivate_madvise_notifier_for_range - Disable callbacks for a VMA
+ * @vm: VM
+ * @start: VMA start
+ * @end: VMA end
+ */
+static void xe_vm_deactivate_madvise_notifier_for_range(struct xe_vm *vm, u64 
start, u64 end)
+{
+       struct xe_madvise_notifier *notifier;
+       unsigned long index = start;
+
+       lockdep_assert_held_write(&vm->lock);
+
+       if (!vm->svm.madvise_work.wq)
+               return;
+
+       /*
+        * Only exact-match notifiers are disabled. Broader notifiers may still
+        * cover CPU-only split siblings.
+        */
+       mt_for_each(&vm->svm.madvise_notifiers, notifier, index, end - 1)
+               if (notifier->vma_start == start && notifier->vma_end == end)
+                       WRITE_ONCE(notifier->active, false);
+}
+
+/**
+ * xe_vm_madvise_gpu_touch - Disable madvise notifier after GPU touch
+ * @vm: VM
+ * @vma: GPU-touched VMA
+ */
+void xe_vm_madvise_gpu_touch(struct xe_vm *vm, struct xe_vma *vma)
+{
+       lockdep_assert_held_write(&vm->lock);
+
+       /* Only AUTORESET VMAs have madvise notifiers. */
+       if (!(vma->gpuva.flags & XE_VMA_MADV_AUTORESET))
+               return;
+
+       xe_vm_deactivate_madvise_notifier_for_range(vm,
+                                               xe_vma_start(vma),
+                                               xe_vma_end(vma));
+}
diff --git a/drivers/gpu/drm/xe/xe_vm_madvise.h 
b/drivers/gpu/drm/xe/xe_vm_madvise.h
index e2013605e190..d7ea6ff6b0c5 100644
--- a/drivers/gpu/drm/xe/xe_vm_madvise.h
+++ b/drivers/gpu/drm/xe/xe_vm_madvise.h
@@ -20,5 +20,6 @@ int xe_vm_madvise_ioctl(struct drm_device *dev, void *data,
 int xe_vm_madvise_init(struct xe_vm *vm);
 void xe_vm_madvise_fini(struct xe_vm *vm);
 int xe_vm_madvise_register_notifier_range(struct xe_vm *vm, u64 start, u64 
end);
+void xe_vm_madvise_gpu_touch(struct xe_vm *vm, struct xe_vma *vma);
 
 #endif
diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h
index d47bc338628d..4cb3fd619acf 100644
--- a/drivers/gpu/drm/xe/xe_vm_types.h
+++ b/drivers/gpu/drm/xe/xe_vm_types.h
@@ -50,6 +50,13 @@ struct xe_madvise_notifier {
        u64 vma_end;
        /** @link: Entry on vm->svm.madvise_notifier_list. */
        struct list_head link;
+       /**
+        * @active: Fast-path callback gate.
+        *
+        * Read locklessly by the MMU notifier callback. The worker still checks
+        * cpu_autoreset_active under vm->lock before resetting attrs.
+        */
+       bool active;
        /** @work_lock: Serialises pending interval state. */
        spinlock_t work_lock;
        /** @work_pending: Pending interval is available for the worker. */
-- 
2.43.0

Reply via email to