1 | /* |
2 | * Copyright 2018 Advanced Micro Devices, Inc. |
3 | * All Rights Reserved. |
4 | * |
5 | * Permission is hereby granted, free of charge, to any person obtaining a |
6 | * copy of this software and associated documentation files (the |
7 | * "Software"), to deal in the Software without restriction, including |
8 | * without limitation the rights to use, copy, modify, merge, publish, |
9 | * distribute, sub license, and/or sell copies of the Software, and to |
10 | * permit persons to whom the Software is furnished to do so, subject to |
11 | * the following conditions: |
12 | * |
13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
15 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL |
16 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, |
17 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
18 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE |
19 | * USE OR OTHER DEALINGS IN THE SOFTWARE. |
20 | * |
21 | * The above copyright notice and this permission notice (including the |
22 | * next paragraph) shall be included in all copies or substantial portions |
23 | * of the Software. |
24 | * |
25 | */ |
26 | |
27 | #include <linux/io-64-nonatomic-lo-hi.h> |
28 | #ifdef CONFIG_X86 |
29 | #include <asm/hypervisor.h> |
30 | #endif |
31 | |
32 | #include "amdgpu.h" |
33 | #include "amdgpu_gmc.h" |
34 | #include "amdgpu_ras.h" |
35 | #include "amdgpu_reset.h" |
36 | #include "amdgpu_xgmi.h" |
37 | |
38 | #include <drm/drm_drv.h> |
39 | #include <drm/ttm/ttm_tt.h> |
40 | |
41 | /** |
42 | * amdgpu_gmc_pdb0_alloc - allocate vram for pdb0 |
43 | * |
44 | * @adev: amdgpu_device pointer |
45 | * |
46 | * Allocate video memory for pdb0 and map it for CPU access |
47 | * Returns 0 for success, error for failure. |
48 | */ |
49 | int amdgpu_gmc_pdb0_alloc(struct amdgpu_device *adev) |
50 | { |
51 | int r; |
52 | struct amdgpu_bo_param bp; |
53 | u64 vram_size = adev->gmc.xgmi.node_segment_size * adev->gmc.xgmi.num_physical_nodes; |
54 | uint32_t pde0_page_shift = adev->gmc.vmid0_page_table_block_size + 21; |
55 | uint32_t npdes = (vram_size + (1ULL << pde0_page_shift) -1) >> pde0_page_shift; |
56 | |
57 | memset(&bp, 0, sizeof(bp)); |
58 | bp.size = PAGE_ALIGN((npdes + 1) * 8); |
59 | bp.byte_align = PAGE_SIZE; |
60 | bp.domain = AMDGPU_GEM_DOMAIN_VRAM; |
61 | bp.flags = AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED | |
62 | AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS; |
63 | bp.type = ttm_bo_type_kernel; |
64 | bp.resv = NULL; |
65 | bp.bo_ptr_size = sizeof(struct amdgpu_bo); |
66 | |
67 | r = amdgpu_bo_create(adev, bp: &bp, bo_ptr: &adev->gmc.pdb0_bo); |
68 | if (r) |
69 | return r; |
70 | |
71 | r = amdgpu_bo_reserve(bo: adev->gmc.pdb0_bo, no_intr: false); |
72 | if (unlikely(r != 0)) |
73 | goto bo_reserve_failure; |
74 | |
75 | r = amdgpu_bo_pin(bo: adev->gmc.pdb0_bo, AMDGPU_GEM_DOMAIN_VRAM); |
76 | if (r) |
77 | goto bo_pin_failure; |
78 | r = amdgpu_bo_kmap(bo: adev->gmc.pdb0_bo, ptr: &adev->gmc.ptr_pdb0); |
79 | if (r) |
80 | goto bo_kmap_failure; |
81 | |
82 | amdgpu_bo_unreserve(bo: adev->gmc.pdb0_bo); |
83 | return 0; |
84 | |
85 | bo_kmap_failure: |
86 | amdgpu_bo_unpin(bo: adev->gmc.pdb0_bo); |
87 | bo_pin_failure: |
88 | amdgpu_bo_unreserve(bo: adev->gmc.pdb0_bo); |
89 | bo_reserve_failure: |
90 | amdgpu_bo_unref(bo: &adev->gmc.pdb0_bo); |
91 | return r; |
92 | } |
93 | |
94 | /** |
95 | * amdgpu_gmc_get_pde_for_bo - get the PDE for a BO |
96 | * |
97 | * @bo: the BO to get the PDE for |
98 | * @level: the level in the PD hirarchy |
99 | * @addr: resulting addr |
100 | * @flags: resulting flags |
101 | * |
102 | * Get the address and flags to be used for a PDE (Page Directory Entry). |
103 | */ |
104 | void amdgpu_gmc_get_pde_for_bo(struct amdgpu_bo *bo, int level, |
105 | uint64_t *addr, uint64_t *flags) |
106 | { |
107 | struct amdgpu_device *adev = amdgpu_ttm_adev(bdev: bo->tbo.bdev); |
108 | |
109 | switch (bo->tbo.resource->mem_type) { |
110 | case TTM_PL_TT: |
111 | *addr = bo->tbo.ttm->dma_address[0]; |
112 | break; |
113 | case TTM_PL_VRAM: |
114 | *addr = amdgpu_bo_gpu_offset(bo); |
115 | break; |
116 | default: |
117 | *addr = 0; |
118 | break; |
119 | } |
120 | *flags = amdgpu_ttm_tt_pde_flags(ttm: bo->tbo.ttm, mem: bo->tbo.resource); |
121 | amdgpu_gmc_get_vm_pde(adev, level, addr, flags); |
122 | } |
123 | |
124 | /* |
125 | * amdgpu_gmc_pd_addr - return the address of the root directory |
126 | */ |
127 | uint64_t amdgpu_gmc_pd_addr(struct amdgpu_bo *bo) |
128 | { |
129 | struct amdgpu_device *adev = amdgpu_ttm_adev(bdev: bo->tbo.bdev); |
130 | uint64_t pd_addr; |
131 | |
132 | /* TODO: move that into ASIC specific code */ |
133 | if (adev->asic_type >= CHIP_VEGA10) { |
134 | uint64_t flags = AMDGPU_PTE_VALID; |
135 | |
136 | amdgpu_gmc_get_pde_for_bo(bo, level: -1, addr: &pd_addr, flags: &flags); |
137 | pd_addr |= flags; |
138 | } else { |
139 | pd_addr = amdgpu_bo_gpu_offset(bo); |
140 | } |
141 | return pd_addr; |
142 | } |
143 | |
144 | /** |
145 | * amdgpu_gmc_set_pte_pde - update the page tables using CPU |
146 | * |
147 | * @adev: amdgpu_device pointer |
148 | * @cpu_pt_addr: cpu address of the page table |
149 | * @gpu_page_idx: entry in the page table to update |
150 | * @addr: dst addr to write into pte/pde |
151 | * @flags: access flags |
152 | * |
153 | * Update the page tables using CPU. |
154 | */ |
155 | int amdgpu_gmc_set_pte_pde(struct amdgpu_device *adev, void *cpu_pt_addr, |
156 | uint32_t gpu_page_idx, uint64_t addr, |
157 | uint64_t flags) |
158 | { |
159 | void __iomem *ptr = (void *)cpu_pt_addr; |
160 | uint64_t value; |
161 | |
162 | /* |
163 | * The following is for PTE only. GART does not have PDEs. |
164 | */ |
165 | value = addr & 0x0000FFFFFFFFF000ULL; |
166 | value |= flags; |
167 | writeq(val: value, addr: ptr + (gpu_page_idx * 8)); |
168 | |
169 | return 0; |
170 | } |
171 | |
172 | /** |
173 | * amdgpu_gmc_agp_addr - return the address in the AGP address space |
174 | * |
175 | * @bo: TTM BO which needs the address, must be in GTT domain |
176 | * |
177 | * Tries to figure out how to access the BO through the AGP aperture. Returns |
178 | * AMDGPU_BO_INVALID_OFFSET if that is not possible. |
179 | */ |
180 | uint64_t amdgpu_gmc_agp_addr(struct ttm_buffer_object *bo) |
181 | { |
182 | struct amdgpu_device *adev = amdgpu_ttm_adev(bdev: bo->bdev); |
183 | |
184 | if (bo->ttm->num_pages != 1 || bo->ttm->caching == ttm_cached) |
185 | return AMDGPU_BO_INVALID_OFFSET; |
186 | |
187 | if (bo->ttm->dma_address[0] + PAGE_SIZE >= adev->gmc.agp_size) |
188 | return AMDGPU_BO_INVALID_OFFSET; |
189 | |
190 | return adev->gmc.agp_start + bo->ttm->dma_address[0]; |
191 | } |
192 | |
193 | /** |
194 | * amdgpu_gmc_vram_location - try to find VRAM location |
195 | * |
196 | * @adev: amdgpu device structure holding all necessary information |
197 | * @mc: memory controller structure holding memory information |
198 | * @base: base address at which to put VRAM |
199 | * |
200 | * Function will try to place VRAM at base address provided |
201 | * as parameter. |
202 | */ |
203 | void amdgpu_gmc_vram_location(struct amdgpu_device *adev, struct amdgpu_gmc *mc, |
204 | u64 base) |
205 | { |
206 | uint64_t vis_limit = (uint64_t)amdgpu_vis_vram_limit << 20; |
207 | uint64_t limit = (uint64_t)amdgpu_vram_limit << 20; |
208 | |
209 | mc->vram_start = base; |
210 | mc->vram_end = mc->vram_start + mc->mc_vram_size - 1; |
211 | if (limit < mc->real_vram_size) |
212 | mc->real_vram_size = limit; |
213 | |
214 | if (vis_limit && vis_limit < mc->visible_vram_size) |
215 | mc->visible_vram_size = vis_limit; |
216 | |
217 | if (mc->real_vram_size < mc->visible_vram_size) |
218 | mc->visible_vram_size = mc->real_vram_size; |
219 | |
220 | if (mc->xgmi.num_physical_nodes == 0) { |
221 | mc->fb_start = mc->vram_start; |
222 | mc->fb_end = mc->vram_end; |
223 | } |
224 | dev_info(adev->dev, "VRAM: %lluM 0x%016llX - 0x%016llX (%lluM used)\n" , |
225 | mc->mc_vram_size >> 20, mc->vram_start, |
226 | mc->vram_end, mc->real_vram_size >> 20); |
227 | } |
228 | |
229 | /** amdgpu_gmc_sysvm_location - place vram and gart in sysvm aperture |
230 | * |
231 | * @adev: amdgpu device structure holding all necessary information |
232 | * @mc: memory controller structure holding memory information |
233 | * |
234 | * This function is only used if use GART for FB translation. In such |
235 | * case, we use sysvm aperture (vmid0 page tables) for both vram |
236 | * and gart (aka system memory) access. |
237 | * |
238 | * GPUVM (and our organization of vmid0 page tables) require sysvm |
239 | * aperture to be placed at a location aligned with 8 times of native |
240 | * page size. For example, if vm_context0_cntl.page_table_block_size |
241 | * is 12, then native page size is 8G (2M*2^12), sysvm should start |
242 | * with a 64G aligned address. For simplicity, we just put sysvm at |
243 | * address 0. So vram start at address 0 and gart is right after vram. |
244 | */ |
245 | void amdgpu_gmc_sysvm_location(struct amdgpu_device *adev, struct amdgpu_gmc *mc) |
246 | { |
247 | u64 hive_vram_start = 0; |
248 | u64 hive_vram_end = mc->xgmi.node_segment_size * mc->xgmi.num_physical_nodes - 1; |
249 | mc->vram_start = mc->xgmi.node_segment_size * mc->xgmi.physical_node_id; |
250 | mc->vram_end = mc->vram_start + mc->xgmi.node_segment_size - 1; |
251 | mc->gart_start = hive_vram_end + 1; |
252 | mc->gart_end = mc->gart_start + mc->gart_size - 1; |
253 | mc->fb_start = hive_vram_start; |
254 | mc->fb_end = hive_vram_end; |
255 | dev_info(adev->dev, "VRAM: %lluM 0x%016llX - 0x%016llX (%lluM used)\n" , |
256 | mc->mc_vram_size >> 20, mc->vram_start, |
257 | mc->vram_end, mc->real_vram_size >> 20); |
258 | dev_info(adev->dev, "GART: %lluM 0x%016llX - 0x%016llX\n" , |
259 | mc->gart_size >> 20, mc->gart_start, mc->gart_end); |
260 | } |
261 | |
262 | /** |
263 | * amdgpu_gmc_gart_location - try to find GART location |
264 | * |
265 | * @adev: amdgpu device structure holding all necessary information |
266 | * @mc: memory controller structure holding memory information |
267 | * @gart_placement: GART placement policy with respect to VRAM |
268 | * |
269 | * Function will place try to place GART before or after VRAM. |
270 | * If GART size is bigger than space left then we ajust GART size. |
271 | * Thus function will never fails. |
272 | */ |
273 | void amdgpu_gmc_gart_location(struct amdgpu_device *adev, struct amdgpu_gmc *mc, |
274 | enum amdgpu_gart_placement gart_placement) |
275 | { |
276 | const uint64_t four_gb = 0x100000000ULL; |
277 | u64 size_af, size_bf; |
278 | /*To avoid the hole, limit the max mc address to AMDGPU_GMC_HOLE_START*/ |
279 | u64 max_mc_address = min(adev->gmc.mc_mask, AMDGPU_GMC_HOLE_START - 1); |
280 | |
281 | /* VCE doesn't like it when BOs cross a 4GB segment, so align |
282 | * the GART base on a 4GB boundary as well. |
283 | */ |
284 | size_bf = mc->fb_start; |
285 | size_af = max_mc_address + 1 - ALIGN(mc->fb_end + 1, four_gb); |
286 | |
287 | if (mc->gart_size > max(size_bf, size_af)) { |
288 | dev_warn(adev->dev, "limiting GART\n" ); |
289 | mc->gart_size = max(size_bf, size_af); |
290 | } |
291 | |
292 | switch (gart_placement) { |
293 | case AMDGPU_GART_PLACEMENT_HIGH: |
294 | mc->gart_start = max_mc_address - mc->gart_size + 1; |
295 | break; |
296 | case AMDGPU_GART_PLACEMENT_LOW: |
297 | mc->gart_start = 0; |
298 | break; |
299 | case AMDGPU_GART_PLACEMENT_BEST_FIT: |
300 | default: |
301 | if ((size_bf >= mc->gart_size && size_bf < size_af) || |
302 | (size_af < mc->gart_size)) |
303 | mc->gart_start = 0; |
304 | else |
305 | mc->gart_start = max_mc_address - mc->gart_size + 1; |
306 | break; |
307 | } |
308 | |
309 | mc->gart_start &= ~(four_gb - 1); |
310 | mc->gart_end = mc->gart_start + mc->gart_size - 1; |
311 | dev_info(adev->dev, "GART: %lluM 0x%016llX - 0x%016llX\n" , |
312 | mc->gart_size >> 20, mc->gart_start, mc->gart_end); |
313 | } |
314 | |
315 | /** |
316 | * amdgpu_gmc_agp_location - try to find AGP location |
317 | * @adev: amdgpu device structure holding all necessary information |
318 | * @mc: memory controller structure holding memory information |
319 | * |
320 | * Function will place try to find a place for the AGP BAR in the MC address |
321 | * space. |
322 | * |
323 | * AGP BAR will be assigned the largest available hole in the address space. |
324 | * Should be called after VRAM and GART locations are setup. |
325 | */ |
326 | void amdgpu_gmc_agp_location(struct amdgpu_device *adev, struct amdgpu_gmc *mc) |
327 | { |
328 | const uint64_t sixteen_gb = 1ULL << 34; |
329 | const uint64_t sixteen_gb_mask = ~(sixteen_gb - 1); |
330 | u64 size_af, size_bf; |
331 | |
332 | if (mc->fb_start > mc->gart_start) { |
333 | size_bf = (mc->fb_start & sixteen_gb_mask) - |
334 | ALIGN(mc->gart_end + 1, sixteen_gb); |
335 | size_af = mc->mc_mask + 1 - ALIGN(mc->fb_end + 1, sixteen_gb); |
336 | } else { |
337 | size_bf = mc->fb_start & sixteen_gb_mask; |
338 | size_af = (mc->gart_start & sixteen_gb_mask) - |
339 | ALIGN(mc->fb_end + 1, sixteen_gb); |
340 | } |
341 | |
342 | if (size_bf > size_af) { |
343 | mc->agp_start = (mc->fb_start - size_bf) & sixteen_gb_mask; |
344 | mc->agp_size = size_bf; |
345 | } else { |
346 | mc->agp_start = ALIGN(mc->fb_end + 1, sixteen_gb); |
347 | mc->agp_size = size_af; |
348 | } |
349 | |
350 | mc->agp_end = mc->agp_start + mc->agp_size - 1; |
351 | dev_info(adev->dev, "AGP: %lluM 0x%016llX - 0x%016llX\n" , |
352 | mc->agp_size >> 20, mc->agp_start, mc->agp_end); |
353 | } |
354 | |
355 | /** |
356 | * amdgpu_gmc_set_agp_default - Set the default AGP aperture value. |
357 | * @adev: amdgpu device structure holding all necessary information |
358 | * @mc: memory controller structure holding memory information |
359 | * |
360 | * To disable the AGP aperture, you need to set the start to a larger |
361 | * value than the end. This function sets the default value which |
362 | * can then be overridden using amdgpu_gmc_agp_location() if you want |
363 | * to enable the AGP aperture on a specific chip. |
364 | * |
365 | */ |
366 | void amdgpu_gmc_set_agp_default(struct amdgpu_device *adev, |
367 | struct amdgpu_gmc *mc) |
368 | { |
369 | mc->agp_start = 0xffffffffffff; |
370 | mc->agp_end = 0; |
371 | mc->agp_size = 0; |
372 | } |
373 | |
374 | /** |
375 | * amdgpu_gmc_fault_key - get hask key from vm fault address and pasid |
376 | * |
377 | * @addr: 48 bit physical address, page aligned (36 significant bits) |
378 | * @pasid: 16 bit process address space identifier |
379 | */ |
380 | static inline uint64_t amdgpu_gmc_fault_key(uint64_t addr, uint16_t pasid) |
381 | { |
382 | return addr << 4 | pasid; |
383 | } |
384 | |
385 | /** |
386 | * amdgpu_gmc_filter_faults - filter VM faults |
387 | * |
388 | * @adev: amdgpu device structure |
389 | * @ih: interrupt ring that the fault received from |
390 | * @addr: address of the VM fault |
391 | * @pasid: PASID of the process causing the fault |
392 | * @timestamp: timestamp of the fault |
393 | * |
394 | * Returns: |
395 | * True if the fault was filtered and should not be processed further. |
396 | * False if the fault is a new one and needs to be handled. |
397 | */ |
398 | bool amdgpu_gmc_filter_faults(struct amdgpu_device *adev, |
399 | struct amdgpu_ih_ring *ih, uint64_t addr, |
400 | uint16_t pasid, uint64_t timestamp) |
401 | { |
402 | struct amdgpu_gmc *gmc = &adev->gmc; |
403 | uint64_t stamp, key = amdgpu_gmc_fault_key(addr, pasid); |
404 | struct amdgpu_gmc_fault *fault; |
405 | uint32_t hash; |
406 | |
407 | /* Stale retry fault if timestamp goes backward */ |
408 | if (amdgpu_ih_ts_after(timestamp, ih->processed_timestamp)) |
409 | return true; |
410 | |
411 | /* If we don't have space left in the ring buffer return immediately */ |
412 | stamp = max(timestamp, AMDGPU_GMC_FAULT_TIMEOUT + 1) - |
413 | AMDGPU_GMC_FAULT_TIMEOUT; |
414 | if (gmc->fault_ring[gmc->last_fault].timestamp >= stamp) |
415 | return true; |
416 | |
417 | /* Try to find the fault in the hash */ |
418 | hash = hash_64(val: key, AMDGPU_GMC_FAULT_HASH_ORDER); |
419 | fault = &gmc->fault_ring[gmc->fault_hash[hash].idx]; |
420 | while (fault->timestamp >= stamp) { |
421 | uint64_t tmp; |
422 | |
423 | if (atomic64_read(v: &fault->key) == key) { |
424 | /* |
425 | * if we get a fault which is already present in |
426 | * the fault_ring and the timestamp of |
427 | * the fault is after the expired timestamp, |
428 | * then this is a new fault that needs to be added |
429 | * into the fault ring. |
430 | */ |
431 | if (fault->timestamp_expiry != 0 && |
432 | amdgpu_ih_ts_after(fault->timestamp_expiry, |
433 | timestamp)) |
434 | break; |
435 | else |
436 | return true; |
437 | } |
438 | |
439 | tmp = fault->timestamp; |
440 | fault = &gmc->fault_ring[fault->next]; |
441 | |
442 | /* Check if the entry was reused */ |
443 | if (fault->timestamp >= tmp) |
444 | break; |
445 | } |
446 | |
447 | /* Add the fault to the ring */ |
448 | fault = &gmc->fault_ring[gmc->last_fault]; |
449 | atomic64_set(v: &fault->key, i: key); |
450 | fault->timestamp = timestamp; |
451 | |
452 | /* And update the hash */ |
453 | fault->next = gmc->fault_hash[hash].idx; |
454 | gmc->fault_hash[hash].idx = gmc->last_fault++; |
455 | return false; |
456 | } |
457 | |
458 | /** |
459 | * amdgpu_gmc_filter_faults_remove - remove address from VM faults filter |
460 | * |
461 | * @adev: amdgpu device structure |
462 | * @addr: address of the VM fault |
463 | * @pasid: PASID of the process causing the fault |
464 | * |
465 | * Remove the address from fault filter, then future vm fault on this address |
466 | * will pass to retry fault handler to recover. |
467 | */ |
468 | void amdgpu_gmc_filter_faults_remove(struct amdgpu_device *adev, uint64_t addr, |
469 | uint16_t pasid) |
470 | { |
471 | struct amdgpu_gmc *gmc = &adev->gmc; |
472 | uint64_t key = amdgpu_gmc_fault_key(addr, pasid); |
473 | struct amdgpu_ih_ring *ih; |
474 | struct amdgpu_gmc_fault *fault; |
475 | uint32_t last_wptr; |
476 | uint64_t last_ts; |
477 | uint32_t hash; |
478 | uint64_t tmp; |
479 | |
480 | if (adev->irq.retry_cam_enabled) |
481 | return; |
482 | |
483 | ih = &adev->irq.ih1; |
484 | /* Get the WPTR of the last entry in IH ring */ |
485 | last_wptr = amdgpu_ih_get_wptr(adev, ih); |
486 | /* Order wptr with ring data. */ |
487 | rmb(); |
488 | /* Get the timetamp of the last entry in IH ring */ |
489 | last_ts = amdgpu_ih_decode_iv_ts(adev, ih, last_wptr, -1); |
490 | |
491 | hash = hash_64(val: key, AMDGPU_GMC_FAULT_HASH_ORDER); |
492 | fault = &gmc->fault_ring[gmc->fault_hash[hash].idx]; |
493 | do { |
494 | if (atomic64_read(v: &fault->key) == key) { |
495 | /* |
496 | * Update the timestamp when this fault |
497 | * expired. |
498 | */ |
499 | fault->timestamp_expiry = last_ts; |
500 | break; |
501 | } |
502 | |
503 | tmp = fault->timestamp; |
504 | fault = &gmc->fault_ring[fault->next]; |
505 | } while (fault->timestamp < tmp); |
506 | } |
507 | |
508 | int amdgpu_gmc_ras_sw_init(struct amdgpu_device *adev) |
509 | { |
510 | int r; |
511 | |
512 | /* umc ras block */ |
513 | r = amdgpu_umc_ras_sw_init(adev); |
514 | if (r) |
515 | return r; |
516 | |
517 | /* mmhub ras block */ |
518 | r = amdgpu_mmhub_ras_sw_init(adev); |
519 | if (r) |
520 | return r; |
521 | |
522 | /* hdp ras block */ |
523 | r = amdgpu_hdp_ras_sw_init(adev); |
524 | if (r) |
525 | return r; |
526 | |
527 | /* mca.x ras block */ |
528 | r = amdgpu_mca_mp0_ras_sw_init(adev); |
529 | if (r) |
530 | return r; |
531 | |
532 | r = amdgpu_mca_mp1_ras_sw_init(adev); |
533 | if (r) |
534 | return r; |
535 | |
536 | r = amdgpu_mca_mpio_ras_sw_init(adev); |
537 | if (r) |
538 | return r; |
539 | |
540 | /* xgmi ras block */ |
541 | r = amdgpu_xgmi_ras_sw_init(adev); |
542 | if (r) |
543 | return r; |
544 | |
545 | return 0; |
546 | } |
547 | |
548 | int amdgpu_gmc_ras_late_init(struct amdgpu_device *adev) |
549 | { |
550 | return 0; |
551 | } |
552 | |
553 | void amdgpu_gmc_ras_fini(struct amdgpu_device *adev) |
554 | { |
555 | |
556 | } |
557 | |
558 | /* |
559 | * The latest engine allocation on gfx9/10 is: |
560 | * Engine 2, 3: firmware |
561 | * Engine 0, 1, 4~16: amdgpu ring, |
562 | * subject to change when ring number changes |
563 | * Engine 17: Gart flushes |
564 | */ |
565 | #define AMDGPU_VMHUB_INV_ENG_BITMAP 0x1FFF3 |
566 | |
567 | int amdgpu_gmc_allocate_vm_inv_eng(struct amdgpu_device *adev) |
568 | { |
569 | struct amdgpu_ring *ring; |
570 | unsigned vm_inv_engs[AMDGPU_MAX_VMHUBS] = {0}; |
571 | unsigned i; |
572 | unsigned vmhub, inv_eng; |
573 | |
574 | /* init the vm inv eng for all vmhubs */ |
575 | for_each_set_bit(i, adev->vmhubs_mask, AMDGPU_MAX_VMHUBS) { |
576 | vm_inv_engs[i] = AMDGPU_VMHUB_INV_ENG_BITMAP; |
577 | /* reserve engine 5 for firmware */ |
578 | if (adev->enable_mes) |
579 | vm_inv_engs[i] &= ~(1 << 5); |
580 | /* reserve mmhub engine 3 for firmware */ |
581 | if (adev->enable_umsch_mm) |
582 | vm_inv_engs[i] &= ~(1 << 3); |
583 | } |
584 | |
585 | for (i = 0; i < adev->num_rings; ++i) { |
586 | ring = adev->rings[i]; |
587 | vmhub = ring->vm_hub; |
588 | |
589 | if (ring == &adev->mes.ring || |
590 | ring == &adev->umsch_mm.ring) |
591 | continue; |
592 | |
593 | inv_eng = ffs(vm_inv_engs[vmhub]); |
594 | if (!inv_eng) { |
595 | dev_err(adev->dev, "no VM inv eng for ring %s\n" , |
596 | ring->name); |
597 | return -EINVAL; |
598 | } |
599 | |
600 | ring->vm_inv_eng = inv_eng - 1; |
601 | vm_inv_engs[vmhub] &= ~(1 << ring->vm_inv_eng); |
602 | |
603 | dev_info(adev->dev, "ring %s uses VM inv eng %u on hub %u\n" , |
604 | ring->name, ring->vm_inv_eng, ring->vm_hub); |
605 | } |
606 | |
607 | return 0; |
608 | } |
609 | |
610 | void amdgpu_gmc_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid, |
611 | uint32_t vmhub, uint32_t flush_type) |
612 | { |
613 | struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring; |
614 | struct amdgpu_vmhub *hub = &adev->vmhub[vmhub]; |
615 | struct dma_fence *fence; |
616 | struct amdgpu_job *job; |
617 | int r; |
618 | |
619 | if (!hub->sdma_invalidation_workaround || vmid || |
620 | !adev->mman.buffer_funcs_enabled || |
621 | !adev->ib_pool_ready || amdgpu_in_reset(adev) || |
622 | !ring->sched.ready) { |
623 | |
624 | /* |
625 | * A GPU reset should flush all TLBs anyway, so no need to do |
626 | * this while one is ongoing. |
627 | */ |
628 | if (!down_read_trylock(sem: &adev->reset_domain->sem)) |
629 | return; |
630 | |
631 | if (adev->gmc.flush_tlb_needs_extra_type_2) |
632 | adev->gmc.gmc_funcs->flush_gpu_tlb(adev, vmid, |
633 | vmhub, 2); |
634 | |
635 | if (adev->gmc.flush_tlb_needs_extra_type_0 && flush_type == 2) |
636 | adev->gmc.gmc_funcs->flush_gpu_tlb(adev, vmid, |
637 | vmhub, 0); |
638 | |
639 | adev->gmc.gmc_funcs->flush_gpu_tlb(adev, vmid, vmhub, |
640 | flush_type); |
641 | up_read(sem: &adev->reset_domain->sem); |
642 | return; |
643 | } |
644 | |
645 | /* The SDMA on Navi 1x has a bug which can theoretically result in memory |
646 | * corruption if an invalidation happens at the same time as an VA |
647 | * translation. Avoid this by doing the invalidation from the SDMA |
648 | * itself at least for GART. |
649 | */ |
650 | mutex_lock(&adev->mman.gtt_window_lock); |
651 | r = amdgpu_job_alloc_with_ib(adev: ring->adev, entity: &adev->mman.high_pr, |
652 | AMDGPU_FENCE_OWNER_UNDEFINED, |
653 | size: 16 * 4, pool_type: AMDGPU_IB_POOL_IMMEDIATE, |
654 | job: &job); |
655 | if (r) |
656 | goto error_alloc; |
657 | |
658 | job->vm_pd_addr = amdgpu_gmc_pd_addr(bo: adev->gart.bo); |
659 | job->vm_needs_flush = true; |
660 | job->ibs->ptr[job->ibs->length_dw++] = ring->funcs->nop; |
661 | amdgpu_ring_pad_ib(ring, &job->ibs[0]); |
662 | fence = amdgpu_job_submit(job); |
663 | mutex_unlock(lock: &adev->mman.gtt_window_lock); |
664 | |
665 | dma_fence_wait(fence, intr: false); |
666 | dma_fence_put(fence); |
667 | |
668 | return; |
669 | |
670 | error_alloc: |
671 | mutex_unlock(lock: &adev->mman.gtt_window_lock); |
672 | dev_err(adev->dev, "Error flushing GPU TLB using the SDMA (%d)!\n" , r); |
673 | } |
674 | |
675 | int amdgpu_gmc_flush_gpu_tlb_pasid(struct amdgpu_device *adev, uint16_t pasid, |
676 | uint32_t flush_type, bool all_hub, |
677 | uint32_t inst) |
678 | { |
679 | u32 usec_timeout = amdgpu_sriov_vf(adev) ? SRIOV_USEC_TIMEOUT : |
680 | adev->usec_timeout; |
681 | struct amdgpu_ring *ring = &adev->gfx.kiq[inst].ring; |
682 | struct amdgpu_kiq *kiq = &adev->gfx.kiq[inst]; |
683 | unsigned int ndw; |
684 | signed long r; |
685 | uint32_t seq; |
686 | |
687 | if (!adev->gmc.flush_pasid_uses_kiq || !ring->sched.ready || |
688 | !down_read_trylock(sem: &adev->reset_domain->sem)) { |
689 | |
690 | if (adev->gmc.flush_tlb_needs_extra_type_2) |
691 | adev->gmc.gmc_funcs->flush_gpu_tlb_pasid(adev, pasid, |
692 | 2, all_hub, |
693 | inst); |
694 | |
695 | if (adev->gmc.flush_tlb_needs_extra_type_0 && flush_type == 2) |
696 | adev->gmc.gmc_funcs->flush_gpu_tlb_pasid(adev, pasid, |
697 | 0, all_hub, |
698 | inst); |
699 | |
700 | adev->gmc.gmc_funcs->flush_gpu_tlb_pasid(adev, pasid, |
701 | flush_type, all_hub, |
702 | inst); |
703 | return 0; |
704 | } |
705 | |
706 | /* 2 dwords flush + 8 dwords fence */ |
707 | ndw = kiq->pmf->invalidate_tlbs_size + 8; |
708 | |
709 | if (adev->gmc.flush_tlb_needs_extra_type_2) |
710 | ndw += kiq->pmf->invalidate_tlbs_size; |
711 | |
712 | if (adev->gmc.flush_tlb_needs_extra_type_0) |
713 | ndw += kiq->pmf->invalidate_tlbs_size; |
714 | |
715 | spin_lock(lock: &adev->gfx.kiq[inst].ring_lock); |
716 | amdgpu_ring_alloc(ring, ndw); |
717 | if (adev->gmc.flush_tlb_needs_extra_type_2) |
718 | kiq->pmf->kiq_invalidate_tlbs(ring, pasid, 2, all_hub); |
719 | |
720 | if (flush_type == 2 && adev->gmc.flush_tlb_needs_extra_type_0) |
721 | kiq->pmf->kiq_invalidate_tlbs(ring, pasid, 0, all_hub); |
722 | |
723 | kiq->pmf->kiq_invalidate_tlbs(ring, pasid, flush_type, all_hub); |
724 | r = amdgpu_fence_emit_polling(ring, s: &seq, MAX_KIQ_REG_WAIT); |
725 | if (r) { |
726 | amdgpu_ring_undo(ring); |
727 | spin_unlock(lock: &adev->gfx.kiq[inst].ring_lock); |
728 | goto error_unlock_reset; |
729 | } |
730 | |
731 | amdgpu_ring_commit(ring); |
732 | spin_unlock(lock: &adev->gfx.kiq[inst].ring_lock); |
733 | r = amdgpu_fence_wait_polling(ring, wait_seq: seq, timeout: usec_timeout); |
734 | if (r < 1) { |
735 | dev_err(adev->dev, "wait for kiq fence error: %ld.\n" , r); |
736 | r = -ETIME; |
737 | goto error_unlock_reset; |
738 | } |
739 | r = 0; |
740 | |
741 | error_unlock_reset: |
742 | up_read(sem: &adev->reset_domain->sem); |
743 | return r; |
744 | } |
745 | |
746 | /** |
747 | * amdgpu_gmc_tmz_set -- check and set if a device supports TMZ |
748 | * @adev: amdgpu_device pointer |
749 | * |
750 | * Check and set if an the device @adev supports Trusted Memory |
751 | * Zones (TMZ). |
752 | */ |
753 | void amdgpu_gmc_tmz_set(struct amdgpu_device *adev) |
754 | { |
755 | switch (amdgpu_ip_version(adev, ip: GC_HWIP, inst: 0)) { |
756 | /* RAVEN */ |
757 | case IP_VERSION(9, 2, 2): |
758 | case IP_VERSION(9, 1, 0): |
759 | /* RENOIR looks like RAVEN */ |
760 | case IP_VERSION(9, 3, 0): |
761 | /* GC 10.3.7 */ |
762 | case IP_VERSION(10, 3, 7): |
763 | /* GC 11.0.1 */ |
764 | case IP_VERSION(11, 0, 1): |
765 | if (amdgpu_tmz == 0) { |
766 | adev->gmc.tmz_enabled = false; |
767 | dev_info(adev->dev, |
768 | "Trusted Memory Zone (TMZ) feature disabled (cmd line)\n" ); |
769 | } else { |
770 | adev->gmc.tmz_enabled = true; |
771 | dev_info(adev->dev, |
772 | "Trusted Memory Zone (TMZ) feature enabled\n" ); |
773 | } |
774 | break; |
775 | case IP_VERSION(10, 1, 10): |
776 | case IP_VERSION(10, 1, 1): |
777 | case IP_VERSION(10, 1, 2): |
778 | case IP_VERSION(10, 1, 3): |
779 | case IP_VERSION(10, 3, 0): |
780 | case IP_VERSION(10, 3, 2): |
781 | case IP_VERSION(10, 3, 4): |
782 | case IP_VERSION(10, 3, 5): |
783 | case IP_VERSION(10, 3, 6): |
784 | /* VANGOGH */ |
785 | case IP_VERSION(10, 3, 1): |
786 | /* YELLOW_CARP*/ |
787 | case IP_VERSION(10, 3, 3): |
788 | case IP_VERSION(11, 0, 4): |
789 | case IP_VERSION(11, 5, 0): |
790 | /* Don't enable it by default yet. |
791 | */ |
792 | if (amdgpu_tmz < 1) { |
793 | adev->gmc.tmz_enabled = false; |
794 | dev_info(adev->dev, |
795 | "Trusted Memory Zone (TMZ) feature disabled as experimental (default)\n" ); |
796 | } else { |
797 | adev->gmc.tmz_enabled = true; |
798 | dev_info(adev->dev, |
799 | "Trusted Memory Zone (TMZ) feature enabled as experimental (cmd line)\n" ); |
800 | } |
801 | break; |
802 | default: |
803 | adev->gmc.tmz_enabled = false; |
804 | dev_info(adev->dev, |
805 | "Trusted Memory Zone (TMZ) feature not supported\n" ); |
806 | break; |
807 | } |
808 | } |
809 | |
810 | /** |
811 | * amdgpu_gmc_noretry_set -- set per asic noretry defaults |
812 | * @adev: amdgpu_device pointer |
813 | * |
814 | * Set a per asic default for the no-retry parameter. |
815 | * |
816 | */ |
817 | void amdgpu_gmc_noretry_set(struct amdgpu_device *adev) |
818 | { |
819 | struct amdgpu_gmc *gmc = &adev->gmc; |
820 | uint32_t gc_ver = amdgpu_ip_version(adev, ip: GC_HWIP, inst: 0); |
821 | bool noretry_default = (gc_ver == IP_VERSION(9, 0, 1) || |
822 | gc_ver == IP_VERSION(9, 3, 0) || |
823 | gc_ver == IP_VERSION(9, 4, 0) || |
824 | gc_ver == IP_VERSION(9, 4, 1) || |
825 | gc_ver == IP_VERSION(9, 4, 2) || |
826 | gc_ver == IP_VERSION(9, 4, 3) || |
827 | gc_ver >= IP_VERSION(10, 3, 0)); |
828 | |
829 | gmc->noretry = (amdgpu_noretry == -1) ? noretry_default : amdgpu_noretry; |
830 | } |
831 | |
832 | void amdgpu_gmc_set_vm_fault_masks(struct amdgpu_device *adev, int hub_type, |
833 | bool enable) |
834 | { |
835 | struct amdgpu_vmhub *hub; |
836 | u32 tmp, reg, i; |
837 | |
838 | hub = &adev->vmhub[hub_type]; |
839 | for (i = 0; i < 16; i++) { |
840 | reg = hub->vm_context0_cntl + hub->ctx_distance * i; |
841 | |
842 | tmp = (hub_type == AMDGPU_GFXHUB(0)) ? |
843 | RREG32_SOC15_IP(GC, reg) : |
844 | RREG32_SOC15_IP(MMHUB, reg); |
845 | |
846 | if (enable) |
847 | tmp |= hub->vm_cntx_cntl_vm_fault; |
848 | else |
849 | tmp &= ~hub->vm_cntx_cntl_vm_fault; |
850 | |
851 | (hub_type == AMDGPU_GFXHUB(0)) ? |
852 | WREG32_SOC15_IP(GC, reg, tmp) : |
853 | WREG32_SOC15_IP(MMHUB, reg, tmp); |
854 | } |
855 | } |
856 | |
857 | void amdgpu_gmc_get_vbios_allocations(struct amdgpu_device *adev) |
858 | { |
859 | unsigned size; |
860 | |
861 | /* |
862 | * Some ASICs need to reserve a region of video memory to avoid access |
863 | * from driver |
864 | */ |
865 | adev->mman.stolen_reserved_offset = 0; |
866 | adev->mman.stolen_reserved_size = 0; |
867 | |
868 | /* |
869 | * TODO: |
870 | * Currently there is a bug where some memory client outside |
871 | * of the driver writes to first 8M of VRAM on S3 resume, |
872 | * this overrides GART which by default gets placed in first 8M and |
873 | * causes VM_FAULTS once GTT is accessed. |
874 | * Keep the stolen memory reservation until the while this is not solved. |
875 | */ |
876 | switch (adev->asic_type) { |
877 | case CHIP_VEGA10: |
878 | adev->mman.keep_stolen_vga_memory = true; |
879 | /* |
880 | * VEGA10 SRIOV VF with MS_HYPERV host needs some firmware reserved area. |
881 | */ |
882 | #ifdef CONFIG_X86 |
883 | if (amdgpu_sriov_vf(adev) && hypervisor_is_type(type: X86_HYPER_MS_HYPERV)) { |
884 | adev->mman.stolen_reserved_offset = 0x500000; |
885 | adev->mman.stolen_reserved_size = 0x200000; |
886 | } |
887 | #endif |
888 | break; |
889 | case CHIP_RAVEN: |
890 | case CHIP_RENOIR: |
891 | adev->mman.keep_stolen_vga_memory = true; |
892 | break; |
893 | default: |
894 | adev->mman.keep_stolen_vga_memory = false; |
895 | break; |
896 | } |
897 | |
898 | if (amdgpu_sriov_vf(adev) || |
899 | !amdgpu_device_has_display_hardware(adev)) { |
900 | size = 0; |
901 | } else { |
902 | size = amdgpu_gmc_get_vbios_fb_size(adev); |
903 | |
904 | if (adev->mman.keep_stolen_vga_memory) |
905 | size = max(size, (unsigned)AMDGPU_VBIOS_VGA_ALLOCATION); |
906 | } |
907 | |
908 | /* set to 0 if the pre-OS buffer uses up most of vram */ |
909 | if ((adev->gmc.real_vram_size - size) < (8 * 1024 * 1024)) |
910 | size = 0; |
911 | |
912 | if (size > AMDGPU_VBIOS_VGA_ALLOCATION) { |
913 | adev->mman.stolen_vga_size = AMDGPU_VBIOS_VGA_ALLOCATION; |
914 | adev->mman.stolen_extended_size = size - adev->mman.stolen_vga_size; |
915 | } else { |
916 | adev->mman.stolen_vga_size = size; |
917 | adev->mman.stolen_extended_size = 0; |
918 | } |
919 | } |
920 | |
921 | /** |
922 | * amdgpu_gmc_init_pdb0 - initialize PDB0 |
923 | * |
924 | * @adev: amdgpu_device pointer |
925 | * |
926 | * This function is only used when GART page table is used |
927 | * for FB address translatioin. In such a case, we construct |
928 | * a 2-level system VM page table: PDB0->PTB, to cover both |
929 | * VRAM of the hive and system memory. |
930 | * |
931 | * PDB0 is static, initialized once on driver initialization. |
932 | * The first n entries of PDB0 are used as PTE by setting |
933 | * P bit to 1, pointing to VRAM. The n+1'th entry points |
934 | * to a big PTB covering system memory. |
935 | * |
936 | */ |
937 | void amdgpu_gmc_init_pdb0(struct amdgpu_device *adev) |
938 | { |
939 | int i; |
940 | uint64_t flags = adev->gart.gart_pte_flags; //TODO it is UC. explore NC/RW? |
941 | /* Each PDE0 (used as PTE) covers (2^vmid0_page_table_block_size)*2M |
942 | */ |
943 | u64 vram_size = adev->gmc.xgmi.node_segment_size * adev->gmc.xgmi.num_physical_nodes; |
944 | u64 pde0_page_size = (1ULL<<adev->gmc.vmid0_page_table_block_size)<<21; |
945 | u64 vram_addr = adev->vm_manager.vram_base_offset - |
946 | adev->gmc.xgmi.physical_node_id * adev->gmc.xgmi.node_segment_size; |
947 | u64 vram_end = vram_addr + vram_size; |
948 | u64 gart_ptb_gpu_pa = amdgpu_gmc_vram_pa(adev, bo: adev->gart.bo); |
949 | int idx; |
950 | |
951 | if (!drm_dev_enter(dev: adev_to_drm(adev), idx: &idx)) |
952 | return; |
953 | |
954 | flags |= AMDGPU_PTE_VALID | AMDGPU_PTE_READABLE; |
955 | flags |= AMDGPU_PTE_WRITEABLE; |
956 | flags |= AMDGPU_PTE_SNOOPED; |
957 | flags |= AMDGPU_PTE_FRAG((adev->gmc.vmid0_page_table_block_size + 9*1)); |
958 | flags |= AMDGPU_PDE_PTE; |
959 | |
960 | /* The first n PDE0 entries are used as PTE, |
961 | * pointing to vram |
962 | */ |
963 | for (i = 0; vram_addr < vram_end; i++, vram_addr += pde0_page_size) |
964 | amdgpu_gmc_set_pte_pde(adev, cpu_pt_addr: adev->gmc.ptr_pdb0, gpu_page_idx: i, addr: vram_addr, flags); |
965 | |
966 | /* The n+1'th PDE0 entry points to a huge |
967 | * PTB who has more than 512 entries each |
968 | * pointing to a 4K system page |
969 | */ |
970 | flags = AMDGPU_PTE_VALID; |
971 | flags |= AMDGPU_PDE_BFS(0) | AMDGPU_PTE_SNOOPED; |
972 | /* Requires gart_ptb_gpu_pa to be 4K aligned */ |
973 | amdgpu_gmc_set_pte_pde(adev, cpu_pt_addr: adev->gmc.ptr_pdb0, gpu_page_idx: i, addr: gart_ptb_gpu_pa, flags); |
974 | drm_dev_exit(idx); |
975 | } |
976 | |
977 | /** |
978 | * amdgpu_gmc_vram_mc2pa - calculate vram buffer's physical address from MC |
979 | * address |
980 | * |
981 | * @adev: amdgpu_device pointer |
982 | * @mc_addr: MC address of buffer |
983 | */ |
984 | uint64_t amdgpu_gmc_vram_mc2pa(struct amdgpu_device *adev, uint64_t mc_addr) |
985 | { |
986 | return mc_addr - adev->gmc.vram_start + adev->vm_manager.vram_base_offset; |
987 | } |
988 | |
989 | /** |
990 | * amdgpu_gmc_vram_pa - calculate vram buffer object's physical address from |
991 | * GPU's view |
992 | * |
993 | * @adev: amdgpu_device pointer |
994 | * @bo: amdgpu buffer object |
995 | */ |
996 | uint64_t amdgpu_gmc_vram_pa(struct amdgpu_device *adev, struct amdgpu_bo *bo) |
997 | { |
998 | return amdgpu_gmc_vram_mc2pa(adev, mc_addr: amdgpu_bo_gpu_offset(bo)); |
999 | } |
1000 | |
1001 | /** |
1002 | * amdgpu_gmc_vram_cpu_pa - calculate vram buffer object's physical address |
1003 | * from CPU's view |
1004 | * |
1005 | * @adev: amdgpu_device pointer |
1006 | * @bo: amdgpu buffer object |
1007 | */ |
1008 | uint64_t amdgpu_gmc_vram_cpu_pa(struct amdgpu_device *adev, struct amdgpu_bo *bo) |
1009 | { |
1010 | return amdgpu_bo_gpu_offset(bo) - adev->gmc.vram_start + adev->gmc.aper_base; |
1011 | } |
1012 | |
1013 | int amdgpu_gmc_vram_checking(struct amdgpu_device *adev) |
1014 | { |
1015 | struct amdgpu_bo *vram_bo = NULL; |
1016 | uint64_t vram_gpu = 0; |
1017 | void *vram_ptr = NULL; |
1018 | |
1019 | int ret, size = 0x100000; |
1020 | uint8_t cptr[10]; |
1021 | |
1022 | ret = amdgpu_bo_create_kernel(adev, size, PAGE_SIZE, |
1023 | AMDGPU_GEM_DOMAIN_VRAM, |
1024 | bo_ptr: &vram_bo, |
1025 | gpu_addr: &vram_gpu, |
1026 | cpu_addr: &vram_ptr); |
1027 | if (ret) |
1028 | return ret; |
1029 | |
1030 | memset(vram_ptr, 0x86, size); |
1031 | memset(cptr, 0x86, 10); |
1032 | |
1033 | /** |
1034 | * Check the start, the mid, and the end of the memory if the content of |
1035 | * each byte is the pattern "0x86". If yes, we suppose the vram bo is |
1036 | * workable. |
1037 | * |
1038 | * Note: If check the each byte of whole 1M bo, it will cost too many |
1039 | * seconds, so here, we just pick up three parts for emulation. |
1040 | */ |
1041 | ret = memcmp(p: vram_ptr, q: cptr, size: 10); |
1042 | if (ret) |
1043 | return ret; |
1044 | |
1045 | ret = memcmp(p: vram_ptr + (size / 2), q: cptr, size: 10); |
1046 | if (ret) |
1047 | return ret; |
1048 | |
1049 | ret = memcmp(p: vram_ptr + size - 10, q: cptr, size: 10); |
1050 | if (ret) |
1051 | return ret; |
1052 | |
1053 | amdgpu_bo_free_kernel(bo: &vram_bo, gpu_addr: &vram_gpu, |
1054 | cpu_addr: &vram_ptr); |
1055 | |
1056 | return 0; |
1057 | } |
1058 | |
1059 | static ssize_t current_memory_partition_show( |
1060 | struct device *dev, struct device_attribute *addr, char *buf) |
1061 | { |
1062 | struct drm_device *ddev = dev_get_drvdata(dev); |
1063 | struct amdgpu_device *adev = drm_to_adev(ddev); |
1064 | enum amdgpu_memory_partition mode; |
1065 | |
1066 | mode = adev->gmc.gmc_funcs->query_mem_partition_mode(adev); |
1067 | switch (mode) { |
1068 | case AMDGPU_NPS1_PARTITION_MODE: |
1069 | return sysfs_emit(buf, fmt: "NPS1\n" ); |
1070 | case AMDGPU_NPS2_PARTITION_MODE: |
1071 | return sysfs_emit(buf, fmt: "NPS2\n" ); |
1072 | case AMDGPU_NPS3_PARTITION_MODE: |
1073 | return sysfs_emit(buf, fmt: "NPS3\n" ); |
1074 | case AMDGPU_NPS4_PARTITION_MODE: |
1075 | return sysfs_emit(buf, fmt: "NPS4\n" ); |
1076 | case AMDGPU_NPS6_PARTITION_MODE: |
1077 | return sysfs_emit(buf, fmt: "NPS6\n" ); |
1078 | case AMDGPU_NPS8_PARTITION_MODE: |
1079 | return sysfs_emit(buf, fmt: "NPS8\n" ); |
1080 | default: |
1081 | return sysfs_emit(buf, fmt: "UNKNOWN\n" ); |
1082 | } |
1083 | |
1084 | return sysfs_emit(buf, fmt: "UNKNOWN\n" ); |
1085 | } |
1086 | |
1087 | static DEVICE_ATTR_RO(current_memory_partition); |
1088 | |
1089 | int amdgpu_gmc_sysfs_init(struct amdgpu_device *adev) |
1090 | { |
1091 | if (!adev->gmc.gmc_funcs->query_mem_partition_mode) |
1092 | return 0; |
1093 | |
1094 | return device_create_file(device: adev->dev, |
1095 | entry: &dev_attr_current_memory_partition); |
1096 | } |
1097 | |
1098 | void amdgpu_gmc_sysfs_fini(struct amdgpu_device *adev) |
1099 | { |
1100 | device_remove_file(dev: adev->dev, attr: &dev_attr_current_memory_partition); |
1101 | } |
1102 | |