forked from Minki/linux
drm/i915: Unify aliasing ppgtt handling
With the dynamic pagetable alloc code aliasing ppgtt special-cases where again mixed in all over the place with the low-level init code. Extract the va preallocation and clearing again into the common code where aliasing ppgtt gets set up. Note that with this we don't set the size of the aliasing ppgtt to the size of the parent ggtt address space. Which isn't required at all since except for the ppgtt setup/cleanup code no one ever looks at this. Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
This commit is contained in:
parent
061dd49310
commit
5c5f645773
@ -387,50 +387,6 @@ fail_bitmap:
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* alloc_pt_range() - Allocate a multiple page tables
|
||||
* @pd: The page directory which will have at least @count entries
|
||||
* available to point to the allocated page tables.
|
||||
* @pde: First page directory entry for which we are allocating.
|
||||
* @count: Number of pages to allocate.
|
||||
* @dev: DRM device.
|
||||
*
|
||||
* Allocates multiple page table pages and sets the appropriate entries in the
|
||||
* page table structure within the page directory. Function cleans up after
|
||||
* itself on any failures.
|
||||
*
|
||||
* Return: 0 if allocation succeeded.
|
||||
*/
|
||||
static int alloc_pt_range(struct i915_page_directory *pd, uint16_t pde, size_t count,
|
||||
struct drm_device *dev)
|
||||
{
|
||||
int i, ret;
|
||||
|
||||
/* 512 is the max page tables per page_directory on any platform. */
|
||||
if (WARN_ON(pde + count > I915_PDES))
|
||||
return -EINVAL;
|
||||
|
||||
for (i = pde; i < pde + count; i++) {
|
||||
struct i915_page_table *pt = alloc_pt_single(dev);
|
||||
|
||||
if (IS_ERR(pt)) {
|
||||
ret = PTR_ERR(pt);
|
||||
goto err_out;
|
||||
}
|
||||
WARN(pd->page_table[i],
|
||||
"Leaking page directory entry %d (%p)\n",
|
||||
i, pd->page_table[i]);
|
||||
pd->page_table[i] = pt;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
while (i-- > pde)
|
||||
unmap_and_free_pt(pd->page_table[i], dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void unmap_and_free_pd(struct i915_page_directory *pd,
|
||||
struct drm_device *dev)
|
||||
{
|
||||
@ -971,7 +927,7 @@ err_out:
|
||||
* space.
|
||||
*
|
||||
*/
|
||||
static int gen8_ppgtt_init_common(struct i915_hw_ppgtt *ppgtt, uint64_t size)
|
||||
static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
|
||||
{
|
||||
ppgtt->scratch_pt = alloc_pt_single(ppgtt->base.dev);
|
||||
if (IS_ERR(ppgtt->scratch_pt))
|
||||
@ -985,8 +941,9 @@ static int gen8_ppgtt_init_common(struct i915_hw_ppgtt *ppgtt, uint64_t size)
|
||||
gen8_initialize_pd(&ppgtt->base, ppgtt->scratch_pd);
|
||||
|
||||
ppgtt->base.start = 0;
|
||||
ppgtt->base.total = size;
|
||||
ppgtt->base.total = 1ULL << 32;
|
||||
ppgtt->base.cleanup = gen8_ppgtt_cleanup;
|
||||
ppgtt->base.allocate_va_range = gen8_alloc_va_range;
|
||||
ppgtt->base.insert_entries = gen8_ppgtt_insert_entries;
|
||||
ppgtt->base.clear_range = gen8_ppgtt_clear_range;
|
||||
ppgtt->base.unbind_vma = ppgtt_unbind_vma;
|
||||
@ -997,46 +954,6 @@ static int gen8_ppgtt_init_common(struct i915_hw_ppgtt *ppgtt, uint64_t size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gen8_aliasing_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
|
||||
{
|
||||
struct drm_device *dev = ppgtt->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
uint64_t start = 0, size = dev_priv->gtt.base.total;
|
||||
int ret;
|
||||
|
||||
ret = gen8_ppgtt_init_common(ppgtt, dev_priv->gtt.base.total);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Aliasing PPGTT has to always work and be mapped because of the way we
|
||||
* use RESTORE_INHIBIT in the context switch. This will be fixed
|
||||
* eventually. */
|
||||
ret = gen8_alloc_va_range(&ppgtt->base, start, size);
|
||||
if (ret) {
|
||||
unmap_and_free_pd(ppgtt->scratch_pd, ppgtt->base.dev);
|
||||
unmap_and_free_pt(ppgtt->scratch_pt, ppgtt->base.dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ppgtt->base.allocate_va_range = NULL;
|
||||
ppgtt->base.clear_range(&ppgtt->base, 0, ppgtt->base.total, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = gen8_ppgtt_init_common(ppgtt, (1ULL << 32));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ppgtt->base.allocate_va_range = gen8_alloc_va_range;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void gen6_dump_ppgtt(struct i915_hw_ppgtt *ppgtt, struct seq_file *m)
|
||||
{
|
||||
struct i915_address_space *vm = &ppgtt->base;
|
||||
@ -1533,7 +1450,7 @@ static void gen6_scratch_va_range(struct i915_hw_ppgtt *ppgtt,
|
||||
ppgtt->pd.page_table[pde] = ppgtt->scratch_pt;
|
||||
}
|
||||
|
||||
static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt, bool aliasing)
|
||||
static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
|
||||
{
|
||||
struct drm_device *dev = ppgtt->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
@ -1556,18 +1473,7 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt, bool aliasing)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (aliasing) {
|
||||
/* preallocate all pts */
|
||||
ret = alloc_pt_range(&ppgtt->pd, 0, I915_PDES,
|
||||
ppgtt->base.dev);
|
||||
|
||||
if (ret) {
|
||||
gen6_ppgtt_cleanup(&ppgtt->base);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ppgtt->base.allocate_va_range = aliasing ? NULL : gen6_alloc_va_range;
|
||||
ppgtt->base.allocate_va_range = gen6_alloc_va_range;
|
||||
ppgtt->base.clear_range = gen6_ppgtt_clear_range;
|
||||
ppgtt->base.insert_entries = gen6_ppgtt_insert_entries;
|
||||
ppgtt->base.unbind_vma = ppgtt_unbind_vma;
|
||||
@ -1583,10 +1489,7 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt, bool aliasing)
|
||||
ppgtt->pd_addr = (gen6_pte_t __iomem *)dev_priv->gtt.gsm +
|
||||
ppgtt->pd.pd_offset / sizeof(gen6_pte_t);
|
||||
|
||||
if (aliasing)
|
||||
ppgtt->base.clear_range(&ppgtt->base, 0, ppgtt->base.total, true);
|
||||
else
|
||||
gen6_scratch_va_range(ppgtt, 0, ppgtt->base.total);
|
||||
gen6_scratch_va_range(ppgtt, 0, ppgtt->base.total);
|
||||
|
||||
gen6_write_page_range(dev_priv, &ppgtt->pd, 0, ppgtt->base.total);
|
||||
|
||||
@ -1600,8 +1503,7 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt, bool aliasing)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __hw_ppgtt_init(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt,
|
||||
bool aliasing)
|
||||
static int __hw_ppgtt_init(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
@ -1609,9 +1511,7 @@ static int __hw_ppgtt_init(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt,
|
||||
ppgtt->base.scratch = dev_priv->gtt.base.scratch;
|
||||
|
||||
if (INTEL_INFO(dev)->gen < 8)
|
||||
return gen6_ppgtt_init(ppgtt, aliasing);
|
||||
else if (aliasing)
|
||||
return gen8_aliasing_ppgtt_init(ppgtt);
|
||||
return gen6_ppgtt_init(ppgtt);
|
||||
else
|
||||
return gen8_ppgtt_init(ppgtt);
|
||||
}
|
||||
@ -1620,7 +1520,7 @@ int i915_ppgtt_init(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt)
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int ret = 0;
|
||||
|
||||
ret = __hw_ppgtt_init(dev, ppgtt, false);
|
||||
ret = __hw_ppgtt_init(dev, ppgtt);
|
||||
if (ret == 0) {
|
||||
kref_init(&ppgtt->ref);
|
||||
drm_mm_init(&ppgtt->base.mm, ppgtt->base.start,
|
||||
@ -2255,13 +2155,27 @@ static int i915_gem_setup_global_gtt(struct drm_device *dev,
|
||||
if (!ppgtt)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = __hw_ppgtt_init(dev, ppgtt, true);
|
||||
ret = __hw_ppgtt_init(dev, ppgtt);
|
||||
if (ret) {
|
||||
ppgtt->base.cleanup(&ppgtt->base);
|
||||
kfree(ppgtt);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ppgtt->base.allocate_va_range)
|
||||
ret = ppgtt->base.allocate_va_range(&ppgtt->base, 0,
|
||||
ppgtt->base.total);
|
||||
if (ret) {
|
||||
ppgtt->base.cleanup(&ppgtt->base);
|
||||
kfree(ppgtt);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ppgtt->base.clear_range(&ppgtt->base,
|
||||
ppgtt->base.start,
|
||||
ppgtt->base.total,
|
||||
true);
|
||||
|
||||
dev_priv->mm.aliasing_ppgtt = ppgtt;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user