amd-drm-fixes-7.2-2026-08-06: amdgpu: - JPEG queue reset fixes - GC 12 fix - GMC 12.1 fixes - Lockdep false positive fix - Userq fix - Bounds checking fixes - Devcoredump fixes - DCN 2.0.1 fix - Aperture mapping fix - DC avmute fix - DC self refresh fix radeon: - Performance regression fix Signed-off-by: Dave Airlie <airlied@redhat.com>
Unified · Split
| @@ -42,6 +42,26 @@ · 41 unmodified lines | ||
| 42 | 42 | #include "amdgpu_ras.h" |
| 43 | 43 | #include "amdgpu_hmm.h" |
| 44 | 44 | |
| 45 | +/* | |
| 46 | + * Maximum IB length (dwords) for rings whose emit_ib packet format | |
| 47 | + * documents a 20-bit size field. | |
| 48 | + */ | |
| 49 | +#define AMDGPU_GFX_SDMA_IB_PACKET_SIZE_MAX_DW 0xFFFFF | |
| 50 | +#define AMDGPU_MM_IB_PACKET_SIZE_MAX_DW 0x7FFFF0 | |
| 51 | + | |
| 52 | +static u32 amdgpu_cs_ib_packet_size_max_dw(enum amdgpu_ring_type type) | |
| 53 | +{ | |
| 54 | + switch (type) { | |
| 55 | + case AMDGPU_RING_TYPE_GFX: | |
| 56 | + case AMDGPU_RING_TYPE_COMPUTE: | |
| 57 | + case AMDGPU_RING_TYPE_SDMA: | |
| 58 | + case AMDGPU_RING_TYPE_VPE: | |
| 59 | + return AMDGPU_GFX_SDMA_IB_PACKET_SIZE_MAX_DW; | |
| 60 | + default: | |
| 61 | + return AMDGPU_MM_IB_PACKET_SIZE_MAX_DW; | |
| 62 | + } | |
| 63 | +} | |
| 64 | + | |
| 45 | 65 | static int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, |
| 46 | 66 | struct amdgpu_device *adev, |
| 47 | 67 | struct drm_file *filp, |
| @@ -345,7 +365,6 @@ static int amdgpu_cs_p2_ib(struct amdgpu_cs_parser *p, · 297 unmodified lines | ||
| 345 | 365 | |
| 346 | 366 | job = p->jobs[r]; |
| 347 | 367 | ring = amdgpu_job_ring(job); |
| 348 | − ib = &job->ibs[job->num_ibs++]; | |
| 349 | 368 | |
| 350 | 369 | /* submissions to kernel queues are disabled */ |
| 351 | 370 | if (ring->no_user_submission) |
| @@ -374,6 +393,12 @@ static int amdgpu_cs_p2_ib(struct amdgpu_cs_parser *p, · 22 unmodified lines | ||
| 374 | 393 | return -EINVAL; |
| 375 | 394 | } |
| 376 | 395 | |
| 396 | + if (chunk_ib->ib_bytes / 4 > | |
| 397 | + amdgpu_cs_ib_packet_size_max_dw(ring->funcs->type)) | |
| 398 | + return -EINVAL; | |
| 399 | + | |
| 400 | + ib = &job->ibs[job->num_ibs++]; | |
| 401 | + | |
| 377 | 402 | if (chunk_ib->flags & AMDGPU_IB_FLAG_PREAMBLE) |
| 378 | 403 | job->preamble_status |= AMDGPU_PREAMBLE_IB_PRESENT; |
| 379 | 404 | |
| @@ -342,7 +342,7 @@ amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_inf · 341 unmodified lines | ||
| 342 | 342 | struct amdgpu_ip_block *ip_block; |
| 343 | 343 | struct amdgpu_ring *ring; |
| 344 | 344 | int ver, i, j; |
| 345 | − u32 ring_idx, off; | |
| 345 | + u32 ring_idx; | |
| 346 | 346 | bool sizing_pass; |
| 347 | 347 | |
| 348 | 348 | sizing_pass = buffer == NULL; |
| @@ -442,7 +442,6 @@ amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_inf · 93 unmodified lines | ||
| 442 | 442 | for (i = 0; i < coredump->num_rings; i++) { |
| 443 | 443 | ring_idx = coredump->rings[i].ring_index; |
| 444 | 444 | ring = coredump->adev->rings[ring_idx]; |
| 445 | − off = coredump->rings[i].offset; | |
| 446 | 445 | |
| 447 | 446 | drm_printf(&p, "ring name: %s\n", ring->name); |
| 448 | 447 | drm_printf(&p, "Rptr: 0x%llx Wptr: 0x%llx RB mask: %x\n", |
| @@ -451,12 +450,18 @@ amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_inf · 2 unmodified lines | ||
| 451 | 450 | ring->buf_mask); |
| 452 | 451 | drm_printf(&p, "Ring size in dwords: %d\n", |
| 453 | 452 | ring->ring_size / 4); |
| 453 | + | |
| 454 | + if (!coredump->rings[i].ring_dw) { | |
| 455 | + drm_printf(&p, "Ring contents unavailable\n"); | |
| 456 | + continue; | |
| 457 | + } | |
| 458 | + | |
| 454 | 459 | drm_printf(&p, "Ring contents\n"); |
| 455 | 460 | drm_printf(&p, "Offset \t Value\n"); |
| 456 | 461 | |
| 457 | 462 | for (j = 0; j < ring->ring_size; j += 4) |
| 458 | 463 | drm_printf(&p, "0x%x \t 0x%x\n", j, |
| 459 | − coredump->rings_dw[off + j / 4]); | |
| 464 | + coredump->rings[i].ring_dw[j / 4]); | |
| 460 | 465 | } |
| 461 | 466 | } |
| 462 | 467 | |
| @@ -497,10 +502,12 @@ amdgpu_devcoredump_read(char *buffer, loff_t offset, size_t count, · 34 unmodified lines | ||
| 497 | 502 | static void amdgpu_devcoredump_free(void *data) |
| 498 | 503 | { |
| 499 | 504 | struct amdgpu_coredump_info *coredump = data; |
| 505 | + u32 i; | |
| 500 | 506 | |
| 501 | 507 | kvfree(coredump->formatted); |
| 508 | + for (i = 0; i < coredump->num_rings; i++) | |
| 509 | + kvfree(coredump->rings[i].ring_dw); | |
| 502 | 510 | kvfree(coredump->rings); |
| 503 | − kvfree(coredump->rings_dw); | |
| 504 | 511 | kvfree(data); |
| 505 | 512 | } |
| 506 | 513 | |
| @@ -542,9 +549,9 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check, · 35 unmodified lines | ||
| 542 | 549 | struct amdgpu_coredump_info *coredump; |
| 543 | 550 | size_t size = sizeof(*coredump); |
| 544 | 551 | struct drm_sched_job *s_job; |
| 545 | − u64 total_ring_size, ring_count; | |
| 552 | + u64 ring_count; | |
| 546 | 553 | struct amdgpu_ring *ring; |
| 547 | − int i, off, idx; | |
| 554 | + int i, idx; | |
| 548 | 555 | |
| 549 | 556 | /* No need to generate a new coredump if there's one in progress already. */ |
| 550 | 557 | if (work_busy(&adev->coredump_work)) |
| @@ -553,7 +560,7 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check, · 2 unmodified lines | ||
| 553 | 560 | if (job && job->pasid) |
| 554 | 561 | size += sizeof(struct amdgpu_coredump_ib_info) * job->num_ibs; |
| 555 | 562 | |
| 556 | − coredump = kzalloc(size, GFP_NOWAIT); | |
| 563 | + coredump = kvzalloc(size, GFP_NOWAIT); | |
| 557 | 564 | if (!coredump) |
| 558 | 565 | return; |
| 559 | 566 | |
| @@ -584,7 +591,6 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check, · 24 unmodified lines | ||
| 584 | 591 | |
| 585 | 592 | /* Dump ring content if memory allocation succeeds. */ |
| 586 | 593 | ring_count = 0; |
| 587 | − total_ring_size = 0; | |
| 588 | 594 | for (i = 0; i < adev->num_rings; i++) { |
| 589 | 595 | ring = adev->rings[i]; |
| 590 | 596 | |
| @@ -593,34 +599,34 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check, · 2 unmodified lines | ||
| 593 | 599 | coredump->ring != ring) |
| 594 | 600 | continue; |
| 595 | 601 | |
| 596 | − total_ring_size += ring->ring_size; | |
| 597 | 602 | ring_count++; |
| 598 | 603 | } |
| 599 | − coredump->rings_dw = kzalloc(total_ring_size, GFP_NOWAIT); | |
| 600 | − coredump->rings = kcalloc(ring_count, sizeof(struct amdgpu_coredump_ring), GFP_NOWAIT); | |
| 601 | − if (coredump->rings && coredump->rings_dw) { | |
| 602 | − for (i = 0, off = 0, idx = 0; i < adev->num_rings && idx < ring_count; i++) { | |
| 604 | + if (ring_count) | |
| 605 | + coredump->rings = kvcalloc(ring_count, | |
| 606 | + sizeof(struct amdgpu_coredump_ring), | |
| 607 | + GFP_NOWAIT); | |
| 608 | + if (coredump->rings) { | |
| 609 | + for (i = 0, idx = 0; i < adev->num_rings && idx < ring_count; i++) { | |
| 610 | + struct amdgpu_coredump_ring *cdump_ring; | |
| 611 | + | |
| 603 | 612 | ring = adev->rings[i]; |
| 604 | 613 | |
| 605 | 614 | if (atomic_read(&ring->fence_drv.last_seq) == ring->fence_drv.sync_seq && |
| 606 | 615 | coredump->ring != ring) |
| 607 | 616 | continue; |
| 608 | 617 | |
| 609 | − coredump->rings[idx].ring_index = ring->idx; | |
| 610 | − coredump->rings[idx].rptr = amdgpu_ring_get_rptr(ring); | |
| 611 | − coredump->rings[idx].wptr = amdgpu_ring_get_wptr(ring); | |
| 612 | − coredump->rings[idx].offset = off; | |
| 618 | + cdump_ring = &coredump->rings[idx]; | |
| 619 | + | |
| 620 | + cdump_ring->ring_dw = kvzalloc(ring->ring_size, GFP_NOWAIT); | |
| 621 | + if (cdump_ring->ring_dw) | |
| 622 | + memcpy(cdump_ring->ring_dw, ring->ring, ring->ring_size); | |
| 613 | 623 | |
| 614 | − memcpy(&coredump->rings_dw[off], ring->ring, ring->ring_size); | |
| 615 | − off += ring->ring_size / 4; | |
| 624 | + cdump_ring->ring_index = ring->idx; | |
| 625 | + cdump_ring->rptr = amdgpu_ring_get_rptr(ring); | |
| 626 | + cdump_ring->wptr = amdgpu_ring_get_wptr(ring); | |
| 616 | 627 | idx++; |
| 617 | 628 | } |
| 618 | 629 | coredump->num_rings = idx; |
| 619 | − } else { | |
| 620 | − kvfree(coredump->rings_dw); | |
| 621 | − kvfree(coredump->rings); | |
| 622 | − coredump->rings_dw = NULL; | |
| 623 | − coredump->rings = NULL; | |
| 624 | 630 | } |
| 625 | 631 | |
| 626 | 632 | coredump->adev = adev; |
| @@ -34,8 +34,8 @@ · 33 unmodified lines | ||
| 34 | 34 | struct amdgpu_coredump_ring { |
| 35 | 35 | u64 rptr; |
| 36 | 36 | u64 wptr; |
| 37 | + u32 *ring_dw; | |
| 37 | 38 | u32 ring_index; |
| 38 | − u32 offset; | |
| 39 | 39 | }; |
| 40 | 40 | |
| 41 | 41 | struct amdgpu_coredump_ib_info { |
| @@ -53,7 +53,6 @@ struct amdgpu_coredump_info { · 11 unmodified lines | ||
| 53 | 53 | struct amdgpu_ring *ring; |
| 54 | 54 | |
| 55 | 55 | struct amdgpu_coredump_ring *rings; |
| 56 | − u32 *rings_dw; | |
| 57 | 56 | u32 num_rings; |
| 58 | 57 | |
| 59 | 58 | /* Readable form of coredevdump, generate once to speed up |
| @@ -4194,6 +4194,8 @@ static void amdgpu_device_unmap_mmio(struct amdgpu_device *adev) · 4193 unmodified lines | ||
| 4194 | 4194 | |
| 4195 | 4195 | iounmap(adev->rmmio); |
| 4196 | 4196 | adev->rmmio = NULL; |
| 4197 | + if (adev->mman.aper_base_kaddr) | |
| 4198 | + iounmap(adev->mman.aper_base_kaddr); | |
| 4197 | 4199 | adev->mman.aper_base_kaddr = NULL; |
| 4198 | 4200 | |
| 4199 | 4201 | /* Memory manager related */ |
| @@ -135,6 +135,21 @@ int amdgpu_lockdep_init(void) · 134 unmodified lines | ||
| 135 | 135 | lockdep_set_class(&locks->srbm_mutex, &amdgpu_srbm_lock_key); |
| 136 | 136 | lockdep_set_class(&locks->grbm_idx_mutex, &amdgpu_grbm_lock_key); |
| 137 | 137 | lockdep_set_class(&locks->mmio_idx_lock, &amdgpu_mmio_lock_key); |
| 138 | + | |
| 139 | + /* | |
| 140 | + * Register fs_reclaim lock class FIRST, before taking any locks. | |
| 141 | + * | |
| 142 | + * This acquire/release pair does NOT create a static lockdep edge | |
| 143 | + * (no locks are held between acquire and release). It only registers | |
| 144 | + * the fs_reclaim lock class with lockdep. | |
| 145 | + * | |
| 146 | + * The actual fs_reclaim -> notifier_lock dependency is established at | |
| 147 | + * RUNTIME when memory reclaim invokes MMU notifiers: | |
| 148 | + * fs_reclaim (held by reclaim) -> notifier_lock (acquired in callback) | |
| 149 | + */ | |
| 150 | + fs_reclaim_acquire(GFP_KERNEL); | |
| 151 | + fs_reclaim_release(GFP_KERNEL); | |
| 152 | + | |
| 138 | 153 | /* |
| 139 | 154 | * Take locks in the correct order to train lockdep. |
| 140 | 155 | * This establishes the dependency chain. |
| @@ -154,11 +169,6 @@ int amdgpu_lockdep_init(void) · 13 unmodified lines | ||
| 154 | 169 | |
| 155 | 170 | /* Level 6: Reset control lock */ |
| 156 | 171 | mutex_lock(&locks->reset_lock); |
| 157 | − /* | |
| 158 | − * Mark potential memory reclaim boundary. | |
| 159 | − * GPU operations might trigger memory allocation/reclaim. | |
| 160 | − */ | |
| 161 | − fs_reclaim_acquire(GFP_KERNEL); | |
| 162 | 172 | |
| 163 | 173 | /* Level 7: SRBM register access */ |
| 164 | 174 | mutex_lock(&locks->srbm_mutex); |
| @@ -176,7 +186,6 @@ int amdgpu_lockdep_init(void) · 11 unmodified lines | ||
| 176 | 186 | spin_unlock_irqrestore(&locks->mmio_idx_lock, flags); |
| 177 | 187 | mutex_unlock(&locks->grbm_idx_mutex); |
| 178 | 188 | mutex_unlock(&locks->srbm_mutex); |
| 179 | − fs_reclaim_release(GFP_KERNEL); | |
| 180 | 189 | |
| 181 | 190 | mutex_unlock(&locks->reset_lock); |
| 182 | 191 | up_read(&reset_domain->sem); |
| @@ -2120,23 +2120,17 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) · 2119 unmodified lines | ||
| 2120 | 2120 | /* Change the size here instead of the init above so only lpfn is affected */ |
| 2121 | 2121 | amdgpu_ttm_disable_buffer_funcs(adev); |
| 2122 | 2122 | #ifdef CONFIG_64BIT |
| 2123 | − if (adev->gmc.xgmi.connected_to_cpu) { | |
| 2124 | − void *kaddr = devm_memremap(adev->dev, adev->gmc.aper_base, | |
| 2125 | − adev->gmc.visible_vram_size, | |
| 2126 | − MEMREMAP_WB); | |
| 2127 | − if (IS_ERR(kaddr)) | |
| 2128 | − return PTR_ERR(kaddr); | |
| 2129 | − adev->mman.aper_base_kaddr = (__force void __iomem *)kaddr; | |
| 2130 | − } else if (adev->gmc.is_app_apu) { | |
| 2123 | +#ifdef CONFIG_X86 | |
| 2124 | + if (adev->gmc.xgmi.connected_to_cpu) | |
| 2125 | + adev->mman.aper_base_kaddr = ioremap_cache(adev->gmc.aper_base, | |
| 2126 | + adev->gmc.visible_vram_size); | |
| 2127 | + else if (adev->gmc.is_app_apu) | |
| 2131 | 2128 | DRM_DEBUG_DRIVER( |
| 2132 | 2129 | "No need to ioremap when real vram size is 0\n"); |
| 2133 | − } else { | |
| 2134 | − adev->mman.aper_base_kaddr = devm_ioremap_wc(adev->dev, | |
| 2135 | − adev->gmc.aper_base, | |
| 2136 | − adev->gmc.visible_vram_size); | |
| 2137 | − if (!adev->mman.aper_base_kaddr) | |
| 2138 | − return -ENOMEM; | |
| 2139 | − } | |
| 2130 | + else | |
| 2131 | +#endif | |
| 2132 | + adev->mman.aper_base_kaddr = ioremap_wc(adev->gmc.aper_base, | |
| 2133 | + adev->gmc.visible_vram_size); | |
| 2140 | 2134 | #endif |
| 2141 | 2135 | |
| 2142 | 2136 | amdgpu_ttm_init_vram_resv_regions(adev); |
| @@ -2287,7 +2281,10 @@ void amdgpu_ttm_fini(struct amdgpu_device *adev) · 144 unmodified lines | ||
| 2287 | 2281 | amdgpu_ttm_unmark_vram_reserved(adev, AMDGPU_RESV_FW_VRAM_USAGE); |
| 2288 | 2282 | amdgpu_ttm_unmark_vram_reserved(adev, AMDGPU_RESV_DRV_VRAM_USAGE); |
| 2289 | 2283 | |
| 2290 | − adev->mman.aper_base_kaddr = NULL; | |
| 2284 | + if (adev->mman.aper_base_kaddr) { | |
| 2285 | + iounmap(adev->mman.aper_base_kaddr); | |
| 2286 | + adev->mman.aper_base_kaddr = NULL; | |
| 2287 | + } | |
| 2291 | 2288 | |
| 2292 | 2289 | if (!adev->gmc.is_app_apu) |
| 2293 | 2290 | amdgpu_vram_mgr_fini(adev); |
| @@ -700,7 +700,12 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args) · 699 unmodified lines | ||
| 700 | 700 | if (!adev->userq_halt_for_enforce_isolation || |
| 701 | 701 | ((queue->queue_type != AMDGPU_HW_IP_GFX) && |
| 702 | 702 | (queue->queue_type != AMDGPU_HW_IP_COMPUTE))) { |
| 703 | + /* Serialize the map against an in-progress GPU reset (MES is | |
| 704 | + * unresponsive during recovery), matching amdgpu_userq_cleanup(). | |
| 705 | + */ | |
| 706 | + down_read(&adev->reset_domain->sem); | |
| 703 | 707 | r = amdgpu_userq_map_helper(queue); |
| 708 | + up_read(&adev->reset_domain->sem); | |
| 704 | 709 | if (r) { |
| 705 | 710 | drm_file_err(uq_mgr->file, "Failed to map Queue\n"); |
| 706 | 711 | mutex_unlock(&uq_mgr->userq_mutex); |
| @@ -1823,6 +1823,11 @@ static void gfx_v12_0_constants_init(struct amdgpu_device *adev) · 1822 unmodified lines | ||
| 1823 | 1823 | gfx_v12_0_get_tcc_info(adev); |
| 1824 | 1824 | adev->gfx.config.pa_sc_tile_steering_override = 0; |
| 1825 | 1825 | |
| 1826 | + /* Set whether texture coordinate truncation is conformant. */ | |
| 1827 | + tmp = RREG32_SOC15(GC, 0, regTA_CNTL2); | |
| 1828 | + adev->gfx.config.ta_cntl2_truncate_coord_mode = | |
| 1829 | + REG_GET_FIELD(tmp, TA_CNTL2, TRUNCATE_COORD_MODE); | |
| 1830 | + | |
| 1826 | 1831 | /* XXX SH_MEM regs */ |
| 1827 | 1832 | /* where to put LDS, scratch, GPUVM in FSA64 space */ |
| 1828 | 1833 | mutex_lock(&adev->srbm_mutex); |
| @@ -267,9 +267,24 @@ static bool gmc_v12_1_get_vmid_pasid_mapping_info(struct amdgpu_device *adev, · 266 unmodified lines | ||
| 267 | 267 | * by the amdgpu vm/hsa code. |
| 268 | 268 | */ |
| 269 | 269 | |
| 270 | +/** | |
| 271 | + * gmc_v12_1_use_invalidate_semaphore - judge whether to use semaphore | |
| 272 | + * | |
| 273 | + * @adev: amdgpu_device pointer | |
| 274 | + * @vmhub: vmhub type | |
| 275 | + * | |
| 276 | + */ | |
| 277 | +static bool gmc_v12_1_use_invalidate_semaphore(struct amdgpu_device *adev, | |
| 278 | + uint32_t vmhub) | |
| 279 | +{ | |
| 280 | + return ((!AMDGPU_IS_GFXHUB(vmhub)) && | |
| 281 | + (!amdgpu_sriov_vf(adev))); | |
| 282 | +} | |
| 283 | + | |
| 270 | 284 | static void gmc_v12_1_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid, |
| 271 | 285 | unsigned int vmhub, uint32_t flush_type) |
| 272 | 286 | { |
| 287 | + bool use_semaphore = gmc_v12_1_use_invalidate_semaphore(adev, vmhub); | |
| 273 | 288 | struct amdgpu_vmhub *hub = &adev->vmhub[vmhub]; |
| 274 | 289 | u32 inv_req = hub->vmhub_funcs->get_invalidate_req(vmid, flush_type); |
| 275 | 290 | u32 tmp; |
| @@ -283,6 +298,19 @@ static void gmc_v12_1_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid, · 7 unmodified lines | ||
| 283 | 298 | |
| 284 | 299 | spin_lock(&adev->gmc.invalidate_lock); |
| 285 | 300 | |
| 301 | + if (use_semaphore) { | |
| 302 | + for (i = 0; i < adev->usec_timeout; i++) { | |
| 303 | + /* a read return value of 1 means semaphore acuqire */ | |
| 304 | + tmp = RREG32_RLC_NO_KIQ(hub->vm_inv_eng0_sem + hub->eng_distance * eng, hub_ip); | |
| 305 | + if (tmp & 0x1) | |
| 306 | + break; | |
| 307 | + udelay(1); | |
| 308 | + } | |
| 309 | + | |
| 310 | + if (i >= adev->usec_timeout) | |
| 311 | + DRM_ERROR("Timeout waiting for sem acquire in VM flush!\n"); | |
| 312 | + } | |
| 313 | + | |
| 286 | 314 | WREG32_RLC_NO_KIQ(hub->vm_inv_eng0_req + hub->eng_distance * eng, inv_req, hub_ip); |
| 287 | 315 | |
| 288 | 316 | /* Wait for ACK with a delay.*/ |
| @@ -296,6 +324,9 @@ static void gmc_v12_1_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid, · 7 unmodified lines | ||
| 296 | 324 | udelay(1); |
| 297 | 325 | } |
| 298 | 326 | |
| 327 | + if (use_semaphore) | |
| 328 | + WREG32_RLC_NO_KIQ(hub->vm_inv_eng0_sem + hub->eng_distance * eng, 0, hub_ip); | |
| 329 | + | |
| 299 | 330 | /* Issue additional private vm invalidation to MMHUB */ |
| 300 | 331 | if (!AMDGPU_IS_GFXHUB(vmhub) && |
| 301 | 332 | (hub->vm_l2_bank_select_reserved_cid2) && |
| @@ -396,7 +427,7 @@ static void gmc_v12_1_flush_gpu_tlb_pasid(struct amdgpu_device *adev, · 94 unmodified lines | ||
| 396 | 427 | |
| 397 | 428 | if (all_hub) { |
| 398 | 429 | /* invalidate mm_hub */ |
| 399 | − if (test_bit(AMDGPU_MMHUB1(0), adev->vmhubs_mask)) { | |
| 430 | + if (test_bit(AMDGPU_MMHUB0(0), adev->vmhubs_mask)) { | |
| 400 | 431 | input.hub_id = AMDGPU_MMHUB0(0); |
| 401 | 432 | adev->mes.funcs->invalidate_tlbs_pasid(&adev->mes, &input); |
| 402 | 433 | } |
| @@ -431,10 +462,17 @@ static void gmc_v12_1_flush_gpu_tlb_pasid(struct amdgpu_device *adev, · 28 unmodified lines | ||
| 431 | 462 | static uint64_t gmc_v12_1_emit_flush_gpu_tlb(struct amdgpu_ring *ring, |
| 432 | 463 | unsigned vmid, uint64_t pd_addr) |
| 433 | 464 | { |
| 465 | + bool use_semaphore = gmc_v12_1_use_invalidate_semaphore(ring->adev, ring->vm_hub); | |
| 434 | 466 | struct amdgpu_vmhub *hub = &ring->adev->vmhub[ring->vm_hub]; |
| 435 | 467 | uint32_t req = hub->vmhub_funcs->get_invalidate_req(vmid, 0); |
| 436 | 468 | unsigned eng = ring->vm_inv_eng; |
| 437 | 469 | |
| 470 | + if (use_semaphore) | |
| 471 | + /* a read return value of 1 means semaphore acuqire */ | |
| 472 | + amdgpu_ring_emit_reg_wait(ring, | |
| 473 | + hub->vm_inv_eng0_sem + | |
| 474 | + hub->eng_distance * eng, 0x1, 0x1); | |
| 475 | + | |
| 438 | 476 | amdgpu_ring_emit_wreg(ring, hub->ctx0_ptb_addr_lo32 + |
| 439 | 477 | (hub->ctx_addr_distance * vmid), |
| 440 | 478 | lower_32_bits(pd_addr)); |
| @@ -449,6 +487,14 @@ static uint64_t gmc_v12_1_emit_flush_gpu_tlb(struct amdgpu_ring *ring, · 8 unmodified lines | ||
| 449 | 487 | hub->eng_distance * eng, |
| 450 | 488 | req, 1 << vmid); |
| 451 | 489 | |
| 490 | + if (use_semaphore) | |
| 491 | + /* | |
| 492 | + * add semaphore release after invalidation, | |
| 493 | + * write with 0 means semaphore release | |
| 494 | + */ | |
| 495 | + amdgpu_ring_emit_wreg(ring, hub->vm_inv_eng0_sem + | |
| 496 | + hub->eng_distance * eng, 0); | |
| 497 | + | |
| 452 | 498 | return pd_addr; |
| 453 | 499 | } |
| 454 | 500 | |
| @@ -772,15 +772,28 @@ static int jpeg_v4_0_5_ring_reset(struct amdgpu_ring *ring, · 771 unmodified lines | ||
| 772 | 772 | unsigned int vmid, |
| 773 | 773 | struct amdgpu_fence *timedout_fence) |
| 774 | 774 | { |
| 775 | + struct amdgpu_device *adev = ring->adev; | |
| 776 | + u32 pg_flags = adev->pg_flags; | |
| 775 | 777 | int r; |
| 776 | 778 | |
| 777 | 779 | amdgpu_ring_reset_helper_begin(ring, timedout_fence); |
| 778 | − r = jpeg_v4_0_5_stop(ring->adev); | |
| 779 | − if (r) | |
| 780 | − return r; | |
| 781 | − r = jpeg_v4_0_5_start(ring->adev); | |
| 780 | + | |
| 781 | + /* | |
| 782 | + * The DPG stop path only clears the JPEG_PG_MODE bit and never resets a | |
| 783 | + * hung JRBC, so the post-reset ring test times out and the driver falls | |
| 784 | + * back to a full MODE1 reset. Temporarily force the static power-gating | |
| 785 | + * path so the stop/start sequence actually power-cycles the JPEG block | |
| 786 | + * (JMI soft reset + static power off/on), matching the working jpeg_v4_0 | |
| 787 | + * reset. | |
| 788 | + */ | |
| 789 | + adev->pg_flags &= ~AMD_PG_SUPPORT_JPEG_DPG; | |
| 790 | + r = jpeg_v4_0_5_stop(adev); | |
| 791 | + if (!r) | |
| 792 | + r = jpeg_v4_0_5_start(adev); | |
| 793 | + adev->pg_flags = pg_flags; | |
| 782 | 794 | if (r) |
| 783 | 795 | return r; |
| 796 | + | |
| 784 | 797 | return amdgpu_ring_reset_helper_end(ring, timedout_fence); |
| 785 | 798 | } |
| 786 | 799 | |
| @@ -648,15 +648,28 @@ static int jpeg_v5_0_0_ring_reset(struct amdgpu_ring *ring, · 647 unmodified lines | ||
| 648 | 648 | unsigned int vmid, |
| 649 | 649 | struct amdgpu_fence *timedout_fence) |
| 650 | 650 | { |
| 651 | + struct amdgpu_device *adev = ring->adev; | |
| 652 | + u32 pg_flags = adev->pg_flags; | |
| 651 | 653 | int r; |
| 652 | 654 | |
| 653 | 655 | amdgpu_ring_reset_helper_begin(ring, timedout_fence); |
| 654 | − r = jpeg_v5_0_0_stop(ring->adev); | |
| 655 | − if (r) | |
| 656 | − return r; | |
| 657 | − r = jpeg_v5_0_0_start(ring->adev); | |
| 656 | + | |
| 657 | + /* | |
| 658 | + * The DPG stop path only clears the JPEG_PG_MODE bit and never resets a | |
| 659 | + * hung JRBC, so the post-reset ring test times out and the driver falls | |
| 660 | + * back to a full MODE1 reset. Temporarily force the static power-gating | |
| 661 | + * path so the stop/start sequence actually power-cycles the JPEG block | |
| 662 | + * (JMI soft reset + ONO1 power off/on), matching the working jpeg_v4_0 | |
| 663 | + * reset. | |
| 664 | + */ | |
| 665 | + adev->pg_flags &= ~AMD_PG_SUPPORT_JPEG_DPG; | |
| 666 | + r = jpeg_v5_0_0_stop(adev); | |
| 667 | + if (!r) | |
| 668 | + r = jpeg_v5_0_0_start(adev); | |
| 669 | + adev->pg_flags = pg_flags; | |
| 658 | 670 | if (r) |
| 659 | 671 | return r; |
| 672 | + | |
| 660 | 673 | return amdgpu_ring_reset_helper_end(ring, timedout_fence); |
| 661 | 674 | } |
| 662 | 675 | |
| @@ -655,15 +655,28 @@ static int jpeg_v5_3_0_ring_reset(struct amdgpu_ring *ring, · 654 unmodified lines | ||
| 655 | 655 | unsigned int vmid, |
| 656 | 656 | struct amdgpu_fence *timedout_fence) |
| 657 | 657 | { |
| 658 | + struct amdgpu_device *adev = ring->adev; | |
| 659 | + u32 pg_flags = adev->pg_flags; | |
| 658 | 660 | int r; |
| 659 | 661 | |
| 660 | 662 | amdgpu_ring_reset_helper_begin(ring, timedout_fence); |
| 661 | − r = jpeg_v5_3_0_stop(ring->adev); | |
| 662 | − if (r) | |
| 663 | − return r; | |
| 664 | − r = jpeg_v5_3_0_start(ring->adev); | |
| 663 | + | |
| 664 | + /* | |
| 665 | + * The DPG stop path only clears the JPEG_PG_MODE bit and never resets a | |
| 666 | + * hung JRBC, so the post-reset ring test times out and the driver falls | |
| 667 | + * back to a full MODE1 reset. Temporarily force the static power-gating | |
| 668 | + * path so the stop/start sequence actually power-cycles the JPEG block | |
| 669 | + * (JMI soft reset + static power off/on), matching the working jpeg_v4_0 | |
| 670 | + * reset. | |
| 671 | + */ | |
| 672 | + adev->pg_flags &= ~AMD_PG_SUPPORT_JPEG_DPG; | |
| 673 | + r = jpeg_v5_3_0_stop(adev); | |
| 674 | + if (!r) | |
| 675 | + r = jpeg_v5_3_0_start(adev); | |
| 676 | + adev->pg_flags = pg_flags; | |
| 665 | 677 | if (r) |
| 666 | 678 | return r; |
| 679 | + | |
| 667 | 680 | return amdgpu_ring_reset_helper_end(ring, timedout_fence); |
| 668 | 681 | } |
| 669 | 682 | |
| @@ -2189,6 +2189,11 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) · 2188 unmodified lines | ||
| 2189 | 2189 | init_data.flags.unify_link_enc_assignment = true; |
| 2190 | 2190 | init_data.flags.usb4_bw_alloc_support = true; |
| 2191 | 2191 | } |
| 2192 | + | |
| 2193 | + /* DCN201 audio desyncs using DP SS */ | |
| 2194 | + if (adev->apu_flags & AMD_APU_IS_CYAN_SKILLFISH2) | |
| 2195 | + init_data.flags.ignore_dpref_ss = true; | |
| 2196 | + | |
| 2192 | 2197 | retrieve_dmi_info(&adev->dm); |
| 2193 | 2198 | if (adev->dm.edp0_on_dp1_quirk) |
| 2194 | 2199 | init_data.flags.support_edp0_on_dp1 = true; |
| @@ -119,7 +119,11 @@ void amdgpu_dm_crtc_set_static_screen_optimze( · 118 unmodified lines | ||
| 119 | 119 | struct dc_link *link = stream->link; |
| 120 | 120 | bool set_vsync_event = !sso_enable; |
| 121 | 121 | |
| 122 | − if (!allow_sr_entry) | |
| 122 | + /* | |
| 123 | + * allow_sr_entry gates only entry. A disable request must still set | |
| 124 | + * the vsync events to force Replay and PSR1 out and keep them blocked. | |
| 125 | + */ | |
| 126 | + if (sso_enable && !allow_sr_entry) | |
| 123 | 127 | return; |
| 124 | 128 | |
| 125 | 129 | amdgpu_dm_replay_set_event(dm, stream, |
| @@ -1348,7 +1348,10 @@ void dce110_set_avmute(struct pipe_ctx *pipe_ctx, bool enable) · 1347 unmodified lines | ||
| 1348 | 1348 | * process the mute state, especially after link re-establishment |
| 1349 | 1349 | * with HDMI 2.0 scrambling enabled. |
| 1350 | 1350 | */ |
| 1351 | − if (enable && pipe_ctx->stream_res.tg->funcs->is_tg_enabled(pipe_ctx->stream_res.tg)) { | |
| 1351 | + if (enable && pipe_ctx->stream_res.tg && | |
| 1352 | + pipe_ctx->stream_res.tg->funcs->is_tg_enabled && | |
| 1353 | + pipe_ctx->stream_res.tg->funcs->wait_for_state && | |
| 1354 | + pipe_ctx->stream_res.tg->funcs->is_tg_enabled(pipe_ctx->stream_res.tg)) { | |
| 1352 | 1355 | int i; |
| 1353 | 1356 | |
| 1354 | 1357 | pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE); |
| @@ -360,6 +360,13 @@ static bool radeon_fence_is_signaled(struct dma_fence *f) · 359 unmodified lines | ||
| 360 | 360 | if (atomic64_read(&rdev->fence_drv[ring].last_seq) >= seq) |
| 361 | 361 | return true; |
| 362 | 362 | |
| 363 | + if (down_read_trylock(&rdev->exclusive_lock)) { | |
| 364 | + radeon_fence_activity(rdev, ring); | |
| 365 | + up_read(&rdev->exclusive_lock); | |
| 366 | + | |
| 367 | + if (atomic64_read(&rdev->fence_drv[ring].last_seq) >= seq) | |
| 368 | + return true; | |
| 369 | + } | |
| 363 | 370 | return false; |
| 364 | 371 | } |
| 365 | 372 | |