drm/i915/gt: Add a routine to iterate over the pagetables of a GTT
authorChris Wilson <chris@chris-wilson.co.uk>
Thu, 17 Jun 2021 06:30:11 +0000 (08:30 +0200)
committerMatthew Auld <matthew.auld@intel.com>
Thu, 17 Jun 2021 13:23:03 +0000 (14:23 +0100)
In the next patch, we will want to look at the dma addresses of
individual page tables, so add a routine to iterate over them.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Matthew Auld <matthew.auld@intel.com>
Signed-off-by: Matthew Auld <matthew.auld@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20210617063018.92802-6-thomas.hellstrom@linux.intel.com
drivers/gpu/drm/i915/gt/gen8_ppgtt.c
drivers/gpu/drm/i915/gt/intel_gtt.h

index 1b676d7700bffe5ee25affe53ccd53974f92a1ce..3d02c726c74633db42e55ade5288f4afd95f3926 100644 (file)
@@ -361,6 +361,54 @@ static void gen8_ppgtt_alloc(struct i915_address_space *vm,
                           &start, start + length, vm->top);
 }
 
+static void __gen8_ppgtt_foreach(struct i915_address_space *vm,
+                                struct i915_page_directory *pd,
+                                u64 *start, u64 end, int lvl,
+                                void (*fn)(struct i915_address_space *vm,
+                                           struct i915_page_table *pt,
+                                           void *data),
+                                void *data)
+{
+       unsigned int idx, len;
+
+       len = gen8_pd_range(*start, end, lvl--, &idx);
+
+       spin_lock(&pd->lock);
+       do {
+               struct i915_page_table *pt = pd->entry[idx];
+
+               atomic_inc(&pt->used);
+               spin_unlock(&pd->lock);
+
+               if (lvl) {
+                       __gen8_ppgtt_foreach(vm, as_pd(pt), start, end, lvl,
+                                            fn, data);
+               } else {
+                       fn(vm, pt, data);
+                       *start += gen8_pt_count(*start, end);
+               }
+
+               spin_lock(&pd->lock);
+               atomic_dec(&pt->used);
+       } while (idx++, --len);
+       spin_unlock(&pd->lock);
+}
+
+static void gen8_ppgtt_foreach(struct i915_address_space *vm,
+                              u64 start, u64 length,
+                              void (*fn)(struct i915_address_space *vm,
+                                         struct i915_page_table *pt,
+                                         void *data),
+                              void *data)
+{
+       start >>= GEN8_PTE_SHIFT;
+       length >>= GEN8_PTE_SHIFT;
+
+       __gen8_ppgtt_foreach(vm, i915_vm_to_ppgtt(vm)->pd,
+                            &start, start + length, vm->top,
+                            fn, data);
+}
+
 static __always_inline u64
 gen8_ppgtt_insert_pte(struct i915_ppgtt *ppgtt,
                      struct i915_page_directory *pdp,
@@ -755,6 +803,7 @@ struct i915_ppgtt *gen8_ppgtt_create(struct intel_gt *gt)
        ppgtt->vm.insert_page = gen8_ppgtt_insert_entry;
        ppgtt->vm.allocate_va_range = gen8_ppgtt_alloc;
        ppgtt->vm.clear_range = gen8_ppgtt_clear;
+       ppgtt->vm.foreach = gen8_ppgtt_foreach;
 
        ppgtt->vm.pte_encode = gen8_pte_encode;
 
index edea95b97c36e8f92de357b5dae1e61d8ebb5201..9bd89f2a01ff1b1801a83140c0cb185617f5da41 100644 (file)
@@ -296,6 +296,13 @@ struct i915_address_space {
                               u32 flags);
        void (*cleanup)(struct i915_address_space *vm);
 
+       void (*foreach)(struct i915_address_space *vm,
+                       u64 start, u64 length,
+                       void (*fn)(struct i915_address_space *vm,
+                                  struct i915_page_table *pt,
+                                  void *data),
+                       void *data);
+
        struct i915_vma_ops vma_ops;
 
        I915_SELFTEST_DECLARE(struct fault_attr fault_attr);