Skip to content

Commit 83f706e

Browse files
committed
drm/gpusvm: export drm_gpusvm_pages API
Export get/unmap/free pages API. We also need to tweak the SVM init to allow skipping much of the unneeded parts. Signed-off-by: Matthew Auld <matthew.auld@intel.com> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com> Cc: Matthew Brost <matthew.brost@intel.com> Reviewed-by: Matthew Brost <matthew.brost@intel.com> Link: https://lore.kernel.org/r/20250828142430.615826-15-matthew.auld@intel.com
1 parent 6364afd commit 83f706e

File tree

2 files changed

+67
-15
lines changed

2 files changed

+67
-15
lines changed

drivers/gpu/drm/drm_gpusvm.c

Lines changed: 51 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,12 @@ static const struct mmu_interval_notifier_ops drm_gpusvm_notifier_ops = {
373373
*
374374
* This function initializes the GPU SVM.
375375
*
376+
* Note: If only using the simple drm_gpusvm_pages API (get/unmap/free),
377+
* then only @gpusvm, @name, and @drm are expected. However, the same base
378+
* @gpusvm can also be used with both modes together in which case the full
379+
* setup is needed, where the core drm_gpusvm_pages API will simply never use
380+
* the other fields.
381+
*
376382
* Return: 0 on success, a negative error code on failure.
377383
*/
378384
int drm_gpusvm_init(struct drm_gpusvm *gpusvm,
@@ -383,8 +389,16 @@ int drm_gpusvm_init(struct drm_gpusvm *gpusvm,
383389
const struct drm_gpusvm_ops *ops,
384390
const unsigned long *chunk_sizes, int num_chunks)
385391
{
386-
if (!ops->invalidate || !num_chunks)
387-
return -EINVAL;
392+
if (mm) {
393+
if (!ops->invalidate || !num_chunks)
394+
return -EINVAL;
395+
mmgrab(mm);
396+
} else {
397+
/* No full SVM mode, only core drm_gpusvm_pages API. */
398+
if (ops || num_chunks || mm_range || notifier_size ||
399+
device_private_page_owner)
400+
return -EINVAL;
401+
}
388402

389403
gpusvm->name = name;
390404
gpusvm->drm = drm;
@@ -397,7 +411,6 @@ int drm_gpusvm_init(struct drm_gpusvm *gpusvm,
397411
gpusvm->chunk_sizes = chunk_sizes;
398412
gpusvm->num_chunks = num_chunks;
399413

400-
mmgrab(mm);
401414
gpusvm->root = RB_ROOT_CACHED;
402415
INIT_LIST_HEAD(&gpusvm->notifier_list);
403416

@@ -489,7 +502,8 @@ void drm_gpusvm_fini(struct drm_gpusvm *gpusvm)
489502
drm_gpusvm_range_remove(gpusvm, range);
490503
}
491504

492-
mmdrop(gpusvm->mm);
505+
if (gpusvm->mm)
506+
mmdrop(gpusvm->mm);
493507
WARN_ON(!RB_EMPTY_ROOT(&gpusvm->root.rb_root));
494508
}
495509
EXPORT_SYMBOL_GPL(drm_gpusvm_fini);
@@ -1044,6 +1058,27 @@ static void __drm_gpusvm_free_pages(struct drm_gpusvm *gpusvm,
10441058
}
10451059
}
10461060

1061+
/**
1062+
* drm_gpusvm_free_pages() - Free dma-mapping associated with GPU SVM pages
1063+
* struct
1064+
* @gpusvm: Pointer to the GPU SVM structure
1065+
* @svm_pages: Pointer to the GPU SVM pages structure
1066+
* @npages: Number of mapped pages
1067+
*
1068+
* This function unmaps and frees the dma address array associated with a GPU
1069+
* SVM pages struct.
1070+
*/
1071+
void drm_gpusvm_free_pages(struct drm_gpusvm *gpusvm,
1072+
struct drm_gpusvm_pages *svm_pages,
1073+
unsigned long npages)
1074+
{
1075+
drm_gpusvm_notifier_lock(gpusvm);
1076+
__drm_gpusvm_unmap_pages(gpusvm, svm_pages, npages);
1077+
__drm_gpusvm_free_pages(gpusvm, svm_pages);
1078+
drm_gpusvm_notifier_unlock(gpusvm);
1079+
}
1080+
EXPORT_SYMBOL_GPL(drm_gpusvm_free_pages);
1081+
10471082
/**
10481083
* drm_gpusvm_range_remove() - Remove GPU SVM range
10491084
* @gpusvm: Pointer to the GPU SVM structure
@@ -1220,13 +1255,12 @@ static bool drm_gpusvm_pages_valid_unlocked(struct drm_gpusvm *gpusvm,
12201255
*
12211256
* Return: 0 on success, negative error code on failure.
12221257
*/
1223-
static int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
1224-
struct drm_gpusvm_pages *svm_pages,
1225-
struct mm_struct *mm,
1226-
struct mmu_interval_notifier *notifier,
1227-
unsigned long pages_start,
1228-
unsigned long pages_end,
1229-
const struct drm_gpusvm_ctx *ctx)
1258+
int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
1259+
struct drm_gpusvm_pages *svm_pages,
1260+
struct mm_struct *mm,
1261+
struct mmu_interval_notifier *notifier,
1262+
unsigned long pages_start, unsigned long pages_end,
1263+
const struct drm_gpusvm_ctx *ctx)
12301264
{
12311265
struct hmm_range hmm_range = {
12321266
.default_flags = HMM_PFN_REQ_FAULT | (ctx->read_only ? 0 :
@@ -1415,6 +1449,7 @@ static int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
14151449
goto retry;
14161450
return err;
14171451
}
1452+
EXPORT_SYMBOL_GPL(drm_gpusvm_get_pages);
14181453

14191454
/**
14201455
* drm_gpusvm_range_get_pages() - Get pages for a GPU SVM range
@@ -1451,10 +1486,10 @@ EXPORT_SYMBOL_GPL(drm_gpusvm_range_get_pages);
14511486
* Must be called in the invalidate() callback of the corresponding notifier for
14521487
* IOMMU security model.
14531488
*/
1454-
static void drm_gpusvm_unmap_pages(struct drm_gpusvm *gpusvm,
1455-
struct drm_gpusvm_pages *svm_pages,
1456-
unsigned long npages,
1457-
const struct drm_gpusvm_ctx *ctx)
1489+
void drm_gpusvm_unmap_pages(struct drm_gpusvm *gpusvm,
1490+
struct drm_gpusvm_pages *svm_pages,
1491+
unsigned long npages,
1492+
const struct drm_gpusvm_ctx *ctx)
14581493
{
14591494
if (ctx->in_notifier)
14601495
lockdep_assert_held_write(&gpusvm->notifier_lock);
@@ -1466,6 +1501,7 @@ static void drm_gpusvm_unmap_pages(struct drm_gpusvm *gpusvm,
14661501
if (!ctx->in_notifier)
14671502
drm_gpusvm_notifier_unlock(gpusvm);
14681503
}
1504+
EXPORT_SYMBOL_GPL(drm_gpusvm_unmap_pages);
14691505

14701506
/**
14711507
* drm_gpusvm_range_unmap_pages() - Unmap pages associated with a GPU SVM range

include/drm/drm_gpusvm.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,22 @@ drm_gpusvm_range_find(struct drm_gpusvm_notifier *notifier, unsigned long start,
307307
void drm_gpusvm_range_set_unmapped(struct drm_gpusvm_range *range,
308308
const struct mmu_notifier_range *mmu_range);
309309

310+
int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
311+
struct drm_gpusvm_pages *svm_pages,
312+
struct mm_struct *mm,
313+
struct mmu_interval_notifier *notifier,
314+
unsigned long pages_start, unsigned long pages_end,
315+
const struct drm_gpusvm_ctx *ctx);
316+
317+
void drm_gpusvm_unmap_pages(struct drm_gpusvm *gpusvm,
318+
struct drm_gpusvm_pages *svm_pages,
319+
unsigned long npages,
320+
const struct drm_gpusvm_ctx *ctx);
321+
322+
void drm_gpusvm_free_pages(struct drm_gpusvm *gpusvm,
323+
struct drm_gpusvm_pages *svm_pages,
324+
unsigned long npages);
325+
310326
#ifdef CONFIG_LOCKDEP
311327
/**
312328
* drm_gpusvm_driver_set_lock() - Set the lock protecting accesses to GPU SVM

0 commit comments

Comments
 (0)