summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--linux-core/drmP.h2
-rw-r--r--linux-core/drm_irq.c49
-rw-r--r--linux-core/drm_sysfs.c2
-rw-r--r--linux-core/i915_drv.c13
4 files changed, 44 insertions, 22 deletions
diff --git a/linux-core/drmP.h b/linux-core/drmP.h
index 297d8d60..0f42d5b6 100644
--- a/linux-core/drmP.h
+++ b/linux-core/drmP.h
@@ -647,7 +647,7 @@ struct drm_driver {
void (*postclose) (struct drm_device *, struct drm_file *);
void (*lastclose) (struct drm_device *);
int (*unload) (struct drm_device *);
- int (*suspend) (struct drm_device *);
+ int (*suspend) (struct drm_device *, pm_message_t state);
int (*resume) (struct drm_device *);
int (*dma_ioctl) (struct drm_device *dev, void *data, struct drm_file *file_priv);
void (*dma_ready) (struct drm_device *);
diff --git a/linux-core/drm_irq.c b/linux-core/drm_irq.c
index cb279bcd..9df4ed24 100644
--- a/linux-core/drm_irq.c
+++ b/linux-core/drm_irq.c
@@ -88,6 +88,36 @@ static void vblank_disable_fn(unsigned long arg)
}
}
+static void drm_vblank_cleanup(struct drm_device *dev)
+{
+ /* Bail if the driver didn't call drm_vblank_init() */
+ if (dev->num_crtcs == 0)
+ return;
+
+ del_timer(&dev->vblank_disable_timer);
+
+ vblank_disable_fn((unsigned long)dev);
+
+ drm_free(dev->vbl_queue, sizeof(*dev->vbl_queue) * dev->num_crtcs,
+ DRM_MEM_DRIVER);
+ drm_free(dev->vbl_sigs, sizeof(*dev->vbl_sigs) * dev->num_crtcs,
+ DRM_MEM_DRIVER);
+ drm_free(dev->_vblank_count, sizeof(*dev->_vblank_count) *
+ dev->num_crtcs, DRM_MEM_DRIVER);
+ drm_free(dev->vblank_refcount, sizeof(*dev->vblank_refcount) *
+ dev->num_crtcs, DRM_MEM_DRIVER);
+ drm_free(dev->vblank_enabled, sizeof(*dev->vblank_enabled) *
+ dev->num_crtcs, DRM_MEM_DRIVER);
+ drm_free(dev->last_vblank, sizeof(*dev->last_vblank) * dev->num_crtcs,
+ DRM_MEM_DRIVER);
+ drm_free(dev->vblank_premodeset, sizeof(*dev->vblank_premodeset) *
+ dev->num_crtcs, DRM_MEM_DRIVER);
+ drm_free(dev->vblank_offset, sizeof(*dev->vblank_offset) * dev->num_crtcs,
+ DRM_MEM_DRIVER);
+
+ dev->num_crtcs = 0;
+}
+
int drm_vblank_init(struct drm_device *dev, int num_crtcs)
{
int i, ret = -ENOMEM;
@@ -147,22 +177,7 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs)
return 0;
err:
- drm_free(dev->vbl_queue, sizeof(*dev->vbl_queue) * num_crtcs,
- DRM_MEM_DRIVER);
- drm_free(dev->vbl_sigs, sizeof(*dev->vbl_sigs) * num_crtcs,
- DRM_MEM_DRIVER);
- drm_free(dev->_vblank_count, sizeof(*dev->_vblank_count) * num_crtcs,
- DRM_MEM_DRIVER);
- drm_free(dev->vblank_refcount, sizeof(*dev->vblank_refcount) *
- num_crtcs, DRM_MEM_DRIVER);
- drm_free(dev->vblank_enabled, sizeof(*dev->vblank_enabled) * num_crtcs,
- DRM_MEM_DRIVER);
- drm_free(dev->last_vblank, sizeof(*dev->last_vblank) * num_crtcs,
- DRM_MEM_DRIVER);
- drm_free(dev->vblank_premodeset, sizeof(*dev->vblank_premodeset) *
- num_crtcs, DRM_MEM_DRIVER);
- drm_free(dev->vblank_offset, sizeof(*dev->vblank_offset) * num_crtcs,
- DRM_MEM_DRIVER);
+ drm_vblank_cleanup(dev);
return ret;
}
EXPORT_SYMBOL(drm_vblank_init);
@@ -258,6 +273,8 @@ int drm_irq_uninstall(struct drm_device * dev)
dev->driver->irq_uninstall(dev);
+ drm_vblank_cleanup(dev);
+
free_irq(dev->irq, dev);
dev->locked_tasklet_func = NULL;
diff --git a/linux-core/drm_sysfs.c b/linux-core/drm_sysfs.c
index f03e5d4e..3372a713 100644
--- a/linux-core/drm_sysfs.c
+++ b/linux-core/drm_sysfs.c
@@ -38,7 +38,7 @@ static int drm_sysfs_suspend(struct device *dev, pm_message_t state)
if (drm_minor->type == DRM_MINOR_CONTROL)
if (drm_dev->driver->suspend)
- return drm_dev->driver->suspend(drm_dev);
+ return drm_dev->driver->suspend(drm_dev, state);
return 0;
}
diff --git a/linux-core/i915_drv.c b/linux-core/i915_drv.c
index 64c805f5..0123d412 100644
--- a/linux-core/i915_drv.c
+++ b/linux-core/i915_drv.c
@@ -264,7 +264,7 @@ static void i915_restore_vga(struct drm_device *dev)
}
-static int i915_suspend(struct drm_device *dev)
+static int i915_suspend(struct drm_device *dev, pm_message_t state)
{
struct drm_i915_private *dev_priv = dev->dev_private;
int i;
@@ -275,6 +275,9 @@ static int i915_suspend(struct drm_device *dev)
return -ENODEV;
}
+ if (state.event == PM_EVENT_PRETHAW)
+ return 0;
+
pci_save_state(dev->pdev);
pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB);
@@ -389,9 +392,11 @@ static int i915_suspend(struct drm_device *dev)
i915_save_vga(dev);
- /* Shut down the device */
- pci_disable_device(dev->pdev);
- pci_set_power_state(dev->pdev, PCI_D3hot);
+ if (state.event == PM_EVENT_SUSPEND) {
+ /* Shut down the device */
+ pci_disable_device(dev->pdev);
+ pci_set_power_state(dev->pdev, PCI_D3hot);
+ }
return 0;
}