diff options
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_gtt.c | 45 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_gtt.h | 26 |
2 files changed, 55 insertions, 16 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index c02b37e32f7b..06fb928bdab3 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -538,27 +538,40 @@ static void gen8_ppgtt_insert_entries(struct i915_address_space *vm, } } -static void gen8_free_page_tables(struct i915_pagedir *pd, struct drm_device *dev) +static void gen8_teardown_va_range(struct i915_address_space *vm, + uint64_t start, uint64_t length) { - int i; - - if (!pd->page) - return; - - for (i = 0; i < I915_PDES_PER_PD; i++) { - free_pt_single(pd->page_tables[i], dev); - pd->page_tables[i] = NULL; + struct i915_hw_ppgtt *ppgtt = + container_of(vm, struct i915_hw_ppgtt, base); + struct i915_pagedir *pd; + struct i915_pagetab *pt; + uint64_t temp; + uint32_t pdpe, pde; + + gen8_for_each_pdpe(pd, &ppgtt->pdp, start, length, temp, pdpe) { + uint64_t pd_len = gen8_clamp_pd(start, length); + uint64_t pd_start = start; + gen8_for_each_pde(pt, pd, pd_start, pd_len, temp, pde) { + free_pt_single(pt, vm->dev); + } + free_pd_single(pd, vm->dev); } } -static void gen8_ppgtt_free(struct i915_hw_ppgtt *ppgtt) +/* This function will die soon */ +static void gen8_free_full_pagedir(struct i915_hw_ppgtt *ppgtt, int i) { - int i; + gen8_teardown_va_range(&ppgtt->base, + i << GEN8_PDPE_SHIFT, + (1 << GEN8_PDPE_SHIFT)); +} - for (i = 0; i < ppgtt->num_pd_pages; i++) { - gen8_free_page_tables(ppgtt->pdp.pagedirs[i], ppgtt->base.dev); - free_pd_single(ppgtt->pdp.pagedirs[i], ppgtt->base.dev); - } +static void gen8_ppgtt_free(struct i915_hw_ppgtt *ppgtt) +{ + trace_i915_va_teardown(&ppgtt->base, + ppgtt->base.start, ppgtt->base.total); + gen8_teardown_va_range(&ppgtt->base, + ppgtt->base.start, ppgtt->base.total); } static void gen8_ppgtt_cleanup(struct i915_address_space *vm) @@ -587,7 +600,7 @@ static int gen8_ppgtt_allocate_page_tables(struct i915_hw_ppgtt *ppgtt) unwind_out: while (i--) - gen8_free_page_tables(ppgtt->pdp.pagedirs[i], ppgtt->base.dev); + gen8_free_full_pagedir(ppgtt, i); return -ENOMEM; } diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index b3044f6420b5..38c2f8e3faa7 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -396,6 +396,32 @@ static inline size_t gen6_pde_count(uint32_t addr, uint32_t length) return i915_pde_count(addr, length, GEN6_PDE_SHIFT); } +#define gen8_for_each_pde(pt, pd, start, length, temp, iter) \ + for (iter = gen8_pde_index(start), pt = (pd)->page_tables[iter]; \ + length > 0 && iter < I915_PDES_PER_PD; \ + pt = (pd)->page_tables[++iter], \ + temp = ALIGN(start+1, 1 << GEN8_PDE_SHIFT) - start, \ + temp = min(temp, length), \ + start += temp, length -= temp) + +#define gen8_for_each_pdpe(pd, pdp, start, length, temp, iter) \ + for (iter = gen8_pdpe_index(start), pd = (pdp)->pagedirs[iter]; \ + length > 0 && iter < GEN8_LEGACY_PDPES; \ + pd = (pdp)->pagedirs[++iter], \ + temp = ALIGN(start+1, 1 << GEN8_PDPE_SHIFT) - start, \ + temp = min(temp, length), \ + start += temp, length -= temp) + +/* Clamp length to the next pagedir boundary */ +static inline uint64_t gen8_clamp_pd(uint64_t start, uint64_t length) +{ + uint64_t next_pd = ALIGN(start + 1, 1 << GEN8_PDPE_SHIFT); + if (next_pd > (start + length)) + return length; + + return next_pd - start; +} + static inline uint32_t gen8_pte_index(uint64_t address) { return i915_pte_index(address, GEN8_PDE_SHIFT); |