Rev 6321 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 6321 | Rev 6661 | ||
---|---|---|---|
1 | /* |
1 | /* |
2 | * Copyright 2008 Advanced Micro Devices, Inc. |
2 | * Copyright 2008 Advanced Micro Devices, Inc. |
3 | * Copyright 2008 Red Hat Inc. |
3 | * Copyright 2008 Red Hat Inc. |
4 | * Copyright 2009 Jerome Glisse. |
4 | * Copyright 2009 Jerome Glisse. |
5 | * |
5 | * |
6 | * Permission is hereby granted, free of charge, to any person obtaining a |
6 | * Permission is hereby granted, free of charge, to any person obtaining a |
7 | * copy of this software and associated documentation files (the "Software"), |
7 | * copy of this software and associated documentation files (the "Software"), |
8 | * to deal in the Software without restriction, including without limitation |
8 | * to deal in the Software without restriction, including without limitation |
9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
10 | * and/or sell copies of the Software, and to permit persons to whom the |
10 | * and/or sell copies of the Software, and to permit persons to whom the |
11 | * Software is furnished to do so, subject to the following conditions: |
11 | * Software is furnished to do so, subject to the following conditions: |
12 | * |
12 | * |
13 | * The above copyright notice and this permission notice shall be included in |
13 | * The above copyright notice and this permission notice shall be included in |
14 | * all copies or substantial portions of the Software. |
14 | * all copies or substantial portions of the Software. |
15 | * |
15 | * |
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR |
19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR |
20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
22 | * OTHER DEALINGS IN THE SOFTWARE. |
22 | * OTHER DEALINGS IN THE SOFTWARE. |
23 | * |
23 | * |
24 | * Authors: Dave Airlie |
24 | * Authors: Dave Airlie |
25 | * Alex Deucher |
25 | * Alex Deucher |
26 | * Jerome Glisse |
26 | * Jerome Glisse |
27 | */ |
27 | */ |
28 | #include |
28 | #include |
29 | #include |
29 | #include |
30 | #include "radeon.h" |
30 | #include "radeon.h" |
31 | - | ||
32 | #undef CONFIG_X86 |
- | |
33 | void* pci_alloc_consistent(struct pci_dev *hwdev, size_t size, |
- | |
34 | addr_t *dma_handle) |
- | |
35 | { |
- | |
36 | - | ||
37 | size = (size + 0x7FFF) & ~0x7FFF; |
- | |
38 | - | ||
39 | *dma_handle = AllocPages(size >> 12); |
- | |
40 | return (void*)MapIoMem(*dma_handle, size, PG_SW+PG_NOCACHE); |
- | |
41 | } |
- | |
42 | 31 | ||
43 | /* |
32 | /* |
44 | * GART |
33 | * GART |
45 | * The GART (Graphics Aperture Remapping Table) is an aperture |
34 | * The GART (Graphics Aperture Remapping Table) is an aperture |
46 | * in the GPU's address space. System pages can be mapped into |
35 | * in the GPU's address space. System pages can be mapped into |
47 | * the aperture and look like contiguous pages from the GPU's |
36 | * the aperture and look like contiguous pages from the GPU's |
48 | * perspective. A page table maps the pages in the aperture |
37 | * perspective. A page table maps the pages in the aperture |
49 | * to the actual backing pages in system memory. |
38 | * to the actual backing pages in system memory. |
50 | * |
39 | * |
51 | * Radeon GPUs support both an internal GART, as described above, |
40 | * Radeon GPUs support both an internal GART, as described above, |
52 | * and AGP. AGP works similarly, but the GART table is configured |
41 | * and AGP. AGP works similarly, but the GART table is configured |
53 | * and maintained by the northbridge rather than the driver. |
42 | * and maintained by the northbridge rather than the driver. |
54 | * Radeon hw has a separate AGP aperture that is programmed to |
43 | * Radeon hw has a separate AGP aperture that is programmed to |
55 | * point to the AGP aperture provided by the northbridge and the |
44 | * point to the AGP aperture provided by the northbridge and the |
56 | * requests are passed through to the northbridge aperture. |
45 | * requests are passed through to the northbridge aperture. |
57 | * Both AGP and internal GART can be used at the same time, however |
46 | * Both AGP and internal GART can be used at the same time, however |
58 | * that is not currently supported by the driver. |
47 | * that is not currently supported by the driver. |
59 | * |
48 | * |
60 | * This file handles the common internal GART management. |
49 | * This file handles the common internal GART management. |
61 | */ |
50 | */ |
62 | 51 | ||
63 | /* |
52 | /* |
64 | * Common GART table functions. |
53 | * Common GART table functions. |
65 | */ |
54 | */ |
66 | /** |
55 | /** |
67 | * radeon_gart_table_ram_alloc - allocate system ram for gart page table |
56 | * radeon_gart_table_ram_alloc - allocate system ram for gart page table |
68 | * |
57 | * |
69 | * @rdev: radeon_device pointer |
58 | * @rdev: radeon_device pointer |
70 | * |
59 | * |
71 | * Allocate system memory for GART page table |
60 | * Allocate system memory for GART page table |
72 | * (r1xx-r3xx, non-pcie r4xx, rs400). These asics require the |
61 | * (r1xx-r3xx, non-pcie r4xx, rs400). These asics require the |
73 | * gart table to be in system memory. |
62 | * gart table to be in system memory. |
74 | * Returns 0 for success, -ENOMEM for failure. |
63 | * Returns 0 for success, -ENOMEM for failure. |
75 | */ |
64 | */ |
76 | int radeon_gart_table_ram_alloc(struct radeon_device *rdev) |
65 | int radeon_gart_table_ram_alloc(struct radeon_device *rdev) |
77 | { |
66 | { |
78 | void *ptr; |
67 | void *ptr; |
79 | 68 | ||
80 | ptr = pci_alloc_consistent(rdev->pdev, rdev->gart.table_size, |
69 | ptr = pci_alloc_consistent(rdev->pdev, rdev->gart.table_size, |
81 | &rdev->gart.table_addr); |
70 | &rdev->gart.table_addr); |
82 | if (ptr == NULL) { |
71 | if (ptr == NULL) { |
83 | return -ENOMEM; |
72 | return -ENOMEM; |
84 | } |
73 | } |
85 | #ifdef CONFIG_X86 |
74 | #ifdef CONFIG_X86 |
86 | if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480 || |
75 | if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480 || |
87 | rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) { |
76 | rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) { |
88 | set_memory_uc((unsigned long)ptr, |
77 | set_memory_uc((unsigned long)ptr, |
89 | rdev->gart.table_size >> PAGE_SHIFT); |
78 | rdev->gart.table_size >> PAGE_SHIFT); |
90 | } |
79 | } |
91 | #endif |
80 | #endif |
92 | rdev->gart.ptr = ptr; |
81 | rdev->gart.ptr = ptr; |
93 | memset((void *)rdev->gart.ptr, 0, rdev->gart.table_size); |
82 | memset((void *)rdev->gart.ptr, 0, rdev->gart.table_size); |
94 | return 0; |
83 | return 0; |
95 | } |
84 | } |
96 | 85 | ||
97 | /** |
86 | /** |
98 | * radeon_gart_table_ram_free - free system ram for gart page table |
87 | * radeon_gart_table_ram_free - free system ram for gart page table |
99 | * |
88 | * |
100 | * @rdev: radeon_device pointer |
89 | * @rdev: radeon_device pointer |
101 | * |
90 | * |
102 | * Free system memory for GART page table |
91 | * Free system memory for GART page table |
103 | * (r1xx-r3xx, non-pcie r4xx, rs400). These asics require the |
92 | * (r1xx-r3xx, non-pcie r4xx, rs400). These asics require the |
104 | * gart table to be in system memory. |
93 | * gart table to be in system memory. |
105 | */ |
94 | */ |
106 | void radeon_gart_table_ram_free(struct radeon_device *rdev) |
95 | void radeon_gart_table_ram_free(struct radeon_device *rdev) |
107 | { |
96 | { |
108 | if (rdev->gart.ptr == NULL) { |
97 | if (rdev->gart.ptr == NULL) { |
109 | return; |
98 | return; |
110 | } |
99 | } |
111 | #ifdef CONFIG_X86 |
100 | #ifdef CONFIG_X86 |
112 | if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480 || |
101 | if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480 || |
113 | rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) { |
102 | rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) { |
114 | set_memory_wb((unsigned long)rdev->gart.ptr, |
103 | set_memory_wb((unsigned long)rdev->gart.ptr, |
115 | rdev->gart.table_size >> PAGE_SHIFT); |
104 | rdev->gart.table_size >> PAGE_SHIFT); |
116 | } |
105 | } |
117 | #endif |
106 | #endif |
118 | rdev->gart.ptr = NULL; |
107 | rdev->gart.ptr = NULL; |
119 | rdev->gart.table_addr = 0; |
108 | rdev->gart.table_addr = 0; |
120 | } |
109 | } |
121 | 110 | ||
122 | /** |
111 | /** |
123 | * radeon_gart_table_vram_alloc - allocate vram for gart page table |
112 | * radeon_gart_table_vram_alloc - allocate vram for gart page table |
124 | * |
113 | * |
125 | * @rdev: radeon_device pointer |
114 | * @rdev: radeon_device pointer |
126 | * |
115 | * |
127 | * Allocate video memory for GART page table |
116 | * Allocate video memory for GART page table |
128 | * (pcie r4xx, r5xx+). These asics require the |
117 | * (pcie r4xx, r5xx+). These asics require the |
129 | * gart table to be in video memory. |
118 | * gart table to be in video memory. |
130 | * Returns 0 for success, error for failure. |
119 | * Returns 0 for success, error for failure. |
131 | */ |
120 | */ |
132 | int radeon_gart_table_vram_alloc(struct radeon_device *rdev) |
121 | int radeon_gart_table_vram_alloc(struct radeon_device *rdev) |
133 | { |
122 | { |
134 | int r; |
123 | int r; |
135 | 124 | ||
136 | if (rdev->gart.robj == NULL) { |
125 | if (rdev->gart.robj == NULL) { |
137 | r = radeon_bo_create(rdev, rdev->gart.table_size, |
126 | r = radeon_bo_create(rdev, rdev->gart.table_size, |
138 | PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, |
127 | PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, |
139 | 0, NULL, NULL, &rdev->gart.robj); |
128 | 0, NULL, NULL, &rdev->gart.robj); |
140 | if (r) { |
129 | if (r) { |
141 | return r; |
130 | return r; |
142 | } |
131 | } |
143 | } |
132 | } |
144 | return 0; |
133 | return 0; |
145 | } |
134 | } |
146 | 135 | ||
147 | /** |
136 | /** |
148 | * radeon_gart_table_vram_pin - pin gart page table in vram |
137 | * radeon_gart_table_vram_pin - pin gart page table in vram |
149 | * |
138 | * |
150 | * @rdev: radeon_device pointer |
139 | * @rdev: radeon_device pointer |
151 | * |
140 | * |
152 | * Pin the GART page table in vram so it will not be moved |
141 | * Pin the GART page table in vram so it will not be moved |
153 | * by the memory manager (pcie r4xx, r5xx+). These asics require the |
142 | * by the memory manager (pcie r4xx, r5xx+). These asics require the |
154 | * gart table to be in video memory. |
143 | * gart table to be in video memory. |
155 | * Returns 0 for success, error for failure. |
144 | * Returns 0 for success, error for failure. |
156 | */ |
145 | */ |
157 | int radeon_gart_table_vram_pin(struct radeon_device *rdev) |
146 | int radeon_gart_table_vram_pin(struct radeon_device *rdev) |
158 | { |
147 | { |
159 | uint64_t gpu_addr; |
148 | uint64_t gpu_addr; |
160 | int r; |
149 | int r; |
161 | 150 | ||
162 | r = radeon_bo_reserve(rdev->gart.robj, false); |
151 | r = radeon_bo_reserve(rdev->gart.robj, false); |
163 | if (unlikely(r != 0)) |
152 | if (unlikely(r != 0)) |
164 | return r; |
153 | return r; |
165 | r = radeon_bo_pin(rdev->gart.robj, |
154 | r = radeon_bo_pin(rdev->gart.robj, |
166 | RADEON_GEM_DOMAIN_VRAM, &gpu_addr); |
155 | RADEON_GEM_DOMAIN_VRAM, &gpu_addr); |
167 | if (r) { |
156 | if (r) { |
168 | radeon_bo_unreserve(rdev->gart.robj); |
157 | radeon_bo_unreserve(rdev->gart.robj); |
169 | return r; |
158 | return r; |
170 | } |
159 | } |
171 | r = radeon_bo_kmap(rdev->gart.robj, &rdev->gart.ptr); |
160 | r = radeon_bo_kmap(rdev->gart.robj, &rdev->gart.ptr); |
172 | if (r) |
161 | if (r) |
173 | radeon_bo_unpin(rdev->gart.robj); |
162 | radeon_bo_unpin(rdev->gart.robj); |
174 | radeon_bo_unreserve(rdev->gart.robj); |
163 | radeon_bo_unreserve(rdev->gart.robj); |
175 | rdev->gart.table_addr = gpu_addr; |
164 | rdev->gart.table_addr = gpu_addr; |
176 | 165 | ||
177 | if (!r) { |
166 | if (!r) { |
178 | int i; |
167 | int i; |
179 | 168 | ||
180 | /* We might have dropped some GART table updates while it wasn't |
169 | /* We might have dropped some GART table updates while it wasn't |
181 | * mapped, restore all entries |
170 | * mapped, restore all entries |
182 | */ |
171 | */ |
183 | for (i = 0; i < rdev->gart.num_gpu_pages; i++) |
172 | for (i = 0; i < rdev->gart.num_gpu_pages; i++) |
184 | radeon_gart_set_page(rdev, i, rdev->gart.pages_entry[i]); |
173 | radeon_gart_set_page(rdev, i, rdev->gart.pages_entry[i]); |
185 | mb(); |
174 | mb(); |
186 | radeon_gart_tlb_flush(rdev); |
175 | radeon_gart_tlb_flush(rdev); |
187 | } |
176 | } |
188 | 177 | ||
189 | return r; |
178 | return r; |
190 | } |
179 | } |
191 | 180 | ||
192 | /** |
181 | /** |
193 | * radeon_gart_table_vram_unpin - unpin gart page table in vram |
182 | * radeon_gart_table_vram_unpin - unpin gart page table in vram |
194 | * |
183 | * |
195 | * @rdev: radeon_device pointer |
184 | * @rdev: radeon_device pointer |
196 | * |
185 | * |
197 | * Unpin the GART page table in vram (pcie r4xx, r5xx+). |
186 | * Unpin the GART page table in vram (pcie r4xx, r5xx+). |
198 | * These asics require the gart table to be in video memory. |
187 | * These asics require the gart table to be in video memory. |
199 | */ |
188 | */ |
200 | void radeon_gart_table_vram_unpin(struct radeon_device *rdev) |
189 | void radeon_gart_table_vram_unpin(struct radeon_device *rdev) |
201 | { |
190 | { |
202 | int r; |
191 | int r; |
203 | 192 | ||
204 | if (rdev->gart.robj == NULL) { |
193 | if (rdev->gart.robj == NULL) { |
205 | return; |
194 | return; |
206 | } |
195 | } |
207 | r = radeon_bo_reserve(rdev->gart.robj, false); |
196 | r = radeon_bo_reserve(rdev->gart.robj, false); |
208 | if (likely(r == 0)) { |
197 | if (likely(r == 0)) { |
209 | radeon_bo_kunmap(rdev->gart.robj); |
198 | radeon_bo_kunmap(rdev->gart.robj); |
210 | radeon_bo_unpin(rdev->gart.robj); |
199 | radeon_bo_unpin(rdev->gart.robj); |
211 | radeon_bo_unreserve(rdev->gart.robj); |
200 | radeon_bo_unreserve(rdev->gart.robj); |
212 | rdev->gart.ptr = NULL; |
201 | rdev->gart.ptr = NULL; |
213 | } |
202 | } |
214 | } |
203 | } |
215 | 204 | ||
216 | /** |
205 | /** |
217 | * radeon_gart_table_vram_free - free gart page table vram |
206 | * radeon_gart_table_vram_free - free gart page table vram |
218 | * |
207 | * |
219 | * @rdev: radeon_device pointer |
208 | * @rdev: radeon_device pointer |
220 | * |
209 | * |
221 | * Free the video memory used for the GART page table |
210 | * Free the video memory used for the GART page table |
222 | * (pcie r4xx, r5xx+). These asics require the gart table to |
211 | * (pcie r4xx, r5xx+). These asics require the gart table to |
223 | * be in video memory. |
212 | * be in video memory. |
224 | */ |
213 | */ |
225 | void radeon_gart_table_vram_free(struct radeon_device *rdev) |
214 | void radeon_gart_table_vram_free(struct radeon_device *rdev) |
226 | { |
215 | { |
227 | if (rdev->gart.robj == NULL) { |
216 | if (rdev->gart.robj == NULL) { |
228 | return; |
217 | return; |
229 | } |
218 | } |
230 | radeon_bo_unref(&rdev->gart.robj); |
219 | radeon_bo_unref(&rdev->gart.robj); |
231 | } |
220 | } |
232 | 221 | ||
233 | /* |
222 | /* |
234 | * Common gart functions. |
223 | * Common gart functions. |
235 | */ |
224 | */ |
236 | /** |
225 | /** |
237 | * radeon_gart_unbind - unbind pages from the gart page table |
226 | * radeon_gart_unbind - unbind pages from the gart page table |
238 | * |
227 | * |
239 | * @rdev: radeon_device pointer |
228 | * @rdev: radeon_device pointer |
240 | * @offset: offset into the GPU's gart aperture |
229 | * @offset: offset into the GPU's gart aperture |
241 | * @pages: number of pages to unbind |
230 | * @pages: number of pages to unbind |
242 | * |
231 | * |
243 | * Unbinds the requested pages from the gart page table and |
232 | * Unbinds the requested pages from the gart page table and |
244 | * replaces them with the dummy page (all asics). |
233 | * replaces them with the dummy page (all asics). |
245 | */ |
234 | */ |
246 | void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset, |
235 | void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset, |
247 | int pages) |
236 | int pages) |
248 | { |
237 | { |
249 | unsigned t; |
238 | unsigned t; |
250 | unsigned p; |
239 | unsigned p; |
251 | int i, j; |
240 | int i, j; |
252 | 241 | ||
253 | if (!rdev->gart.ready) { |
242 | if (!rdev->gart.ready) { |
254 | WARN(1, "trying to unbind memory from uninitialized GART !\n"); |
243 | WARN(1, "trying to unbind memory from uninitialized GART !\n"); |
255 | return; |
244 | return; |
256 | } |
245 | } |
257 | t = offset / RADEON_GPU_PAGE_SIZE; |
246 | t = offset / RADEON_GPU_PAGE_SIZE; |
258 | p = t / (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); |
247 | p = t / (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); |
259 | for (i = 0; i < pages; i++, p++) { |
248 | for (i = 0; i < pages; i++, p++) { |
260 | if (rdev->gart.pages[p]) { |
249 | if (rdev->gart.pages[p]) { |
261 | rdev->gart.pages[p] = NULL; |
250 | rdev->gart.pages[p] = NULL; |
262 | for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) { |
251 | for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) { |
263 | rdev->gart.pages_entry[t] = rdev->dummy_page.entry; |
252 | rdev->gart.pages_entry[t] = rdev->dummy_page.entry; |
264 | if (rdev->gart.ptr) { |
253 | if (rdev->gart.ptr) { |
265 | radeon_gart_set_page(rdev, t, |
254 | radeon_gart_set_page(rdev, t, |
266 | rdev->dummy_page.entry); |
255 | rdev->dummy_page.entry); |
267 | } |
256 | } |
268 | } |
257 | } |
269 | } |
258 | } |
270 | } |
259 | } |
271 | if (rdev->gart.ptr) { |
260 | if (rdev->gart.ptr) { |
272 | mb(); |
261 | mb(); |
273 | radeon_gart_tlb_flush(rdev); |
262 | radeon_gart_tlb_flush(rdev); |
274 | } |
263 | } |
275 | } |
264 | } |
276 | 265 | ||
277 | /** |
266 | /** |
278 | * radeon_gart_bind - bind pages into the gart page table |
267 | * radeon_gart_bind - bind pages into the gart page table |
279 | * |
268 | * |
280 | * @rdev: radeon_device pointer |
269 | * @rdev: radeon_device pointer |
281 | * @offset: offset into the GPU's gart aperture |
270 | * @offset: offset into the GPU's gart aperture |
282 | * @pages: number of pages to bind |
271 | * @pages: number of pages to bind |
283 | * @pagelist: pages to bind |
272 | * @pagelist: pages to bind |
284 | * @dma_addr: DMA addresses of pages |
273 | * @dma_addr: DMA addresses of pages |
285 | * @flags: RADEON_GART_PAGE_* flags |
274 | * @flags: RADEON_GART_PAGE_* flags |
286 | * |
275 | * |
287 | * Binds the requested pages to the gart page table |
276 | * Binds the requested pages to the gart page table |
288 | * (all asics). |
277 | * (all asics). |
289 | * Returns 0 for success, -EINVAL for failure. |
278 | * Returns 0 for success, -EINVAL for failure. |
290 | */ |
279 | */ |
291 | int radeon_gart_bind(struct radeon_device *rdev, unsigned offset, |
280 | int radeon_gart_bind(struct radeon_device *rdev, unsigned offset, |
292 | int pages, struct page **pagelist, dma_addr_t *dma_addr, |
281 | int pages, struct page **pagelist, dma_addr_t *dma_addr, |
293 | uint32_t flags) |
282 | uint32_t flags) |
294 | { |
283 | { |
295 | unsigned t; |
284 | unsigned t; |
296 | unsigned p; |
285 | unsigned p; |
297 | uint64_t page_base, page_entry; |
286 | uint64_t page_base, page_entry; |
298 | int i, j; |
287 | int i, j; |
299 | 288 | ||
300 | if (!rdev->gart.ready) { |
289 | if (!rdev->gart.ready) { |
301 | WARN(1, "trying to bind memory to uninitialized GART !\n"); |
290 | WARN(1, "trying to bind memory to uninitialized GART !\n"); |
302 | return -EINVAL; |
291 | return -EINVAL; |
303 | } |
292 | } |
304 | t = offset / RADEON_GPU_PAGE_SIZE; |
293 | t = offset / RADEON_GPU_PAGE_SIZE; |
305 | p = t / (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); |
294 | p = t / (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); |
306 | 295 | ||
307 | for (i = 0; i < pages; i++, p++) { |
296 | for (i = 0; i < pages; i++, p++) { |
308 | rdev->gart.pages[p] = pagelist[i]; |
297 | rdev->gart.pages[p] = pagelist[i]; |
309 | page_base = dma_addr[i]; |
298 | page_base = dma_addr[i]; |
310 | for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) { |
299 | for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) { |
311 | page_entry = radeon_gart_get_page_entry(page_base, flags); |
300 | page_entry = radeon_gart_get_page_entry(page_base, flags); |
312 | rdev->gart.pages_entry[t] = page_entry; |
301 | rdev->gart.pages_entry[t] = page_entry; |
313 | if (rdev->gart.ptr) { |
302 | if (rdev->gart.ptr) { |
314 | radeon_gart_set_page(rdev, t, page_entry); |
303 | radeon_gart_set_page(rdev, t, page_entry); |
315 | } |
304 | } |
316 | page_base += RADEON_GPU_PAGE_SIZE; |
305 | page_base += RADEON_GPU_PAGE_SIZE; |
317 | } |
306 | } |
318 | } |
307 | } |
319 | if (rdev->gart.ptr) { |
308 | if (rdev->gart.ptr) { |
320 | mb(); |
309 | mb(); |
321 | radeon_gart_tlb_flush(rdev); |
310 | radeon_gart_tlb_flush(rdev); |
322 | } |
311 | } |
323 | return 0; |
312 | return 0; |
324 | } |
313 | } |
325 | 314 | ||
326 | /** |
315 | /** |
327 | * radeon_gart_init - init the driver info for managing the gart |
316 | * radeon_gart_init - init the driver info for managing the gart |
328 | * |
317 | * |
329 | * @rdev: radeon_device pointer |
318 | * @rdev: radeon_device pointer |
330 | * |
319 | * |
331 | * Allocate the dummy page and init the gart driver info (all asics). |
320 | * Allocate the dummy page and init the gart driver info (all asics). |
332 | * Returns 0 for success, error for failure. |
321 | * Returns 0 for success, error for failure. |
333 | */ |
322 | */ |
334 | int radeon_gart_init(struct radeon_device *rdev) |
323 | int radeon_gart_init(struct radeon_device *rdev) |
335 | { |
324 | { |
336 | int r, i; |
325 | int r, i; |
337 | 326 | ||
338 | if (rdev->gart.pages) { |
327 | if (rdev->gart.pages) { |
339 | return 0; |
328 | return 0; |
340 | } |
329 | } |
341 | /* We need PAGE_SIZE >= RADEON_GPU_PAGE_SIZE */ |
330 | /* We need PAGE_SIZE >= RADEON_GPU_PAGE_SIZE */ |
342 | if (PAGE_SIZE < RADEON_GPU_PAGE_SIZE) { |
331 | if (PAGE_SIZE < RADEON_GPU_PAGE_SIZE) { |
343 | DRM_ERROR("Page size is smaller than GPU page size!\n"); |
332 | DRM_ERROR("Page size is smaller than GPU page size!\n"); |
344 | return -EINVAL; |
333 | return -EINVAL; |
345 | } |
334 | } |
346 | r = radeon_dummy_page_init(rdev); |
335 | r = radeon_dummy_page_init(rdev); |
347 | if (r) |
336 | if (r) |
348 | return r; |
337 | return r; |
349 | /* Compute table size */ |
338 | /* Compute table size */ |
350 | rdev->gart.num_cpu_pages = rdev->mc.gtt_size / PAGE_SIZE; |
339 | rdev->gart.num_cpu_pages = rdev->mc.gtt_size / PAGE_SIZE; |
351 | rdev->gart.num_gpu_pages = rdev->mc.gtt_size / RADEON_GPU_PAGE_SIZE; |
340 | rdev->gart.num_gpu_pages = rdev->mc.gtt_size / RADEON_GPU_PAGE_SIZE; |
352 | DRM_INFO("GART: num cpu pages %u, num gpu pages %u\n", |
341 | DRM_INFO("GART: num cpu pages %u, num gpu pages %u\n", |
353 | rdev->gart.num_cpu_pages, rdev->gart.num_gpu_pages); |
342 | rdev->gart.num_cpu_pages, rdev->gart.num_gpu_pages); |
354 | /* Allocate pages table */ |
343 | /* Allocate pages table */ |
355 | rdev->gart.pages = vzalloc(sizeof(void *) * rdev->gart.num_cpu_pages); |
344 | rdev->gart.pages = vzalloc(sizeof(void *) * rdev->gart.num_cpu_pages); |
356 | if (rdev->gart.pages == NULL) { |
345 | if (rdev->gart.pages == NULL) { |
357 | radeon_gart_fini(rdev); |
346 | radeon_gart_fini(rdev); |
358 | return -ENOMEM; |
347 | return -ENOMEM; |
359 | } |
348 | } |
360 | rdev->gart.pages_entry = KernelAlloc(sizeof(uint64_t) * |
349 | rdev->gart.pages_entry = KernelAlloc(sizeof(uint64_t) * |
361 | rdev->gart.num_gpu_pages); |
350 | rdev->gart.num_gpu_pages); |
362 | if (rdev->gart.pages_entry == NULL) { |
351 | if (rdev->gart.pages_entry == NULL) { |
363 | radeon_gart_fini(rdev); |
352 | radeon_gart_fini(rdev); |
364 | return -ENOMEM; |
353 | return -ENOMEM; |
365 | } |
354 | } |
366 | /* set GART entry to point to the dummy page by default */ |
355 | /* set GART entry to point to the dummy page by default */ |
367 | for (i = 0; i < rdev->gart.num_gpu_pages; i++) |
356 | for (i = 0; i < rdev->gart.num_gpu_pages; i++) |
368 | rdev->gart.pages_entry[i] = rdev->dummy_page.entry; |
357 | rdev->gart.pages_entry[i] = rdev->dummy_page.entry; |
369 | return 0; |
358 | return 0; |
370 | } |
359 | } |
371 | 360 | ||
372 | /** |
361 | /** |
373 | * radeon_gart_fini - tear down the driver info for managing the gart |
362 | * radeon_gart_fini - tear down the driver info for managing the gart |
374 | * |
363 | * |
375 | * @rdev: radeon_device pointer |
364 | * @rdev: radeon_device pointer |
376 | * |
365 | * |
377 | * Tear down the gart driver info and free the dummy page (all asics). |
366 | * Tear down the gart driver info and free the dummy page (all asics). |
378 | */ |
367 | */ |
379 | void radeon_gart_fini(struct radeon_device *rdev) |
368 | void radeon_gart_fini(struct radeon_device *rdev) |
380 | { |
369 | { |
381 | if (rdev->gart.ready) { |
370 | if (rdev->gart.ready) { |
382 | /* unbind pages */ |
371 | /* unbind pages */ |
383 | radeon_gart_unbind(rdev, 0, rdev->gart.num_cpu_pages); |
372 | radeon_gart_unbind(rdev, 0, rdev->gart.num_cpu_pages); |
384 | } |
373 | } |
385 | rdev->gart.ready = false; |
374 | rdev->gart.ready = false; |
386 | vfree(rdev->gart.pages); |
375 | vfree(rdev->gart.pages); |
387 | vfree(rdev->gart.pages_entry); |
376 | vfree(rdev->gart.pages_entry); |
388 | rdev->gart.pages = NULL; |
377 | rdev->gart.pages = NULL; |
389 | rdev->gart.pages_entry = NULL; |
378 | rdev->gart.pages_entry = NULL; |
390 | 379 | ||
391 | radeon_dummy_page_fini(rdev); |
380 | radeon_dummy_page_fini(rdev); |
392 | }>>>>>>> |
381 | }>>>>>>> |