@@ -389,8 +389,9 @@ static struct i915_pagedir *alloc_pd_single(struct drm_device *dev)
}
/* Broadwell Page Directory Pointer Descriptors */
-static int gen8_write_pdp(struct intel_engine_cs *ring, unsigned entry,
- uint64_t val)
+static int gen8_write_pdp(struct intel_engine_cs *ring,
+ unsigned entry,
+ dma_addr_t addr)
{
int ret;
@@ -402,10 +403,10 @@ static int gen8_write_pdp(struct intel_engine_cs *ring, unsigned entry,
intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
intel_ring_emit(ring, GEN8_RING_PDP_UDW(ring, entry));
- intel_ring_emit(ring, (u32)(val >> 32));
+ intel_ring_emit(ring, upper_32_bits(addr));
intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
intel_ring_emit(ring, GEN8_RING_PDP_LDW(ring, entry));
- intel_ring_emit(ring, (u32)(val));
+ intel_ring_emit(ring, lower_32_bits(addr));
intel_ring_advance(ring);
return 0;
@@ -416,12 +417,12 @@ static int gen8_mm_switch(struct i915_hw_ppgtt *ppgtt,
{
int i, ret;
- /* bit of a hack to find the actual last used pd */
- int used_pd = ppgtt->num_pd_entries / I915_PDES_PER_PD;
-
- for (i = used_pd - 1; i >= 0; i--) {
- dma_addr_t addr = ppgtt->pdp.pagedirs[i]->daddr;
- ret = gen8_write_pdp(ring, i, addr);
+ for (i = GEN8_LEGACY_PDPES - 1; i >= 0; i--) {
+ struct i915_pagedir *pd = ppgtt->pdp.pagedirs[i];
+ dma_addr_t pd_daddr = pd ? pd->daddr : ppgtt->scratch_pd->daddr;
+ /* The page directory might be NULL, but we need to clear out
+ * whatever the previous context might have used. */
+ ret = gen8_write_pdp(ring, i, pd_daddr);
if (ret)
return ret;
}
@@ -678,10 +679,16 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt, uint64_t size)
ppgtt->base.start = 0;
ppgtt->base.total = size;
+ ppgtt->scratch_pd = alloc_pt_scratch(ppgtt->base.dev);
+ if (IS_ERR(ppgtt->scratch_pd))
+ return PTR_ERR(ppgtt->scratch_pd);
+
/* 1. Do all our allocations for page directories and page tables. */
ret = gen8_ppgtt_alloc(ppgtt, ppgtt->base.start, ppgtt->base.total);
- if (ret)
+ if (ret) {
+ free_pt_scratch(ppgtt->scratch_pd, ppgtt->base.dev);
return ret;
+ }
/*
* 2. Map all the page directory entires to point to the page tables
@@ -270,7 +270,10 @@ struct i915_hw_ppgtt {
struct i915_pagedir pd;
};
- struct i915_pagetab *scratch_pt;
+ union {
+ struct i915_pagetab *scratch_pt;
+ struct i915_pagetab *scratch_pd; /* Just need the daddr */
+ };
struct drm_i915_file_private *file_priv;