Commit 55a254ac authored by Daniel Vetter's avatar Daniel Vetter

drm/i915: properly restore the ppgtt page directory on resume

The ppgtt page directory lives in a snatched part of the gtt pte
range. Which naturally gets cleared on hibernate when we pull the
power. Suspend to ram (which is what I've tested) works because
despite the fact that this is a mmio region, it is actually back by
system ram.

Fix this by moving the page directory setup code to the ppgtt init
code (which gets called on resume).

This fixes hibernate on my ivb and snb.
Reviewed-by: default avatarBen Widawsky <ben@bwidawsk.net>
Signed-Off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent f47166d2
...@@ -3754,12 +3754,32 @@ void i915_gem_init_ppgtt(struct drm_device *dev) ...@@ -3754,12 +3754,32 @@ void i915_gem_init_ppgtt(struct drm_device *dev)
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
uint32_t pd_offset; uint32_t pd_offset;
struct intel_ring_buffer *ring; struct intel_ring_buffer *ring;
struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
uint32_t __iomem *pd_addr;
uint32_t pd_entry;
int i; int i;
if (!dev_priv->mm.aliasing_ppgtt) if (!dev_priv->mm.aliasing_ppgtt)
return; return;
pd_offset = dev_priv->mm.aliasing_ppgtt->pd_offset;
pd_addr = dev_priv->mm.gtt->gtt + ppgtt->pd_offset/sizeof(uint32_t);
for (i = 0; i < ppgtt->num_pd_entries; i++) {
dma_addr_t pt_addr;
if (dev_priv->mm.gtt->needs_dmar)
pt_addr = ppgtt->pt_dma_addr[i];
else
pt_addr = page_to_phys(ppgtt->pt_pages[i]);
pd_entry = GEN6_PDE_ADDR_ENCODE(pt_addr);
pd_entry |= GEN6_PDE_VALID;
writel(pd_entry, pd_addr + i);
}
readl(pd_addr);
pd_offset = ppgtt->pd_offset;
pd_offset /= 64; /* in cachelines, */ pd_offset /= 64; /* in cachelines, */
pd_offset <<= 16; pd_offset <<= 16;
......
...@@ -65,9 +65,7 @@ int i915_gem_init_aliasing_ppgtt(struct drm_device *dev) ...@@ -65,9 +65,7 @@ int i915_gem_init_aliasing_ppgtt(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct i915_hw_ppgtt *ppgtt; struct i915_hw_ppgtt *ppgtt;
uint32_t pd_entry;
unsigned first_pd_entry_in_global_pt; unsigned first_pd_entry_in_global_pt;
uint32_t __iomem *pd_addr;
int i; int i;
int ret = -ENOMEM; int ret = -ENOMEM;
...@@ -100,7 +98,6 @@ int i915_gem_init_aliasing_ppgtt(struct drm_device *dev) ...@@ -100,7 +98,6 @@ int i915_gem_init_aliasing_ppgtt(struct drm_device *dev)
goto err_pt_alloc; goto err_pt_alloc;
} }
pd_addr = dev_priv->mm.gtt->gtt + first_pd_entry_in_global_pt;
for (i = 0; i < ppgtt->num_pd_entries; i++) { for (i = 0; i < ppgtt->num_pd_entries; i++) {
dma_addr_t pt_addr; dma_addr_t pt_addr;
if (dev_priv->mm.gtt->needs_dmar) { if (dev_priv->mm.gtt->needs_dmar) {
...@@ -117,13 +114,7 @@ int i915_gem_init_aliasing_ppgtt(struct drm_device *dev) ...@@ -117,13 +114,7 @@ int i915_gem_init_aliasing_ppgtt(struct drm_device *dev)
ppgtt->pt_dma_addr[i] = pt_addr; ppgtt->pt_dma_addr[i] = pt_addr;
} else } else
pt_addr = page_to_phys(ppgtt->pt_pages[i]); pt_addr = page_to_phys(ppgtt->pt_pages[i]);
pd_entry = GEN6_PDE_ADDR_ENCODE(pt_addr);
pd_entry |= GEN6_PDE_VALID;
writel(pd_entry, pd_addr + i);
} }
readl(pd_addr);
ppgtt->scratch_page_dma_addr = dev_priv->mm.gtt->scratch_page_dma; ppgtt->scratch_page_dma_addr = dev_priv->mm.gtt->scratch_page_dma;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment