drm/i915: suspend/resume GEM when KMS is active

In the KMS case, we need to suspend/resume GEM as well. So on suspend, make
sure we idle GEM and stop any new rendering from coming in, and on resume,
re-init the framebuffer and clear the suspended flag.

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>

authored by Jesse Barnes and committed by Dave Airlie 5669fcac efbeed96

+24 -2
+22 -1
drivers/gpu/drm/i915/i915_drv.c
··· 27 27 * 28 28 */ 29 29 30 + #include <linux/device.h> 30 31 #include "drmP.h" 31 32 #include "drm.h" 32 33 #include "i915_drm.h" ··· 67 66 68 67 i915_save_state(dev); 69 68 69 + /* If KMS is active, we do the leavevt stuff here */ 70 + if (drm_core_check_feature(dev, DRIVER_MODESET) && i915_gem_idle(dev)) { 71 + dev_err(&dev->pdev->dev, "GEM idle failed, aborting suspend\n"); 72 + return -EBUSY; 73 + } 74 + 70 75 intel_opregion_free(dev); 71 76 72 77 if (state.event == PM_EVENT_SUSPEND) { ··· 86 79 87 80 static int i915_resume(struct drm_device *dev) 88 81 { 82 + struct drm_i915_private *dev_priv = dev->dev_private; 83 + int ret = 0; 84 + 89 85 pci_set_power_state(dev->pdev, PCI_D0); 90 86 pci_restore_state(dev->pdev); 91 87 if (pci_enable_device(dev->pdev)) ··· 99 89 100 90 intel_opregion_init(dev); 101 91 102 - return 0; 92 + /* KMS EnterVT equivalent */ 93 + if (drm_core_check_feature(dev, DRIVER_MODESET)) { 94 + mutex_lock(&dev->struct_mutex); 95 + dev_priv->mm.suspended = 0; 96 + 97 + ret = i915_gem_init_ringbuffer(dev); 98 + if (ret != 0) 99 + ret = -1; 100 + mutex_unlock(&dev->struct_mutex); 101 + } 102 + 103 + return ret; 103 104 } 104 105 105 106 static struct vm_operations_struct i915_gem_vm_ops = {
+1
drivers/gpu/drm/i915/i915_drv.h
··· 618 618 void i915_gem_cleanup_ringbuffer(struct drm_device *dev); 619 619 int i915_gem_do_init(struct drm_device *dev, unsigned long start, 620 620 unsigned long end); 621 + int i915_gem_idle(struct drm_device *dev); 621 622 int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); 622 623 int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, 623 624 int write);
+1 -1
drivers/gpu/drm/i915/i915_gem.c
··· 2973 2973 return 0; 2974 2974 } 2975 2975 2976 - static int 2976 + int 2977 2977 i915_gem_idle(struct drm_device *dev) 2978 2978 { 2979 2979 drm_i915_private_t *dev_priv = dev->dev_private;