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
