drm/i915/gtt: Split gen8_ppgtt_clear_pte_range
authorMichał Winiarski <michal.winiarski@intel.com>
Thu, 13 Oct 2016 12:02:41 +0000 (14:02 +0200)
committerChris Wilson <chris@chris-wilson.co.uk>
Fri, 14 Oct 2016 11:40:33 +0000 (12:40 +0100)
Let's use more top-down approach, where each gen8_ppgtt_clear_* function
is responsible for clearing the struct passed as an argument and calling
relevant clear_range functions on lower-level tables.
Doing this rather than operating on PTE ranges makes the implementation
of shrinking page tables quite simple.

v2: Drop min when calculating num_entries, no negation in 48b ppgtt
check, no newlines in vars block (Joonas)

Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Cc: Michel Thierry <michel.thierry@intel.com>
Cc: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Michał Winiarski <michal.winiarski@intel.com>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/1476360162-24062-2-git-send-email-michal.winiarski@intel.com
drivers/gpu/drm/i915/i915_gem_gtt.c

index 6de50e44954dd9ea75dca87e16c14bfef0e6079c..2350fdfe38c48caf59d1682c8db32e3bb324baa3 100644 (file)
@@ -706,59 +706,78 @@ static int gen8_48b_mm_switch(struct i915_hw_ppgtt *ppgtt,
        return gen8_write_pdp(req, 0, px_dma(&ppgtt->pml4));
 }
 
-static void gen8_ppgtt_clear_pte_range(struct i915_address_space *vm,
-                                      struct i915_page_directory_pointer *pdp,
-                                      uint64_t start,
-                                      uint64_t length,
-                                      gen8_pte_t scratch_pte)
+static void gen8_ppgtt_clear_pt(struct i915_address_space *vm,
+                               struct i915_page_table *pt,
+                               uint64_t start,
+                               uint64_t length)
 {
        struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
+
+       unsigned int pte_start = gen8_pte_index(start);
+       unsigned int num_entries = gen8_pte_count(start, length);
+       uint64_t pte;
        gen8_pte_t *pt_vaddr;
-       unsigned pdpe = gen8_pdpe_index(start);
-       unsigned pde = gen8_pde_index(start);
-       unsigned pte = gen8_pte_index(start);
-       unsigned num_entries = length >> PAGE_SHIFT;
-       unsigned last_pte, i;
+       gen8_pte_t scratch_pte = gen8_pte_encode(vm->scratch_page.daddr,
+                                                I915_CACHE_LLC);
 
-       if (WARN_ON(!pdp))
+       if (WARN_ON(!px_page(pt)))
                return;
 
-       while (num_entries) {
-               struct i915_page_directory *pd;
-               struct i915_page_table *pt;
+       bitmap_clear(pt->used_ptes, pte_start, num_entries);
 
-               if (WARN_ON(!pdp->page_directory[pdpe]))
-                       break;
+       pt_vaddr = kmap_px(pt);
+
+       for (pte = pte_start; pte < num_entries; pte++)
+               pt_vaddr[pte] = scratch_pte;
 
-               pd = pdp->page_directory[pdpe];
+       kunmap_px(ppgtt, pt_vaddr);
+}
+
+static void gen8_ppgtt_clear_pd(struct i915_address_space *vm,
+                               struct i915_page_directory *pd,
+                               uint64_t start,
+                               uint64_t length)
+{
+       struct i915_page_table *pt;
+       uint64_t pde;
 
+       gen8_for_each_pde(pt, pd, start, length, pde) {
                if (WARN_ON(!pd->page_table[pde]))
                        break;
 
-               pt = pd->page_table[pde];
+               gen8_ppgtt_clear_pt(vm, pt, start, length);
+       }
+}
 
-               if (WARN_ON(!px_page(pt)))
-                       break;
+static void gen8_ppgtt_clear_pdp(struct i915_address_space *vm,
+                                struct i915_page_directory_pointer *pdp,
+                                uint64_t start,
+                                uint64_t length)
+{
+       struct i915_page_directory *pd;
+       uint64_t pdpe;
 
-               last_pte = pte + num_entries;
-               if (last_pte > GEN8_PTES)
-                       last_pte = GEN8_PTES;
+       gen8_for_each_pdpe(pd, pdp, start, length, pdpe) {
+               if (WARN_ON(!pdp->page_directory[pdpe]))
+                       break;
 
-               pt_vaddr = kmap_px(pt);
+               gen8_ppgtt_clear_pd(vm, pd, start, length);
+       }
+}
 
-               for (i = pte; i < last_pte; i++) {
-                       pt_vaddr[i] = scratch_pte;
-                       num_entries--;
-               }
+static void gen8_ppgtt_clear_pml4(struct i915_address_space *vm,
+                                 struct i915_pml4 *pml4,
+                                 uint64_t start,
+                                 uint64_t length)
+{
+       struct i915_page_directory_pointer *pdp;
+       uint64_t pml4e;
 
-               kunmap_px(ppgtt, pt_vaddr);
+       gen8_for_each_pml4e(pdp, pml4, start, length, pml4e) {
+               if (WARN_ON(!pml4->pdps[pml4e]))
+                       break;
 
-               pte = 0;
-               if (++pde == I915_PDES) {
-                       if (++pdpe == I915_PDPES_PER_PDP(vm->dev))
-                               break;
-                       pde = 0;
-               }
+               gen8_ppgtt_clear_pdp(vm, pdp, start, length);
        }
 }
 
@@ -766,21 +785,11 @@ static void gen8_ppgtt_clear_range(struct i915_address_space *vm,
                                   uint64_t start, uint64_t length)
 {
        struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
-       gen8_pte_t scratch_pte = gen8_pte_encode(vm->scratch_page.daddr,
-                                                I915_CACHE_LLC);
 
-       if (!USES_FULL_48BIT_PPGTT(vm->dev)) {
-               gen8_ppgtt_clear_pte_range(vm, &ppgtt->pdp, start, length,
-                                          scratch_pte);
-       } else {
-               uint64_t pml4e;
-               struct i915_page_directory_pointer *pdp;
-
-               gen8_for_each_pml4e(pdp, &ppgtt->pml4, start, length, pml4e) {
-                       gen8_ppgtt_clear_pte_range(vm, pdp, start, length,
-                                                  scratch_pte);
-               }
-       }
+       if (USES_FULL_48BIT_PPGTT(vm->dev))
+               gen8_ppgtt_clear_pml4(vm, &ppgtt->pml4, start, length);
+       else
+               gen8_ppgtt_clear_pdp(vm, &ppgtt->pdp, start, length);
 }
 
 static void