diff mbox series

[2/3] drm/i915/gtt: refactor the storage assumptions around paging structures

Message ID 20200103200030.334215-2-matthew.auld@intel.com (mailing list archive)
State New, archived
Headers show
Series [1/3] drm/i915: make stolen more region centric | expand

Commit Message

Matthew Auld Jan. 3, 2020, 8 p.m. UTC
We currently assume we have struct pages for the backing storage of our
paging structures, however in the future we may also want to support
allocating storage from non-page backed memory, while still being able
to map it into the kernel address space for CPU access.

Signed-off-by: Matthew Auld <matthew.auld@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_gem_gtt.c | 109 +++++++++++++++++++++-------
 drivers/gpu/drm/i915/i915_gem_gtt.h |   7 ++
 2 files changed, 88 insertions(+), 28 deletions(-)

Comments

Chris Wilson Jan. 3, 2020, 8:31 p.m. UTC | #1
Quoting Matthew Auld (2020-01-03 20:00:29)
> We currently assume we have struct pages for the backing storage of our
> paging structures, however in the future we may also want to support
> allocating storage from non-page backed memory, while still being able
> to map it into the kernel address space for CPU access.

Please, let's not put a vfunc this deep / frequent. The next step was to
move this into gt/intel_gtt.c, gt/gen6_ppgtt.c, gt/gen8_ppgtt.c and
possibly gt/gen12_ppgtt.c for future directions.
-Chris
diff mbox series

Patch

diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 1efe58ad0ce9..48b3b9e681c9 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -588,11 +588,20 @@  static void i915_address_space_init(struct i915_address_space *vm, int subclass)
 	INIT_LIST_HEAD(&vm->bound_list);
 }
 
-static int __setup_page_dma(struct i915_address_space *vm,
-			    struct i915_page_dma *p,
-			    gfp_t gfp)
+static void *kmap_page_dma_system(const struct i915_page_dma *p)
+{
+	return kmap_atomic(p->page);
+}
+
+static void kunmap_page_dma_system(void *vaddr)
+{
+	kunmap_atomic(vaddr);
+}
+
+static int setup_page_dma_system(struct i915_address_space *vm,
+				 struct i915_page_dma *p)
 {
-	p->page = vm_alloc_page(vm, gfp | I915_GFP_ALLOW_FAIL);
+	p->page = vm_alloc_page(vm, __GFP_HIGHMEM | I915_GFP_ALLOW_FAIL);
 	if (unlikely(!p->page))
 		return -ENOMEM;
 
@@ -606,28 +615,54 @@  static int __setup_page_dma(struct i915_address_space *vm,
 		return -ENOMEM;
 	}
 
+	p->kmap = kmap_page_dma_system;
+	p->kunmap = kunmap_page_dma_system;
+
 	return 0;
 }
 
+static void cleanup_page_dma_system(struct i915_address_space *vm,
+				    struct i915_page_dma *p)
+{
+	dma_unmap_page(vm->dma, p->daddr, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+	vm_free_page(vm, p->page);
+}
+
+static int __setup_page_dma(struct i915_address_space *vm,
+			    struct i915_page_dma *p)
+{
+	return vm->setup_page_dma(vm, p);
+}
+
 static int setup_page_dma(struct i915_address_space *vm,
 			  struct i915_page_dma *p)
 {
-	return __setup_page_dma(vm, p, __GFP_HIGHMEM);
+	return __setup_page_dma(vm, p);
 }
 
 static void cleanup_page_dma(struct i915_address_space *vm,
 			     struct i915_page_dma *p)
 {
-	dma_unmap_page(vm->dma, p->daddr, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
-	vm_free_page(vm, p->page);
+	vm->cleanup_page_dma(vm, p);
 }
 
-#define kmap_atomic_px(px) kmap_atomic(px_base(px)->page)
+static void kunmap_page_dma(const struct i915_page_dma *p, void *vaddr)
+{
+	p->kunmap(vaddr);
+}
+
+static void *kmap_page_dma(const struct i915_page_dma *p)
+{
+	return p->kmap(p);
+}
+
+#define kmap_atomic_px(px) kmap_page_dma(px_base(px))
+#define kunmap_atomic_px(px, vaddr) kunmap_page_dma(px_base(px), vaddr)
 
 static void
 fill_page_dma(const struct i915_page_dma *p, const u64 val, unsigned int count)
 {
-	kunmap_atomic(memset64(kmap_atomic(p->page), val, count));
+	kunmap_page_dma(p, memset64(kmap_page_dma(p), val, count));
 }
 
 #define fill_px(px, v) fill_page_dma(px_base(px), (v), PAGE_SIZE / sizeof(u64))
@@ -728,7 +763,7 @@  static struct i915_page_table *alloc_pt(struct i915_address_space *vm)
 {
 	struct i915_page_table *pt;
 
-	pt = kmalloc(sizeof(*pt), I915_GFP_ALLOW_FAIL);
+	pt = kzalloc(sizeof(*pt), I915_GFP_ALLOW_FAIL);
 	if (unlikely(!pt))
 		return ERR_PTR(-ENOMEM);
 
@@ -782,10 +817,10 @@  write_dma_entry(struct i915_page_dma * const pdma,
 		const unsigned short idx,
 		const u64 encoded_entry)
 {
-	u64 * const vaddr = kmap_atomic(pdma->page);
+	u64 * const vaddr = kmap_page_dma(pdma);
 
 	vaddr[idx] = encoded_entry;
-	kunmap_atomic(vaddr);
+	kunmap_page_dma(pdma, vaddr);
 }
 
 static inline void
@@ -1017,7 +1052,7 @@  static u64 __gen8_ppgtt_clear(struct i915_address_space * const vm,
 			memset64(vaddr + gen8_pd_index(start, 0),
 				 vm->scratch[0].encode,
 				 count);
-			kunmap_atomic(vaddr);
+			kunmap_atomic_px(pt, vaddr);
 
 			atomic_sub(count, &pt->used);
 			start += count;
@@ -1184,10 +1219,12 @@  gen8_ppgtt_insert_pte(struct i915_ppgtt *ppgtt,
 {
 	struct i915_page_directory *pd;
 	const gen8_pte_t pte_encode = gen8_pte_encode(0, cache_level, flags);
+	struct i915_page_table *pt;
 	gen8_pte_t *vaddr;
 
 	pd = i915_pd_entry(pdp, gen8_pd_index(idx, 2));
-	vaddr = kmap_atomic_px(i915_pt_entry(pd, gen8_pd_index(idx, 1)));
+	pt = i915_pt_entry(pd, gen8_pd_index(idx, 1));
+	vaddr = kmap_atomic_px(pt);
 	do {
 		vaddr[gen8_pd_index(idx, 0)] = pte_encode | iter->dma;
 
@@ -1212,11 +1249,12 @@  gen8_ppgtt_insert_pte(struct i915_ppgtt *ppgtt,
 				pd = pdp->entry[gen8_pd_index(idx, 2)];
 			}
 
-			kunmap_atomic(vaddr);
-			vaddr = kmap_atomic_px(i915_pt_entry(pd, gen8_pd_index(idx, 1)));
+			kunmap_atomic_px(pt, vaddr);
+			pt = i915_pt_entry(pd, gen8_pd_index(idx, 1));
+			vaddr = kmap_atomic_px(pt);
 		}
 	} while (1);
-	kunmap_atomic(vaddr);
+	kunmap_atomic_px(pt, vaddr);
 
 	return idx;
 }
@@ -1237,6 +1275,7 @@  static void gen8_ppgtt_insert_huge(struct i915_vma *vma,
 			gen8_pdp_for_page_address(vma->vm, start);
 		struct i915_page_directory * const pd =
 			i915_pd_entry(pdp, __gen8_pte_index(start, 2));
+		struct i915_page_table *base;
 		gen8_pte_t encode = pte_encode;
 		unsigned int maybe_64K = -1;
 		unsigned int page_size;
@@ -1251,7 +1290,7 @@  static void gen8_ppgtt_insert_huge(struct i915_vma *vma,
 			encode |= GEN8_PDE_PS_2M;
 			page_size = I915_GTT_PAGE_SIZE_2M;
 
-			vaddr = kmap_atomic_px(pd);
+			base = &pd->pt;
 		} else {
 			struct i915_page_table *pt =
 				i915_pt_entry(pd, __gen8_pte_index(start, 1));
@@ -1266,9 +1305,11 @@  static void gen8_ppgtt_insert_huge(struct i915_vma *vma,
 			     rem >= (I915_PDES - index) * I915_GTT_PAGE_SIZE))
 				maybe_64K = __gen8_pte_index(start, 1);
 
-			vaddr = kmap_atomic_px(pt);
+			base = pt;
 		}
 
+		vaddr = kmap_atomic_px(base);
+
 		do {
 			GEM_BUG_ON(iter->sg->length < page_size);
 			vaddr[index++] = encode | iter->dma;
@@ -1296,7 +1337,7 @@  static void gen8_ppgtt_insert_huge(struct i915_vma *vma,
 			}
 		} while (rem >= page_size && index < I915_PDES);
 
-		kunmap_atomic(vaddr);
+		kunmap_atomic_px(base, vaddr);
 
 		/*
 		 * Is it safe to mark the 2M block as 64K? -- Either we have
@@ -1312,7 +1353,7 @@  static void gen8_ppgtt_insert_huge(struct i915_vma *vma,
 					      I915_GTT_PAGE_SIZE_2M)))) {
 			vaddr = kmap_atomic_px(pd);
 			vaddr[maybe_64K] |= GEN8_PDE_IPS_64K;
-			kunmap_atomic(vaddr);
+			kunmap_atomic_px(pd, vaddr);
 			page_size = I915_GTT_PAGE_SIZE_64K;
 
 			/*
@@ -1325,15 +1366,17 @@  static void gen8_ppgtt_insert_huge(struct i915_vma *vma,
 			 * selftests.
 			 */
 			if (I915_SELFTEST_ONLY(vma->vm->scrub_64K)) {
+				struct i915_page_table *pt =
+						i915_pt_entry(pd, maybe_64K);
 				u16 i;
 
 				encode = vma->vm->scratch[0].encode;
-				vaddr = kmap_atomic_px(i915_pt_entry(pd, maybe_64K));
+				vaddr = kmap_atomic_px(pt);
 
 				for (i = 1; i < index; i += 16)
 					memset64(vaddr + i, encode, 15);
 
-				kunmap_atomic(vaddr);
+				kunmap_atomic_px(pt, vaddr);
 			}
 		}
 
@@ -1510,6 +1553,9 @@  static struct i915_ppgtt *gen8_ppgtt_create(struct drm_i915_private *i915)
 	if (IS_CHERRYVIEW(i915) || IS_BROXTON(i915))
 		ppgtt->vm.pt_kmap_wc = true;
 
+	ppgtt->vm.setup_page_dma = setup_page_dma_system;
+	ppgtt->vm.cleanup_page_dma = cleanup_page_dma_system;
+
 	err = gen8_init_scratch(&ppgtt->vm);
 	if (err)
 		goto err_free;
@@ -1644,7 +1690,7 @@  static void gen6_ppgtt_clear_range(struct i915_address_space *vm,
 
 		vaddr = kmap_atomic_px(pt);
 		memset32(vaddr + pte, scratch_pte, count);
-		kunmap_atomic(vaddr);
+		kunmap_atomic_px(pt, vaddr);
 
 		pte = 0;
 	}
@@ -1662,11 +1708,13 @@  static void gen6_ppgtt_insert_entries(struct i915_address_space *vm,
 	unsigned act_pte = first_entry % GEN6_PTES;
 	const u32 pte_encode = vm->pte_encode(0, cache_level, flags);
 	struct sgt_dma iter = sgt_dma(vma);
+	struct i915_page_table *pt;
 	gen6_pte_t *vaddr;
 
 	GEM_BUG_ON(pd->entry[act_pt] == &vm->scratch[1]);
 
-	vaddr = kmap_atomic_px(i915_pt_entry(pd, act_pt));
+	pt = i915_pt_entry(pd, act_pt);
+	vaddr = kmap_atomic_px(pt);
 	do {
 		vaddr[act_pte] = pte_encode | GEN6_PTE_ADDR_ENCODE(iter.dma);
 
@@ -1681,12 +1729,14 @@  static void gen6_ppgtt_insert_entries(struct i915_address_space *vm,
 		}
 
 		if (++act_pte == GEN6_PTES) {
-			kunmap_atomic(vaddr);
-			vaddr = kmap_atomic_px(i915_pt_entry(pd, ++act_pt));
+			kunmap_atomic_px(pt, vaddr);
+
+			pt = i915_pt_entry(pd, ++act_pt);
+			vaddr = kmap_atomic_px(pt);
 			act_pte = 0;
 		}
 	} while (1);
-	kunmap_atomic(vaddr);
+	kunmap_atomic_px(pt, vaddr);
 
 	vma->page_sizes.gtt = I915_GTT_PAGE_SIZE;
 }
@@ -1990,6 +2040,9 @@  static struct i915_ppgtt *gen6_ppgtt_create(struct drm_i915_private *i915)
 
 	ppgtt->base.vm.pte_encode = ggtt->vm.pte_encode;
 
+	ppgtt->base.vm.setup_page_dma = setup_page_dma_system;
+	ppgtt->base.vm.cleanup_page_dma = cleanup_page_dma_system;
+
 	ppgtt->base.pd = __alloc_pd(sizeof(*ppgtt->base.pd));
 	if (!ppgtt->base.pd) {
 		err = -ENOMEM;
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h
index 31a4a96ddd0d..42ba96dffc3f 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.h
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.h
@@ -226,6 +226,9 @@  struct i915_page_dma {
 		 */
 		u32 ggtt_offset;
 	};
+
+	void *(*kmap)(const struct i915_page_dma *p);
+	void (*kunmap)(void *vaddr);
 };
 
 struct i915_page_scratch {
@@ -345,6 +348,10 @@  struct i915_address_space {
 			  u32 flags); /* Create a valid PTE */
 #define PTE_READ_ONLY	(1<<0)
 
+	int (*setup_page_dma)(struct i915_address_space *vm,
+			      struct i915_page_dma *p);
+	void (*cleanup_page_dma)(struct i915_address_space *vm,
+				 struct i915_page_dma *p);
 	int (*allocate_va_range)(struct i915_address_space *vm,
 				 u64 start, u64 length);
 	void (*clear_range)(struct i915_address_space *vm,