aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/drm/i915_dma.c
diff options
context:
space:
mode:
authorJesse Barnes <jesse.barnes@intel.com>2007-11-21 23:14:14 -0500
committerDave Airlie <airlied@redhat.com>2008-02-07 00:09:38 -0500
commitba8bbcf6ff4650712f64c0ef61139c73898e2165 (patch)
treebd82043d355bdb060ec8291992bca912880f780a /drivers/char/drm/i915_dma.c
parente8b962b6df50b74afed14af7f7a7d569b3ba70ac (diff)
i915: add suspend/resume support
Add suspend/resume support to the i915 driver. Moves some of the initialization into the driver load routine, and fixes up places where we assumed no dev_private existed in some of the cleanup paths. This allows us to suspend/resume properly even if X isn't running. Signed-off-by: Dave Airlie <airlied@linux.ie>
Diffstat (limited to 'drivers/char/drm/i915_dma.c')
-rw-r--r--drivers/char/drm/i915_dma.c113
1 files changed, 57 insertions, 56 deletions
diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c
index 842db3233e9e..b8db9652e9dd 100644
--- a/drivers/char/drm/i915_dma.c
+++ b/drivers/char/drm/i915_dma.c
@@ -31,17 +31,6 @@
31#include "i915_drm.h" 31#include "i915_drm.h"
32#include "i915_drv.h" 32#include "i915_drv.h"
33 33
34#define IS_I965G(dev) (dev->pci_device == 0x2972 || \
35 dev->pci_device == 0x2982 || \
36 dev->pci_device == 0x2992 || \
37 dev->pci_device == 0x29A2 || \
38 dev->pci_device == 0x2A02 || \
39 dev->pci_device == 0x2A12)
40
41#define IS_G33(dev) (dev->pci_device == 0x29b2 || \
42 dev->pci_device == 0x29c2 || \
43 dev->pci_device == 0x29d2)
44
45/* Really want an OS-independent resettable timer. Would like to have 34/* Really want an OS-independent resettable timer. Would like to have
46 * this loop run for (eg) 3 sec, but have the timer reset every time 35 * this loop run for (eg) 3 sec, but have the timer reset every time
47 * the head pointer changes, so that EBUSY only happens if the ring 36 * the head pointer changes, so that EBUSY only happens if the ring
@@ -90,6 +79,7 @@ void i915_kernel_lost_context(struct drm_device * dev)
90 79
91static int i915_dma_cleanup(struct drm_device * dev) 80static int i915_dma_cleanup(struct drm_device * dev)
92{ 81{
82 drm_i915_private_t *dev_priv = dev->dev_private;
93 /* Make sure interrupts are disabled here because the uninstall ioctl 83 /* Make sure interrupts are disabled here because the uninstall ioctl
94 * may not have been called from userspace and after dev_private 84 * may not have been called from userspace and after dev_private
95 * is freed, it's too late. 85 * is freed, it's too late.
@@ -97,52 +87,42 @@ static int i915_dma_cleanup(struct drm_device * dev)
97 if (dev->irq) 87 if (dev->irq)
98 drm_irq_uninstall(dev); 88 drm_irq_uninstall(dev);
99 89
100 if (dev->dev_private) { 90 if (dev_priv->ring.virtual_start) {
101 drm_i915_private_t *dev_priv = 91 drm_core_ioremapfree(&dev_priv->ring.map, dev);
102 (drm_i915_private_t *) dev->dev_private; 92 dev_priv->ring.virtual_start = 0;
103 93 dev_priv->ring.map.handle = 0;
104 if (dev_priv->ring.virtual_start) { 94 dev_priv->ring.map.size = 0;
105 drm_core_ioremapfree(&dev_priv->ring.map, dev); 95 }
106 }
107
108 if (dev_priv->status_page_dmah) {
109 drm_pci_free(dev, dev_priv->status_page_dmah);
110 /* Need to rewrite hardware status page */
111 I915_WRITE(0x02080, 0x1ffff000);
112 }
113
114 if (dev_priv->status_gfx_addr) {
115 dev_priv->status_gfx_addr = 0;
116 drm_core_ioremapfree(&dev_priv->hws_map, dev);
117 I915_WRITE(0x2080, 0x1ffff000);
118 }
119 96
120 drm_free(dev->dev_private, sizeof(drm_i915_private_t), 97 if (dev_priv->status_page_dmah) {
121 DRM_MEM_DRIVER); 98 drm_pci_free(dev, dev_priv->status_page_dmah);
99 dev_priv->status_page_dmah = NULL;
100 /* Need to rewrite hardware status page */
101 I915_WRITE(0x02080, 0x1ffff000);
102 }
122 103
123 dev->dev_private = NULL; 104 if (dev_priv->status_gfx_addr) {
105 dev_priv->status_gfx_addr = 0;
106 drm_core_ioremapfree(&dev_priv->hws_map, dev);
107 I915_WRITE(0x2080, 0x1ffff000);
124 } 108 }
125 109
126 return 0; 110 return 0;
127} 111}
128 112
129static int i915_initialize(struct drm_device * dev, 113static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
130 drm_i915_private_t * dev_priv,
131 drm_i915_init_t * init)
132{ 114{
133 memset(dev_priv, 0, sizeof(drm_i915_private_t)); 115 drm_i915_private_t *dev_priv = dev->dev_private;
134 116
135 dev_priv->sarea = drm_getsarea(dev); 117 dev_priv->sarea = drm_getsarea(dev);
136 if (!dev_priv->sarea) { 118 if (!dev_priv->sarea) {
137 DRM_ERROR("can not find sarea!\n"); 119 DRM_ERROR("can not find sarea!\n");
138 dev->dev_private = (void *)dev_priv;
139 i915_dma_cleanup(dev); 120 i915_dma_cleanup(dev);
140 return -EINVAL; 121 return -EINVAL;
141 } 122 }
142 123
143 dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset); 124 dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
144 if (!dev_priv->mmio_map) { 125 if (!dev_priv->mmio_map) {
145 dev->dev_private = (void *)dev_priv;
146 i915_dma_cleanup(dev); 126 i915_dma_cleanup(dev);
147 DRM_ERROR("can not find mmio map!\n"); 127 DRM_ERROR("can not find mmio map!\n");
148 return -EINVAL; 128 return -EINVAL;
@@ -165,7 +145,6 @@ static int i915_initialize(struct drm_device * dev,
165 drm_core_ioremap(&dev_priv->ring.map, dev); 145 drm_core_ioremap(&dev_priv->ring.map, dev);
166 146
167 if (dev_priv->ring.map.handle == NULL) { 147 if (dev_priv->ring.map.handle == NULL) {
168 dev->dev_private = (void *)dev_priv;
169 i915_dma_cleanup(dev); 148 i915_dma_cleanup(dev);
170 DRM_ERROR("can not ioremap virtual address for" 149 DRM_ERROR("can not ioremap virtual address for"
171 " ring buffer\n"); 150 " ring buffer\n");
@@ -197,7 +176,6 @@ static int i915_initialize(struct drm_device * dev,
197 drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff); 176 drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff);
198 177
199 if (!dev_priv->status_page_dmah) { 178 if (!dev_priv->status_page_dmah) {
200 dev->dev_private = (void *)dev_priv;
201 i915_dma_cleanup(dev); 179 i915_dma_cleanup(dev);
202 DRM_ERROR("Can not allocate hardware status page\n"); 180 DRM_ERROR("Can not allocate hardware status page\n");
203 return -ENOMEM; 181 return -ENOMEM;
@@ -209,7 +187,6 @@ static int i915_initialize(struct drm_device * dev,
209 I915_WRITE(0x02080, dev_priv->dma_status_page); 187 I915_WRITE(0x02080, dev_priv->dma_status_page);
210 } 188 }
211 DRM_DEBUG("Enabled hardware status page\n"); 189 DRM_DEBUG("Enabled hardware status page\n");
212 dev->dev_private = (void *)dev_priv;
213 return 0; 190 return 0;
214} 191}
215 192
@@ -254,17 +231,12 @@ static int i915_dma_resume(struct drm_device * dev)
254static int i915_dma_init(struct drm_device *dev, void *data, 231static int i915_dma_init(struct drm_device *dev, void *data,
255 struct drm_file *file_priv) 232 struct drm_file *file_priv)
256{ 233{
257 drm_i915_private_t *dev_priv;
258 drm_i915_init_t *init = data; 234 drm_i915_init_t *init = data;
259 int retcode = 0; 235 int retcode = 0;
260 236
261 switch (init->func) { 237 switch (init->func) {
262 case I915_INIT_DMA: 238 case I915_INIT_DMA:
263 dev_priv = drm_alloc(sizeof(drm_i915_private_t), 239 retcode = i915_initialize(dev, init);
264 DRM_MEM_DRIVER);
265 if (dev_priv == NULL)
266 return -ENOMEM;
267 retcode = i915_initialize(dev, dev_priv, init);
268 break; 240 break;
269 case I915_CLEANUP_DMA: 241 case I915_CLEANUP_DMA:
270 retcode = i915_dma_cleanup(dev); 242 retcode = i915_dma_cleanup(dev);
@@ -765,7 +737,6 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
765 737
766 drm_core_ioremap(&dev_priv->hws_map, dev); 738 drm_core_ioremap(&dev_priv->hws_map, dev);
767 if (dev_priv->hws_map.handle == NULL) { 739 if (dev_priv->hws_map.handle == NULL) {
768 dev->dev_private = (void *)dev_priv;
769 i915_dma_cleanup(dev); 740 i915_dma_cleanup(dev);
770 dev_priv->status_gfx_addr = 0; 741 dev_priv->status_gfx_addr = 0;
771 DRM_ERROR("can not ioremap virtual address for" 742 DRM_ERROR("can not ioremap virtual address for"
@@ -784,6 +755,10 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
784 755
785int i915_driver_load(struct drm_device *dev, unsigned long flags) 756int i915_driver_load(struct drm_device *dev, unsigned long flags)
786{ 757{
758 struct drm_i915_private *dev_priv = dev->dev_private;
759 unsigned long base, size;
760 int ret = 0, mmio_bar = IS_I9XX(dev) ? 0 : 1;
761
787 /* i915 has 4 more counters */ 762 /* i915 has 4 more counters */
788 dev->counters += 4; 763 dev->counters += 4;
789 dev->types[6] = _DRM_STAT_IRQ; 764 dev->types[6] = _DRM_STAT_IRQ;
@@ -791,24 +766,50 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
791 dev->types[8] = _DRM_STAT_SECONDARY; 766 dev->types[8] = _DRM_STAT_SECONDARY;
792 dev->types[9] = _DRM_STAT_DMA; 767 dev->types[9] = _DRM_STAT_DMA;
793 768
769 dev_priv = drm_alloc(sizeof(drm_i915_private_t), DRM_MEM_DRIVER);
770 if (dev_priv == NULL)
771 return -ENOMEM;
772
773 memset(dev_priv, 0, sizeof(drm_i915_private_t));
774
775 dev->dev_private = (void *)dev_priv;
776
777 /* Add register map (needed for suspend/resume) */
778 base = drm_get_resource_start(dev, mmio_bar);
779 size = drm_get_resource_len(dev, mmio_bar);
780
781 ret = drm_addmap(dev, base, size, _DRM_REGISTERS, _DRM_KERNEL,
782 &dev_priv->mmio_map);
783 return ret;
784}
785
786int i915_driver_unload(struct drm_device *dev)
787{
788 struct drm_i915_private *dev_priv = dev->dev_private;
789
790 if (dev_priv->mmio_map)
791 drm_rmmap(dev, dev_priv->mmio_map);
792
793 drm_free(dev->dev_private, sizeof(drm_i915_private_t),
794 DRM_MEM_DRIVER);
795
794 return 0; 796 return 0;
795} 797}
796 798
797void i915_driver_lastclose(struct drm_device * dev) 799void i915_driver_lastclose(struct drm_device * dev)
798{ 800{
799 if (dev->dev_private) { 801 drm_i915_private_t *dev_priv = dev->dev_private;
800 drm_i915_private_t *dev_priv = dev->dev_private; 802
803 if (dev_priv->agp_heap)
801 i915_mem_takedown(&(dev_priv->agp_heap)); 804 i915_mem_takedown(&(dev_priv->agp_heap));
802 } 805
803 i915_dma_cleanup(dev); 806 i915_dma_cleanup(dev);
804} 807}
805 808
806void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv) 809void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
807{ 810{
808 if (dev->dev_private) { 811 drm_i915_private_t *dev_priv = dev->dev_private;
809 drm_i915_private_t *dev_priv = dev->dev_private; 812 i915_mem_release(dev, file_priv, dev_priv->agp_heap);
810 i915_mem_release(dev, file_priv, dev_priv->agp_heap);
811 }
812} 813}
813 814
814struct drm_ioctl_desc i915_ioctls[] = { 815struct drm_ioctl_desc i915_ioctls[] = {