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.a...@intel.com>
Cc: Chris Wilson <ch...@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(-)

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,
-- 
2.20.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to