Make the HMM fault step of drm_gpusvm_get_pages(), including its -EBUSY retry loop, into a helper drm_gpusvm_hmm_fault(). The existing logic of the public drm_gpusvm_get_pages() is not changed, only relocated, so there is no functional change. Keeping the retry loop in common code also means drivers never have to open-code their own fault/retry loop.
A single fault can later be shared by several drm_gpusvm_pages instances that mirror the same CPU range. This prepares get_pages() to split the shared MM-level fault from the per-device DMA mapping. No functional change intended. Suggested-by: Matthew Brost <[email protected]> Signed-off-by: Honglei Huang <[email protected]> --- drivers/gpu/drm/drm_gpusvm.c | 67 ++++++++++++++++++++++++------------ 1 file changed, 45 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c index fcfe635bc195..507ef6f0a60e 100644 --- a/drivers/gpu/drm/drm_gpusvm.c +++ b/drivers/gpu/drm/drm_gpusvm.c @@ -1442,6 +1442,50 @@ static bool drm_gpusvm_pages_valid_unlocked(struct drm_gpusvm *gpusvm, return pages_valid; } +/** + * drm_gpusvm_hmm_fault() - Run the shared HMM fault for a CPU range + * @gpusvm: Pointer to the GPU SVM structure + * @mm: The mm corresponding to the CPU range + * @hmm_range: The hmm_range to fault. + * @pfns: The pfn array to populate (size @npages) + * @timeout: jiffies deadline for the -EBUSY retry loop + * + * Fault the CPU pages of the range into @pfns. This is the MM level step. + * + * Return: 0 on success, negative error code on failure. + */ +static int drm_gpusvm_hmm_fault(struct drm_gpusvm *gpusvm, + struct mm_struct *mm, + struct hmm_range *hmm_range, + unsigned long *pfns, + unsigned long timeout) +{ + int err; + + if (!mmget_not_zero(mm)) + return -EFAULT; + + hmm_range->hmm_pfns = pfns; + while (true) { + mmap_read_lock(mm); + err = hmm_range_fault(hmm_range); + mmap_read_unlock(mm); + + if (err == -EBUSY) { + if (time_after(jiffies, timeout)) + break; + + hmm_range->notifier_seq = + mmu_interval_read_begin(hmm_range->notifier); + continue; + } + break; + } + mmput(mm); + + return err; +} + /** * drm_gpusvm_get_pages() - Get pages and populate GPU SVM pages struct * @gpusvm: Pointer to the GPU SVM structure @@ -1503,28 +1547,7 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm, if (!pfns) return -ENOMEM; - if (!mmget_not_zero(mm)) { - err = -EFAULT; - goto err_free; - } - - hmm_range.hmm_pfns = pfns; - while (true) { - mmap_read_lock(mm); - err = hmm_range_fault(&hmm_range); - mmap_read_unlock(mm); - - if (err == -EBUSY) { - if (time_after(jiffies, timeout)) - break; - - hmm_range.notifier_seq = - mmu_interval_read_begin(notifier); - continue; - } - break; - } - mmput(mm); + err = drm_gpusvm_hmm_fault(gpusvm, mm, &hmm_range, pfns, timeout); if (err) goto err_free; -- 2.34.1
