diff options
author | David Miller <davem@davemloft.net> | 2009-02-12 05:15:27 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2009-03-13 00:23:59 -0400 |
commit | 5a7aad9a559a5488cbef7aa3d4d96fc28220b8ae (patch) | |
tree | 4a35fea85696e6cd41c81c71f34c2f7cf086aae3 /drivers/gpu/drm/ati_pcigart.c | |
parent | 8e1004580e0c862cb6bbe2ff8e496f846c54052f (diff) |
drm: ati_pcigart: Do not access I/O MEM space using pointer derefs.
The PCI GART table initialization code treats the GART table mapping
unconditionally as a kernel virtual address.
But it could be in the framebuffer, for example, and thus we're
dealing with a PCI MEM space ioremap() cookie. Treating that as a
virtual address is illegal and will crash some system types (such as
sparc64 where the ioremap() return value is actually a physical I/O
address).
So access the area correctly, using gart_info->gart_table_location as
our guide.
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Dave Airlie <airlied@linux.ie>
Diffstat (limited to 'drivers/gpu/drm/ati_pcigart.c')
-rw-r--r-- | drivers/gpu/drm/ati_pcigart.c | 26 |
1 files changed, 20 insertions, 6 deletions
diff --git a/drivers/gpu/drm/ati_pcigart.c b/drivers/gpu/drm/ati_pcigart.c index c533d0c9ec61..2cd827a56ffe 100644 --- a/drivers/gpu/drm/ati_pcigart.c +++ b/drivers/gpu/drm/ati_pcigart.c | |||
@@ -95,10 +95,11 @@ EXPORT_SYMBOL(drm_ati_pcigart_cleanup); | |||
95 | 95 | ||
96 | int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info) | 96 | int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info) |
97 | { | 97 | { |
98 | struct drm_local_map *map = &gart_info->mapping; | ||
98 | struct drm_sg_mem *entry = dev->sg; | 99 | struct drm_sg_mem *entry = dev->sg; |
99 | void *address = NULL; | 100 | void *address = NULL; |
100 | unsigned long pages; | 101 | unsigned long pages; |
101 | u32 *pci_gart, page_base; | 102 | u32 *pci_gart, page_base, gart_idx; |
102 | dma_addr_t bus_address = 0; | 103 | dma_addr_t bus_address = 0; |
103 | int i, j, ret = 0; | 104 | int i, j, ret = 0; |
104 | int max_pages; | 105 | int max_pages; |
@@ -133,8 +134,14 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga | |||
133 | pages = (entry->pages <= max_pages) | 134 | pages = (entry->pages <= max_pages) |
134 | ? entry->pages : max_pages; | 135 | ? entry->pages : max_pages; |
135 | 136 | ||
136 | memset(pci_gart, 0, max_pages * sizeof(u32)); | 137 | if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) { |
138 | memset(pci_gart, 0, max_pages * sizeof(u32)); | ||
139 | } else { | ||
140 | for (gart_idx = 0; gart_idx < max_pages; gart_idx++) | ||
141 | DRM_WRITE32(map, gart_idx * sizeof(u32), 0); | ||
142 | } | ||
137 | 143 | ||
144 | gart_idx = 0; | ||
138 | for (i = 0; i < pages; i++) { | 145 | for (i = 0; i < pages; i++) { |
139 | /* we need to support large memory configurations */ | 146 | /* we need to support large memory configurations */ |
140 | entry->busaddr[i] = pci_map_page(dev->pdev, entry->pagelist[i], | 147 | entry->busaddr[i] = pci_map_page(dev->pdev, entry->pagelist[i], |
@@ -149,19 +156,26 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga | |||
149 | page_base = (u32) entry->busaddr[i]; | 156 | page_base = (u32) entry->busaddr[i]; |
150 | 157 | ||
151 | for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) { | 158 | for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) { |
159 | u32 val; | ||
160 | |||
152 | switch(gart_info->gart_reg_if) { | 161 | switch(gart_info->gart_reg_if) { |
153 | case DRM_ATI_GART_IGP: | 162 | case DRM_ATI_GART_IGP: |
154 | *pci_gart = cpu_to_le32((page_base) | 0xc); | 163 | val = page_base | 0xc; |
155 | break; | 164 | break; |
156 | case DRM_ATI_GART_PCIE: | 165 | case DRM_ATI_GART_PCIE: |
157 | *pci_gart = cpu_to_le32((page_base >> 8) | 0xc); | 166 | val = (page_base >> 8) | 0xc; |
158 | break; | 167 | break; |
159 | default: | 168 | default: |
160 | case DRM_ATI_GART_PCI: | 169 | case DRM_ATI_GART_PCI: |
161 | *pci_gart = cpu_to_le32(page_base); | 170 | val = page_base; |
162 | break; | 171 | break; |
163 | } | 172 | } |
164 | pci_gart++; | 173 | if (gart_info->gart_table_location == |
174 | DRM_ATI_GART_MAIN) | ||
175 | pci_gart[gart_idx] = cpu_to_le32(val); | ||
176 | else | ||
177 | DRM_WRITE32(map, gart_idx * sizeof(u32), val); | ||
178 | gart_idx++; | ||
165 | page_base += ATI_PCIGART_PAGE_SIZE; | 179 | page_base += ATI_PCIGART_PAGE_SIZE; |
166 | } | 180 | } |
167 | } | 181 | } |