diff mbox

[1/3] drm/i915/gtt: Split gen8_ppgtt_clear_pte_range

Message ID 1475589267-12440-1-git-send-email-michal.winiarski@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Michał Winiarski Oct. 4, 2016, 1:54 p.m. UTC
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.

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>
---
 drivers/gpu/drm/i915/i915_gem_gtt.c | 115 +++++++++++++++++++++---------------
 1 file changed, 66 insertions(+), 49 deletions(-)

Comments

Joonas Lahtinen Oct. 5, 2016, 5:44 a.m. UTC | #1
I wonder if GCC is doing the right thing, do we have some benchmark for
this, Chris, Mika? The code is much more readable in my eyes after the
changes.

On ti, 2016-10-04 at 15:54 +0200, Michał Winiarski wrote:
> +static void gen8_ppgtt_clear_pt(struct i915_address_space *vm,
> +				struct i915_page_table *pt,
> +				uint64_t start,
> +				uint64_t length,
> +				bool use_scratch)
>  {
>  	struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
> +
> +	unsigned int pte_start = gen8_pte_index(start);
> +	unsigned int num_entries = min(gen8_pte_count(start, length),
> +				       GEN8_PTES);

i915_pte_count (called by gen8_pte_count) states following;

"the max value would be GEN6_PTES for GEN6, and GEN8_PTES for GEN8."

GEM_BUG_ON(num_entries > GEN8_PTES); would be the standard recipe for
paranoia. But I don't think it's needed here. 

> +	uint64_t pte;
> +

No newlines to the variable block, keep it tight.

> @@ -768,21 +793,13 @@ static void gen8_ppgtt_clear_range(struct i915_address_space *vm,
>  				   bool use_scratch)
>  {
>  	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, use_scratch);
>  
> -	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))

Now that this is so much simplified, the negation could be removed, and
just just write if (USES_FULL_...)

Other than above, looks good to me.

Regards, Joonas
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 0bb4232..6086122 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -706,59 +706,84 @@  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,
+				bool use_scratch)
 {
 	struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
+
+	unsigned int pte_start = gen8_pte_index(start);
+	unsigned int num_entries = min(gen8_pte_count(start, length),
+				       GEN8_PTES);
+	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, use_scratch);
 
-	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);
 
-		pd = pdp->page_directory[pdpe];
+	for (pte = pte_start; pte < num_entries; pte++)
+		pt_vaddr[pte] = scratch_pte;
 
+	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,
+				bool use_scratch)
+{
+	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, use_scratch);
+	}
+}
 
-		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,
+				 bool use_scratch)
+{
+	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, use_scratch);
+	}
+}
 
-		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,
+				  bool use_scratch)
+{
+	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, use_scratch);
 	}
 }
 
@@ -768,21 +793,13 @@  static void gen8_ppgtt_clear_range(struct i915_address_space *vm,
 				   bool use_scratch)
 {
 	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, use_scratch);
 
-	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_pdp(vm, &ppgtt->pdp, start, length,
+				     use_scratch);
+	else
+		gen8_ppgtt_clear_pml4(vm, &ppgtt->pml4, start, length,
+				      use_scratch);
 }
 
 static void