[PATCH v3 5/7] drm/gpusvm: export drm_gpusvm_pages API
Matthew Brost
matthew.brost at intel.com
Thu Apr 24 22:04:11 UTC 2025
On Thu, Apr 24, 2025 at 03:01:21PM -0700, Matthew Brost wrote:
> On Thu, Apr 24, 2025 at 01:18:33PM +0100, Matthew Auld wrote:
> > 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 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 | 66 ++++++++++++++++++++++++++++--------
> > include/drm/drm_gpusvm.h | 16 +++++++++
> > 2 files changed, 67 insertions(+), 15 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c
> > index fbe0d70ef163..0e0a3c995b4b 100644
> > --- a/drivers/gpu/drm/drm_gpusvm.c
> > +++ b/drivers/gpu/drm/drm_gpusvm.c
> > @@ -539,6 +539,12 @@ static const struct mmu_interval_notifier_ops drm_gpusvm_notifier_ops = {
> > *
> > * This function initializes the GPU SVM.
> > *
> > + * Note: If only using the simple drm_gpusvm_pages API (get/unmap/free),
> > + * then only @gpusvm, @name, and @drm are expected. However, the same base
> > + * @gpusvm can also be used with both modes together in which case the full
> > + * setup is needed, where the core drm_gpusvm_pages API will simply never use
> > + * the other fields.
> > + *
> > * Return: 0 on success, a negative error code on failure.
> > */
> > int drm_gpusvm_init(struct drm_gpusvm *gpusvm,
> > @@ -549,8 +555,16 @@ int drm_gpusvm_init(struct drm_gpusvm *gpusvm,
> > const struct drm_gpusvm_ops *ops,
> > const unsigned long *chunk_sizes, int num_chunks)
> > {
> > - if (!ops->invalidate || !num_chunks)
> > - return -EINVAL;
> > + if (mm) {
>
> Do you still need this if statement if GPU SVM is shared between userptr
> and SVM? Shouldn't we always pass in the MM?
>
> Or is this for the mode where SVM is disabled in Xe and we just use the
> get_pages functionality?
>
Nevermind, I see how this is used in the following patch. Make sense.
With that:
Reviewed-by: Matthew Brost <matthew.brost at intel.com>
> Matt
>
> > + if (!ops->invalidate || !num_chunks)
> > + return -EINVAL;
> > + mmgrab(mm);
> > + } else {
> > + /* No full SVM mode, only core drm_gpusvm_pages API. */
> > + if (ops || num_chunks || mm_range || notifier_size ||
> > + device_private_page_owner)
> > + return -EINVAL;
> > + }
> >
> > gpusvm->name = name;
> > gpusvm->drm = drm;
> > @@ -563,7 +577,6 @@ int drm_gpusvm_init(struct drm_gpusvm *gpusvm,
> > gpusvm->chunk_sizes = chunk_sizes;
> > gpusvm->num_chunks = num_chunks;
> >
> > - mmgrab(mm);
> > gpusvm->root = RB_ROOT_CACHED;
> > INIT_LIST_HEAD(&gpusvm->notifier_list);
> >
> > @@ -671,7 +684,8 @@ void drm_gpusvm_fini(struct drm_gpusvm *gpusvm)
> > drm_gpusvm_range_remove(gpusvm, range);
> > }
> >
> > - mmdrop(gpusvm->mm);
> > + if (gpusvm->mm)
> > + mmdrop(gpusvm->mm);
> > WARN_ON(!RB_EMPTY_ROOT(&gpusvm->root.rb_root));
> > }
> > EXPORT_SYMBOL_GPL(drm_gpusvm_fini);
> > @@ -1185,6 +1199,27 @@ static void __drm_gpusvm_free_pages(struct drm_gpusvm *gpusvm,
> > }
> > }
> >
> > +/**
> > + * drm_gpusvm_free_pages() - Free dma-mapping associated with GPU SVM pages
> > + * struct
> > + * @gpusvm: Pointer to the GPU SVM structure
> > + * @svm_pages: Pointer to the GPU SVM pages structure
> > + * @npages: Number of mapped pages
> > + *
> > + * This function unmaps and frees the dma address array associated with a GPU
> > + * SVM pages struct.
> > + */
> > +void drm_gpusvm_free_pages(struct drm_gpusvm *gpusvm,
> > + struct drm_gpusvm_pages *svm_pages,
> > + unsigned long npages)
> > +{
> > + drm_gpusvm_notifier_lock(gpusvm);
> > + __drm_gpusvm_unmap_pages(gpusvm, svm_pages, npages);
> > + __drm_gpusvm_free_pages(gpusvm, svm_pages);
> > + drm_gpusvm_notifier_unlock(gpusvm);
> > +}
> > +EXPORT_SYMBOL_GPL(drm_gpusvm_free_pages);
> > +
> > /**
> > * drm_gpusvm_range_remove() - Remove GPU SVM range
> > * @gpusvm: Pointer to the GPU SVM structure
> > @@ -1360,13 +1395,12 @@ static bool drm_gpusvm_pages_valid_unlocked(struct drm_gpusvm *gpusvm,
> > *
> > * Return: 0 on success, negative error code on failure.
> > */
> > -static int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
> > - struct drm_gpusvm_pages *svm_pages,
> > - struct mm_struct *mm,
> > - struct mmu_interval_notifier *notifier,
> > - unsigned long pages_start,
> > - unsigned long pages_end,
> > - const struct drm_gpusvm_ctx *ctx)
> > +int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
> > + struct drm_gpusvm_pages *svm_pages,
> > + struct mm_struct *mm,
> > + struct mmu_interval_notifier *notifier,
> > + unsigned long pages_start, unsigned long pages_end,
> > + const struct drm_gpusvm_ctx *ctx)
> > {
> > struct hmm_range hmm_range = {
> > .default_flags = HMM_PFN_REQ_FAULT | (ctx->read_only ? 0 :
> > @@ -1548,6 +1582,7 @@ static int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
> > goto retry;
> > return err;
> > }
> > +EXPORT_SYMBOL_GPL(drm_gpusvm_get_pages);
> >
> > /**
> > * drm_gpusvm_range_get_pages() - Get pages for a GPU SVM range
> > @@ -1583,10 +1618,10 @@ EXPORT_SYMBOL_GPL(drm_gpusvm_range_get_pages);
> > * Must be called in the invalidate() callback of the corresponding notifier for
> > * IOMMU security model.
> > */
> > -static void drm_gpusvm_unmap_pages(struct drm_gpusvm *gpusvm,
> > - struct drm_gpusvm_pages *svm_pages,
> > - unsigned long npages,
> > - const struct drm_gpusvm_ctx *ctx)
> > +void drm_gpusvm_unmap_pages(struct drm_gpusvm *gpusvm,
> > + struct drm_gpusvm_pages *svm_pages,
> > + unsigned long npages,
> > + const struct drm_gpusvm_ctx *ctx)
> > {
> > if (ctx->in_notifier)
> > lockdep_assert_held_write(&gpusvm->notifier_lock);
> > @@ -1598,6 +1633,7 @@ static void drm_gpusvm_unmap_pages(struct drm_gpusvm *gpusvm,
> > if (!ctx->in_notifier)
> > drm_gpusvm_notifier_unlock(gpusvm);
> > }
> > +EXPORT_SYMBOL_GPL(drm_gpusvm_unmap_pages);
> >
> > /**
> > * drm_gpusvm_range_unmap_pages() - Unmap pages associated with a GPU SVM range
> > diff --git a/include/drm/drm_gpusvm.h b/include/drm/drm_gpusvm.h
> > index 1b7ed4f4a8e2..611aaba1ac80 100644
> > --- a/include/drm/drm_gpusvm.h
> > +++ b/include/drm/drm_gpusvm.h
> > @@ -370,6 +370,22 @@ void drm_gpusvm_devmem_init(struct drm_gpusvm_devmem *devmem_allocation,
> > const struct drm_gpusvm_devmem_ops *ops,
> > struct drm_pagemap *dpagemap, size_t size);
> >
> > +int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
> > + struct drm_gpusvm_pages *svm_pages,
> > + struct mm_struct *mm,
> > + struct mmu_interval_notifier *notifier,
> > + unsigned long pages_start, unsigned long pages_end,
> > + const struct drm_gpusvm_ctx *ctx);
> > +
> > +void drm_gpusvm_unmap_pages(struct drm_gpusvm *gpusvm,
> > + struct drm_gpusvm_pages *svm_pages,
> > + unsigned long npages,
> > + const struct drm_gpusvm_ctx *ctx);
> > +
> > +void drm_gpusvm_free_pages(struct drm_gpusvm *gpusvm,
> > + struct drm_gpusvm_pages *svm_pages,
> > + unsigned long npages);
> > +
> > #ifdef CONFIG_LOCKDEP
> > /**
> > * drm_gpusvm_driver_set_lock() - Set the lock protecting accesses to GPU SVM
> > --
> > 2.49.0
> >
More information about the Intel-xe
mailing list