aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_gem_gtt.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2017-02-27 12:26:52 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2017-02-27 13:09:19 +0000
commitbf75d59eff679d2e2b7af5c6958a088f8a458f7a (patch)
tree209ec2333db313a9b293dc5cfdc4f589a992f445 /drivers/gpu/drm/i915/i915_gem_gtt.c
parentdrm/i915/bdw: Do not write the replay bit of the ring mode register (diff)
downloadlinux-dev-bf75d59eff679d2e2b7af5c6958a088f8a458f7a.tar.xz
linux-dev-bf75d59eff679d2e2b7af5c6958a088f8a458f7a.zip
drm/i915: Only unwind the local pgtable layer if empty
Only if we allocated the layer and the lower level failed should we remove this layer when unwinding. Otherwise we ignore the overlapping entries by overwriting the old layer with scratch. Fixes: c5d092a4293f ("drm/i915: Remove bitmap tracking for used-pml4") Fixes: e2b763caa6eb ("drm/i915: Remove bitmap tracking for used-pdpes") Reported-by: Matthew Auld <matthew.william.auld@gmail.com> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=99947 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.auld@intel.com> Reviewed-by: Matthew Auld <matthew.auld@intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/20170227122654.27651-1-chris@chris-wilson.co.uk
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem_gtt.c')
-rw-r--r--drivers/gpu/drm/i915/i915_gem_gtt.c37
1 files changed, 26 insertions, 11 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 6fdbd5ae4fcb..c3a121ab8914 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -716,10 +716,13 @@ static bool gen8_ppgtt_clear_pd(struct i915_address_space *vm,
u32 pde;
gen8_for_each_pde(pt, pd, start, length, pde) {
+ GEM_BUG_ON(pt == vm->scratch_pt);
+
if (!gen8_ppgtt_clear_pt(vm, pt, start, length))
continue;
gen8_ppgtt_set_pde(vm, pd, vm->scratch_pt, pde);
+ GEM_BUG_ON(!pd->used_pdes);
pd->used_pdes--;
free_pt(vm, pt);
@@ -755,10 +758,13 @@ static bool gen8_ppgtt_clear_pdp(struct i915_address_space *vm,
unsigned int pdpe;
gen8_for_each_pdpe(pd, pdp, start, length, pdpe) {
+ GEM_BUG_ON(pd == vm->scratch_pd);
+
if (!gen8_ppgtt_clear_pd(vm, pd, start, length))
continue;
gen8_ppgtt_set_pdpe(vm, pdp, vm->scratch_pd, pdpe);
+ GEM_BUG_ON(!pdp->used_pdpes);
pdp->used_pdpes--;
free_pd(vm, pd);
@@ -801,6 +807,8 @@ static void gen8_ppgtt_clear_4lvl(struct i915_address_space *vm,
GEM_BUG_ON(!USES_FULL_48BIT_PPGTT(vm->i915));
gen8_for_each_pml4e(pdp, pml4, start, length, pml4e) {
+ GEM_BUG_ON(pdp == vm->scratch_pdp);
+
if (!gen8_ppgtt_clear_pdp(vm, pdp, start, length))
continue;
@@ -1089,6 +1097,7 @@ static int gen8_ppgtt_alloc_pd(struct i915_address_space *vm,
gen8_ppgtt_set_pde(vm, pd, pt, pde);
pd->used_pdes++;
+ GEM_BUG_ON(pd->used_pdes > I915_PDES);
}
pt->used_ptes += gen8_pte_count(start, length);
@@ -1118,21 +1127,25 @@ static int gen8_ppgtt_alloc_pdp(struct i915_address_space *vm,
gen8_initialize_pd(vm, pd);
gen8_ppgtt_set_pdpe(vm, pdp, pd, pdpe);
pdp->used_pdpes++;
+ GEM_BUG_ON(pdp->used_pdpes > I915_PDPES_PER_PDP(vm));
mark_tlbs_dirty(i915_vm_to_ppgtt(vm));
}
ret = gen8_ppgtt_alloc_pd(vm, pd, start, length);
- if (unlikely(ret)) {
- gen8_ppgtt_set_pdpe(vm, pdp, vm->scratch_pd, pdpe);
- pdp->used_pdpes--;
- free_pd(vm, pd);
- goto unwind;
- }
+ if (unlikely(ret))
+ goto unwind_pd;
}
return 0;
+unwind_pd:
+ if (!pd->used_pdes) {
+ gen8_ppgtt_set_pdpe(vm, pdp, vm->scratch_pd, pdpe);
+ GEM_BUG_ON(!pdp->used_pdpes);
+ pdp->used_pdpes--;
+ free_pd(vm, pd);
+ }
unwind:
gen8_ppgtt_clear_pdp(vm, pdp, from, start - from);
return -ENOMEM;
@@ -1166,15 +1179,17 @@ static int gen8_ppgtt_alloc_4lvl(struct i915_address_space *vm,
}
ret = gen8_ppgtt_alloc_pdp(vm, pdp, start, length);
- if (unlikely(ret)) {
- gen8_ppgtt_set_pml4e(pml4, vm->scratch_pdp, pml4e);
- free_pdp(vm, pdp);
- goto unwind;
- }
+ if (unlikely(ret))
+ goto unwind_pdp;
}
return 0;
+unwind_pdp:
+ if (!pdp->used_pdpes) {
+ gen8_ppgtt_set_pml4e(pml4, vm->scratch_pdp, pml4e);
+ free_pdp(vm, pdp);
+ }
unwind:
gen8_ppgtt_clear_4lvl(vm, from, start - from);
return -ENOMEM;