aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_dma.c
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2008-07-30 16:03:43 -0400
committerDave Airlie <airlied@linux.ie>2008-10-17 17:10:10 -0400
commit398c9cb20b5c6c5d1313912b937d653a46fec578 (patch)
treefab5398ec4bab85394cee9df4f4e34a002480bc9 /drivers/gpu/drm/i915/i915_dma.c
parentd3a6d4467ca44833bcb4ba1893a7aeaae939e4d5 (diff)
i915: Initialize hardware status page at device load when possible.
Some chips were unstable with repeated setup/teardown of the hardware status page. Signed-off-by: Eric Anholt <eric@anholt.net> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/i915/i915_dma.c')
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c86
1 files changed, 57 insertions, 29 deletions
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index aa9e8da9f716..f1b5aa92fa83 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -71,6 +71,52 @@ int i915_wait_ring(struct drm_device * dev, int n, const char *caller)
71 return -EBUSY; 71 return -EBUSY;
72} 72}
73 73
74/**
75 * Sets up the hardware status page for devices that need a physical address
76 * in the register.
77 */
78int i915_init_phys_hws(struct drm_device *dev)
79{
80 drm_i915_private_t *dev_priv = dev->dev_private;
81 /* Program Hardware Status Page */
82 dev_priv->status_page_dmah =
83 drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff);
84
85 if (!dev_priv->status_page_dmah) {
86 DRM_ERROR("Can not allocate hardware status page\n");
87 return -ENOMEM;
88 }
89 dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
90 dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
91
92 memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
93
94 I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
95 DRM_DEBUG("Enabled hardware status page\n");
96 return 0;
97}
98
99/**
100 * Frees the hardware status page, whether it's a physical address or a virtual
101 * address set up by the X Server.
102 */
103void i915_free_hws(struct drm_device *dev)
104{
105 drm_i915_private_t *dev_priv = dev->dev_private;
106 if (dev_priv->status_page_dmah) {
107 drm_pci_free(dev, dev_priv->status_page_dmah);
108 dev_priv->status_page_dmah = NULL;
109 }
110
111 if (dev_priv->status_gfx_addr) {
112 dev_priv->status_gfx_addr = 0;
113 drm_core_ioremapfree(&dev_priv->hws_map, dev);
114 }
115
116 /* Need to rewrite hardware status page */
117 I915_WRITE(HWS_PGA, 0x1ffff000);
118}
119
74void i915_kernel_lost_context(struct drm_device * dev) 120void i915_kernel_lost_context(struct drm_device * dev)
75{ 121{
76 drm_i915_private_t *dev_priv = dev->dev_private; 122 drm_i915_private_t *dev_priv = dev->dev_private;
@@ -103,18 +149,9 @@ static int i915_dma_cleanup(struct drm_device * dev)
103 dev_priv->ring.map.size = 0; 149 dev_priv->ring.map.size = 0;
104 } 150 }
105 151
106 if (dev_priv->status_page_dmah) { 152 /* Clear the HWS virtual address at teardown */
107 drm_pci_free(dev, dev_priv->status_page_dmah); 153 if (I915_NEED_GFX_HWS(dev))
108 dev_priv->status_page_dmah = NULL; 154 i915_free_hws(dev);
109 /* Need to rewrite hardware status page */
110 I915_WRITE(HWS_PGA, 0x1ffff000);
111 }
112
113 if (dev_priv->status_gfx_addr) {
114 dev_priv->status_gfx_addr = 0;
115 drm_core_ioremapfree(&dev_priv->hws_map, dev);
116 I915_WRITE(HWS_PGA, 0x1ffff000);
117 }
118 155
119 return 0; 156 return 0;
120} 157}
@@ -165,23 +202,6 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
165 */ 202 */
166 dev_priv->allow_batchbuffer = 1; 203 dev_priv->allow_batchbuffer = 1;
167 204
168 /* Program Hardware Status Page */
169 if (!I915_NEED_GFX_HWS(dev)) {
170 dev_priv->status_page_dmah =
171 drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff);
172
173 if (!dev_priv->status_page_dmah) {
174 i915_dma_cleanup(dev);
175 DRM_ERROR("Can not allocate hardware status page\n");
176 return -ENOMEM;
177 }
178 dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
179 dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
180
181 memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
182 I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
183 }
184 DRM_DEBUG("Enabled hardware status page\n");
185 return 0; 205 return 0;
186} 206}
187 207
@@ -773,6 +793,12 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
773 _DRM_KERNEL | _DRM_DRIVER, 793 _DRM_KERNEL | _DRM_DRIVER,
774 &dev_priv->mmio_map); 794 &dev_priv->mmio_map);
775 795
796 /* Init HWS */
797 if (!I915_NEED_GFX_HWS(dev)) {
798 ret = i915_init_phys_hws(dev);
799 if (ret != 0)
800 return ret;
801 }
776 802
777 /* On the 945G/GM, the chipset reports the MSI capability on the 803 /* On the 945G/GM, the chipset reports the MSI capability on the
778 * integrated graphics even though the support isn't actually there 804 * integrated graphics even though the support isn't actually there
@@ -796,6 +822,8 @@ int i915_driver_unload(struct drm_device *dev)
796 if (dev->pdev->msi_enabled) 822 if (dev->pdev->msi_enabled)
797 pci_disable_msi(dev->pdev); 823 pci_disable_msi(dev->pdev);
798 824
825 i915_free_hws(dev);
826
799 if (dev_priv->mmio_map) 827 if (dev_priv->mmio_map)
800 drm_rmmap(dev, dev_priv->mmio_map); 828 drm_rmmap(dev, dev_priv->mmio_map);
801 829