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>

authored by Chris Wilson and committed by Daniel Vetter 19b2dbde 7d132055

+8 -17
+2
drivers/gpu/drm/i915/i915_drv.h
··· 1697 struct dma_buf *i915_gem_prime_export(struct drm_device *dev, 1698 struct drm_gem_object *gem_obj, int flags); 1699 1700 /* i915_gem_context.c */ 1701 void i915_gem_context_init(struct drm_device *dev); 1702 void i915_gem_context_fini(struct drm_device *dev);
··· 1697 struct dma_buf *i915_gem_prime_export(struct drm_device *dev, 1698 struct drm_gem_object *gem_obj, int flags); 1699 1700 + void i915_gem_restore_fences(struct drm_device *dev); 1701 + 1702 /* i915_gem_context.c */ 1703 void i915_gem_context_init(struct drm_device *dev); 1704 void i915_gem_context_fini(struct drm_device *dev);
+5 -17
drivers/gpu/drm/i915/i915_gem.c
··· 2117 } 2118 } 2119 2120 - static void i915_gem_reset_fences(struct drm_device *dev) 2121 { 2122 struct drm_i915_private *dev_priv = dev->dev_private; 2123 int i; 2124 2125 for (i = 0; i < dev_priv->num_fence_regs; i++) { 2126 struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[i]; 2127 - 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 } 2137 - 2138 - INIT_LIST_HEAD(&dev_priv->mm.fence_list); 2139 } 2140 2141 void i915_gem_reset(struct drm_device *dev) ··· 2148 obj->base.read_domains &= ~I915_GEM_GPU_DOMAINS; 2149 } 2150 2151 - /* The fence registers are invalidated so clear them out */ 2152 - i915_gem_reset_fences(dev); 2153 } 2154 2155 /** ··· 3854 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 3855 i915_gem_evict_everything(dev); 3856 3857 - i915_gem_reset_fences(dev); 3858 - 3859 /* Hack! Don't let anybody do execbuf while we don't control the chip. 3860 * We need to replace this with a semaphore, or something. 3861 * And not confound mm.suspended! ··· 4180 dev_priv->num_fence_regs = 8; 4181 4182 /* Initialize fence registers to zero */ 4183 - i915_gem_reset_fences(dev); 4184 4185 i915_gem_detect_bit_6_swizzle(dev); 4186 init_waitqueue_head(&dev_priv->pending_flip_queue);
··· 2117 } 2118 } 2119 2120 + void i915_gem_restore_fences(struct drm_device *dev) 2121 { 2122 struct drm_i915_private *dev_priv = dev->dev_private; 2123 int i; 2124 2125 for (i = 0; i < dev_priv->num_fence_regs; i++) { 2126 struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[i]; 2127 + i915_gem_write_fence(dev, i, reg->obj); 2128 } 2129 } 2130 2131 void i915_gem_reset(struct drm_device *dev) ··· 2158 obj->base.read_domains &= ~I915_GEM_GPU_DOMAINS; 2159 } 2160 2161 + i915_gem_restore_fences(dev); 2162 } 2163 2164 /** ··· 3865 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 3866 i915_gem_evict_everything(dev); 3867 3868 /* Hack! Don't let anybody do execbuf while we don't control the chip. 3869 * We need to replace this with a semaphore, or something. 3870 * And not confound mm.suspended! ··· 4193 dev_priv->num_fence_regs = 8; 4194 4195 /* Initialize fence registers to zero */ 4196 + INIT_LIST_HEAD(&dev_priv->mm.fence_list); 4197 + i915_gem_restore_fences(dev); 4198 4199 i915_gem_detect_bit_6_swizzle(dev); 4200 init_waitqueue_head(&dev_priv->pending_flip_queue);
+1
drivers/gpu/drm/i915/i915_suspend.c
··· 384 385 mutex_lock(&dev->struct_mutex); 386 387 i915_restore_display(dev); 388 389 if (!drm_core_check_feature(dev, DRIVER_MODESET)) {
··· 384 385 mutex_lock(&dev->struct_mutex); 386 387 + i915_gem_restore_fences(dev); 388 i915_restore_display(dev); 389 390 if (!drm_core_check_feature(dev, DRIVER_MODESET)) {