[PATCH 6/7] drm/gpusvm: support basic_range

Matthew Auld matthew.auld at intel.com
Thu Mar 20 17:30:03 UTC 2025


Idea is to use this for userptr, where we mostly just need
get/unmap/free pages, plus some kind of common notifier lock at the svm
level (provided by gpusvm). The range itself also maps to a single
notifier, covering the entire range (provided by the user).

TODO: needs proper kernel-doc, assuming this change makes sense.

Signed-off-by: Matthew Auld <matthew.auld at intel.com>
Cc: Thomas Hellström <thomas.hellstrom at linux.intel.com>
Cc: Matthew Brost <matthew.brost at intel.com>
---
 drivers/gpu/drm/drm_gpusvm.c | 138 +++++++++++++++++++++++++++++------
 include/drm/drm_gpusvm.h     |  23 ++++++
 2 files changed, 137 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c
index 2beca5a6dc0a..ca571610214c 100644
--- a/drivers/gpu/drm/drm_gpusvm.c
+++ b/drivers/gpu/drm/drm_gpusvm.c
@@ -521,6 +521,41 @@ static const struct mmu_interval_notifier_ops drm_gpusvm_notifier_ops = {
 	.invalidate = drm_gpusvm_notifier_invalidate,
 };
 
+static void __drm_gpusvm_init(struct drm_gpusvm *gpusvm, const char *name,
+			      struct drm_device *drm, struct mm_struct *mm,
+			      void *device_private_page_owner,
+			      unsigned long mm_start, unsigned long mm_range,
+			      unsigned long notifier_size,
+			      const struct drm_gpusvm_ops *ops,
+			      const unsigned long *chunk_sizes, int num_chunks)
+{
+	gpusvm->name = name;
+	gpusvm->drm = drm;
+	gpusvm->mm = mm;
+	gpusvm->device_private_page_owner = device_private_page_owner;
+	gpusvm->mm_start = mm_start;
+	gpusvm->mm_range = mm_range;
+	gpusvm->notifier_size = notifier_size;
+	gpusvm->ops = ops;
+	gpusvm->chunk_sizes = chunk_sizes;
+	gpusvm->num_chunks = num_chunks;
+
+	if (mm)
+		mmgrab(mm);
+	gpusvm->root = RB_ROOT_CACHED;
+	INIT_LIST_HEAD(&gpusvm->notifier_list);
+
+	init_rwsem(&gpusvm->notifier_lock);
+
+	fs_reclaim_acquire(GFP_KERNEL);
+	might_lock(&gpusvm->notifier_lock);
+	fs_reclaim_release(GFP_KERNEL);
+
+#ifdef CONFIG_LOCKDEP
+	gpusvm->lock_dep_map = NULL;
+#endif
+}
+
 /**
  * drm_gpusvm_init() - Initialize the GPU SVM.
  * @gpusvm: Pointer to the GPU SVM structure.
@@ -552,35 +587,32 @@ int drm_gpusvm_init(struct drm_gpusvm *gpusvm,
 	if (!ops->invalidate || !num_chunks)
 		return -EINVAL;
 
-	gpusvm->name = name;
-	gpusvm->drm = drm;
-	gpusvm->mm = mm;
-	gpusvm->device_private_page_owner = device_private_page_owner;
-	gpusvm->mm_start = mm_start;
-	gpusvm->mm_range = mm_range;
-	gpusvm->notifier_size = notifier_size;
-	gpusvm->ops = ops;
-	gpusvm->chunk_sizes = chunk_sizes;
-	gpusvm->num_chunks = num_chunks;
-
-	mmgrab(mm);
-	gpusvm->root = RB_ROOT_CACHED;
-	INIT_LIST_HEAD(&gpusvm->notifier_list);
-
-	init_rwsem(&gpusvm->notifier_lock);
-
-	fs_reclaim_acquire(GFP_KERNEL);
-	might_lock(&gpusvm->notifier_lock);
-	fs_reclaim_release(GFP_KERNEL);
-
-#ifdef CONFIG_LOCKDEP
-	gpusvm->lock_dep_map = NULL;
-#endif
+	__drm_gpusvm_init(gpusvm, name, drm, mm, device_private_page_owner,
+			  mm_start, mm_range, notifier_size, ops, chunk_sizes,
+			  num_chunks);
 
 	return 0;
 }
 EXPORT_SYMBOL_GPL(drm_gpusvm_init);
 
+static bool drm_gpusvm_is_basic(struct drm_gpusvm *svm)
+{
+	return !svm->mm;
+}
+
+void drm_gpusvm_basic_init(struct drm_gpusvm *gpusvm, const char *name,
+			   struct drm_device *drm)
+{
+	__drm_gpusvm_init(gpusvm, name, drm, NULL, NULL, 0, 0, 0, NULL, NULL,
+			  0);
+}
+EXPORT_SYMBOL_GPL(drm_gpusvm_basic_init);
+
+void drm_gpusvm_basic_fini(struct drm_gpusvm *gpusvm)
+{
+}
+EXPORT_SYMBOL_GPL(drm_gpusvm_basic_fini);
+
 /**
  * drm_gpusvm_notifier_find() - Find GPU SVM notifier
  * @gpusvm: Pointer to the GPU SVM structure
@@ -1001,6 +1033,27 @@ static void drm_gpusvm_driver_lock_held(struct drm_gpusvm *gpusvm)
 }
 #endif
 
+void drm_gpusvm_basic_range_init(struct drm_gpusvm *svm,
+				 struct drm_gpusvm_basic_range *range,
+				 struct mmu_interval_notifier *notifier,
+				 unsigned long *notifier_seq)
+{
+	WARN_ON(!drm_gpusvm_is_basic(svm));
+
+	range->gpusvm = svm;
+	range->notifier = notifier;
+	range->notifier_seq = notifier_seq;
+	*notifier_seq = LONG_MAX;
+	memset(&range->pages, 0, sizeof(range->pages));
+}
+EXPORT_SYMBOL_GPL(drm_gpusvm_basic_range_init);
+
+void drm_gpusvm_basic_range_fini(struct drm_gpusvm_basic_range *range)
+{
+	WARN_ON(range->pages.flags.has_dma_mapping);
+}
+EXPORT_SYMBOL_GPL(drm_gpusvm_basic_range_fini);
+
 /**
  * drm_gpusvm_range_find_or_insert() - Find or insert GPU SVM range
  * @gpusvm: Pointer to the GPU SVM structure
@@ -1176,6 +1229,19 @@ static void drm_gpusvm_free_pages(struct drm_gpusvm *gpusvm,
 	}
 }
 
+void drm_gpusvm_basic_range_free_pages(struct drm_gpusvm_basic_range *range)
+{
+	unsigned long npages =
+		npages_in_range(range->notifier->interval_tree.start,
+				range->notifier->interval_tree.last + 1);
+
+	drm_gpusvm_notifier_lock(range->gpusvm);
+	__drm_gpusvm_unmap_pages(range->gpusvm, &range->pages, npages);
+	drm_gpusvm_free_pages(range->gpusvm, &range->pages);
+	drm_gpusvm_notifier_unlock(range->gpusvm);
+}
+EXPORT_SYMBOL_GPL(drm_gpusvm_basic_range_free_pages);
+
 /**
  * drm_gpusvm_range_remove() - Remove GPU SVM range
  * @gpusvm: Pointer to the GPU SVM structure
@@ -1545,6 +1611,20 @@ int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
 }
 EXPORT_SYMBOL_GPL(drm_gpusvm_range_get_pages);
 
+int drm_gpusvm_basic_range_get_pages(struct drm_gpusvm_basic_range *range,
+				     const struct drm_gpusvm_ctx *ctx)
+{
+	drm_gpusvm_driver_lock_held(range->gpusvm);
+
+	return drm_gpusvm_get_pages(range->gpusvm, &range->pages,
+				    range->notifier->mm, range->notifier,
+				    range->notifier_seq,
+				    range->notifier->interval_tree.start,
+				    range->notifier->interval_tree.last + 1,
+				    ctx);
+}
+EXPORT_SYMBOL_GPL(drm_gpusvm_basic_range_get_pages);
+
 static void drm_gpusvm_unmap_pages(struct drm_gpusvm *gpusvm,
 				   unsigned long mm_start, unsigned long mm_end,
 				   struct drm_gpusvm_pages *svm_pages,
@@ -1585,6 +1665,16 @@ void drm_gpusvm_range_unmap_pages(struct drm_gpusvm *gpusvm,
 }
 EXPORT_SYMBOL_GPL(drm_gpusvm_range_unmap_pages);
 
+void drm_gpusvm_basic_range_unmap_pages(struct drm_gpusvm_basic_range *range,
+					const struct drm_gpusvm_ctx *ctx)
+{
+	drm_gpusvm_unmap_pages(range->gpusvm,
+			       range->notifier->interval_tree.start,
+			       range->notifier->interval_tree.last + 1,
+			       &range->pages, ctx);
+}
+EXPORT_SYMBOL_GPL(drm_gpusvm_basic_range_unmap_pages);
+
 /**
  * drm_gpusvm_migration_unlock_put_page() - Put a migration page
  * @page: Pointer to the page to put
diff --git a/include/drm/drm_gpusvm.h b/include/drm/drm_gpusvm.h
index c15c733ef0ad..82c4e58fa84c 100644
--- a/include/drm/drm_gpusvm.h
+++ b/include/drm/drm_gpusvm.h
@@ -305,6 +305,29 @@ struct drm_gpusvm_ctx {
 	unsigned int devmem_possible :1;
 };
 
+struct drm_gpusvm_basic_range {
+	struct drm_gpusvm *gpusvm;
+	struct drm_gpusvm_pages pages;
+	struct mmu_interval_notifier *notifier;
+	unsigned long *notifier_seq;
+};
+
+void drm_gpusvm_basic_init(struct drm_gpusvm *gpusvm, const char *name,
+			   struct drm_device *drm);
+void drm_gpusvm_basic_fini(struct drm_gpusvm *gpusvm);
+
+void drm_gpusvm_basic_range_init(struct drm_gpusvm *svm,
+				 struct drm_gpusvm_basic_range *range,
+				 struct mmu_interval_notifier *notifier,
+				 unsigned long *notifier_seq);
+void drm_gpusvm_basic_range_fini(struct drm_gpusvm_basic_range *range);
+
+int drm_gpusvm_basic_range_get_pages(struct drm_gpusvm_basic_range *range,
+				     const struct drm_gpusvm_ctx *ctx);
+void drm_gpusvm_basic_range_unmap_pages(struct drm_gpusvm_basic_range *range,
+					const struct drm_gpusvm_ctx *ctx);
+void drm_gpusvm_basic_range_free_pages(struct drm_gpusvm_basic_range *range);
+
 int drm_gpusvm_init(struct drm_gpusvm *gpusvm,
 		    const char *name, struct drm_device *drm,
 		    struct mm_struct *mm, void *device_private_page_owner,
-- 
2.48.1



More information about the Intel-xe mailing list