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 * 28 */ 29 30 #include "drmP.h" 31 #include "drm.h" 32 #include "i915_drm.h" ··· 67 68 i915_save_state(dev); 69 70 intel_opregion_free(dev); 71 72 if (state.event == PM_EVENT_SUSPEND) { ··· 86 87 static int i915_resume(struct drm_device *dev) 88 { 89 pci_set_power_state(dev->pdev, PCI_D0); 90 pci_restore_state(dev->pdev); 91 if (pci_enable_device(dev->pdev)) ··· 99 100 intel_opregion_init(dev); 101 102 - return 0; 103 } 104 105 static struct vm_operations_struct i915_gem_vm_ops = {
··· 27 * 28 */ 29 30 + #include <linux/device.h> 31 #include "drmP.h" 32 #include "drm.h" 33 #include "i915_drm.h" ··· 66 67 i915_save_state(dev); 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 + 75 intel_opregion_free(dev); 76 77 if (state.event == PM_EVENT_SUSPEND) { ··· 79 80 static int i915_resume(struct drm_device *dev) 81 { 82 + struct drm_i915_private *dev_priv = dev->dev_private; 83 + int ret = 0; 84 + 85 pci_set_power_state(dev->pdev, PCI_D0); 86 pci_restore_state(dev->pdev); 87 if (pci_enable_device(dev->pdev)) ··· 89 90 intel_opregion_init(dev); 91 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; 104 } 105 106 static struct vm_operations_struct i915_gem_vm_ops = {
+1
drivers/gpu/drm/i915/i915_drv.h
··· 618 void i915_gem_cleanup_ringbuffer(struct drm_device *dev); 619 int i915_gem_do_init(struct drm_device *dev, unsigned long start, 620 unsigned long end); 621 int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); 622 int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, 623 int write);
··· 618 void i915_gem_cleanup_ringbuffer(struct drm_device *dev); 619 int i915_gem_do_init(struct drm_device *dev, unsigned long start, 620 unsigned long end); 621 + int i915_gem_idle(struct drm_device *dev); 622 int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); 623 int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, 624 int write);
+1 -1
drivers/gpu/drm/i915/i915_gem.c
··· 2973 return 0; 2974 } 2975 2976 - static int 2977 i915_gem_idle(struct drm_device *dev) 2978 { 2979 drm_i915_private_t *dev_priv = dev->dev_private;
··· 2973 return 0; 2974 } 2975 2976 + int 2977 i915_gem_idle(struct drm_device *dev) 2978 { 2979 drm_i915_private_t *dev_priv = dev->dev_private;