1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29#include <linux/pci.h>
30#include <linux/vmalloc.h>
31
32#include <drm/amdgpu_drm.h>
33#ifdef CONFIG_X86
34#include <asm/set_memory.h>
35#endif
36#include "amdgpu.h"
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72static int amdgpu_gart_dummy_page_init(struct amdgpu_device *adev)
73{
74 struct page *dummy_page = ttm_glob.dummy_read_page;
75
76 if (adev->dummy_page_addr)
77 return 0;
78 adev->dummy_page_addr = dma_map_page(&adev->pdev->dev, dummy_page, 0,
79 PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
80 if (dma_mapping_error(&adev->pdev->dev, adev->dummy_page_addr)) {
81 dev_err(&adev->pdev->dev, "Failed to DMA MAP the dummy page\n");
82 adev->dummy_page_addr = 0;
83 return -ENOMEM;
84 }
85 return 0;
86}
87
88
89
90
91
92
93
94
95void amdgpu_gart_dummy_page_fini(struct amdgpu_device *adev)
96{
97 if (!adev->dummy_page_addr)
98 return;
99 pci_unmap_page(adev->pdev, adev->dummy_page_addr,
100 PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
101 adev->dummy_page_addr = 0;
102}
103
104
105
106
107
108
109
110
111
112
113
114int amdgpu_gart_table_vram_alloc(struct amdgpu_device *adev)
115{
116 int r;
117
118 if (adev->gart.bo == NULL) {
119 struct amdgpu_bo_param bp;
120
121 memset(&bp, 0, sizeof(bp));
122 bp.size = adev->gart.table_size;
123 bp.byte_align = PAGE_SIZE;
124 bp.domain = AMDGPU_GEM_DOMAIN_VRAM;
125 bp.flags = AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
126 AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;
127 bp.type = ttm_bo_type_kernel;
128 bp.resv = NULL;
129 bp.bo_ptr_size = sizeof(struct amdgpu_bo);
130
131 r = amdgpu_bo_create(adev, &bp, &adev->gart.bo);
132 if (r) {
133 return r;
134 }
135 }
136 return 0;
137}
138
139
140
141
142
143
144
145
146
147
148
149int amdgpu_gart_table_vram_pin(struct amdgpu_device *adev)
150{
151 int r;
152
153 r = amdgpu_bo_reserve(adev->gart.bo, false);
154 if (unlikely(r != 0))
155 return r;
156 r = amdgpu_bo_pin(adev->gart.bo, AMDGPU_GEM_DOMAIN_VRAM);
157 if (r) {
158 amdgpu_bo_unreserve(adev->gart.bo);
159 return r;
160 }
161 r = amdgpu_bo_kmap(adev->gart.bo, &adev->gart.ptr);
162 if (r)
163 amdgpu_bo_unpin(adev->gart.bo);
164 amdgpu_bo_unreserve(adev->gart.bo);
165 return r;
166}
167
168
169
170
171
172
173
174
175
176void amdgpu_gart_table_vram_unpin(struct amdgpu_device *adev)
177{
178 int r;
179
180 if (adev->gart.bo == NULL) {
181 return;
182 }
183 r = amdgpu_bo_reserve(adev->gart.bo, true);
184 if (likely(r == 0)) {
185 amdgpu_bo_kunmap(adev->gart.bo);
186 amdgpu_bo_unpin(adev->gart.bo);
187 amdgpu_bo_unreserve(adev->gart.bo);
188 adev->gart.ptr = NULL;
189 }
190}
191
192
193
194
195
196
197
198
199
200
201void amdgpu_gart_table_vram_free(struct amdgpu_device *adev)
202{
203 if (adev->gart.bo == NULL) {
204 return;
205 }
206 amdgpu_bo_unref(&adev->gart.bo);
207 adev->gart.ptr = NULL;
208}
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224int amdgpu_gart_unbind(struct amdgpu_device *adev, uint64_t offset,
225 int pages)
226{
227 unsigned t;
228 unsigned p;
229 int i, j;
230 u64 page_base;
231
232 uint64_t flags = 0;
233
234 if (!adev->gart.ready) {
235 WARN(1, "trying to unbind memory from uninitialized GART !\n");
236 return -EINVAL;
237 }
238
239 t = offset / AMDGPU_GPU_PAGE_SIZE;
240 p = t / AMDGPU_GPU_PAGES_IN_CPU_PAGE;
241 for (i = 0; i < pages; i++, p++) {
242 page_base = adev->dummy_page_addr;
243 if (!adev->gart.ptr)
244 continue;
245
246 for (j = 0; j < AMDGPU_GPU_PAGES_IN_CPU_PAGE; j++, t++) {
247 amdgpu_gmc_set_pte_pde(adev, adev->gart.ptr,
248 t, page_base, flags);
249 page_base += AMDGPU_GPU_PAGE_SIZE;
250 }
251 }
252 mb();
253 amdgpu_device_flush_hdp(adev, NULL);
254 for (i = 0; i < adev->num_vmhubs; i++)
255 amdgpu_gmc_flush_gpu_tlb(adev, 0, i, 0);
256
257 return 0;
258}
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273int amdgpu_gart_map(struct amdgpu_device *adev, uint64_t offset,
274 int pages, dma_addr_t *dma_addr, uint64_t flags,
275 void *dst)
276{
277 uint64_t page_base;
278 unsigned i, j, t;
279
280 if (!adev->gart.ready) {
281 WARN(1, "trying to bind memory to uninitialized GART !\n");
282 return -EINVAL;
283 }
284
285 t = offset / AMDGPU_GPU_PAGE_SIZE;
286
287 for (i = 0; i < pages; i++) {
288 page_base = dma_addr[i];
289 for (j = 0; j < AMDGPU_GPU_PAGES_IN_CPU_PAGE; j++, t++) {
290 amdgpu_gmc_set_pte_pde(adev, dst, t, page_base, flags);
291 page_base += AMDGPU_GPU_PAGE_SIZE;
292 }
293 }
294 return 0;
295}
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310int amdgpu_gart_bind(struct amdgpu_device *adev, uint64_t offset,
311 int pages, dma_addr_t *dma_addr,
312 uint64_t flags)
313{
314 if (!adev->gart.ready) {
315 WARN(1, "trying to bind memory to uninitialized GART !\n");
316 return -EINVAL;
317 }
318
319 if (!adev->gart.ptr)
320 return 0;
321
322 return amdgpu_gart_map(adev, offset, pages, dma_addr, flags,
323 adev->gart.ptr);
324}
325
326
327
328
329
330
331
332
333
334void amdgpu_gart_invalidate_tlb(struct amdgpu_device *adev)
335{
336 int i;
337
338 mb();
339 amdgpu_device_flush_hdp(adev, NULL);
340 for (i = 0; i < adev->num_vmhubs; i++)
341 amdgpu_gmc_flush_gpu_tlb(adev, 0, i, 0);
342}
343
344
345
346
347
348
349
350
351
352int amdgpu_gart_init(struct amdgpu_device *adev)
353{
354 int r;
355
356 if (adev->dummy_page_addr)
357 return 0;
358
359
360 if (PAGE_SIZE < AMDGPU_GPU_PAGE_SIZE) {
361 DRM_ERROR("Page size is smaller than GPU page size!\n");
362 return -EINVAL;
363 }
364 r = amdgpu_gart_dummy_page_init(adev);
365 if (r)
366 return r;
367
368 adev->gart.num_cpu_pages = adev->gmc.gart_size / PAGE_SIZE;
369 adev->gart.num_gpu_pages = adev->gmc.gart_size / AMDGPU_GPU_PAGE_SIZE;
370 DRM_INFO("GART: num cpu pages %u, num gpu pages %u\n",
371 adev->gart.num_cpu_pages, adev->gart.num_gpu_pages);
372
373 return 0;
374}
375