From: Honglei Huang <[email protected]>

Add invalidate_ranges callback and checkpoint timestamp:
- amdgpu_svm_capture_checkpoint_ts: capture interrupt handler write
  pointer timestamp for stale retry fault filtering
- amdgpu_svm_range_invalidate: invalidate_ranges callback dispatching
  per-range notifier begin/end with TLB flush batching, checkpoint
  timestamp capture on MMU_NOTIFY_UNMAP events

These complete the invalidation path: attribute changes trigger
invalidate_interval, while MMU notifier events flow through
amdgpu_svm_invalidate (in amdgpu_svm.c) which dispatches to this
callback via svm->invalidate_ranges() to perform PTE zap, TLB flush,
and GC queueing.

Signed-off-by: Honglei Huang <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_svm_range.c | 49 +++++++++++++++++++
 1 file changed, 49 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_svm_range.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_svm_range.c
index a5ce4c488..98e66a301 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_svm_range.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_svm_range.c
@@ -698,3 +698,52 @@ amdgpu_svm_range_put_if_dequeued(struct amdgpu_svm *svm,
        if (release_kref)
                drm_gpusvm_range_put(&range->base);
 }
+
+void amdgpu_svm_capture_checkpoint_ts(struct amdgpu_svm *svm)
+{
+       struct amdgpu_device *adev = svm->adev;
+       struct amdgpu_ih_ring *ih;
+       uint32_t checkpoint_wptr;
+
+       if (!adev->irq.retry_cam_enabled && adev->irq.ih1.ring_size) {
+               ih = &adev->irq.ih1;
+               checkpoint_wptr = amdgpu_ih_get_wptr(adev, ih);
+               if (ih->rptr != checkpoint_wptr) {
+                       WRITE_ONCE(svm->checkpoint_ts,
+                                  amdgpu_ih_decode_iv_ts(adev, ih,
+                                                         checkpoint_wptr, -1));
+                       return;
+               }
+       }
+
+       ih = &adev->irq.ih_soft;
+       checkpoint_wptr = amdgpu_ih_get_wptr(adev, ih);
+       if (ih->rptr != checkpoint_wptr)
+               WRITE_ONCE(svm->checkpoint_ts,
+                          amdgpu_ih_decode_iv_ts(adev, ih,
+                                                 checkpoint_wptr, -1));
+}
+
+void amdgpu_svm_range_invalidate(struct amdgpu_svm *svm,
+                                struct drm_gpusvm_notifier *notifier,
+                                const struct mmu_notifier_range *mmu_range,
+                                struct drm_gpusvm_range *first,
+                                uint64_t adj_start, uint64_t adj_end)
+{
+       struct drm_gpusvm_range *r;
+       bool needs_flush = false;
+
+       if (mmu_range->event == MMU_NOTIFY_UNMAP)
+               amdgpu_svm_capture_checkpoint_ts(svm);
+
+       r = first;
+       drm_gpusvm_for_each_range(r, notifier, adj_start, adj_end)
+               needs_flush |= amdgpu_svm_range_notifier_event_begin(svm, r,
+                                                                    mmu_range);
+       if (needs_flush)
+               svm->flush_tlb(svm);
+
+       r = first;
+       drm_gpusvm_for_each_range(r, notifier, adj_start, adj_end)
+               amdgpu_svm_range_notifier_event_end(svm, r, mmu_range);
+}
-- 
2.34.1

Reply via email to