drm/i915: suspend/resume GEM when KMS is active
authorJesse Barnes <jbarnes@virtuousgeek.org>
Tue, 17 Feb 2009 23:13:31 +0000 (15:13 -0800)
committerDave Airlie <airlied@redhat.com>
Mon, 23 Feb 2009 00:06:23 +0000 (10:06 +1000)
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>
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c

index a31cbdbc3c546ff96a916f93326e5cffcfc4dbfc..0692622ee2b3dc3d75e47c086a344b1e0fd8bb3b 100644 (file)
@@ -27,6 +27,7 @@
  *
  */
 
+#include <linux/device.h>
 #include "drmP.h"
 #include "drm.h"
 #include "i915_drm.h"
@@ -66,6 +67,12 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state)
 
        i915_save_state(dev);
 
+       /* If KMS is active, we do the leavevt stuff here */
+       if (drm_core_check_feature(dev, DRIVER_MODESET) && i915_gem_idle(dev)) {
+               dev_err(&dev->pdev->dev, "GEM idle failed, aborting suspend\n");
+               return -EBUSY;
+       }
+
        intel_opregion_free(dev);
 
        if (state.event == PM_EVENT_SUSPEND) {
@@ -79,6 +86,9 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state)
 
 static int i915_resume(struct drm_device *dev)
 {
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int ret = 0;
+
        pci_set_power_state(dev->pdev, PCI_D0);
        pci_restore_state(dev->pdev);
        if (pci_enable_device(dev->pdev))
@@ -89,7 +99,18 @@ static int i915_resume(struct drm_device *dev)
 
        intel_opregion_init(dev);
 
-       return 0;
+       /* KMS EnterVT equivalent */
+       if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+               mutex_lock(&dev->struct_mutex);
+               dev_priv->mm.suspended = 0;
+
+               ret = i915_gem_init_ringbuffer(dev);
+               if (ret != 0)
+                       ret = -1;
+               mutex_unlock(&dev->struct_mutex);
+       }
+
+       return ret;
 }
 
 static struct vm_operations_struct i915_gem_vm_ops = {
index 135a08f615cd066802f9888cfe860239e05c3984..17fa40858d26147b5ae6ca041adb5984c05ac06a 100644 (file)
@@ -618,6 +618,7 @@ int i915_gem_init_ringbuffer(struct drm_device *dev);
 void i915_gem_cleanup_ringbuffer(struct drm_device *dev);
 int i915_gem_do_init(struct drm_device *dev, unsigned long start,
                     unsigned long end);
+int i915_gem_idle(struct drm_device *dev);
 int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
 int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj,
                                      int write);
index 0f50574076b195b68188796d41e8f3e643553dc5..58c789da95a312410e9a7ad47ac7270704ae218a 100644 (file)
@@ -2973,7 +2973,7 @@ i915_gem_evict_from_list(struct drm_device *dev, struct list_head *head)
        return 0;
 }
 
-static int
+int
 i915_gem_idle(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;