aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2017-02-25 13:11:22 -0500
committerChris Wilson <chris@chris-wilson.co.uk>2017-02-25 13:54:38 -0500
commit9e89f9ee3b16cca56bed5fa45e63f422d3ac2c3a (patch)
treebc7ad5c7c8df635166295cbc3b72ef360d9e601a
parentaa149431279166025bc457007e5a1fdcb4d2db9b (diff)
drm/i915: Advance start address on crossing PML (48b ppgtt) boundary
When advancing onto the next 4th level page table entry, we need to reset our indices to 0. Currently we restart from the original address which means we start with an offset into the next PML table. Fixes: 894ccebee2b0 ("drm/i915: Micro-optimise gen8_ppgtt_insert_entries()") Reported-by: Matthew Auld <matthew.william.auld@gmail.com> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=99948 Testcase: igt/drv_selftest/live_gtt Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Matthew Auld <matthew.william.auld@gmail.com> Tested-by: Matthew Auld <matthew.william.auld@gmail.com> Reviewed-by: Matthew Auld <matthew.william.auld@gmail.com> Link: http://patchwork.freedesktop.org/patch/msgid/20170225181122.4788-4-chris@chris-wilson.co.uk
-rw-r--r--drivers/gpu/drm/i915/i915_gem_gtt.c63
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 {
815 dma_addr_t dma, max; 815 dma_addr_t dma, max;
816}; 816};
817 817
818struct gen8_insert_pte {
819 u16 pml4e;
820 u16 pdpe;
821 u16 pde;
822 u16 pte;
823};
824
825static __always_inline struct gen8_insert_pte gen8_insert_pte(u64 start)
826{
827 return (struct gen8_insert_pte) {
828 gen8_pml4e_index(start),
829 gen8_pdpe_index(start),
830 gen8_pde_index(start),
831 gen8_pte_index(start),
832 };
833}
834
818static __always_inline bool 835static __always_inline bool
819gen8_ppgtt_insert_pte_entries(struct i915_hw_ppgtt *ppgtt, 836gen8_ppgtt_insert_pte_entries(struct i915_hw_ppgtt *ppgtt,
820 struct i915_page_directory_pointer *pdp, 837 struct i915_page_directory_pointer *pdp,
821 struct sgt_dma *iter, 838 struct sgt_dma *iter,
822 u64 start, 839 struct gen8_insert_pte *idx,
823 enum i915_cache_level cache_level) 840 enum i915_cache_level cache_level)
824{ 841{
825 unsigned int pdpe = gen8_pdpe_index(start);
826 unsigned int pde = gen8_pde_index(start);
827 unsigned int pte = gen8_pte_index(start);
828 struct i915_page_directory *pd; 842 struct i915_page_directory *pd;
829 const gen8_pte_t pte_encode = gen8_pte_encode(0, cache_level); 843 const gen8_pte_t pte_encode = gen8_pte_encode(0, cache_level);
830 gen8_pte_t *vaddr; 844 gen8_pte_t *vaddr;
831 bool ret; 845 bool ret;
832 846
833 GEM_BUG_ON(pdpe >= I915_PDPES_PER_PDP(vm)); 847 GEM_BUG_ON(idx->pdpe >= I915_PDPES_PER_PDP(vm));
834 pd = pdp->page_directory[pdpe]; 848 pd = pdp->page_directory[idx->pdpe];
835 vaddr = kmap_atomic_px(pd->page_table[pde]); 849 vaddr = kmap_atomic_px(pd->page_table[idx->pde]);
836 do { 850 do {
837 vaddr[pte] = pte_encode | iter->dma; 851 vaddr[idx->pte] = pte_encode | iter->dma;
852
838 iter->dma += PAGE_SIZE; 853 iter->dma += PAGE_SIZE;
839 if (iter->dma >= iter->max) { 854 if (iter->dma >= iter->max) {
840 iter->sg = __sg_next(iter->sg); 855 iter->sg = __sg_next(iter->sg);
@@ -847,22 +862,25 @@ gen8_ppgtt_insert_pte_entries(struct i915_hw_ppgtt *ppgtt,
847 iter->max = iter->dma + iter->sg->length; 862 iter->max = iter->dma + iter->sg->length;
848 } 863 }
849 864
850 if (++pte == GEN8_PTES) { 865 if (++idx->pte == GEN8_PTES) {
851 if (++pde == I915_PDES) { 866 idx->pte = 0;
867
868 if (++idx->pde == I915_PDES) {
869 idx->pde = 0;
870
852 /* Limited by sg length for 3lvl */ 871 /* Limited by sg length for 3lvl */
853 if (++pdpe == GEN8_PML4ES_PER_PML4) { 872 if (++idx->pdpe == GEN8_PML4ES_PER_PML4) {
873 idx->pdpe = 0;
854 ret = true; 874 ret = true;
855 break; 875 break;
856 } 876 }
857 877
858 GEM_BUG_ON(pdpe >= I915_PDPES_PER_PDP(vm)); 878 GEM_BUG_ON(idx->pdpe >= I915_PDPES_PER_PDP(vm));
859 pd = pdp->page_directory[pdpe]; 879 pd = pdp->page_directory[idx->pdpe];
860 pde = 0;
861 } 880 }
862 881
863 kunmap_atomic(vaddr); 882 kunmap_atomic(vaddr);
864 vaddr = kmap_atomic_px(pd->page_table[pde]); 883 vaddr = kmap_atomic_px(pd->page_table[idx->pde]);
865 pte = 0;
866 } 884 }
867 } while (1); 885 } while (1);
868 kunmap_atomic(vaddr); 886 kunmap_atomic(vaddr);
@@ -882,9 +900,10 @@ static void gen8_ppgtt_insert_3lvl(struct i915_address_space *vm,
882 .dma = sg_dma_address(iter.sg), 900 .dma = sg_dma_address(iter.sg),
883 .max = iter.dma + iter.sg->length, 901 .max = iter.dma + iter.sg->length,
884 }; 902 };
903 struct gen8_insert_pte idx = gen8_insert_pte(start);
885 904
886 gen8_ppgtt_insert_pte_entries(ppgtt, &ppgtt->pdp, &iter, 905 gen8_ppgtt_insert_pte_entries(ppgtt, &ppgtt->pdp, &iter, &idx,
887 start, cache_level); 906 cache_level);
888} 907}
889 908
890static void gen8_ppgtt_insert_4lvl(struct i915_address_space *vm, 909static 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,
900 .max = iter.dma + iter.sg->length, 919 .max = iter.dma + iter.sg->length,
901 }; 920 };
902 struct i915_page_directory_pointer **pdps = ppgtt->pml4.pdps; 921 struct i915_page_directory_pointer **pdps = ppgtt->pml4.pdps;
903 unsigned int pml4e = gen8_pml4e_index(start); 922 struct gen8_insert_pte idx = gen8_insert_pte(start);
904 923
905 while (gen8_ppgtt_insert_pte_entries(ppgtt, pdps[pml4e++], &iter, 924 while (gen8_ppgtt_insert_pte_entries(ppgtt, pdps[idx.pml4e++], &iter,
906 start, cache_level)) 925 &idx, cache_level))
907 GEM_BUG_ON(pml4e >= GEN8_PML4ES_PER_PML4); 926 GEM_BUG_ON(idx.pml4e >= GEN8_PML4ES_PER_PML4);
908} 927}
909 928
910static void gen8_free_page_tables(struct i915_address_space *vm, 929static void gen8_free_page_tables(struct i915_address_space *vm,