From 6c41e5381fb8ea890943b6679fe6ae7ac4cfea4d Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 20 Feb 2008 10:02:20 +1000 Subject: drm: add support for passing state into the suspend hooks. fix i915 driver to use state for hibernate save avoidance. Signed-off-by: Dave Airlie --- linux-core/drmP.h | 2 +- linux-core/drm_sysfs.c | 2 +- linux-core/i915_drv.c | 13 +++++++++---- 3 files changed, 11 insertions(+), 6 deletions(-) (limited to 'linux-core') diff --git a/linux-core/drmP.h b/linux-core/drmP.h index 33f3649e..f196e11d 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -617,7 +617,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_sysfs.c b/linux-core/drm_sysfs.c index 3aaac11b..c02e2049 100644 --- a/linux-core/drm_sysfs.c +++ b/linux-core/drm_sysfs.c @@ -36,7 +36,7 @@ static int drm_sysfs_suspend(struct device *dev, pm_message_t state) printk(KERN_ERR "%s\n", __FUNCTION__); 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 9d8b4685..cfcb62ed 100644 --- a/linux-core/i915_drv.c +++ b/linux-core/i915_drv.c @@ -263,7 +263,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; @@ -274,6 +274,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); @@ -388,9 +391,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; } -- cgit v1.2.3 From 374b41e5bcdb5c22471c8c16dd794ac54c4f76d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Thu, 21 Feb 2008 11:49:38 +0100 Subject: linux: Clean up vblank related resources from drm_irq_uninstall(). This fixes at least two problems: * The vblank_disable_fn timer callback could get called after the DRM was de-initialized, e.g. on X server shutdown. * Leak of vblank related resources when disabling and re-enabling the IRQ, e.g. on an X server reset. --- linux-core/drm_irq.c | 49 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 16 deletions(-) (limited to 'linux-core') diff --git a/linux-core/drm_irq.c b/linux-core/drm_irq.c index e4940bb7..1a035657 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; -- cgit v1.2.3