[PATCH 09/10] drm/i915/gtt: Recursive ppgtt alloc for gen8
Chris Wilson
chris at chris-wilson.co.uk
Sat Jul 6 14:52:36 UTC 2019
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
drivers/gpu/drm/i915/i915_gem_gtt.c | 266 +++++++++-------------------
1 file changed, 79 insertions(+), 187 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 8725b4817ee0..9befbd647315 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -974,187 +974,96 @@ static void gen8_ppgtt_clear(struct i915_address_space *vm,
GEM_BUG_ON(length);
}
-static void gen8_ppgtt_clear_pd(struct i915_address_space *vm,
- struct i915_page_directory *pd,
- u64 start, u64 length)
-{
- __gen8_ppgtt_clear(vm, pd, &start, &length, 1);
-}
-
-static void gen8_ppgtt_clear_pdp(struct i915_address_space *vm,
- struct i915_page_directory * const pdp,
- u64 start, u64 length)
-{
- __gen8_ppgtt_clear(vm, pdp, &start, &length, 2);
-}
-
-static int gen8_ppgtt_alloc_pd(struct i915_address_space *vm,
- struct i915_page_directory *pd,
- u64 start, u64 length)
+static int __gen8_ppgtt_alloc(struct i915_address_space *vm,
+ struct i915_page_directory *pd,
+ u64 *start, u64 *length, int lvl)
{
struct i915_page_table *pt, *alloc = NULL;
- u64 from = start;
- unsigned int pde;
+ unsigned int idx, len;
int ret = 0;
+ GEM_BUG_ON(!px_used(pd)); /* Our parents must be pinned! */
+
+ len = gen8_pd_range(*start, *length, lvl, &idx);
+ GEM_BUG_ON(!len);
+
spin_lock(&pd->lock);
- gen8_for_each_pde(pt, pd, start, length, pde) {
- const int count = gen8_pte_count(start, length);
+ do {
+ GEM_BUG_ON(!atomic_read(px_used(pd)));
+ pt = pd->entry[idx];
- if (px_base(pt) == &vm->scratch[1]) {
+ if (px_base(pt) == &vm->scratch[lvl]) {
spin_unlock(&pd->lock);
pt = fetch_and_zero(&alloc);
if (!pt)
- pt = alloc_pt(vm);
+ pt = (lvl > 1) ? &alloc_pd(vm)->pt : alloc_pt(vm);
if (IS_ERR(pt)) {
ret = PTR_ERR(pt);
- goto unwind;
+ goto out;
}
- if (count < GEN8_PTES || intel_vgpu_active(vm->i915))
+ if (lvl > 1)
+ init_pd(as_pd(pt), &vm->scratch[lvl - 1]);
+ else if (len < I915_PDES || intel_vgpu_active(vm->i915))
fill_px(pt, vm->scratch_pte);
spin_lock(&pd->lock);
- if (pd->entry[pde] == &vm->scratch[1]) {
- set_pd_entry(pd, pde, pt);
+ if (pd->entry[idx] == &vm->scratch[lvl]) {
+ set_pd_entry(pd, idx, pt);
} else {
alloc = pt;
- pt = pd->entry[pde];
+ pt = pd->entry[idx];
}
}
- atomic_add(count, &pt->used);
- }
- spin_unlock(&pd->lock);
- goto out;
-
-unwind:
- gen8_ppgtt_clear_pd(vm, pd, from, start - from);
-out:
- if (alloc)
- free_px(vm, alloc);
- return ret;
-}
-
-static int gen8_ppgtt_alloc_pdp(struct i915_address_space *vm,
- struct i915_page_directory *pdp,
- u64 start, u64 length)
-{
- struct i915_page_directory *pd, *alloc = NULL;
- u64 from = start;
- unsigned int pdpe;
- int ret = 0;
+ if (lvl > 1) {
+ atomic_inc(&pt->used);
+ spin_unlock(&pd->lock);
- spin_lock(&pdp->lock);
- gen8_for_each_pdpe(pd, pdp, start, length, pdpe) {
- if (px_base(pd) == &vm->scratch[2]) {
- spin_unlock(&pdp->lock);
-
- pd = fetch_and_zero(&alloc);
- if (!pd)
- pd = alloc_pd(vm);
- if (IS_ERR(pd)) {
- ret = PTR_ERR(pd);
- goto unwind;
- }
+ ret = __gen8_ppgtt_alloc(vm, as_pd(pt),
+ start, length, lvl - 1);
+ if (unlikely(ret))
+ goto release;
- init_pd(pd, &vm->scratch[1]);
+ spin_lock(&pd->lock);
+ atomic_dec(&pt->used);
+ GEM_BUG_ON(!atomic_read(&pt->used));
+ } else {
+ unsigned int count = gen8_pt_count(*start, *length);
- spin_lock(&pdp->lock);
- if (pdp->entry[pdpe] == &vm->scratch[2]) {
- set_pd_entry(pdp, pdpe, pd);
- } else {
- alloc = pd;
- pd = pdp->entry[pdpe];
- }
+ atomic_add(count, &pt->used);
+ *start += count << GEN8_PTE_SHIFT;
+ *length -= count << GEN8_PTE_SHIFT;
}
- atomic_inc(px_used(pd));
- spin_unlock(&pdp->lock);
-
- ret = gen8_ppgtt_alloc_pd(vm, pd, start, length);
- if (unlikely(ret))
- goto unwind_pd;
-
- spin_lock(&pdp->lock);
- atomic_dec(px_used(pd));
- }
- spin_unlock(&pdp->lock);
+ } while (idx++, --len);
+ spin_unlock(&pd->lock);
goto out;
-unwind_pd:
- if (release_pd_entry(pdp, pdpe, &pd->pt, &vm->scratch[2]))
- free_px(vm, pd);
-unwind:
- gen8_ppgtt_clear_pdp(vm, pdp, from, start - from);
+release:
+ if (release_pd_entry(pd, idx, pt, &vm->scratch[lvl]))
+ free_pd(vm, px_base(pt));
out:
if (alloc)
- free_px(vm, alloc);
+ free_pd(vm, &alloc->base);
return ret;
}
-static int gen8_ppgtt_alloc_3lvl(struct i915_address_space *vm,
- u64 start, u64 length)
-{
- return gen8_ppgtt_alloc_pdp(vm,
- i915_vm_to_ppgtt(vm)->pd, start, length);
-}
-
-static int gen8_ppgtt_alloc_4lvl(struct i915_address_space *vm,
- u64 start, u64 length)
+static int gen8_ppgtt_alloc(struct i915_address_space *vm,
+ u64 start, u64 length)
{
- struct i915_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
- struct i915_page_directory * const pml4 = ppgtt->pd;
- struct i915_page_directory *pdp, *alloc = NULL;
u64 from = start;
- int ret = 0;
- u32 pml4e;
-
- spin_lock(&pml4->lock);
- gen8_for_each_pml4e(pdp, pml4, start, length, pml4e) {
- if (px_base(pdp) == &vm->scratch[3]) {
- spin_unlock(&pml4->lock);
-
- pdp = fetch_and_zero(&alloc);
- if (!pdp)
- pdp = alloc_pd(vm);
- if (IS_ERR(pdp)) {
- ret = PTR_ERR(pdp);
- goto unwind;
- }
-
- init_pd(pdp, &vm->scratch[2]);
-
- spin_lock(&pml4->lock);
- if (pml4->entry[pml4e] == &vm->scratch[3]) {
- set_pd_entry(pml4, pml4e, pdp);
- } else {
- alloc = pdp;
- pdp = pml4->entry[pml4e];
- }
- }
- atomic_inc(px_used(pdp));
- spin_unlock(&pml4->lock);
-
- ret = gen8_ppgtt_alloc_pdp(vm, pdp, start, length);
- if (unlikely(ret))
- goto unwind_pdp;
+ int err;
- spin_lock(&pml4->lock);
- atomic_dec(px_used(pdp));
+ err = __gen8_ppgtt_alloc(vm, i915_vm_to_ppgtt(vm)->pd,
+ &start, &length, vm->top);
+ if (!err) {
+ GEM_BUG_ON(length);
+ return 0;
}
- spin_unlock(&pml4->lock);
- goto out;
-unwind_pdp:
- if (release_pd_entry(pml4, pml4e, &pdp->pt, &vm->scratch[3]))
- free_px(vm, pdp);
-unwind:
gen8_ppgtt_clear(vm, from, start - from);
-out:
- if (alloc)
- free_px(vm, alloc);
- return ret;
+ return err;
}
static inline struct sgt_dma {
@@ -1452,26 +1361,28 @@ static int gen8_init_scratch(struct i915_address_space *vm)
static int gen8_preallocate_top_level_pdp(struct i915_ppgtt *ppgtt)
{
struct i915_address_space *vm = &ppgtt->vm;
- struct i915_page_directory *pdp = ppgtt->pd;
- struct i915_page_directory *pd;
- u64 start = 0, length = ppgtt->vm.total;
- u64 from = start;
- unsigned int pdpe;
+ struct i915_page_directory *pd = ppgtt->pd;
+ unsigned int idx;
+
+ GEM_BUG_ON(vm->top != 2);
+ GEM_BUG_ON(GEN8_3LVL_PDPES != ppgtt->vm.total >> gen8_pd_shift(2));
- gen8_for_each_pdpe(pd, pdp, start, length, pdpe) {
- pd = alloc_pd(vm);
- if (IS_ERR(pd))
+ for (idx = 0; idx < GEN8_3LVL_PDPES; idx++) {
+ struct i915_page_directory *pde;
+
+ pde = alloc_pd(vm);
+ if (IS_ERR(pde))
goto unwind;
- init_pd(pd, &vm->scratch[1]);
- set_pd_entry(pdp, pdpe, pd);
+ init_pd(pde, &vm->scratch[1]);
+ set_pd_entry(pd, idx, &pde->pt);
}
return 0;
unwind:
- gen8_ppgtt_clear_pdp(vm, pdp, from, start - from);
- atomic_set(px_used(pdp), 0);
+ gen8_ppgtt_clear(vm, 0, idx << gen8_pd_shift(2));
+ atomic_set(px_used(pd), 0);
return -ENOMEM;
}
@@ -1494,47 +1405,29 @@ static void ppgtt_init(struct i915_ppgtt *ppgtt, struct intel_gt *gt)
ppgtt->vm.top = i915_vm_is_4lvl(&ppgtt->vm) ? 3 : 2;
}
-static void init_pd_n(struct i915_address_space *vm,
- struct i915_page_directory *pd,
- struct i915_page_dma *to,
- const unsigned int entries)
-{
- const u64 daddr = gen8_pde_encode(to->daddr, I915_CACHE_LLC);
- u64 * const vaddr = kmap_atomic_px(pd);
-
- memset64(vaddr, daddr, entries);
- kunmap_atomic(vaddr);
-
- memset_p(pd->entry, to, entries);
-}
-
static struct i915_page_directory *
gen8_alloc_top_pd(struct i915_address_space *vm)
{
+ const int top = vm->top;
+ const int count = vm->total >> gen8_pd_shift(top);
struct i915_page_directory *pd;
+ void *vaddr;
- if (i915_vm_is_4lvl(vm)) {
- pd = alloc_pd(vm);
- if (!IS_ERR(pd))
- init_pd(pd, &vm->scratch[3]);
+ GEM_BUG_ON((vm->total - 1) >> gen8_pd_shift(top + 1));
+ pd = alloc_pd(vm);
+ if (IS_ERR(pd))
return pd;
- }
-
- /* 3lvl */
- pd = __alloc_pd();
- if (!pd)
- return ERR_PTR(-ENOMEM);
-
- pd->entry[GEN8_3LVL_PDPES] = NULL;
- if (unlikely(setup_page_dma(vm, px_base(pd)))) {
- kfree(pd);
- return ERR_PTR(-ENOMEM);
- }
+ vaddr = kmap_atomic_px(pd);
+ memset64(vaddr,
+ gen8_pde_encode(px_dma(&vm->scratch[top]), I915_CACHE_LLC),
+ count);
+ kunmap_atomic(vaddr);
- init_pd_n(vm, pd, &vm->scratch[2], GEN8_3LVL_PDPES);
+ memset_p(pd->entry, &vm->scratch[top], count);
+ atomic_inc(px_used(pd)); /* mark as pinned */
return pd;
}
@@ -1581,7 +1474,6 @@ static struct i915_ppgtt *gen8_ppgtt_create(struct drm_i915_private *i915)
}
if (i915_vm_is_4lvl(&ppgtt->vm)) {
- ppgtt->vm.allocate_va_range = gen8_ppgtt_alloc_4lvl;
ppgtt->vm.insert_entries = gen8_ppgtt_insert_4lvl;
} else {
if (intel_vgpu_active(i915)) {
@@ -1590,10 +1482,10 @@ static struct i915_ppgtt *gen8_ppgtt_create(struct drm_i915_private *i915)
goto err_free_pd;
}
- ppgtt->vm.allocate_va_range = gen8_ppgtt_alloc_3lvl;
ppgtt->vm.insert_entries = gen8_ppgtt_insert_3lvl;
}
+ ppgtt->vm.allocate_va_range = gen8_ppgtt_alloc;
ppgtt->vm.clear_range = gen8_ppgtt_clear;
if (intel_vgpu_active(i915))
--
2.20.1
More information about the Intel-gfx-trybot
mailing list