From: Honglei Huang <[email protected]>

drm_gpusvm_pages is the layer that actually represents physical
pages/mappings it owns the dma_addr array, the dma_iova_state...
With the previous patch, so drm_gpusvm_pages is now strictly about
physical pages and their DMA view.

Since now the drm_gpusvm_pages instance is inherently bound to one
specific drm_device, make that ownership explicit by giving
drm_gpusvm_pages its own drm_device handle, and drive all DMA through
it instead of through the gpusvm:

  - Add drm to struct drm_gpusvm_pages and route all DMA in
    drm_gpusvm_get_pages() / __drm_gpusvm_unmap_pages() through
    svm_pages->drm instead of gpusvm->drm.
  - Bind svm_pages->drm where the pages object is initialised
    (drm_gpusvm_range_alloc() and the xe userptr setup) and require
    it to be set on entry to drm_gpusvm_get_pages(); the dma device
    is immutable for the lifetime of the pages instance. A later
    patch introduces drm_gpusvm_init_pages() to centralise this.

Suggested-by: Matthew Brost <[email protected]>
Signed-off-by: Honglei Huang <[email protected]>
---
 drivers/gpu/drm/drm_gpusvm.c    | 30 ++++++++++++++++++++----------
 drivers/gpu/drm/xe/xe_userptr.c |  2 ++
 include/drm/drm_gpusvm.h        |  2 ++
 3 files changed, 24 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c
index 6cb38c76dc7..d6407c94cdd 100644
--- a/drivers/gpu/drm/drm_gpusvm.c
+++ b/drivers/gpu/drm/drm_gpusvm.c
@@ -641,6 +641,7 @@ drm_gpusvm_range_alloc(struct drm_gpusvm *gpusvm,
        range->itree.last = ALIGN(fault_addr + 1, chunk_size) - 1;
        INIT_LIST_HEAD(&range->entry);
        range->pages.notifier_seq = LONG_MAX;
+       range->pages.drm = gpusvm->drm;
        range->flags.migrate_devmem = migrate_devmem ? 1 : 0;
 
        return range;
@@ -1135,11 +1136,16 @@ static void __drm_gpusvm_unmap_pages(struct drm_gpusvm 
*gpusvm,
                                     unsigned long npages)
 {
        struct drm_pagemap *dpagemap = svm_pages->dpagemap;
-       struct device *dev = gpusvm->drm->dev;
+       struct device *dev;
        unsigned long i, j;
 
        lockdep_assert_held(&gpusvm->notifier_lock);
 
+       if (!svm_pages->drm)
+               return;
+
+       dev = svm_pages->drm->dev;
+
        if (svm_pages->flags.has_dma_mapping) {
                struct drm_gpusvm_pages_flags flags = {
                        .__flags = svm_pages->flags.__flags,
@@ -1421,6 +1427,9 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
                                                           DMA_BIDIRECTIONAL;
        struct dma_iova_state *state = &svm_pages->state;
 
+       if (!svm_pages->drm)
+               return -EINVAL;
+
 retry:
        if (time_after(jiffies, timeout))
                return -EBUSY;
@@ -1520,7 +1529,7 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
 
                                pagemap = page_pgmap(page);
                                dpagemap = drm_pagemap_page_to_dpagemap(page);
-                               if (drm_WARN_ON(gpusvm->drm, !dpagemap)) {
+                               if (drm_WARN_ON(svm_pages->drm, !dpagemap)) {
                                        /*
                                         * Raced. This is not supposed to happen
                                         * since hmm_range_fault() should've 
migrated
@@ -1532,10 +1541,10 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
                        }
                        svm_pages->dma_addr[j] =
                                dpagemap->ops->device_map(dpagemap,
-                                                         gpusvm->drm->dev,
+                                                         svm_pages->drm->dev,
                                                          page, order,
                                                          dma_dir);
-                       if (dma_mapping_error(gpusvm->drm->dev,
+                       if (dma_mapping_error(svm_pages->drm->dev,
                                              svm_pages->dma_addr[j].addr)) {
                                err = -EFAULT;
                                goto err_unmap;
@@ -1555,11 +1564,11 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
                        }
 
                        if (!i)
-                               dma_iova_try_alloc(gpusvm->drm->dev, state,
+                               dma_iova_try_alloc(svm_pages->drm->dev, state,
                                                   0, npages * PAGE_SIZE);
 
                        if (dma_use_iova(state)) {
-                               err = dma_iova_link(gpusvm->drm->dev, state,
+                               err = dma_iova_link(svm_pages->drm->dev, state,
                                                    hmm_pfn_to_phys(pfns[i]),
                                                    svm_pages->state_offset,
                                                    PAGE_SIZE << order,
@@ -1570,11 +1579,11 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
                                addr = state->addr + svm_pages->state_offset;
                                svm_pages->state_offset += PAGE_SIZE << order;
                        } else {
-                               addr = dma_map_page(gpusvm->drm->dev,
+                               addr = dma_map_page(svm_pages->drm->dev,
                                                    page, 0,
                                                    PAGE_SIZE << order,
                                                    dma_dir);
-                               if (dma_mapping_error(gpusvm->drm->dev, addr)) {
+                               if (dma_mapping_error(svm_pages->drm->dev, 
addr)) {
                                        err = -EFAULT;
                                        goto err_unmap;
                                }
@@ -1590,7 +1599,7 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
        }
 
        if (dma_use_iova(state)) {
-               err = dma_iova_sync(gpusvm->drm->dev, state, 0,
+               err = dma_iova_sync(svm_pages->drm->dev, state, 0,
                                    svm_pages->state_offset);
                if (err)
                        goto err_unmap;
@@ -1640,7 +1649,8 @@ int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
                               struct drm_gpusvm_range *range,
                               const struct drm_gpusvm_ctx *ctx)
 {
-       return drm_gpusvm_get_pages(gpusvm, &range->pages, gpusvm->mm,
+       return drm_gpusvm_get_pages(gpusvm, &range->pages,
+                                   gpusvm->mm,
                                    &range->notifier->notifier,
                                    drm_gpusvm_range_start(range),
                                    drm_gpusvm_range_end(range), ctx);
diff --git a/drivers/gpu/drm/xe/xe_userptr.c b/drivers/gpu/drm/xe/xe_userptr.c
index 6761005c0b9..1b540e62af6 100644
--- a/drivers/gpu/drm/xe/xe_userptr.c
+++ b/drivers/gpu/drm/xe/xe_userptr.c
@@ -390,6 +390,7 @@ int xe_userptr_setup(struct xe_userptr_vma *uvma, unsigned 
long start,
                     unsigned long range)
 {
        struct xe_userptr *userptr = &uvma->userptr;
+       struct xe_vm *vm = xe_vma_vm(&uvma->vma);
        int err;
 
        INIT_LIST_HEAD(&userptr->invalidate_link);
@@ -402,6 +403,7 @@ int xe_userptr_setup(struct xe_userptr_vma *uvma, unsigned 
long start,
                return err;
 
        userptr->pages.notifier_seq = LONG_MAX;
+       userptr->pages.drm = &vm->xe->drm;
 
        return 0;
 }
diff --git a/include/drm/drm_gpusvm.h b/include/drm/drm_gpusvm.h
index 251a7266a73..842353afb27 100644
--- a/include/drm/drm_gpusvm.h
+++ b/include/drm/drm_gpusvm.h
@@ -129,6 +129,7 @@ struct drm_gpusvm_pages_flags {
 /**
  * struct drm_gpusvm_pages - Structure representing a GPU SVM mapped pages
  *
+ * @drm: The DRM device that owns the dma mappings
  * @dma_addr: Device address array
  * @dpagemap: The struct drm_pagemap of the device pages we're dma-mapping.
  *            Note this is assuming only one drm_pagemap per range is allowed.
@@ -138,6 +139,7 @@ struct drm_gpusvm_pages_flags {
  * @flags: Flags for the range; see &struct drm_gpusvm_pages_flags
  */
 struct drm_gpusvm_pages {
+       struct drm_device *drm;
        struct drm_pagemap_addr *dma_addr;
        struct drm_pagemap *dpagemap;
        struct dma_iova_state state;
-- 
2.34.1

Reply via email to