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

Reply via email to