diff options
author | Dave Airlie <airlied@redhat.com> | 2010-02-05 01:00:07 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2010-02-11 04:11:32 -0500 |
commit | 82568565683b4991964a5fc89a9ca0c7122818e8 (patch) | |
tree | 3c04fa40a00a440a322c802abd41175e90b71e21 /drivers/gpu/drm | |
parent | e34398952e056bbd99f9099fae77be26e5c6aa78 (diff) |
drm/radeon/kms: set gart pages to invalid on unbind and point to dummy page
this uses a new entrypoint to invalidate gart entries instead of using 0.
Changed to rather than pointing to 0 address point empty entry to dummy
page. This might help to avoid hard lockup if for some wrong
reasons GPU try to access unmapped GART entry.
I'm not 100% sure this is going to work, we probably need to allocate
a dummy page and point all the GTT entries at it similiar to what AGP does.
but we can test this first I suppose.
Signed-off-by: Jerome Glisse <jglisse@redhat.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/radeon/evergreen.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/r100.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/r300.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/r600.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_device.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_gart.c | 32 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/rs400.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/rs600.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/rv770.c | 1 |
10 files changed, 40 insertions, 3 deletions
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index c2f9752e4ee0..3368920df5f4 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c | |||
@@ -93,6 +93,7 @@ int evergreen_pcie_gart_enable(struct radeon_device *rdev) | |||
93 | r = radeon_gart_table_vram_pin(rdev); | 93 | r = radeon_gart_table_vram_pin(rdev); |
94 | if (r) | 94 | if (r) |
95 | return r; | 95 | return r; |
96 | radeon_gart_restore(rdev); | ||
96 | /* Setup L2 cache */ | 97 | /* Setup L2 cache */ |
97 | WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING | | 98 | WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING | |
98 | ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE | | 99 | ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE | |
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 346ae3d7e0d4..bc7d9e9211c8 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c | |||
@@ -197,6 +197,7 @@ int r100_pci_gart_enable(struct radeon_device *rdev) | |||
197 | { | 197 | { |
198 | uint32_t tmp; | 198 | uint32_t tmp; |
199 | 199 | ||
200 | radeon_gart_restore(rdev); | ||
200 | /* discard memory request outside of configured range */ | 201 | /* discard memory request outside of configured range */ |
201 | tmp = RREG32(RADEON_AIC_CNTL) | RADEON_DIS_OUT_OF_PCI_GART_ACCESS; | 202 | tmp = RREG32(RADEON_AIC_CNTL) | RADEON_DIS_OUT_OF_PCI_GART_ACCESS; |
202 | WREG32(RADEON_AIC_CNTL, tmp); | 203 | WREG32(RADEON_AIC_CNTL, tmp); |
diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index 5897bd00591e..654aca1cdf05 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c | |||
@@ -117,6 +117,7 @@ int rv370_pcie_gart_enable(struct radeon_device *rdev) | |||
117 | r = radeon_gart_table_vram_pin(rdev); | 117 | r = radeon_gart_table_vram_pin(rdev); |
118 | if (r) | 118 | if (r) |
119 | return r; | 119 | return r; |
120 | radeon_gart_restore(rdev); | ||
120 | /* discard memory request outside of configured range */ | 121 | /* discard memory request outside of configured range */ |
121 | tmp = RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD; | 122 | tmp = RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD; |
122 | WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp); | 123 | WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp); |
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index c9723daee357..4facbab20456 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c | |||
@@ -416,6 +416,7 @@ int r600_pcie_gart_enable(struct radeon_device *rdev) | |||
416 | r = radeon_gart_table_vram_pin(rdev); | 416 | r = radeon_gart_table_vram_pin(rdev); |
417 | if (r) | 417 | if (r) |
418 | return r; | 418 | return r; |
419 | radeon_gart_restore(rdev); | ||
419 | 420 | ||
420 | /* Setup L2 cache */ | 421 | /* Setup L2 cache */ |
421 | WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING | | 422 | WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING | |
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 9eeca6f07222..993cdf20d8e6 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
@@ -1145,6 +1145,7 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v) | |||
1145 | /* AGP */ | 1145 | /* AGP */ |
1146 | extern void radeon_agp_disable(struct radeon_device *rdev); | 1146 | extern void radeon_agp_disable(struct radeon_device *rdev); |
1147 | extern int radeon_gart_table_vram_pin(struct radeon_device *rdev); | 1147 | extern int radeon_gart_table_vram_pin(struct radeon_device *rdev); |
1148 | extern void radeon_gart_restore(struct radeon_device *rdev); | ||
1148 | extern int radeon_modeset_init(struct radeon_device *rdev); | 1149 | extern int radeon_modeset_init(struct radeon_device *rdev); |
1149 | extern void radeon_modeset_fini(struct radeon_device *rdev); | 1150 | extern void radeon_modeset_fini(struct radeon_device *rdev); |
1150 | extern bool radeon_card_posted(struct radeon_device *rdev); | 1151 | extern bool radeon_card_posted(struct radeon_device *rdev); |
@@ -1269,7 +1270,6 @@ extern void r600_ring_init(struct radeon_device *rdev, unsigned ring_size); | |||
1269 | extern int r600_cp_resume(struct radeon_device *rdev); | 1270 | extern int r600_cp_resume(struct radeon_device *rdev); |
1270 | extern void r600_cp_fini(struct radeon_device *rdev); | 1271 | extern void r600_cp_fini(struct radeon_device *rdev); |
1271 | extern int r600_count_pipe_bits(uint32_t val); | 1272 | extern int r600_count_pipe_bits(uint32_t val); |
1272 | extern int r600_gart_clear_page(struct radeon_device *rdev, int i); | ||
1273 | extern int r600_mc_wait_for_idle(struct radeon_device *rdev); | 1273 | extern int r600_mc_wait_for_idle(struct radeon_device *rdev); |
1274 | extern int r600_pcie_gart_init(struct radeon_device *rdev); | 1274 | extern int r600_pcie_gart_init(struct radeon_device *rdev); |
1275 | extern void r600_pcie_gart_tlb_flush(struct radeon_device *rdev); | 1275 | extern void r600_pcie_gart_tlb_flush(struct radeon_device *rdev); |
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index c224c1d944ef..fb55faf8e284 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c | |||
@@ -238,6 +238,8 @@ bool radeon_boot_test_post_card(struct radeon_device *rdev) | |||
238 | 238 | ||
239 | int radeon_dummy_page_init(struct radeon_device *rdev) | 239 | int radeon_dummy_page_init(struct radeon_device *rdev) |
240 | { | 240 | { |
241 | if (rdev->dummy_page.page) | ||
242 | return 0; | ||
241 | rdev->dummy_page.page = alloc_page(GFP_DMA32 | GFP_KERNEL | __GFP_ZERO); | 243 | rdev->dummy_page.page = alloc_page(GFP_DMA32 | GFP_KERNEL | __GFP_ZERO); |
242 | if (rdev->dummy_page.page == NULL) | 244 | if (rdev->dummy_page.page == NULL) |
243 | return -ENOMEM; | 245 | return -ENOMEM; |
diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index e73d56e83fa6..1770d3c07fd0 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c | |||
@@ -139,6 +139,7 @@ void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset, | |||
139 | unsigned t; | 139 | unsigned t; |
140 | unsigned p; | 140 | unsigned p; |
141 | int i, j; | 141 | int i, j; |
142 | u64 page_base; | ||
142 | 143 | ||
143 | if (!rdev->gart.ready) { | 144 | if (!rdev->gart.ready) { |
144 | WARN(1, "trying to unbind memory to unitialized GART !\n"); | 145 | WARN(1, "trying to unbind memory to unitialized GART !\n"); |
@@ -151,9 +152,11 @@ void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset, | |||
151 | pci_unmap_page(rdev->pdev, rdev->gart.pages_addr[p], | 152 | pci_unmap_page(rdev->pdev, rdev->gart.pages_addr[p], |
152 | PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); | 153 | PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); |
153 | rdev->gart.pages[p] = NULL; | 154 | rdev->gart.pages[p] = NULL; |
154 | rdev->gart.pages_addr[p] = 0; | 155 | rdev->gart.pages_addr[p] = rdev->dummy_page.addr; |
156 | page_base = rdev->gart.pages_addr[p]; | ||
155 | for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) { | 157 | for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) { |
156 | radeon_gart_set_page(rdev, t, 0); | 158 | radeon_gart_set_page(rdev, t, page_base); |
159 | page_base += RADEON_GPU_PAGE_SIZE; | ||
157 | } | 160 | } |
158 | } | 161 | } |
159 | } | 162 | } |
@@ -199,8 +202,26 @@ int radeon_gart_bind(struct radeon_device *rdev, unsigned offset, | |||
199 | return 0; | 202 | return 0; |
200 | } | 203 | } |
201 | 204 | ||
205 | void radeon_gart_restore(struct radeon_device *rdev) | ||
206 | { | ||
207 | int i, j, t; | ||
208 | u64 page_base; | ||
209 | |||
210 | for (i = 0, t = 0; i < rdev->gart.num_cpu_pages; i++) { | ||
211 | page_base = rdev->gart.pages_addr[i]; | ||
212 | for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) { | ||
213 | radeon_gart_set_page(rdev, t, page_base); | ||
214 | page_base += RADEON_GPU_PAGE_SIZE; | ||
215 | } | ||
216 | } | ||
217 | mb(); | ||
218 | radeon_gart_tlb_flush(rdev); | ||
219 | } | ||
220 | |||
202 | int radeon_gart_init(struct radeon_device *rdev) | 221 | int radeon_gart_init(struct radeon_device *rdev) |
203 | { | 222 | { |
223 | int r, i; | ||
224 | |||
204 | if (rdev->gart.pages) { | 225 | if (rdev->gart.pages) { |
205 | return 0; | 226 | return 0; |
206 | } | 227 | } |
@@ -209,6 +230,9 @@ int radeon_gart_init(struct radeon_device *rdev) | |||
209 | DRM_ERROR("Page size is smaller than GPU page size!\n"); | 230 | DRM_ERROR("Page size is smaller than GPU page size!\n"); |
210 | return -EINVAL; | 231 | return -EINVAL; |
211 | } | 232 | } |
233 | r = radeon_dummy_page_init(rdev); | ||
234 | if (r) | ||
235 | return r; | ||
212 | /* Compute table size */ | 236 | /* Compute table size */ |
213 | rdev->gart.num_cpu_pages = rdev->mc.gtt_size / PAGE_SIZE; | 237 | rdev->gart.num_cpu_pages = rdev->mc.gtt_size / PAGE_SIZE; |
214 | rdev->gart.num_gpu_pages = rdev->mc.gtt_size / RADEON_GPU_PAGE_SIZE; | 238 | rdev->gart.num_gpu_pages = rdev->mc.gtt_size / RADEON_GPU_PAGE_SIZE; |
@@ -227,6 +251,10 @@ int radeon_gart_init(struct radeon_device *rdev) | |||
227 | radeon_gart_fini(rdev); | 251 | radeon_gart_fini(rdev); |
228 | return -ENOMEM; | 252 | return -ENOMEM; |
229 | } | 253 | } |
254 | /* set GART entry to point to the dummy page by default */ | ||
255 | for (i = 0; i < rdev->gart.num_cpu_pages; i++) { | ||
256 | rdev->gart.pages_addr[i] = rdev->dummy_page.addr; | ||
257 | } | ||
230 | return 0; | 258 | return 0; |
231 | } | 259 | } |
232 | 260 | ||
diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c index 287fcebfb4e6..1e4582e27c14 100644 --- a/drivers/gpu/drm/radeon/rs400.c +++ b/drivers/gpu/drm/radeon/rs400.c | |||
@@ -113,6 +113,7 @@ int rs400_gart_enable(struct radeon_device *rdev) | |||
113 | uint32_t size_reg; | 113 | uint32_t size_reg; |
114 | uint32_t tmp; | 114 | uint32_t tmp; |
115 | 115 | ||
116 | radeon_gart_restore(rdev); | ||
116 | tmp = RREG32_MC(RS690_AIC_CTRL_SCRATCH); | 117 | tmp = RREG32_MC(RS690_AIC_CTRL_SCRATCH); |
117 | tmp |= RS690_DIS_OUT_OF_PCI_GART_ACCESS; | 118 | tmp |= RS690_DIS_OUT_OF_PCI_GART_ACCESS; |
118 | WREG32_MC(RS690_AIC_CTRL_SCRATCH, tmp); | 119 | WREG32_MC(RS690_AIC_CTRL_SCRATCH, tmp); |
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index 979b00034de9..28c8690c7a35 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c | |||
@@ -213,6 +213,7 @@ int rs600_gart_enable(struct radeon_device *rdev) | |||
213 | r = radeon_gart_table_vram_pin(rdev); | 213 | r = radeon_gart_table_vram_pin(rdev); |
214 | if (r) | 214 | if (r) |
215 | return r; | 215 | return r; |
216 | radeon_gart_restore(rdev); | ||
216 | /* Enable bus master */ | 217 | /* Enable bus master */ |
217 | tmp = RREG32(R_00004C_BUS_CNTL) & C_00004C_BUS_MASTER_DIS; | 218 | tmp = RREG32(R_00004C_BUS_CNTL) & C_00004C_BUS_MASTER_DIS; |
218 | WREG32(R_00004C_BUS_CNTL, tmp); | 219 | WREG32(R_00004C_BUS_CNTL, tmp); |
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 3ecd138815d8..6f1f4abbe88c 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c | |||
@@ -56,6 +56,7 @@ int rv770_pcie_gart_enable(struct radeon_device *rdev) | |||
56 | r = radeon_gart_table_vram_pin(rdev); | 56 | r = radeon_gart_table_vram_pin(rdev); |
57 | if (r) | 57 | if (r) |
58 | return r; | 58 | return r; |
59 | radeon_gart_restore(rdev); | ||
59 | /* Setup L2 cache */ | 60 | /* Setup L2 cache */ |
60 | WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING | | 61 | WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING | |
61 | ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE | | 62 | ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE | |