diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem_gtt.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_gtt.c | 63 |
1 files changed, 41 insertions, 22 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index e6e0dfa761dd..6fdbd5ae4fcb 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -815,26 +815,41 @@ struct sgt_dma { dma_addr_t dma, max; }; +struct gen8_insert_pte { + u16 pml4e; + u16 pdpe; + u16 pde; + u16 pte; +}; + +static __always_inline struct gen8_insert_pte gen8_insert_pte(u64 start) +{ + return (struct gen8_insert_pte) { + gen8_pml4e_index(start), + gen8_pdpe_index(start), + gen8_pde_index(start), + gen8_pte_index(start), + }; +} + static __always_inline bool gen8_ppgtt_insert_pte_entries(struct i915_hw_ppgtt *ppgtt, struct i915_page_directory_pointer *pdp, struct sgt_dma *iter, - u64 start, + struct gen8_insert_pte *idx, enum i915_cache_level cache_level) { - unsigned int pdpe = gen8_pdpe_index(start); - unsigned int pde = gen8_pde_index(start); - unsigned int pte = gen8_pte_index(start); struct i915_page_directory *pd; const gen8_pte_t pte_encode = gen8_pte_encode(0, cache_level); gen8_pte_t *vaddr; bool ret; - GEM_BUG_ON(pdpe >= I915_PDPES_PER_PDP(vm)); - pd = pdp->page_directory[pdpe]; - vaddr = kmap_atomic_px(pd->page_table[pde]); + GEM_BUG_ON(idx->pdpe >= I915_PDPES_PER_PDP(vm)); + pd = pdp->page_directory[idx->pdpe]; + vaddr = kmap_atomic_px(pd->page_table[idx->pde]); do { - vaddr[pte] = pte_encode | iter->dma; + vaddr[idx->pte] = pte_encode | iter->dma; + iter->dma += PAGE_SIZE; if (iter->dma >= iter->max) { iter->sg = __sg_next(iter->sg); @@ -847,22 +862,25 @@ gen8_ppgtt_insert_pte_entries(struct i915_hw_ppgtt *ppgtt, iter->max = iter->dma + iter->sg->length; } - if (++pte == GEN8_PTES) { - if (++pde == I915_PDES) { + if (++idx->pte == GEN8_PTES) { + idx->pte = 0; + + if (++idx->pde == I915_PDES) { + idx->pde = 0; + /* Limited by sg length for 3lvl */ - if (++pdpe == GEN8_PML4ES_PER_PML4) { + if (++idx->pdpe == GEN8_PML4ES_PER_PML4) { + idx->pdpe = 0; ret = true; break; } - GEM_BUG_ON(pdpe >= I915_PDPES_PER_PDP(vm)); - pd = pdp->page_directory[pdpe]; - pde = 0; + GEM_BUG_ON(idx->pdpe >= I915_PDPES_PER_PDP(vm)); + pd = pdp->page_directory[idx->pdpe]; } kunmap_atomic(vaddr); - vaddr = kmap_atomic_px(pd->page_table[pde]); - pte = 0; + vaddr = kmap_atomic_px(pd->page_table[idx->pde]); } } while (1); kunmap_atomic(vaddr); @@ -882,9 +900,10 @@ static void gen8_ppgtt_insert_3lvl(struct i915_address_space *vm, .dma = sg_dma_address(iter.sg), .max = iter.dma + iter.sg->length, }; + struct gen8_insert_pte idx = gen8_insert_pte(start); - gen8_ppgtt_insert_pte_entries(ppgtt, &ppgtt->pdp, &iter, - start, cache_level); + gen8_ppgtt_insert_pte_entries(ppgtt, &ppgtt->pdp, &iter, &idx, + cache_level); } static void gen8_ppgtt_insert_4lvl(struct i915_address_space *vm, @@ -900,11 +919,11 @@ static void gen8_ppgtt_insert_4lvl(struct i915_address_space *vm, .max = iter.dma + iter.sg->length, }; struct i915_page_directory_pointer **pdps = ppgtt->pml4.pdps; - unsigned int pml4e = gen8_pml4e_index(start); + struct gen8_insert_pte idx = gen8_insert_pte(start); - while (gen8_ppgtt_insert_pte_entries(ppgtt, pdps[pml4e++], &iter, - start, cache_level)) - GEM_BUG_ON(pml4e >= GEN8_PML4ES_PER_PML4); + while (gen8_ppgtt_insert_pte_entries(ppgtt, pdps[idx.pml4e++], &iter, + &idx, cache_level)) + GEM_BUG_ON(idx.pml4e >= GEN8_PML4ES_PER_PML4); } static void gen8_free_page_tables(struct i915_address_space *vm, |