aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2013-06-12 05:15:12 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-06-15 19:10:45 -0400
commit19b2dbde5732170a03bd82cc8bd442cf88d856f7 (patch)
tree2c3da40ef05cb5b8a48945b877600e39a5d40ca5 /drivers
parent7d132055814ef17a6c7b69f342244c410a5e000f (diff)
drm/i915: Restore fences after resume and GPU resets
Stéphane Marchesin found that fences for pinned objects (i.e. the scanout) were not being restored upon resume, leading to corruption on the display and reference counting issues. This is due to a bug in commit 312817a39f17dbb4de000165b5b724e3728cd91c [2.6.38] Author: Chris Wilson <chris@chris-wilson.co.uk> Date: Mon Nov 22 11:50:11 2010 +0000 drm/i915: Only save and restore fences for UMS that zapped the pinned fences even though they were in use. Fortuitously, whilst we forced a VT switch during suspend and resume, no fences were ever pinned at the time. However, we now can do switchless S3 transitions and so the old bug finally surfaces. Reported-by: Stéphane Marchesin <marcheu@chromium.org> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Stéphane Marchesin <marcheu@chromium.org> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h2
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c22
-rw-r--r--drivers/gpu/drm/i915/i915_suspend.c1
3 files changed, 8 insertions, 17 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index b9d00dcf9a2d..9669a0b8b440 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1697,6 +1697,8 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev,
1697struct dma_buf *i915_gem_prime_export(struct drm_device *dev, 1697struct dma_buf *i915_gem_prime_export(struct drm_device *dev,
1698 struct drm_gem_object *gem_obj, int flags); 1698 struct drm_gem_object *gem_obj, int flags);
1699 1699
1700void i915_gem_restore_fences(struct drm_device *dev);
1701
1700/* i915_gem_context.c */ 1702/* i915_gem_context.c */
1701void i915_gem_context_init(struct drm_device *dev); 1703void i915_gem_context_init(struct drm_device *dev);
1702void i915_gem_context_fini(struct drm_device *dev); 1704void i915_gem_context_fini(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 970ad17c99ab..a06974127f22 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2117,25 +2117,15 @@ static void i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv,
2117 } 2117 }
2118} 2118}
2119 2119
2120static void i915_gem_reset_fences(struct drm_device *dev) 2120void i915_gem_restore_fences(struct drm_device *dev)
2121{ 2121{
2122 struct drm_i915_private *dev_priv = dev->dev_private; 2122 struct drm_i915_private *dev_priv = dev->dev_private;
2123 int i; 2123 int i;
2124 2124
2125 for (i = 0; i < dev_priv->num_fence_regs; i++) { 2125 for (i = 0; i < dev_priv->num_fence_regs; i++) {
2126 struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[i]; 2126 struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[i];
2127 2127 i915_gem_write_fence(dev, i, reg->obj);
2128 if (reg->obj)
2129 i915_gem_object_fence_lost(reg->obj);
2130
2131 i915_gem_write_fence(dev, i, NULL);
2132
2133 reg->pin_count = 0;
2134 reg->obj = NULL;
2135 INIT_LIST_HEAD(&reg->lru_list);
2136 } 2128 }
2137
2138 INIT_LIST_HEAD(&dev_priv->mm.fence_list);
2139} 2129}
2140 2130
2141void i915_gem_reset(struct drm_device *dev) 2131void i915_gem_reset(struct drm_device *dev)
@@ -2158,8 +2148,7 @@ void i915_gem_reset(struct drm_device *dev)
2158 obj->base.read_domains &= ~I915_GEM_GPU_DOMAINS; 2148 obj->base.read_domains &= ~I915_GEM_GPU_DOMAINS;
2159 } 2149 }
2160 2150
2161 /* The fence registers are invalidated so clear them out */ 2151 i915_gem_restore_fences(dev);
2162 i915_gem_reset_fences(dev);
2163} 2152}
2164 2153
2165/** 2154/**
@@ -3865,8 +3854,6 @@ i915_gem_idle(struct drm_device *dev)
3865 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 3854 if (!drm_core_check_feature(dev, DRIVER_MODESET))
3866 i915_gem_evict_everything(dev); 3855 i915_gem_evict_everything(dev);
3867 3856
3868 i915_gem_reset_fences(dev);
3869
3870 /* Hack! Don't let anybody do execbuf while we don't control the chip. 3857 /* Hack! Don't let anybody do execbuf while we don't control the chip.
3871 * We need to replace this with a semaphore, or something. 3858 * We need to replace this with a semaphore, or something.
3872 * And not confound mm.suspended! 3859 * And not confound mm.suspended!
@@ -4193,7 +4180,8 @@ i915_gem_load(struct drm_device *dev)
4193 dev_priv->num_fence_regs = 8; 4180 dev_priv->num_fence_regs = 8;
4194 4181
4195 /* Initialize fence registers to zero */ 4182 /* Initialize fence registers to zero */
4196 i915_gem_reset_fences(dev); 4183 INIT_LIST_HEAD(&dev_priv->mm.fence_list);
4184 i915_gem_restore_fences(dev);
4197 4185
4198 i915_gem_detect_bit_6_swizzle(dev); 4186 i915_gem_detect_bit_6_swizzle(dev);
4199 init_waitqueue_head(&dev_priv->pending_flip_queue); 4187 init_waitqueue_head(&dev_priv->pending_flip_queue);
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c
index 41f0fdecfbdc..369b3d8776ab 100644
--- a/drivers/gpu/drm/i915/i915_suspend.c
+++ b/drivers/gpu/drm/i915/i915_suspend.c
@@ -384,6 +384,7 @@ int i915_restore_state(struct drm_device *dev)
384 384
385 mutex_lock(&dev->struct_mutex); 385 mutex_lock(&dev->struct_mutex);
386 386
387 i915_gem_restore_fences(dev);
387 i915_restore_display(dev); 388 i915_restore_display(dev);
388 389
389 if (!drm_core_check_feature(dev, DRIVER_MODESET)) { 390 if (!drm_core_check_feature(dev, DRIVER_MODESET)) {