From cb0de06d1b0afb2d0c600ad748069f5ce27730ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Wed, 29 Jan 2025 16:28:49 +0100 Subject: [PATCH 001/235] drm/amdgpu: remove all KFD fences from the BO on release MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove all KFD BOs from the private dma_resv object. This prevents the KFD from being evict unecessarily when an exported BO is released. Signed-off-by: Christian König Signed-off-by: James Zhu Reviewed-by: Felix Kuehling Reviewed-and-tested-by: James Zhu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h | 5 +- .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 52 ++++++++----------- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 38 ++++++++------ 3 files changed, 47 insertions(+), 48 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h index 236b73e283e8..55d539967695 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h @@ -193,7 +193,7 @@ int kfd_debugfs_kfd_mem_limits(struct seq_file *m, void *data); #if IS_ENABLED(CONFIG_HSA_AMD) bool amdkfd_fence_check_mm(struct dma_fence *f, struct mm_struct *mm); struct amdgpu_amdkfd_fence *to_amdgpu_amdkfd_fence(struct dma_fence *f); -int amdgpu_amdkfd_remove_fence_on_pt_pd_bos(struct amdgpu_bo *bo); +void amdgpu_amdkfd_remove_all_eviction_fences(struct amdgpu_bo *bo); int amdgpu_amdkfd_evict_userptr(struct mmu_interval_notifier *mni, unsigned long cur_seq, struct kgd_mem *mem); int amdgpu_amdkfd_bo_validate_and_fence(struct amdgpu_bo *bo, @@ -213,9 +213,8 @@ struct amdgpu_amdkfd_fence *to_amdgpu_amdkfd_fence(struct dma_fence *f) } static inline -int amdgpu_amdkfd_remove_fence_on_pt_pd_bos(struct amdgpu_bo *bo) +void amdgpu_amdkfd_remove_all_eviction_fences(struct amdgpu_bo *bo) { - return 0; } static inline diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index ea3f7ee18923..62ca12e94581 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -370,40 +370,32 @@ static int amdgpu_amdkfd_remove_eviction_fence(struct amdgpu_bo *bo, return 0; } -int amdgpu_amdkfd_remove_fence_on_pt_pd_bos(struct amdgpu_bo *bo) +/** + * amdgpu_amdkfd_remove_all_eviction_fences - Remove all eviction fences + * @bo: the BO where to remove the evictions fences from. + * + * This functions should only be used on release when all references to the BO + * are already dropped. We remove the eviction fence from the private copy of + * the dma_resv object here since that is what is used during release to + * determine of the BO is idle or not. + */ +void amdgpu_amdkfd_remove_all_eviction_fences(struct amdgpu_bo *bo) { - struct amdgpu_bo *root = bo; - struct amdgpu_vm_bo_base *vm_bo; - struct amdgpu_vm *vm; - struct amdkfd_process_info *info; - struct amdgpu_amdkfd_fence *ef; - int ret; + struct dma_resv *resv = &bo->tbo.base._resv; + struct dma_fence *fence, *stub; + struct dma_resv_iter cursor; - /* we can always get vm_bo from root PD bo.*/ - while (root->parent) - root = root->parent; + dma_resv_assert_held(resv); - vm_bo = root->vm_bo; - if (!vm_bo) - return 0; + stub = dma_fence_get_stub(); + dma_resv_for_each_fence(&cursor, resv, DMA_RESV_USAGE_BOOKKEEP, fence) { + if (!to_amdgpu_amdkfd_fence(fence)) + continue; - vm = vm_bo->vm; - if (!vm) - return 0; - - info = vm->process_info; - if (!info || !info->eviction_fence) - return 0; - - ef = container_of(dma_fence_get(&info->eviction_fence->base), - struct amdgpu_amdkfd_fence, base); - - BUG_ON(!dma_resv_trylock(bo->tbo.base.resv)); - ret = amdgpu_amdkfd_remove_eviction_fence(bo, ef); - dma_resv_unlock(bo->tbo.base.resv); - - dma_fence_put(&ef->base); - return ret; + dma_resv_replace_fences(resv, fence->context, stub, + DMA_RESV_USAGE_BOOKKEEP); + } + dma_fence_put(stub); } static int amdgpu_amdkfd_bo_validate(struct amdgpu_bo *bo, uint32_t domain, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index 96f4b8904e9a..80cd6f5273db 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -1295,28 +1295,36 @@ void amdgpu_bo_release_notify(struct ttm_buffer_object *bo) if (abo->kfd_bo) amdgpu_amdkfd_release_notify(abo); - /* We only remove the fence if the resv has individualized. */ - WARN_ON_ONCE(bo->type == ttm_bo_type_kernel - && bo->base.resv != &bo->base._resv); - if (bo->base.resv == &bo->base._resv) - amdgpu_amdkfd_remove_fence_on_pt_pd_bos(abo); + /* + * We lock the private dma_resv object here and since the BO is about to + * be released nobody else should have a pointer to it. + * So when this locking here fails something is wrong with the reference + * counting. + */ + if (WARN_ON_ONCE(!dma_resv_trylock(&bo->base._resv))) + return; + + amdgpu_amdkfd_remove_all_eviction_fences(abo); if (!bo->resource || bo->resource->mem_type != TTM_PL_VRAM || !(abo->flags & AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE) || adev->in_suspend || drm_dev_is_unplugged(adev_to_drm(adev))) - return; + goto out; - if (WARN_ON_ONCE(!dma_resv_trylock(bo->base.resv))) - return; + r = dma_resv_reserve_fences(&bo->base._resv, 1); + if (r) + goto out; - r = amdgpu_fill_buffer(abo, 0, bo->base.resv, &fence, true); - if (!WARN_ON(r)) { - amdgpu_vram_mgr_set_cleared(bo->resource); - amdgpu_bo_fence(abo, fence, false); - dma_fence_put(fence); - } + r = amdgpu_fill_buffer(abo, 0, &bo->base._resv, &fence, true); + if (WARN_ON(r)) + goto out; - dma_resv_unlock(bo->base.resv); + amdgpu_vram_mgr_set_cleared(bo->resource); + dma_resv_add_fence(&bo->base._resv, fence, DMA_RESV_USAGE_KERNEL); + dma_fence_put(fence); + +out: + dma_resv_unlock(&bo->base._resv); } /** From 7dc340540363a008cee1e160e8f2a4f034f196d4 Mon Sep 17 00:00:00 2001 From: Sunil Khatri Date: Wed, 19 Feb 2025 23:40:52 +0530 Subject: [PATCH 002/235] drm/amdgpu: update the handle ptr in is_idle Update the *handle to amdgpu_ip_block ptr for all functions pointers of is_idle. Signed-off-by: Sunil Khatri Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c | 2 +- drivers/gpu/drm/amd/amdgpu/cik.c | 2 +- drivers/gpu/drm/amd/amdgpu/cik_ih.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/cik_sdma.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/cz_ih.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/dce_v10_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/dce_v11_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/dce_v6_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/dce_v8_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/iceland_ih.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/ih_v6_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/ih_v6_1.c | 2 +- drivers/gpu/drm/amd/amdgpu/ih_v7_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/navi10_ih.c | 2 +- drivers/gpu/drm/amd/amdgpu/nv.c | 2 +- drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/si.c | 2 +- drivers/gpu/drm/amd/amdgpu/si_dma.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/si_ih.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/soc15.c | 2 +- drivers/gpu/drm/amd/amdgpu/soc21.c | 2 +- drivers/gpu/drm/amd/amdgpu/soc24.c | 2 +- drivers/gpu/drm/amd/amdgpu/tonga_ih.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/vce_v2_0.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/vce_v3_0.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/vega10_ih.c | 2 +- drivers/gpu/drm/amd/amdgpu/vega20_ih.c | 2 +- drivers/gpu/drm/amd/amdgpu/vi.c | 2 +- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- drivers/gpu/drm/amd/include/amd_shared.h | 2 +- drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c | 2 +- drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c | 2 +- drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c | 2 +- 78 files changed, 148 insertions(+), 148 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c index deb0785350e8..4926996f94da 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c @@ -579,7 +579,7 @@ static int acp_resume(struct amdgpu_ip_block *ip_block) return 0; } -static bool acp_is_idle(void *handle) +static bool acp_is_idle(struct amdgpu_ip_block *ip_block) { return true; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c index 732744488b03..43fc941dfa57 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c @@ -124,7 +124,7 @@ static int isp_early_init(struct amdgpu_ip_block *ip_block) return 0; } -static bool isp_is_idle(void *handle) +static bool isp_is_idle(struct amdgpu_ip_block *ip_block) { return true; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c index 03308261f894..fc6d02d0f047 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c @@ -627,7 +627,7 @@ static int amdgpu_vkms_resume(struct amdgpu_ip_block *ip_block) return drm_mode_config_helper_resume(adev_to_drm(ip_block->adev)); } -static bool amdgpu_vkms_is_idle(void *handle) +static bool amdgpu_vkms_is_idle(struct amdgpu_ip_block *ip_block) { return true; } diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c index 08d6787893b3..9cd63b4177bf 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik.c +++ b/drivers/gpu/drm/amd/amdgpu/cik.c @@ -2148,7 +2148,7 @@ static int cik_common_resume(struct amdgpu_ip_block *ip_block) return cik_common_hw_init(ip_block); } -static bool cik_common_is_idle(void *handle) +static bool cik_common_is_idle(struct amdgpu_ip_block *ip_block) { return true; } diff --git a/drivers/gpu/drm/amd/amdgpu/cik_ih.c b/drivers/gpu/drm/amd/amdgpu/cik_ih.c index 444563486769..41f4705bdbbd 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/cik_ih.c @@ -345,9 +345,9 @@ static int cik_ih_resume(struct amdgpu_ip_block *ip_block) return cik_ih_hw_init(ip_block); } -static bool cik_ih_is_idle(void *handle) +static bool cik_ih_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; u32 tmp = RREG32(mmSRBM_STATUS); if (tmp & SRBM_STATUS__IH_BUSY_MASK) diff --git a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c index d9bd8f3f17e2..508cea965983 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c +++ b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c @@ -1025,9 +1025,9 @@ static int cik_sdma_resume(struct amdgpu_ip_block *ip_block) return cik_sdma_hw_init(ip_block); } -static bool cik_sdma_is_idle(void *handle) +static bool cik_sdma_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; u32 tmp = RREG32(mmSRBM_STATUS2); if (tmp & (SRBM_STATUS2__SDMA_BUSY_MASK | diff --git a/drivers/gpu/drm/amd/amdgpu/cz_ih.c b/drivers/gpu/drm/amd/amdgpu/cz_ih.c index 82586b76aeda..2f891fb846d5 100644 --- a/drivers/gpu/drm/amd/amdgpu/cz_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/cz_ih.c @@ -341,9 +341,9 @@ static int cz_ih_resume(struct amdgpu_ip_block *ip_block) return cz_ih_hw_init(ip_block); } -static bool cz_ih_is_idle(void *handle) +static bool cz_ih_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; u32 tmp = RREG32(mmSRBM_STATUS); if (REG_GET_FIELD(tmp, SRBM_STATUS, IH_BUSY)) diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c index c5e3d2251b18..df401aded662 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c @@ -2970,7 +2970,7 @@ static int dce_v10_0_resume(struct amdgpu_ip_block *ip_block) return amdgpu_display_resume_helper(adev); } -static bool dce_v10_0_is_idle(void *handle) +static bool dce_v10_0_is_idle(struct amdgpu_ip_block *ip_block) { return true; } diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c index ea42a4472bf6..80f01c3989cd 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c @@ -3108,7 +3108,7 @@ static int dce_v11_0_resume(struct amdgpu_ip_block *ip_block) return amdgpu_display_resume_helper(adev); } -static bool dce_v11_0_is_idle(void *handle) +static bool dce_v11_0_is_idle(struct amdgpu_ip_block *ip_block) { return true; } diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c index 915804a6a1d7..5c3f96630c10 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c @@ -2865,7 +2865,7 @@ static int dce_v6_0_resume(struct amdgpu_ip_block *ip_block) return amdgpu_display_resume_helper(adev); } -static bool dce_v6_0_is_idle(void *handle) +static bool dce_v6_0_is_idle(struct amdgpu_ip_block *ip_block) { return true; } diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c index f2edc0fece5b..d7bd32bfccd0 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c @@ -2887,7 +2887,7 @@ static int dce_v8_0_resume(struct amdgpu_ip_block *ip_block) return amdgpu_display_resume_helper(adev); } -static bool dce_v8_0_is_idle(void *handle) +static bool dce_v8_0_is_idle(struct amdgpu_ip_block *ip_block) { return true; } diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index f54617c6c071..6d514efb0a6d 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -7583,9 +7583,9 @@ static int gfx_v10_0_resume(struct amdgpu_ip_block *ip_block) return gfx_v10_0_hw_init(ip_block); } -static bool gfx_v10_0_is_idle(void *handle) +static bool gfx_v10_0_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; if (REG_GET_FIELD(RREG32_SOC15(GC, 0, mmGRBM_STATUS), GRBM_STATUS, GUI_ACTIVE)) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index 57f1e2b50e5a..2b3ba404955d 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -4787,9 +4787,9 @@ static int gfx_v11_0_resume(struct amdgpu_ip_block *ip_block) return gfx_v11_0_hw_init(ip_block); } -static bool gfx_v11_0_is_idle(void *handle) +static bool gfx_v11_0_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; if (REG_GET_FIELD(RREG32_SOC15(GC, 0, regGRBM_STATUS), GRBM_STATUS, GUI_ACTIVE)) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c index 47490309045f..926fb536bbff 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c @@ -3695,9 +3695,9 @@ static int gfx_v12_0_resume(struct amdgpu_ip_block *ip_block) return gfx_v12_0_hw_init(ip_block); } -static bool gfx_v12_0_is_idle(void *handle) +static bool gfx_v12_0_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; if (REG_GET_FIELD(RREG32_SOC15(GC, 0, regGRBM_STATUS), GRBM_STATUS, GUI_ACTIVE)) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c index f26e2cdec07a..2f5cf87ede88 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c @@ -3167,9 +3167,9 @@ static int gfx_v6_0_resume(struct amdgpu_ip_block *ip_block) return gfx_v6_0_hw_init(ip_block); } -static bool gfx_v6_0_is_idle(void *handle) +static bool gfx_v6_0_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; if (RREG32(mmGRBM_STATUS) & GRBM_STATUS__GUI_ACTIVE_MASK) return false; @@ -3183,7 +3183,7 @@ static int gfx_v6_0_wait_for_idle(struct amdgpu_ip_block *ip_block) struct amdgpu_device *adev = ip_block->adev; for (i = 0; i < adev->usec_timeout; i++) { - if (gfx_v6_0_is_idle(adev)) + if (gfx_v6_0_is_idle(ip_block)) return 0; udelay(1); } diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c index 84745b2453ab..8181bd0e4f18 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c @@ -4515,9 +4515,9 @@ static int gfx_v7_0_resume(struct amdgpu_ip_block *ip_block) return gfx_v7_0_hw_init(ip_block); } -static bool gfx_v7_0_is_idle(void *handle) +static bool gfx_v7_0_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; if (RREG32(mmGRBM_STATUS) & GRBM_STATUS__GUI_ACTIVE_MASK) return false; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 6add76ef75e8..d116a2e2f469 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -4851,9 +4851,9 @@ static int gfx_v8_0_kcq_disable(struct amdgpu_device *adev) return r; } -static bool gfx_v8_0_is_idle(void *handle) +static bool gfx_v8_0_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; if (REG_GET_FIELD(RREG32(mmGRBM_STATUS), GRBM_STATUS, GUI_ACTIVE) || RREG32(mmGRBM_STATUS2) != 0x8) @@ -4892,7 +4892,7 @@ static int gfx_v8_0_wait_for_idle(struct amdgpu_ip_block *ip_block) struct amdgpu_device *adev = ip_block->adev; for (i = 0; i < adev->usec_timeout; i++) { - if (gfx_v8_0_is_idle(adev)) + if (gfx_v8_0_is_idle(ip_block)) return 0; udelay(1); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index e144bce938d5..f7938d318f26 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -4110,9 +4110,9 @@ static int gfx_v9_0_resume(struct amdgpu_ip_block *ip_block) return gfx_v9_0_hw_init(ip_block); } -static bool gfx_v9_0_is_idle(void *handle) +static bool gfx_v9_0_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; if (REG_GET_FIELD(RREG32_SOC15(GC, 0, mmGRBM_STATUS), GRBM_STATUS, GUI_ACTIVE)) @@ -4127,7 +4127,7 @@ static int gfx_v9_0_wait_for_idle(struct amdgpu_ip_block *ip_block) struct amdgpu_device *adev = ip_block->adev; for (i = 0; i < adev->usec_timeout; i++) { - if (gfx_v9_0_is_idle(adev)) + if (gfx_v9_0_is_idle(ip_block)) return 0; udelay(1); } diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c index c88564de50cd..91c1b2f9fe88 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c @@ -2408,9 +2408,9 @@ static int gfx_v9_4_3_resume(struct amdgpu_ip_block *ip_block) return gfx_v9_4_3_hw_init(ip_block); } -static bool gfx_v9_4_3_is_idle(void *handle) +static bool gfx_v9_4_3_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; int i, num_xcc; num_xcc = NUM_XCC(adev->gfx.xcc_mask); @@ -2428,7 +2428,7 @@ static int gfx_v9_4_3_wait_for_idle(struct amdgpu_ip_block *ip_block) struct amdgpu_device *adev = ip_block->adev; for (i = 0; i < adev->usec_timeout; i++) { - if (gfx_v9_4_3_is_idle(adev)) + if (gfx_v9_4_3_is_idle(ip_block)) return 0; udelay(1); } diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index edf6cf42f141..95d894a231fc 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -1076,7 +1076,7 @@ static int gmc_v10_0_resume(struct amdgpu_ip_block *ip_block) return 0; } -static bool gmc_v10_0_is_idle(void *handle) +static bool gmc_v10_0_is_idle(struct amdgpu_ip_block *ip_block) { /* MC is always ready in GMC v10.*/ return true; diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c index f86d0650a05e..ad099f136f84 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c @@ -987,7 +987,7 @@ static int gmc_v11_0_resume(struct amdgpu_ip_block *ip_block) return 0; } -static bool gmc_v11_0_is_idle(void *handle) +static bool gmc_v11_0_is_idle(struct amdgpu_ip_block *ip_block) { /* MC is always ready in GMC v11.*/ return true; diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c index c6d45d0fb9d1..ea7c32d8380b 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c @@ -984,7 +984,7 @@ static int gmc_v12_0_resume(struct amdgpu_ip_block *ip_block) return 0; } -static bool gmc_v12_0_is_idle(void *handle) +static bool gmc_v12_0_is_idle(struct amdgpu_ip_block *ip_block) { /* MC is always ready in GMC v11.*/ return true; diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c index 2245dda92021..a992e79d9581 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c @@ -957,9 +957,9 @@ static int gmc_v6_0_resume(struct amdgpu_ip_block *ip_block) return 0; } -static bool gmc_v6_0_is_idle(void *handle) +static bool gmc_v6_0_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; u32 tmp = RREG32(mmSRBM_STATUS); @@ -976,7 +976,7 @@ static int gmc_v6_0_wait_for_idle(struct amdgpu_ip_block *ip_block) struct amdgpu_device *adev = ip_block->adev; for (i = 0; i < adev->usec_timeout; i++) { - if (gmc_v6_0_is_idle(adev)) + if (gmc_v6_0_is_idle(ip_block)) return 0; udelay(1); } diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c index 9aac4b1101e3..83e39f16044a 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c @@ -1142,9 +1142,9 @@ static int gmc_v7_0_resume(struct amdgpu_ip_block *ip_block) return 0; } -static bool gmc_v7_0_is_idle(void *handle) +static bool gmc_v7_0_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; u32 tmp = RREG32(mmSRBM_STATUS); if (tmp & (SRBM_STATUS__MCB_BUSY_MASK | SRBM_STATUS__MCB_NON_DISPLAY_BUSY_MASK | diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c index 744081652d42..99ca08e9bdb5 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c @@ -1263,9 +1263,9 @@ static int gmc_v8_0_resume(struct amdgpu_ip_block *ip_block) return 0; } -static bool gmc_v8_0_is_idle(void *handle) +static bool gmc_v8_0_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; u32 tmp = RREG32(mmSRBM_STATUS); if (tmp & (SRBM_STATUS__MCB_BUSY_MASK | SRBM_STATUS__MCB_NON_DISPLAY_BUSY_MASK | diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index a80f3e2bcba8..ccb31e724b55 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -2543,7 +2543,7 @@ static int gmc_v9_0_resume(struct amdgpu_ip_block *ip_block) return 0; } -static bool gmc_v9_0_is_idle(void *handle) +static bool gmc_v9_0_is_idle(struct amdgpu_ip_block *ip_block) { /* MC is always ready in GMC v9.*/ return true; diff --git a/drivers/gpu/drm/amd/amdgpu/iceland_ih.c b/drivers/gpu/drm/amd/amdgpu/iceland_ih.c index 8ac3d3282268..1317ede131b6 100644 --- a/drivers/gpu/drm/amd/amdgpu/iceland_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/iceland_ih.c @@ -335,9 +335,9 @@ static int iceland_ih_resume(struct amdgpu_ip_block *ip_block) return iceland_ih_hw_init(ip_block); } -static bool iceland_ih_is_idle(void *handle) +static bool iceland_ih_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; u32 tmp = RREG32(mmSRBM_STATUS); if (REG_GET_FIELD(tmp, SRBM_STATUS, IH_BUSY)) diff --git a/drivers/gpu/drm/amd/amdgpu/ih_v6_0.c b/drivers/gpu/drm/amd/amdgpu/ih_v6_0.c index 7198ddfaa8f4..eb4185dcbd1d 100644 --- a/drivers/gpu/drm/amd/amdgpu/ih_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/ih_v6_0.c @@ -652,7 +652,7 @@ static int ih_v6_0_resume(struct amdgpu_ip_block *ip_block) return ih_v6_0_hw_init(ip_block); } -static bool ih_v6_0_is_idle(void *handle) +static bool ih_v6_0_is_idle(struct amdgpu_ip_block *ip_block) { /* todo */ return true; diff --git a/drivers/gpu/drm/amd/amdgpu/ih_v6_1.c b/drivers/gpu/drm/amd/amdgpu/ih_v6_1.c index 342b166c136d..068ed849dbad 100644 --- a/drivers/gpu/drm/amd/amdgpu/ih_v6_1.c +++ b/drivers/gpu/drm/amd/amdgpu/ih_v6_1.c @@ -631,7 +631,7 @@ static int ih_v6_1_resume(struct amdgpu_ip_block *ip_block) return ih_v6_1_hw_init(ip_block); } -static bool ih_v6_1_is_idle(void *handle) +static bool ih_v6_1_is_idle(struct amdgpu_ip_block *ip_block) { /* todo */ return true; diff --git a/drivers/gpu/drm/amd/amdgpu/ih_v7_0.c b/drivers/gpu/drm/amd/amdgpu/ih_v7_0.c index 71c1c77035e0..40a3530e0453 100644 --- a/drivers/gpu/drm/amd/amdgpu/ih_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/ih_v7_0.c @@ -621,7 +621,7 @@ static int ih_v7_0_resume(struct amdgpu_ip_block *ip_block) return ih_v7_0_hw_init(ip_block); } -static bool ih_v7_0_is_idle(void *handle) +static bool ih_v7_0_is_idle(struct amdgpu_ip_block *ip_block) { /* todo */ return true; diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c index 75843a0e3bfb..4cde8a8bcc83 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c @@ -680,9 +680,9 @@ void jpeg_v2_0_dec_ring_nop(struct amdgpu_ring *ring, uint32_t count) } } -static bool jpeg_v2_0_is_idle(void *handle) +static bool jpeg_v2_0_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; return ((RREG32_SOC15(JPEG, 0, mmUVD_JRBC_STATUS) & UVD_JRBC_STATUS__RB_JOB_DONE_MASK) == @@ -707,7 +707,7 @@ static int jpeg_v2_0_set_clockgating_state(struct amdgpu_ip_block *ip_block, bool enable = (state == AMD_CG_STATE_GATE); if (enable) { - if (!jpeg_v2_0_is_idle(adev)) + if (!jpeg_v2_0_is_idle(ip_block)) return -EBUSY; jpeg_v2_0_enable_clock_gating(adev); } else { diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c index 0a2c1dee2430..8b39e114f3be 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c @@ -515,9 +515,9 @@ static void jpeg_v2_6_dec_ring_insert_end(struct amdgpu_ring *ring) amdgpu_ring_write(ring, (1 << (ring->me * 2 + 14))); } -static bool jpeg_v2_5_is_idle(void *handle) +static bool jpeg_v2_5_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; int i, ret = 1; for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) { @@ -563,7 +563,7 @@ static int jpeg_v2_5_set_clockgating_state(struct amdgpu_ip_block *ip_block, continue; if (enable) { - if (!jpeg_v2_5_is_idle(adev)) + if (!jpeg_v2_5_is_idle(ip_block)) return -EBUSY; jpeg_v2_5_enable_clock_gating(adev, i); } else { diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c index 9faa9c6809df..2f8510c2986b 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c @@ -470,9 +470,9 @@ static void jpeg_v3_0_dec_ring_set_wptr(struct amdgpu_ring *ring) } } -static bool jpeg_v3_0_is_idle(void *handle) +static bool jpeg_v3_0_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; int ret = 1; ret &= (((RREG32_SOC15(JPEG, 0, mmUVD_JRBC_STATUS) & @@ -498,7 +498,7 @@ static int jpeg_v3_0_set_clockgating_state(struct amdgpu_ip_block *ip_block, bool enable = state == AMD_CG_STATE_GATE; if (enable) { - if (!jpeg_v3_0_is_idle(adev)) + if (!jpeg_v3_0_is_idle(ip_block)) return -EBUSY; jpeg_v3_0_enable_clock_gating(adev); } else { diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c index 292d4a234ea6..f17ec5414fd6 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c @@ -630,9 +630,9 @@ static void jpeg_v4_0_dec_ring_set_wptr(struct amdgpu_ring *ring) } } -static bool jpeg_v4_0_is_idle(void *handle) +static bool jpeg_v4_0_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; int ret = 1; ret &= (((RREG32_SOC15(JPEG, 0, regUVD_JRBC_STATUS) & @@ -658,7 +658,7 @@ static int jpeg_v4_0_set_clockgating_state(struct amdgpu_ip_block *ip_block, bool enable = state == AMD_CG_STATE_GATE; if (enable) { - if (!jpeg_v4_0_is_idle(adev)) + if (!jpeg_v4_0_is_idle(ip_block)) return -EBUSY; jpeg_v4_0_enable_clock_gating(adev); } else { diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c index 0588bb80f41e..1a365bfc78bb 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c @@ -960,9 +960,9 @@ void jpeg_v4_0_3_dec_ring_nop(struct amdgpu_ring *ring, uint32_t count) } } -static bool jpeg_v4_0_3_is_idle(void *handle) +static bool jpeg_v4_0_3_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; bool ret = false; int i, j; @@ -1004,7 +1004,7 @@ static int jpeg_v4_0_3_set_clockgating_state(struct amdgpu_ip_block *ip_block, for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) { if (enable) { - if (!jpeg_v4_0_3_is_idle(adev)) + if (!jpeg_v4_0_3_is_idle(ip_block)) return -EBUSY; jpeg_v4_0_3_enable_clock_gating(adev, i); } else { diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c index cbba1d9e8367..974030a5c03c 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c @@ -648,9 +648,9 @@ static void jpeg_v4_0_5_dec_ring_set_wptr(struct amdgpu_ring *ring) } } -static bool jpeg_v4_0_5_is_idle(void *handle) +static bool jpeg_v4_0_5_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; int i, ret = 1; for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) { @@ -693,7 +693,7 @@ static int jpeg_v4_0_5_set_clockgating_state(struct amdgpu_ip_block *ip_block, continue; if (enable) { - if (!jpeg_v4_0_5_is_idle(adev)) + if (!jpeg_v4_0_5_is_idle(ip_block)) return -EBUSY; jpeg_v4_0_5_enable_clock_gating(adev, i); diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c index 4a55e0cf39e4..31d213ccbe0a 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c @@ -559,9 +559,9 @@ static void jpeg_v5_0_0_dec_ring_set_wptr(struct amdgpu_ring *ring) } } -static bool jpeg_v5_0_0_is_idle(void *handle) +static bool jpeg_v5_0_0_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; int ret = 1; ret &= (((RREG32_SOC15(JPEG, 0, regUVD_JRBC_STATUS) & @@ -587,7 +587,7 @@ static int jpeg_v5_0_0_set_clockgating_state(struct amdgpu_ip_block *ip_block, bool enable = (state == AMD_CG_STATE_GATE) ? true : false; if (enable) { - if (!jpeg_v5_0_0_is_idle(adev)) + if (!jpeg_v5_0_0_is_idle(ip_block)) return -EBUSY; jpeg_v5_0_0_enable_clock_gating(adev); } else { diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c index 6e3f522e9133..5d4e2a09acca 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c @@ -516,9 +516,9 @@ static void jpeg_v5_0_1_dec_ring_set_wptr(struct amdgpu_ring *ring) } } -static bool jpeg_v5_0_1_is_idle(void *handle) +static bool jpeg_v5_0_1_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; bool ret = false; int i, j; @@ -567,7 +567,7 @@ static int jpeg_v5_0_1_set_clockgating_state(struct amdgpu_ip_block *ip_block, return 0; for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) { - if (!jpeg_v5_0_1_is_idle(adev)) + if (!jpeg_v5_0_1_is_idle(ip_block)) return -EBUSY; } diff --git a/drivers/gpu/drm/amd/amdgpu/navi10_ih.c b/drivers/gpu/drm/amd/amdgpu/navi10_ih.c index 1c727ccd03b1..4cd325149b63 100644 --- a/drivers/gpu/drm/amd/amdgpu/navi10_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/navi10_ih.c @@ -625,7 +625,7 @@ static int navi10_ih_resume(struct amdgpu_ip_block *ip_block) return navi10_ih_hw_init(ip_block); } -static bool navi10_ih_is_idle(void *handle) +static bool navi10_ih_is_idle(struct amdgpu_ip_block *ip_block) { /* todo */ return true; diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c index 5d4a4e7fd97f..8068f384f56c 100644 --- a/drivers/gpu/drm/amd/amdgpu/nv.c +++ b/drivers/gpu/drm/amd/amdgpu/nv.c @@ -1035,7 +1035,7 @@ static int nv_common_resume(struct amdgpu_ip_block *ip_block) return nv_common_hw_init(ip_block); } -static bool nv_common_is_idle(void *handle) +static bool nv_common_is_idle(struct amdgpu_ip_block *ip_block) { return true; } diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c index 135c5099bfb8..92ce580647cd 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c @@ -911,9 +911,9 @@ static int sdma_v2_4_resume(struct amdgpu_ip_block *ip_block) return sdma_v2_4_hw_init(ip_block); } -static bool sdma_v2_4_is_idle(void *handle) +static bool sdma_v2_4_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; u32 tmp = RREG32(mmSRBM_STATUS2); if (tmp & (SRBM_STATUS2__SDMA_BUSY_MASK | diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c index 6e75a4a85f74..1c076bd1cf73 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c @@ -1200,9 +1200,9 @@ static int sdma_v3_0_resume(struct amdgpu_ip_block *ip_block) return sdma_v3_0_hw_init(ip_block); } -static bool sdma_v3_0_is_idle(void *handle) +static bool sdma_v3_0_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; u32 tmp = RREG32(mmSRBM_STATUS2); if (tmp & (SRBM_STATUS2__SDMA_BUSY_MASK | diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c index d31ee01383df..33ed2b158fcd 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c @@ -2015,9 +2015,9 @@ static int sdma_v4_0_resume(struct amdgpu_ip_block *ip_block) return sdma_v4_0_hw_init(ip_block); } -static bool sdma_v4_0_is_idle(void *handle) +static bool sdma_v4_0_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; u32 i; for (i = 0; i < adev->sdma.num_instances; i++) { diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c index 23a6bb16a0b1..9925b183c07f 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c @@ -1561,9 +1561,9 @@ static int sdma_v4_4_2_resume(struct amdgpu_ip_block *ip_block) return sdma_v4_4_2_hw_init(ip_block); } -static bool sdma_v4_4_2_is_idle(void *handle) +static bool sdma_v4_4_2_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; u32 i; for (i = 0; i < adev->sdma.num_instances; i++) { diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c index 377efb2b8d0e..0dce59f4f6e2 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c @@ -1530,9 +1530,9 @@ static int sdma_v5_0_resume(struct amdgpu_ip_block *ip_block) return sdma_v5_0_hw_init(ip_block); } -static bool sdma_v5_0_is_idle(void *handle) +static bool sdma_v5_0_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; u32 i; for (i = 0; i < adev->sdma.num_instances; i++) { diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c index ce05d895f977..2b39a03ff0c1 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c @@ -1435,9 +1435,9 @@ static int sdma_v5_2_resume(struct amdgpu_ip_block *ip_block) return sdma_v5_2_hw_init(ip_block); } -static bool sdma_v5_2_is_idle(void *handle) +static bool sdma_v5_2_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; u32 i; for (i = 0; i < adev->sdma.num_instances; i++) { diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c index 373703d1596d..c214c3d2149b 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c @@ -1429,9 +1429,9 @@ static int sdma_v6_0_resume(struct amdgpu_ip_block *ip_block) return sdma_v6_0_hw_init(ip_block); } -static bool sdma_v6_0_is_idle(void *handle) +static bool sdma_v6_0_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; u32 i; for (i = 0; i < adev->sdma.num_instances; i++) { diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c index 9eb8f4f9f302..b2706221df99 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c @@ -1430,9 +1430,9 @@ static int sdma_v7_0_resume(struct amdgpu_ip_block *ip_block) return sdma_v7_0_hw_init(ip_block); } -static bool sdma_v7_0_is_idle(void *handle) +static bool sdma_v7_0_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; u32 i; for (i = 0; i < adev->sdma.num_instances; i++) { diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c index 77ef7da2e4fe..026e8376e2c0 100644 --- a/drivers/gpu/drm/amd/amdgpu/si.c +++ b/drivers/gpu/drm/amd/amdgpu/si.c @@ -2644,7 +2644,7 @@ static int si_common_resume(struct amdgpu_ip_block *ip_block) return si_common_hw_init(ip_block); } -static bool si_common_is_idle(void *handle) +static bool si_common_is_idle(struct amdgpu_ip_block *ip_block) { return true; } diff --git a/drivers/gpu/drm/amd/amdgpu/si_dma.c b/drivers/gpu/drm/amd/amdgpu/si_dma.c index dbd78d5345a4..e2089c8da71b 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dma.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dma.c @@ -541,9 +541,9 @@ static int si_dma_resume(struct amdgpu_ip_block *ip_block) return si_dma_hw_init(ip_block); } -static bool si_dma_is_idle(void *handle) +static bool si_dma_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; u32 tmp = RREG32(SRBM_STATUS2); @@ -559,7 +559,7 @@ static int si_dma_wait_for_idle(struct amdgpu_ip_block *ip_block) struct amdgpu_device *adev = ip_block->adev; for (i = 0; i < adev->usec_timeout; i++) { - if (si_dma_is_idle(adev)) + if (si_dma_is_idle(ip_block)) return 0; udelay(1); } diff --git a/drivers/gpu/drm/amd/amdgpu/si_ih.c b/drivers/gpu/drm/amd/amdgpu/si_ih.c index a32b6243c1f8..5c38e1fb1dca 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/si_ih.c @@ -210,9 +210,9 @@ static int si_ih_resume(struct amdgpu_ip_block *ip_block) return si_ih_hw_init(ip_block); } -static bool si_ih_is_idle(void *handle) +static bool si_ih_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; u32 tmp = RREG32(SRBM_STATUS); if (tmp & SRBM_STATUS__IH_BUSY_MASK) @@ -227,7 +227,7 @@ static int si_ih_wait_for_idle(struct amdgpu_ip_block *ip_block) struct amdgpu_device *adev = ip_block->adev; for (i = 0; i < adev->usec_timeout; i++) { - if (si_ih_is_idle(adev)) + if (si_ih_is_idle(ip_block)) return 0; udelay(1); } diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index 2c6d2099e215..8732f766947e 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -1360,7 +1360,7 @@ static int soc15_common_resume(struct amdgpu_ip_block *ip_block) return soc15_common_hw_init(ip_block); } -static bool soc15_common_is_idle(void *handle) +static bool soc15_common_is_idle(struct amdgpu_ip_block *ip_block) { return true; } diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c index 7925cbb61d0d..dd5d04c068f9 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc21.c +++ b/drivers/gpu/drm/amd/amdgpu/soc21.c @@ -952,7 +952,7 @@ static int soc21_common_resume(struct amdgpu_ip_block *ip_block) return soc21_common_hw_init(ip_block); } -static bool soc21_common_is_idle(void *handle) +static bool soc21_common_is_idle(struct amdgpu_ip_block *ip_block) { return true; } diff --git a/drivers/gpu/drm/amd/amdgpu/soc24.c b/drivers/gpu/drm/amd/amdgpu/soc24.c index 4e506c91e978..972b449ab89f 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc24.c +++ b/drivers/gpu/drm/amd/amdgpu/soc24.c @@ -531,7 +531,7 @@ static int soc24_common_resume(struct amdgpu_ip_block *ip_block) return soc24_common_hw_init(ip_block); } -static bool soc24_common_is_idle(void *handle) +static bool soc24_common_is_idle(struct amdgpu_ip_block *ip_block) { return true; } diff --git a/drivers/gpu/drm/amd/amdgpu/tonga_ih.c b/drivers/gpu/drm/amd/amdgpu/tonga_ih.c index 0968e551f7b5..7d17ae56f901 100644 --- a/drivers/gpu/drm/amd/amdgpu/tonga_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/tonga_ih.c @@ -353,9 +353,9 @@ static int tonga_ih_resume(struct amdgpu_ip_block *ip_block) return tonga_ih_hw_init(ip_block); } -static bool tonga_ih_is_idle(void *handle) +static bool tonga_ih_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; u32 tmp = RREG32(mmSRBM_STATUS); if (REG_GET_FIELD(tmp, SRBM_STATUS, IH_BUSY)) diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c b/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c index 5830e799c0a3..6954848d34d4 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c @@ -758,9 +758,9 @@ static int uvd_v3_1_resume(struct amdgpu_ip_block *ip_block) return uvd_v3_1_hw_init(ip_block); } -static bool uvd_v3_1_is_idle(void *handle) +static bool uvd_v3_1_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; return !(RREG32(mmSRBM_STATUS) & SRBM_STATUS__UVD_BUSY_MASK); } diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c index f93079e09215..db6644e3907c 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c @@ -658,9 +658,9 @@ static void uvd_v4_2_set_dcm(struct amdgpu_device *adev, WREG32_UVD_CTX(ixUVD_CGC_CTRL2, tmp2); } -static bool uvd_v4_2_is_idle(void *handle) +static bool uvd_v4_2_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; return !(RREG32(mmSRBM_STATUS) & SRBM_STATUS__UVD_BUSY_MASK); } diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c index 2295c8713d61..71409ad8b7ed 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c @@ -580,9 +580,9 @@ static void uvd_v5_0_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count) } } -static bool uvd_v5_0_is_idle(void *handle) +static bool uvd_v5_0_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; return !(RREG32(mmSRBM_STATUS) & SRBM_STATUS__UVD_BUSY_MASK); } diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c index 070a0624c2c5..1c07b701d0e4 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c @@ -1143,9 +1143,9 @@ static void uvd_v6_0_enc_ring_emit_vm_flush(struct amdgpu_ring *ring, amdgpu_ring_write(ring, vmid); } -static bool uvd_v6_0_is_idle(void *handle) +static bool uvd_v6_0_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; return !(RREG32(mmSRBM_STATUS) & SRBM_STATUS__UVD_BUSY_MASK); } @@ -1156,7 +1156,7 @@ static int uvd_v6_0_wait_for_idle(struct amdgpu_ip_block *ip_block) struct amdgpu_device *adev = ip_block->adev; for (i = 0; i < adev->usec_timeout; i++) { - if (uvd_v6_0_is_idle(adev)) + if (uvd_v6_0_is_idle(ip_block)) return 0; } return -ETIMEDOUT; diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c index c633b7ff2943..a68fef65219d 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c @@ -201,9 +201,9 @@ static void vce_v2_0_mc_resume(struct amdgpu_device *adev) WREG32_FIELD(VCE_SYS_INT_EN, VCE_SYS_INT_TRAP_INTERRUPT_EN, 1); } -static bool vce_v2_0_is_idle(void *handle) +static bool vce_v2_0_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; return !(RREG32(mmSRBM_STATUS2) & SRBM_STATUS2__VCE_BUSY_MASK); } @@ -214,7 +214,7 @@ static int vce_v2_0_wait_for_idle(struct amdgpu_ip_block *ip_block) unsigned i; for (i = 0; i < adev->usec_timeout; i++) { - if (vce_v2_0_is_idle(adev)) + if (vce_v2_0_is_idle(ip_block)) return 0; } return -ETIMEDOUT; diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c index 01248a3982ba..708123899c41 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c @@ -597,9 +597,9 @@ static void vce_v3_0_mc_resume(struct amdgpu_device *adev, int idx) WREG32_FIELD(VCE_SYS_INT_EN, VCE_SYS_INT_TRAP_INTERRUPT_EN, 1); } -static bool vce_v3_0_is_idle(void *handle) +static bool vce_v3_0_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; u32 mask = 0; mask |= (adev->vce.harvest_config & AMDGPU_VCE_HARVEST_VCE0) ? 0 : SRBM_STATUS2__VCE0_BUSY_MASK; @@ -614,7 +614,7 @@ static int vce_v3_0_wait_for_idle(struct amdgpu_ip_block *ip_block) struct amdgpu_device *adev = ip_block->adev; for (i = 0; i < adev->usec_timeout; i++) - if (vce_v3_0_is_idle(adev)) + if (vce_v3_0_is_idle(ip_block)) return 0; return -ETIMEDOUT; diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c index 5ea96c983517..06e1bbcf1a52 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c @@ -1377,9 +1377,9 @@ static int vcn_v1_0_pause_dpg_mode(struct amdgpu_device *adev, return 0; } -static bool vcn_v1_0_is_idle(void *handle) +static bool vcn_v1_0_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; return (RREG32_SOC15(VCN, 0, mmUVD_STATUS) == UVD_STATUS__IDLE); } @@ -1403,7 +1403,7 @@ static int vcn_v1_0_set_clockgating_state(struct amdgpu_ip_block *ip_block, if (enable) { /* wait for STATUS to clear */ - if (!vcn_v1_0_is_idle(adev)) + if (!vcn_v1_0_is_idle(ip_block)) return -EBUSY; vcn_v1_0_enable_clock_gating(adev); } else { diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c index e42cfc731ad8..1e1c8f57d4cd 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c @@ -1317,9 +1317,9 @@ static int vcn_v2_0_pause_dpg_mode(struct amdgpu_device *adev, return 0; } -static bool vcn_v2_0_is_idle(void *handle) +static bool vcn_v2_0_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; return (RREG32_SOC15(VCN, 0, mmUVD_STATUS) == UVD_STATUS__IDLE); } @@ -1346,7 +1346,7 @@ static int vcn_v2_0_set_clockgating_state(struct amdgpu_ip_block *ip_block, if (enable) { /* wait for STATUS to clear */ - if (!vcn_v2_0_is_idle(adev)) + if (!vcn_v2_0_is_idle(ip_block)) return -EBUSY; vcn_v2_0_enable_clock_gating(adev); } else { diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c index 105e59f6132b..a6726afcf89c 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c @@ -1750,9 +1750,9 @@ static void vcn_v2_5_set_enc_ring_funcs(struct amdgpu_device *adev) } } -static bool vcn_v2_5_is_idle(void *handle) +static bool vcn_v2_5_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; int i, ret = 1; for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { @@ -1794,7 +1794,7 @@ static int vcn_v2_5_set_clockgating_state(struct amdgpu_ip_block *ip_block, for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { if (enable) { - if (!vcn_v2_5_is_idle(adev)) + if (!vcn_v2_5_is_idle(ip_block)) return -EBUSY; vcn_v2_5_enable_clock_gating(adev, i); } else { diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c index 63ddd4cca910..f75f996d929e 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c @@ -2103,9 +2103,9 @@ static void vcn_v3_0_set_enc_ring_funcs(struct amdgpu_device *adev) } } -static bool vcn_v3_0_is_idle(void *handle) +static bool vcn_v3_0_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; int i, ret = 1; for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c index 00551d6f0370..fe539f7957f0 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c @@ -1968,9 +1968,9 @@ static void vcn_v4_0_set_unified_ring_funcs(struct amdgpu_device *adev) * * Check whether VCN block is idle */ -static bool vcn_v4_0_is_idle(void *handle) +static bool vcn_v4_0_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; int i, ret = 1; for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c index 75211366f8f6..dda5ee187948 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c @@ -1579,9 +1579,9 @@ static void vcn_v4_0_3_set_unified_ring_funcs(struct amdgpu_device *adev) * * Check whether VCN block is idle */ -static bool vcn_v4_0_3_is_idle(void *handle) +static bool vcn_v4_0_3_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; int i, ret = 1; for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c index 5d757e7de9db..a482658cbf86 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c @@ -1456,9 +1456,9 @@ static void vcn_v4_0_5_set_unified_ring_funcs(struct amdgpu_device *adev) * * Check whether VCN block is idle */ -static bool vcn_v4_0_5_is_idle(void *handle) +static bool vcn_v4_0_5_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; int i, ret = 1; for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c index b6d78381ebfb..e937ed682abd 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c @@ -1196,9 +1196,9 @@ static void vcn_v5_0_0_set_unified_ring_funcs(struct amdgpu_device *adev) * * Check whether VCN block is idle */ -static bool vcn_v5_0_0_is_idle(void *handle) +static bool vcn_v5_0_0_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; int i, ret = 1; for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c index 288a77179036..721c29f52451 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c @@ -931,9 +931,9 @@ static void vcn_v5_0_1_set_unified_ring_funcs(struct amdgpu_device *adev) * * Check whether VCN block is idle */ -static bool vcn_v5_0_1_is_idle(void *handle) +static bool vcn_v5_0_1_is_idle(struct amdgpu_ip_block *ip_block) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_device *adev = ip_block->adev; int i, ret = 1; for (i = 0; i < adev->vcn.num_vcn_inst; ++i) diff --git a/drivers/gpu/drm/amd/amdgpu/vega10_ih.c b/drivers/gpu/drm/amd/amdgpu/vega10_ih.c index 98fc6941159e..eb16916c6473 100644 --- a/drivers/gpu/drm/amd/amdgpu/vega10_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/vega10_ih.c @@ -555,7 +555,7 @@ static int vega10_ih_resume(struct amdgpu_ip_block *ip_block) return vega10_ih_hw_init(ip_block); } -static bool vega10_ih_is_idle(void *handle) +static bool vega10_ih_is_idle(struct amdgpu_ip_block *ip_block) { /* todo */ return true; diff --git a/drivers/gpu/drm/amd/amdgpu/vega20_ih.c b/drivers/gpu/drm/amd/amdgpu/vega20_ih.c index e9e3b2ed4b7b..faa0dd75dd6d 100644 --- a/drivers/gpu/drm/amd/amdgpu/vega20_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/vega20_ih.c @@ -651,7 +651,7 @@ static int vega20_ih_resume(struct amdgpu_ip_block *ip_block) return vega20_ih_hw_init(ip_block); } -static bool vega20_ih_is_idle(void *handle) +static bool vega20_ih_is_idle(struct amdgpu_ip_block *ip_block) { /* todo */ return true; diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c index 12fe571787f4..3bbbb75242d9 100644 --- a/drivers/gpu/drm/amd/amdgpu/vi.c +++ b/drivers/gpu/drm/amd/amdgpu/vi.c @@ -1736,7 +1736,7 @@ static int vi_common_resume(struct amdgpu_ip_block *ip_block) return vi_common_hw_init(ip_block); } -static bool vi_common_is_idle(void *handle) +static bool vi_common_is_idle(struct amdgpu_ip_block *ip_block) { return true; } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 8672c0c3c5db..009e2696f2c8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -321,7 +321,7 @@ static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc, return 0; } -static bool dm_is_idle(void *handle) +static bool dm_is_idle(struct amdgpu_ip_block *ip_block) { /* XXX todo */ return true; diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h index 3e86865563dc..c0538763ec1a 100644 --- a/drivers/gpu/drm/amd/include/amd_shared.h +++ b/drivers/gpu/drm/amd/include/amd_shared.h @@ -405,7 +405,7 @@ struct amd_ip_funcs { int (*prepare_suspend)(struct amdgpu_ip_block *ip_block); int (*suspend)(struct amdgpu_ip_block *ip_block); int (*resume)(struct amdgpu_ip_block *ip_block); - bool (*is_idle)(void *handle); + bool (*is_idle)(struct amdgpu_ip_block *ip_block); int (*wait_for_idle)(struct amdgpu_ip_block *ip_block); bool (*check_soft_reset)(struct amdgpu_ip_block *ip_block); int (*pre_soft_reset)(struct amdgpu_ip_block *ip_block); diff --git a/drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c b/drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c index 67a8e22b1126..68bee21dd665 100644 --- a/drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c +++ b/drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c @@ -3094,7 +3094,7 @@ static int kv_dpm_resume(struct amdgpu_ip_block *ip_block) return 0; } -static bool kv_dpm_is_idle(void *handle) +static bool kv_dpm_is_idle(struct amdgpu_ip_block *ip_block) { return true; } diff --git a/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c b/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c index a87dcf0974bc..c934fc90f925 100644 --- a/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c +++ b/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c @@ -7838,7 +7838,7 @@ static int si_dpm_resume(struct amdgpu_ip_block *ip_block) return 0; } -static bool si_dpm_is_idle(void *handle) +static bool si_dpm_is_idle(struct amdgpu_ip_block *ip_block) { /* XXX */ return true; diff --git a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c index 686345f75f26..be22ed30a3c1 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c @@ -239,7 +239,7 @@ static void pp_late_fini(struct amdgpu_ip_block *ip_block) } -static bool pp_is_idle(void *handle) +static bool pp_is_idle(struct amdgpu_ip_block *ip_block) { return false; } From ee3dc9e204d271c9c7a8d4d38a0bce4745d33e71 Mon Sep 17 00:00:00 2001 From: "chr[]" Date: Wed, 12 Feb 2025 16:51:38 +0100 Subject: [PATCH 003/235] amdgpu/pm/legacy: fix suspend/resume issues resume and irq handler happily races in set_power_state() * amdgpu_legacy_dpm_compute_clocks() needs lock * protect irq work handler * fix dpm_enabled usage v2: fix clang build, integrate Lijo's comments (Alex) Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/2524 Fixes: 3712e7a49459 ("drm/amd/pm: unified lock protections in amdgpu_dpm.c") Reviewed-by: Lijo Lazar Tested-by: Maciej S. Szmigiero # on Oland PRO Signed-off-by: chr[] Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c | 25 +++++++++++++----- .../gpu/drm/amd/pm/legacy-dpm/legacy_dpm.c | 8 ++++-- drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c | 26 ++++++++++++++----- 3 files changed, 45 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c b/drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c index 68bee21dd665..59fae668dc3f 100644 --- a/drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c +++ b/drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c @@ -3042,6 +3042,7 @@ static int kv_dpm_hw_init(struct amdgpu_ip_block *ip_block) if (!amdgpu_dpm) return 0; + mutex_lock(&adev->pm.mutex); kv_dpm_setup_asic(adev); ret = kv_dpm_enable(adev); if (ret) @@ -3049,6 +3050,8 @@ static int kv_dpm_hw_init(struct amdgpu_ip_block *ip_block) else adev->pm.dpm_enabled = true; amdgpu_legacy_dpm_compute_clocks(adev); + mutex_unlock(&adev->pm.mutex); + return ret; } @@ -3066,32 +3069,42 @@ static int kv_dpm_suspend(struct amdgpu_ip_block *ip_block) { struct amdgpu_device *adev = ip_block->adev; + cancel_work_sync(&adev->pm.dpm.thermal.work); + if (adev->pm.dpm_enabled) { + mutex_lock(&adev->pm.mutex); + adev->pm.dpm_enabled = false; /* disable dpm */ kv_dpm_disable(adev); /* reset the power state */ adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps; + mutex_unlock(&adev->pm.mutex); } return 0; } static int kv_dpm_resume(struct amdgpu_ip_block *ip_block) { - int ret; + int ret = 0; struct amdgpu_device *adev = ip_block->adev; - if (adev->pm.dpm_enabled) { + if (!amdgpu_dpm) + return 0; + + if (!adev->pm.dpm_enabled) { + mutex_lock(&adev->pm.mutex); /* asic init will reset to the boot state */ kv_dpm_setup_asic(adev); ret = kv_dpm_enable(adev); - if (ret) + if (ret) { adev->pm.dpm_enabled = false; - else + } else { adev->pm.dpm_enabled = true; - if (adev->pm.dpm_enabled) amdgpu_legacy_dpm_compute_clocks(adev); + } + mutex_unlock(&adev->pm.mutex); } - return 0; + return ret; } static bool kv_dpm_is_idle(struct amdgpu_ip_block *ip_block) diff --git a/drivers/gpu/drm/amd/pm/legacy-dpm/legacy_dpm.c b/drivers/gpu/drm/amd/pm/legacy-dpm/legacy_dpm.c index e861355ebd75..c7518b13e787 100644 --- a/drivers/gpu/drm/amd/pm/legacy-dpm/legacy_dpm.c +++ b/drivers/gpu/drm/amd/pm/legacy-dpm/legacy_dpm.c @@ -1009,9 +1009,12 @@ void amdgpu_dpm_thermal_work_handler(struct work_struct *work) enum amd_pm_state_type dpm_state = POWER_STATE_TYPE_INTERNAL_THERMAL; int temp, size = sizeof(temp); - if (!adev->pm.dpm_enabled) - return; + mutex_lock(&adev->pm.mutex); + if (!adev->pm.dpm_enabled) { + mutex_unlock(&adev->pm.mutex); + return; + } if (!pp_funcs->read_sensor(adev->powerplay.pp_handle, AMDGPU_PP_SENSOR_GPU_TEMP, (void *)&temp, @@ -1033,4 +1036,5 @@ void amdgpu_dpm_thermal_work_handler(struct work_struct *work) adev->pm.dpm.state = dpm_state; amdgpu_legacy_dpm_compute_clocks(adev->powerplay.pp_handle); + mutex_unlock(&adev->pm.mutex); } diff --git a/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c b/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c index c934fc90f925..1c25f3023e93 100644 --- a/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c +++ b/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c @@ -7786,6 +7786,7 @@ static int si_dpm_hw_init(struct amdgpu_ip_block *ip_block) if (!amdgpu_dpm) return 0; + mutex_lock(&adev->pm.mutex); si_dpm_setup_asic(adev); ret = si_dpm_enable(adev); if (ret) @@ -7793,6 +7794,7 @@ static int si_dpm_hw_init(struct amdgpu_ip_block *ip_block) else adev->pm.dpm_enabled = true; amdgpu_legacy_dpm_compute_clocks(adev); + mutex_unlock(&adev->pm.mutex); return ret; } @@ -7810,32 +7812,44 @@ static int si_dpm_suspend(struct amdgpu_ip_block *ip_block) { struct amdgpu_device *adev = ip_block->adev; + cancel_work_sync(&adev->pm.dpm.thermal.work); + if (adev->pm.dpm_enabled) { + mutex_lock(&adev->pm.mutex); + adev->pm.dpm_enabled = false; /* disable dpm */ si_dpm_disable(adev); /* reset the power state */ adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps; + mutex_unlock(&adev->pm.mutex); } + return 0; } static int si_dpm_resume(struct amdgpu_ip_block *ip_block) { - int ret; + int ret = 0; struct amdgpu_device *adev = ip_block->adev; - if (adev->pm.dpm_enabled) { + if (!amdgpu_dpm) + return 0; + + if (!adev->pm.dpm_enabled) { /* asic init will reset to the boot state */ + mutex_lock(&adev->pm.mutex); si_dpm_setup_asic(adev); ret = si_dpm_enable(adev); - if (ret) + if (ret) { adev->pm.dpm_enabled = false; - else + } else { adev->pm.dpm_enabled = true; - if (adev->pm.dpm_enabled) amdgpu_legacy_dpm_compute_clocks(adev); + } + mutex_unlock(&adev->pm.mutex); } - return 0; + + return ret; } static bool si_dpm_is_idle(struct amdgpu_ip_block *ip_block) From 8150827990b709ab5a40c46c30d21b7f7b9e9440 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Wed, 19 Feb 2025 17:34:38 -0500 Subject: [PATCH 004/235] drm/amdkfd: Preserve cp_hqd_pq_control on update_mqd When userspace applications call AMDKFD_IOC_UPDATE_QUEUE. Preserve bitfields that do not need to be modified as they contain flags to track queue states that are used by CP FW. Signed-off-by: David Yat Sin Reviewed-by: Jay Cornwall Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c | 6 ++++-- drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c | 5 +++-- drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v12.c | 5 +++-- drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c | 5 ++++- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c index 2eff37aaf827..1695dd78ede8 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c @@ -107,6 +107,8 @@ static void init_mqd(struct mqd_manager *mm, void **mqd, m->cp_hqd_persistent_state = CP_HQD_PERSISTENT_STATE__PRELOAD_REQ_MASK | 0x53 << CP_HQD_PERSISTENT_STATE__PRELOAD_SIZE__SHIFT; + m->cp_hqd_pq_control = 5 << CP_HQD_PQ_CONTROL__RPTR_BLOCK_SIZE__SHIFT; + m->cp_hqd_pq_control |= CP_HQD_PQ_CONTROL__UNORD_DISPATCH_MASK; m->cp_mqd_control = 1 << CP_MQD_CONTROL__PRIV_STATE__SHIFT; m->cp_mqd_base_addr_lo = lower_32_bits(addr); @@ -167,10 +169,10 @@ static void update_mqd(struct mqd_manager *mm, void *mqd, m = get_mqd(mqd); - m->cp_hqd_pq_control = 5 << CP_HQD_PQ_CONTROL__RPTR_BLOCK_SIZE__SHIFT; + m->cp_hqd_pq_control &= ~CP_HQD_PQ_CONTROL__QUEUE_SIZE_MASK; m->cp_hqd_pq_control |= ffs(q->queue_size / sizeof(unsigned int)) - 1 - 1; - m->cp_hqd_pq_control |= CP_HQD_PQ_CONTROL__UNORD_DISPATCH_MASK; + pr_debug("cp_hqd_pq_control 0x%x\n", m->cp_hqd_pq_control); m->cp_hqd_pq_base_lo = lower_32_bits((uint64_t)q->queue_address >> 8); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c index 68dbc0399c87..3c0ae28c5923 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c @@ -154,6 +154,8 @@ static void init_mqd(struct mqd_manager *mm, void **mqd, m->cp_hqd_persistent_state = CP_HQD_PERSISTENT_STATE__PRELOAD_REQ_MASK | 0x55 << CP_HQD_PERSISTENT_STATE__PRELOAD_SIZE__SHIFT; + m->cp_hqd_pq_control = 5 << CP_HQD_PQ_CONTROL__RPTR_BLOCK_SIZE__SHIFT; + m->cp_hqd_pq_control |= CP_HQD_PQ_CONTROL__UNORD_DISPATCH_MASK; m->cp_mqd_control = 1 << CP_MQD_CONTROL__PRIV_STATE__SHIFT; m->cp_mqd_base_addr_lo = lower_32_bits(addr); @@ -221,10 +223,9 @@ static void update_mqd(struct mqd_manager *mm, void *mqd, m = get_mqd(mqd); - m->cp_hqd_pq_control = 5 << CP_HQD_PQ_CONTROL__RPTR_BLOCK_SIZE__SHIFT; + m->cp_hqd_pq_control &= ~CP_HQD_PQ_CONTROL__QUEUE_SIZE_MASK; m->cp_hqd_pq_control |= ffs(q->queue_size / sizeof(unsigned int)) - 1 - 1; - m->cp_hqd_pq_control |= CP_HQD_PQ_CONTROL__UNORD_DISPATCH_MASK; pr_debug("cp_hqd_pq_control 0x%x\n", m->cp_hqd_pq_control); m->cp_hqd_pq_base_lo = lower_32_bits((uint64_t)q->queue_address >> 8); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v12.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v12.c index 2b72d5b4949b..565858b9044d 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v12.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v12.c @@ -121,6 +121,8 @@ static void init_mqd(struct mqd_manager *mm, void **mqd, m->cp_hqd_persistent_state = CP_HQD_PERSISTENT_STATE__PRELOAD_REQ_MASK | 0x55 << CP_HQD_PERSISTENT_STATE__PRELOAD_SIZE__SHIFT; + m->cp_hqd_pq_control = 5 << CP_HQD_PQ_CONTROL__RPTR_BLOCK_SIZE__SHIFT; + m->cp_hqd_pq_control |= CP_HQD_PQ_CONTROL__UNORD_DISPATCH_MASK; m->cp_mqd_control = 1 << CP_MQD_CONTROL__PRIV_STATE__SHIFT; m->cp_mqd_base_addr_lo = lower_32_bits(addr); @@ -184,10 +186,9 @@ static void update_mqd(struct mqd_manager *mm, void *mqd, m = get_mqd(mqd); - m->cp_hqd_pq_control = 5 << CP_HQD_PQ_CONTROL__RPTR_BLOCK_SIZE__SHIFT; + m->cp_hqd_pq_control &= ~CP_HQD_PQ_CONTROL__QUEUE_SIZE_MASK; m->cp_hqd_pq_control |= ffs(q->queue_size / sizeof(unsigned int)) - 1 - 1; - m->cp_hqd_pq_control |= CP_HQD_PQ_CONTROL__UNORD_DISPATCH_MASK; pr_debug("cp_hqd_pq_control 0x%x\n", m->cp_hqd_pq_control); m->cp_hqd_pq_base_lo = lower_32_bits((uint64_t)q->queue_address >> 8); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c index ff417d5361c4..3014925d95ff 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c @@ -183,6 +183,9 @@ static void init_mqd(struct mqd_manager *mm, void **mqd, m->cp_hqd_persistent_state = CP_HQD_PERSISTENT_STATE__PRELOAD_REQ_MASK | 0x53 << CP_HQD_PERSISTENT_STATE__PRELOAD_SIZE__SHIFT; + m->cp_hqd_pq_control = 5 << CP_HQD_PQ_CONTROL__RPTR_BLOCK_SIZE__SHIFT; + m->cp_hqd_pq_control |= CP_HQD_PQ_CONTROL__UNORD_DISPATCH_MASK; + m->cp_mqd_control = 1 << CP_MQD_CONTROL__PRIV_STATE__SHIFT; m->cp_mqd_base_addr_lo = lower_32_bits(addr); @@ -245,7 +248,7 @@ static void update_mqd(struct mqd_manager *mm, void *mqd, m = get_mqd(mqd); - m->cp_hqd_pq_control = 5 << CP_HQD_PQ_CONTROL__RPTR_BLOCK_SIZE__SHIFT; + m->cp_hqd_pq_control &= ~CP_HQD_PQ_CONTROL__QUEUE_SIZE_MASK; m->cp_hqd_pq_control |= order_base_2(q->queue_size / 4) - 1; pr_debug("cp_hqd_pq_control 0x%x\n", m->cp_hqd_pq_control); From 71209c966320c0e9301ea736b9774429d4f8bdc0 Mon Sep 17 00:00:00 2001 From: Likun Gao Date: Wed, 19 Feb 2025 15:14:32 +0800 Subject: [PATCH 005/235] drm/amdgpu: correct the name of mes_pipe structure Correct the structure name admgpu_mes_pipe to amdgpu_mes_pipe. Signed-off-by: Likun Gao Reviewed-by: Mukul Joshi Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h | 2 +- drivers/gpu/drm/amd/amdgpu/mes_v11_0.c | 14 +++++++------- drivers/gpu/drm/amd/amdgpu/mes_v12_0.c | 14 +++++++------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h index 2df2444ee892..5189a7ac65b3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h @@ -56,7 +56,7 @@ enum amdgpu_mes_priority_level { struct amdgpu_mes_funcs; -enum admgpu_mes_pipe { +enum amdgpu_mes_pipe { AMDGPU_MES_SCHED_PIPE = 0, AMDGPU_MES_KIQ_PIPE, AMDGPU_MAX_MES_PIPES = 2, diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c index 747b05d9b3cf..f57ec3613d21 100644 --- a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c @@ -800,7 +800,7 @@ static const struct amdgpu_mes_funcs mes_v11_0_funcs = { }; static int mes_v11_0_allocate_ucode_buffer(struct amdgpu_device *adev, - enum admgpu_mes_pipe pipe) + enum amdgpu_mes_pipe pipe) { int r; const struct mes_firmware_header_v1_0 *mes_hdr; @@ -835,7 +835,7 @@ static int mes_v11_0_allocate_ucode_buffer(struct amdgpu_device *adev, } static int mes_v11_0_allocate_ucode_data_buffer(struct amdgpu_device *adev, - enum admgpu_mes_pipe pipe) + enum amdgpu_mes_pipe pipe) { int r; const struct mes_firmware_header_v1_0 *mes_hdr; @@ -876,7 +876,7 @@ static int mes_v11_0_allocate_ucode_data_buffer(struct amdgpu_device *adev, } static void mes_v11_0_free_ucode_buffers(struct amdgpu_device *adev, - enum admgpu_mes_pipe pipe) + enum amdgpu_mes_pipe pipe) { amdgpu_bo_free_kernel(&adev->mes.data_fw_obj[pipe], &adev->mes.data_fw_gpu_addr[pipe], @@ -974,7 +974,7 @@ static void mes_v11_0_enable(struct amdgpu_device *adev, bool enable) /* This function is for backdoor MES firmware */ static int mes_v11_0_load_microcode(struct amdgpu_device *adev, - enum admgpu_mes_pipe pipe, bool prime_icache) + enum amdgpu_mes_pipe pipe, bool prime_icache) { int r; uint32_t data; @@ -1046,7 +1046,7 @@ static int mes_v11_0_load_microcode(struct amdgpu_device *adev, } static int mes_v11_0_allocate_eop_buf(struct amdgpu_device *adev, - enum admgpu_mes_pipe pipe) + enum amdgpu_mes_pipe pipe) { int r; u32 *eop; @@ -1257,7 +1257,7 @@ static int mes_v11_0_kiq_enable_queue(struct amdgpu_device *adev) } static int mes_v11_0_queue_init(struct amdgpu_device *adev, - enum admgpu_mes_pipe pipe) + enum amdgpu_mes_pipe pipe) { struct amdgpu_ring *ring; int r; @@ -1340,7 +1340,7 @@ static int mes_v11_0_kiq_ring_init(struct amdgpu_device *adev) } static int mes_v11_0_mqd_sw_init(struct amdgpu_device *adev, - enum admgpu_mes_pipe pipe) + enum amdgpu_mes_pipe pipe) { int r, mqd_size = sizeof(struct v11_compute_mqd); struct amdgpu_ring *ring; diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c index 8d7cf40030f2..494910380057 100644 --- a/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c @@ -901,7 +901,7 @@ static const struct amdgpu_mes_funcs mes_v12_0_funcs = { }; static int mes_v12_0_allocate_ucode_buffer(struct amdgpu_device *adev, - enum admgpu_mes_pipe pipe) + enum amdgpu_mes_pipe pipe) { int r; const struct mes_firmware_header_v1_0 *mes_hdr; @@ -935,7 +935,7 @@ static int mes_v12_0_allocate_ucode_buffer(struct amdgpu_device *adev, } static int mes_v12_0_allocate_ucode_data_buffer(struct amdgpu_device *adev, - enum admgpu_mes_pipe pipe) + enum amdgpu_mes_pipe pipe) { int r; const struct mes_firmware_header_v1_0 *mes_hdr; @@ -969,7 +969,7 @@ static int mes_v12_0_allocate_ucode_data_buffer(struct amdgpu_device *adev, } static void mes_v12_0_free_ucode_buffers(struct amdgpu_device *adev, - enum admgpu_mes_pipe pipe) + enum amdgpu_mes_pipe pipe) { amdgpu_bo_free_kernel(&adev->mes.data_fw_obj[pipe], &adev->mes.data_fw_gpu_addr[pipe], @@ -1075,7 +1075,7 @@ static void mes_v12_0_set_ucode_start_addr(struct amdgpu_device *adev) /* This function is for backdoor MES firmware */ static int mes_v12_0_load_microcode(struct amdgpu_device *adev, - enum admgpu_mes_pipe pipe, bool prime_icache) + enum amdgpu_mes_pipe pipe, bool prime_icache) { int r; uint32_t data; @@ -1139,7 +1139,7 @@ static int mes_v12_0_load_microcode(struct amdgpu_device *adev, } static int mes_v12_0_allocate_eop_buf(struct amdgpu_device *adev, - enum admgpu_mes_pipe pipe) + enum amdgpu_mes_pipe pipe) { int r; u32 *eop; @@ -1360,7 +1360,7 @@ static int mes_v12_0_kiq_enable_queue(struct amdgpu_device *adev) } static int mes_v12_0_queue_init(struct amdgpu_device *adev, - enum admgpu_mes_pipe pipe) + enum amdgpu_mes_pipe pipe) { struct amdgpu_ring *ring; int r; @@ -1460,7 +1460,7 @@ static int mes_v12_0_kiq_ring_init(struct amdgpu_device *adev) } static int mes_v12_0_mqd_sw_init(struct amdgpu_device *adev, - enum admgpu_mes_pipe pipe) + enum amdgpu_mes_pipe pipe) { int r, mqd_size = sizeof(struct v12_compute_mqd); struct amdgpu_ring *ring; From f33044952c24f85a1527f91440b89d4423840de2 Mon Sep 17 00:00:00 2001 From: "Jesse.zhang@amd.com" Date: Tue, 21 Jan 2025 09:18:44 +0800 Subject: [PATCH 006/235] drm/amdgpu/kfd: Add shared SDMA reset functionality with callback support This patch introduces shared SDMA reset functionality between AMDGPU and KFD. The implementation includes the following key changes: 1. Added `amdgpu_sdma_reset_queue`: - Resets a specific SDMA queue by instance ID. - Invokes registered pre-reset and post-reset callbacks to allow KFD and AMDGPU to save/restore their state during the reset process. 2. Added `amdgpu_set_on_reset_callbacks`: - Allows KFD and AMDGPU to register callback functions for pre-reset and post-reset operations. - Callbacks are stored in a global linked list and invoked in the correct order during SDMA reset. This patch ensures that both AMDGPU and KFD can handle SDMA reset events gracefully, with proper state saving and restoration. It also provides a flexible callback mechanism for future extensions. v2: fix CamelCase and put the SDMA helper into amdgpu_sdma.c (Alex) v3: rename the `amdgpu_register_on_reset_callbacks` function to `amdgpu_sdma_register_on_reset_callbacks` move global reset_callback_list to struct amdgpu_sdma (Alex) v4: Update the reset callback function description and rename the reset function to amdgpu_sdma_reset_engine (Alex) Suggested-by: Alex Deucher Suggested-by: Jiadong Zhu Signed-off-by: Jesse Zhang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c | 73 ++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h | 11 ++++ drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c | 2 +- 3 files changed, 85 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c index 174badca27e7..fe39198307ec 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c @@ -460,3 +460,76 @@ void amdgpu_sdma_sysfs_reset_mask_fini(struct amdgpu_device *adev) device_remove_file(adev->dev, &dev_attr_sdma_reset_mask); } } + +/** + * amdgpu_sdma_register_on_reset_callbacks - Register SDMA reset callbacks + * @funcs: Pointer to the callback structure containing pre_reset and post_reset functions + * + * This function allows KFD and AMDGPU to register their own callbacks for handling + * pre-reset and post-reset operations for engine reset. These are needed because engine + * reset will stop all queues on that engine. + */ +void amdgpu_sdma_register_on_reset_callbacks(struct amdgpu_device *adev, struct sdma_on_reset_funcs *funcs) +{ + if (!funcs) + return; + + /* Initialize the list node in the callback structure */ + INIT_LIST_HEAD(&funcs->list); + + /* Add the callback structure to the global list */ + list_add_tail(&funcs->list, &adev->sdma.reset_callback_list); +} + +/** + * amdgpu_sdma_reset_engine - Reset a specific SDMA engine + * @adev: Pointer to the AMDGPU device + * @instance_id: ID of the SDMA engine instance to reset + * + * This function performs the following steps: + * 1. Calls all registered pre_reset callbacks to allow KFD and AMDGPU to save their state. + * 2. Resets the specified SDMA engine instance. + * 3. Calls all registered post_reset callbacks to allow KFD and AMDGPU to restore their state. + * + * Returns: 0 on success, or a negative error code on failure. + */ +int amdgpu_sdma_reset_engine(struct amdgpu_device *adev, uint32_t instance_id) +{ + struct sdma_on_reset_funcs *funcs; + int ret; + + /* Invoke all registered pre_reset callbacks */ + list_for_each_entry(funcs, &adev->sdma.reset_callback_list, list) { + if (funcs->pre_reset) { + ret = funcs->pre_reset(adev, instance_id); + if (ret) { + dev_err(adev->dev, + "beforeReset callback failed for instance %u: %d\n", + instance_id, ret); + return ret; + } + } + } + + /* Perform the SDMA reset for the specified instance */ + ret = amdgpu_dpm_reset_sdma(adev, 1 << instance_id); + if (ret) { + dev_err(adev->dev, "Failed to reset SDMA instance %u\n", instance_id); + return ret; + } + + /* Invoke all registered post_reset callbacks */ + list_for_each_entry(funcs, &adev->sdma.reset_callback_list, list) { + if (funcs->post_reset) { + ret = funcs->post_reset(adev, instance_id); + if (ret) { + dev_err(adev->dev, + "afterReset callback failed for instance %u: %d\n", + instance_id, ret); + return ret; + } + } + } + + return 0; +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h index 5f60736051d1..f91d75848557 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h @@ -98,6 +98,13 @@ struct amdgpu_sdma_ras { struct amdgpu_ras_block_object ras_block; }; +struct sdma_on_reset_funcs { + int (*pre_reset)(struct amdgpu_device *adev, uint32_t instance_id); + int (*post_reset)(struct amdgpu_device *adev, uint32_t instance_id); + /* Linked list node to store this structure in a list; */ + struct list_head list; +}; + struct amdgpu_sdma { struct amdgpu_sdma_instance instance[AMDGPU_MAX_SDMA_INSTANCES]; struct amdgpu_irq_src trap_irq; @@ -118,6 +125,7 @@ struct amdgpu_sdma { struct amdgpu_sdma_ras *ras; uint32_t *ip_dump; uint32_t supported_reset; + struct list_head reset_callback_list; }; /* @@ -157,6 +165,9 @@ struct amdgpu_buffer_funcs { uint32_t byte_count); }; +void amdgpu_sdma_register_on_reset_callbacks(struct amdgpu_device *adev, struct sdma_on_reset_funcs *funcs); +int amdgpu_sdma_reset_engine(struct amdgpu_device *adev, uint32_t instance_id); + #define amdgpu_emit_copy_buffer(adev, ib, s, d, b, t) (adev)->mman.buffer_funcs->emit_copy_buffer((ib), (s), (d), (b), (t)) #define amdgpu_emit_fill_buffer(adev, ib, s, d, b) (adev)->mman.buffer_funcs->emit_fill_buffer((ib), (s), (d), (b)) diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c index 9925b183c07f..aab9e9fe0cb8 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c @@ -1477,7 +1477,7 @@ static int sdma_v4_4_2_sw_init(struct amdgpu_ip_block *ip_block) r = amdgpu_sdma_sysfs_reset_mask_init(adev); if (r) return r; - + INIT_LIST_HEAD(&adev->sdma.reset_callback_list); return r; } From d6e6ea5efbe91466fc2b5943efbeea3a5a0044a7 Mon Sep 17 00:00:00 2001 From: "Jesse.zhang@amd.com" Date: Thu, 23 Jan 2025 16:21:47 +0800 Subject: [PATCH 007/235] drm/amdgpu/sdma: Refactor SDMA reset functionality and add callback support This patch refactors the SDMA reset functionality in the `sdma_v4_4_2` driver to improve modularity and support shared usage between AMDGPU and KFD. The changes include: 1. **Refactored SDMA Reset Logic**: - Split the `sdma_v4_4_2_reset_queue` function into two separate functions: - `sdma_v4_4_2_stop_queue`: Stops the SDMA queue before reset. - `sdma_v4_4_2_restore_queue`: Restores the SDMA queue after reset. - These functions are now used as callbacks for the shared reset mechanism. 2. **Added Callback Support**: - Introduced a new structure `sdma_v4_4_2_reset_funcs` to hold the stop and restore callbacks. - Added `sdma_v4_4_2_set_reset_funcs` to register these callbacks with the shared reset mechanism using `amdgpu_set_on_reset_callbacks`. 3. **Fixed Reset Queue Function**: - Modified `sdma_v4_4_2_reset_queue` to use the shared `amdgpu_sdma_reset_queue` function, ensuring consistency across the driver. This patch ensures that SDMA reset functionality is more modular, reusable, and aligned with the shared reset mechanism between AMDGPU and KFD. v2: Renamed sdma_v4_4_2_set_reset_funcs to sdma_v4_4_2_set_engine_reset_funcs. Renamed sdma_v4_4_2_reset_funcs to sdma_v4_4_2_engine_reset_funcs.(Alex) Suggested-by: Jiadong Zhu Suggested-by: Alex Deucher Signed-off-by: Jesse Zhang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c | 32 +++++++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c index aab9e9fe0cb8..bf00c7d99418 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c @@ -105,6 +105,7 @@ static void sdma_v4_4_2_set_buffer_funcs(struct amdgpu_device *adev); static void sdma_v4_4_2_set_vm_pte_funcs(struct amdgpu_device *adev); static void sdma_v4_4_2_set_irq_funcs(struct amdgpu_device *adev); static void sdma_v4_4_2_set_ras_funcs(struct amdgpu_device *adev); +static void sdma_v4_4_2_set_engine_reset_funcs(struct amdgpu_device *adev); static u32 sdma_v4_4_2_get_reg_offset(struct amdgpu_device *adev, u32 instance, u32 offset) @@ -1330,6 +1331,7 @@ static int sdma_v4_4_2_early_init(struct amdgpu_ip_block *ip_block) sdma_v4_4_2_set_vm_pte_funcs(adev); sdma_v4_4_2_set_irq_funcs(adev); sdma_v4_4_2_set_ras_funcs(adev); + sdma_v4_4_2_set_engine_reset_funcs(adev); return 0; } @@ -1605,8 +1607,14 @@ static int sdma_v4_4_2_soft_reset(struct amdgpu_ip_block *ip_block) static int sdma_v4_4_2_reset_queue(struct amdgpu_ring *ring, unsigned int vmid) { struct amdgpu_device *adev = ring->adev; - int i, r; + u32 id = GET_INST(SDMA0, ring->me); + return amdgpu_sdma_reset_engine(adev, id); +} + +static int sdma_v4_4_2_stop_queue(struct amdgpu_device *adev, uint32_t instance_id) +{ u32 inst_mask; + struct amdgpu_ring *ring = &adev->sdma.instance[instance_id].ring; if (amdgpu_sriov_vf(adev)) return -EINVAL; @@ -1617,10 +1625,16 @@ static int sdma_v4_4_2_reset_queue(struct amdgpu_ring *ring, unsigned int vmid) if (adev->sdma.has_page_queue) sdma_v4_4_2_inst_page_stop(adev, inst_mask); - r = amdgpu_dpm_reset_sdma(adev, 1 << GET_INST(SDMA0, ring->me)); - if (r) - return r; + return 0; +} +static int sdma_v4_4_2_restore_queue(struct amdgpu_device *adev, uint32_t instance_id) +{ + int i; + u32 inst_mask; + struct amdgpu_ring *ring = &adev->sdma.instance[instance_id].ring; + + inst_mask = 1 << ring->me; udelay(50); for (i = 0; i < adev->usec_timeout; i++) { @@ -1638,6 +1652,16 @@ static int sdma_v4_4_2_reset_queue(struct amdgpu_ring *ring, unsigned int vmid) return sdma_v4_4_2_inst_start(adev, inst_mask, true); } +static struct sdma_on_reset_funcs sdma_v4_4_2_engine_reset_funcs = { + .pre_reset = sdma_v4_4_2_stop_queue, + .post_reset = sdma_v4_4_2_restore_queue, +}; + +static void sdma_v4_4_2_set_engine_reset_funcs(struct amdgpu_device *adev) +{ + amdgpu_sdma_register_on_reset_callbacks(adev, &sdma_v4_4_2_engine_reset_funcs); +} + static int sdma_v4_4_2_set_trap_irq_state(struct amdgpu_device *adev, struct amdgpu_irq_src *source, unsigned type, From 2df30ae0ba0b8b529c64f670a5294634db24ed16 Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Wed, 19 Feb 2025 11:53:45 -0700 Subject: [PATCH 008/235] Documentation/gpu: Add acronyms for some firmware components Users can check the file "/sys/kernel/debug/dri/0/amdgpu_firmware_info" to get information on the firmware loaded in the system. This file has multiple acronyms that are not documented in the glossary. This commit introduces some missing acronyms to the AMD glossary documentation. The meaning of each acronym in this commit was extracted from code documentation available in the following files: - drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c - drivers/gpu/drm/amd/include/amd_shared.h Changes since v1: - Expand acronym meanings based on Alex Deucher suggestions. Cc: Mario Limonciello Signed-off-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- Documentation/gpu/amdgpu/amdgpu-glossary.rst | 45 ++++++++++++++++++-- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/Documentation/gpu/amdgpu/amdgpu-glossary.rst b/Documentation/gpu/amdgpu/amdgpu-glossary.rst index 00a47ebb0b0f..1e9283e076ba 100644 --- a/Documentation/gpu/amdgpu/amdgpu-glossary.rst +++ b/Documentation/gpu/amdgpu/amdgpu-glossary.rst @@ -12,6 +12,9 @@ we have a dedicated glossary for Display Core at The number of CUs that are active on the system. The number of active CUs may be less than SE * SH * CU depending on the board configuration. + CE + Constant Engine + CP Command Processor @@ -68,6 +71,9 @@ we have a dedicated glossary for Display Core at IB Indirect Buffer + IMU + Integrated Management Unit (Power Management support) + IP Intellectual Property blocks @@ -80,6 +86,12 @@ we have a dedicated glossary for Display Core at KIQ Kernel Interface Queue + MC + Memory Controller + + ME + MicroEngine (Graphics) + MEC MicroEngine Compute @@ -92,6 +104,9 @@ we have a dedicated glossary for Display Core at MQD Memory Queue Descriptor + PFP + Pre-Fetch Parser (Graphics) + PPLib PowerPlay Library - PowerPlay is the power management component. @@ -99,7 +114,10 @@ we have a dedicated glossary for Display Core at Platform Security Processor RLC - RunList Controller + RunList Controller. This name is a remnant of past ages and doesn't have + much meaning today. It's a group of general-purpose helper engines for + the GFX block. It's involved in GFX power management and SR-IOV, among + other things. SDMA System DMA @@ -110,14 +128,35 @@ we have a dedicated glossary for Display Core at SH SHader array - SMU - System Management Unit + SMU/SMC + System Management Unit / System Management Controller + + SRLC + Save/Restore List Control + + SRLG + Save/Restore List GPM_MEM + + SRLS + Save/Restore List SRM_MEM SS Spread Spectrum + TA + Trusted Application + + TOC + Table of Contents + + UVD + Unified Video Decoder + VCE Video Compression Engine VCN Video Codec Next + + VPE + Video Processing Engine From 793ee232eedff8483a2fff87ae82832e243d381d Mon Sep 17 00:00:00 2001 From: Sathishkumar S Date: Wed, 19 Feb 2025 09:59:03 +0530 Subject: [PATCH 009/235] drm/amdgpu: Do not poweroff UVDJ in JPEG4_0_3 Update power gate setting to not poweroff UVDJ in JPEG4_0_3. Signed-off-by: Sathishkumar S Reviewed-by: Leo Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c index 1a365bfc78bb..b8f06e9c9e62 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c @@ -634,12 +634,6 @@ static void jpeg_v4_0_3_stop_inst(struct amdgpu_device *adev, int inst) UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK, ~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK); - WREG32_SOC15(JPEG, jpeg_inst, regUVD_PGFSM_CONFIG, - 2 << UVD_PGFSM_CONFIG__UVDJ_PWR_CONFIG__SHIFT); - SOC15_WAIT_ON_RREG(JPEG, jpeg_inst, regUVD_PGFSM_STATUS, - UVD_PGFSM_STATUS__UVDJ_PWR_OFF << - UVD_PGFSM_STATUS__UVDJ_PWR_STATUS__SHIFT, - UVD_PGFSM_STATUS__UVDJ_PWR_STATUS_MASK); } /** From 0ca57515606d3a8462abe8dfa83f23c39e5e69a9 Mon Sep 17 00:00:00 2001 From: Lijo Lazar Date: Mon, 17 Feb 2025 10:41:56 +0530 Subject: [PATCH 010/235] drm/amdgpu: Remove redundant logic in GC v9.4.3 GFXOFF check is not needed for GC v9.4.3. Also, save/restore list is available by default. Signed-off-by: Lijo Lazar Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c index 91c1b2f9fe88..50eb856249d5 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c @@ -563,17 +563,6 @@ static int gfx_v9_4_3_init_rlc_microcode(struct amdgpu_device *adev, return err; } -static bool gfx_v9_4_3_should_disable_gfxoff(struct pci_dev *pdev) -{ - return true; -} - -static void gfx_v9_4_3_check_if_need_gfxoff(struct amdgpu_device *adev) -{ - if (gfx_v9_4_3_should_disable_gfxoff(adev->pdev)) - adev->pm.pp_feature &= ~PP_GFXOFF_MASK; -} - static int gfx_v9_4_3_init_cp_compute_microcode(struct amdgpu_device *adev, const char *chip_name) { @@ -600,8 +589,6 @@ static int gfx_v9_4_3_init_cp_compute_microcode(struct amdgpu_device *adev, adev->gfx.mec2_fw_version = adev->gfx.mec_fw_version; adev->gfx.mec2_feature_version = adev->gfx.mec_feature_version; - gfx_v9_4_3_check_if_need_gfxoff(adev); - out: if (err) amdgpu_ucode_release(&adev->gfx.mec_fw); @@ -1362,10 +1349,8 @@ static void gfx_v9_4_3_xcc_init_pg(struct amdgpu_device *adev, int xcc_id) { /* * Rlc save restore list is workable since v2_1. - * And it's needed by gfxoff feature. */ - if (adev->gfx.rlc.is_rlc_v2_1) - gfx_v9_4_3_xcc_enable_save_restore_machine(adev, xcc_id); + gfx_v9_4_3_xcc_enable_save_restore_machine(adev, xcc_id); } static void gfx_v9_4_3_xcc_disable_gpa_mode(struct amdgpu_device *adev, int xcc_id) From 4c02f730165765ad412a1ce8de6ea0d7abc7a333 Mon Sep 17 00:00:00 2001 From: "Jesse.zhang@amd.com" Date: Thu, 20 Feb 2025 14:25:47 +0800 Subject: [PATCH 011/235] drm/amdgpu: Introduce conditional user queue suspension for SDMA resets - Modify the `amdgpu_sdma_reset_engine` function to accept a `suspend_user_queues` parameter. - This parameter allows the function to conditionally suspend and resume user queues during SDMA resets. - Ensure that user queues are suspended only when necessary to avoid unnecessary overhead and potential deadlocks. - Restart the scheduler's work queue for the GFX and page rings after the reset to allow new tasks to be submitted. This change improves synchronization between the KGD and the KFD during SDMA resets, ensuring proper handling of user queues and avoiding race conditions. V2: replace the ring_lock with the existed the scheduler locks for the queues (ring->sched) on the sdma engine.(Alex) v3: call drm_sched_wqueue_stop() rather than job_list_lock. If a GPU ring reset was already initiated for one ring at amdgpu_job_timedout, skip resetting that ring and call drm_sched_wqueue_stop() for the other rings (Alex) replace the common lock (sdma_reset_lock) with DQM lock to to resolve reset races between the two driver sections during KFD eviction.(Jon) Rename the caller to Reset_src and Change AMDGPU_RESET_SRC_SDMA_KGD/KFD to AMDGPU_RESET_SRC_SDMA_HWS/RING (Jon) v4: restart the wqueue if the reset was successful, or fall back to a full adapter reset. (Alex) move definition of reset source to enumeration AMDGPU_RESET_SRCS, and check reset src in amdgpu_sdma_reset_instance (Jon) v5: Call amdgpu_amdkfd_suspend/resume at the start/end of reset function respectively under !SRC_HWS conditions only (Jon) v6: replace the paramter src with a bool suspend_user_queues, remove the paramter src in pre/post func. (Jon) Suggested-by: Alex Deucher Suggested-by: Jiadong Zhu Suggested-by: Jonathan Kim Signed-off-by: Jesse Zhang Acked-by: Jonathan Kim Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c | 56 +++++++++++++++++++++--- drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h | 2 +- drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c | 4 +- 3 files changed, 54 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c index fe39198307ec..9f26da7e7e34 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c @@ -25,6 +25,7 @@ #include "amdgpu.h" #include "amdgpu_sdma.h" #include "amdgpu_ras.h" +#include "amdgpu_reset.h" #define AMDGPU_CSA_SDMA_SIZE 64 /* SDMA CSA reside in the 3rd page of CSA */ @@ -485,6 +486,7 @@ void amdgpu_sdma_register_on_reset_callbacks(struct amdgpu_device *adev, struct * amdgpu_sdma_reset_engine - Reset a specific SDMA engine * @adev: Pointer to the AMDGPU device * @instance_id: ID of the SDMA engine instance to reset + * @suspend_user_queues: check if suspend user queue. * * This function performs the following steps: * 1. Calls all registered pre_reset callbacks to allow KFD and AMDGPU to save their state. @@ -493,10 +495,35 @@ void amdgpu_sdma_register_on_reset_callbacks(struct amdgpu_device *adev, struct * * Returns: 0 on success, or a negative error code on failure. */ -int amdgpu_sdma_reset_engine(struct amdgpu_device *adev, uint32_t instance_id) +int amdgpu_sdma_reset_engine(struct amdgpu_device *adev, uint32_t instance_id, bool suspend_user_queues) { struct sdma_on_reset_funcs *funcs; - int ret; + int ret = 0; + struct amdgpu_sdma_instance *sdma_instance = &adev->sdma.instance[instance_id];; + struct amdgpu_ring *gfx_ring = &sdma_instance->ring; + struct amdgpu_ring *page_ring = &sdma_instance->page; + bool gfx_sched_stopped = false, page_sched_stopped = false; + + /* Suspend KFD if suspend_user_queues is true. + * prevent the destruction of in-flight healthy user queue packets and + * avoid race conditions between KFD and KGD during the reset process. + */ + if (suspend_user_queues) + amdgpu_amdkfd_suspend(adev, false); + + /* Stop the scheduler's work queue for the GFX and page rings if they are running. + * This ensures that no new tasks are submitted to the queues while + * the reset is in progress. + */ + if (!amdgpu_ring_sched_ready(gfx_ring)) { + drm_sched_wqueue_stop(&gfx_ring->sched); + gfx_sched_stopped = true;; + } + + if (adev->sdma.has_page_queue && !amdgpu_ring_sched_ready(page_ring)) { + drm_sched_wqueue_stop(&page_ring->sched); + page_sched_stopped = true; + } /* Invoke all registered pre_reset callbacks */ list_for_each_entry(funcs, &adev->sdma.reset_callback_list, list) { @@ -506,7 +533,7 @@ int amdgpu_sdma_reset_engine(struct amdgpu_device *adev, uint32_t instance_id) dev_err(adev->dev, "beforeReset callback failed for instance %u: %d\n", instance_id, ret); - return ret; + goto exit; } } } @@ -515,7 +542,7 @@ int amdgpu_sdma_reset_engine(struct amdgpu_device *adev, uint32_t instance_id) ret = amdgpu_dpm_reset_sdma(adev, 1 << instance_id); if (ret) { dev_err(adev->dev, "Failed to reset SDMA instance %u\n", instance_id); - return ret; + goto exit; } /* Invoke all registered post_reset callbacks */ @@ -526,10 +553,27 @@ int amdgpu_sdma_reset_engine(struct amdgpu_device *adev, uint32_t instance_id) dev_err(adev->dev, "afterReset callback failed for instance %u: %d\n", instance_id, ret); - return ret; + goto exit; } } } - return 0; +exit: + /* Restart the scheduler's work queue for the GFX and page rings + * if they were stopped by this function. This allows new tasks + * to be submitted to the queues after the reset is complete. + */ + if (ret) { + if (gfx_sched_stopped && amdgpu_ring_sched_ready(gfx_ring)) { + drm_sched_wqueue_start(&gfx_ring->sched); + } + if (page_sched_stopped && amdgpu_ring_sched_ready(page_ring)) { + drm_sched_wqueue_start(&page_ring->sched); + } + } + + if (suspend_user_queues) + amdgpu_amdkfd_resume(adev, false); + + return ret; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h index f91d75848557..dd4bf2e103e5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h @@ -166,7 +166,7 @@ struct amdgpu_buffer_funcs { }; void amdgpu_sdma_register_on_reset_callbacks(struct amdgpu_device *adev, struct sdma_on_reset_funcs *funcs); -int amdgpu_sdma_reset_engine(struct amdgpu_device *adev, uint32_t instance_id); +int amdgpu_sdma_reset_engine(struct amdgpu_device *adev, uint32_t instance_id, bool suspend_user_queues); #define amdgpu_emit_copy_buffer(adev, ib, s, d, b, t) (adev)->mman.buffer_funcs->emit_copy_buffer((ib), (s), (d), (b), (t)) #define amdgpu_emit_fill_buffer(adev, ib, s, d, b) (adev)->mman.buffer_funcs->emit_fill_buffer((ib), (s), (d), (b)) diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c index bf00c7d99418..1529c5516c13 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c @@ -30,6 +30,7 @@ #include "amdgpu_xcp.h" #include "amdgpu_ucode.h" #include "amdgpu_trace.h" +#include "amdgpu_reset.h" #include "sdma/sdma_4_4_2_offset.h" #include "sdma/sdma_4_4_2_sh_mask.h" @@ -1480,6 +1481,7 @@ static int sdma_v4_4_2_sw_init(struct amdgpu_ip_block *ip_block) if (r) return r; INIT_LIST_HEAD(&adev->sdma.reset_callback_list); + return r; } @@ -1608,7 +1610,7 @@ static int sdma_v4_4_2_reset_queue(struct amdgpu_ring *ring, unsigned int vmid) { struct amdgpu_device *adev = ring->adev; u32 id = GET_INST(SDMA0, ring->me); - return amdgpu_sdma_reset_engine(adev, id); + return amdgpu_sdma_reset_engine(adev, id, true); } static int sdma_v4_4_2_stop_queue(struct amdgpu_device *adev, uint32_t instance_id) From 4d3c4f4f7f22670ae7163b5f9bd6cfea28c2efc6 Mon Sep 17 00:00:00 2001 From: "Jesse.zhang@amd.com" Date: Thu, 13 Feb 2025 10:30:07 +0800 Subject: [PATCH 012/235] drm/amdgpu: Introduce cached_rptr and is_guilty callback in amdgpu_ring This patch introduces the following changes: - Add `cached_rptr` to the `amdgpu_ring` structure to store the read pointer before a reset. - Add `is_guilty` callback to the `amdgpu_ring_funcs` structure to check if a ring is guilty of causing a timeout. Suggested-by: Alex Deucher Signed-off-by: Jesse Zhang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 2 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 3 +++ 2 files changed, 5 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c index f53887e2f528..81a7d4faac9c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c @@ -349,6 +349,8 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring, ring->buf_mask = (ring->ring_size / 4) - 1; ring->ptr_mask = ring->funcs->support_64bit_ptrs ? 0xffffffffffffffff : ring->buf_mask; + /* Initialize cached_rptr to 0 */ + ring->cached_rptr = 0; /* Allocate ring buffer */ if (ring->is_mes_queue) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h index 7372e4aed6b0..52f7a9a79e7b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h @@ -238,6 +238,7 @@ struct amdgpu_ring_funcs { void (*patch_de)(struct amdgpu_ring *ring, unsigned offset); int (*reset)(struct amdgpu_ring *ring, unsigned int vmid); void (*emit_cleaner_shader)(struct amdgpu_ring *ring); + bool (*is_guilty)(struct amdgpu_ring *ring); }; struct amdgpu_ring { @@ -307,6 +308,8 @@ struct amdgpu_ring { bool is_sw_ring; unsigned int entry_index; + /* store the cached rptr to restore after reset */ + uint64_t cached_rptr; }; From 0ad649321ae2537191f6cfa15ace5cc48d15f0bc Mon Sep 17 00:00:00 2001 From: "Jesse.zhang@amd.com" Date: Thu, 13 Feb 2025 10:51:38 +0800 Subject: [PATCH 013/235] drm/amdgpu/sdma: Introduce is_guilty callbacks for sdma GFX and PAGE rings This patch introduces the `is_guilty` callbacks for the GFX and PAGE rings. These callbacks check if a ring is guilty of causing a timeout or error. Suggested-by: Alex Deucher Signed-off-by: Jesse Zhang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c | 30 ++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c index 1529c5516c13..4ef828df8e56 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c @@ -1606,6 +1606,34 @@ static int sdma_v4_4_2_soft_reset(struct amdgpu_ip_block *ip_block) return 0; } +static bool sdma_v4_4_2_is_queue_selected(struct amdgpu_device *adev, uint32_t instance_id, bool is_page_queue) +{ + uint32_t reg_offset = is_page_queue ? regSDMA_PAGE_CONTEXT_STATUS : regSDMA_GFX_CONTEXT_STATUS; + uint32_t context_status = RREG32(sdma_v4_4_2_get_reg_offset(adev, instance_id, reg_offset)); + + /* Check if the SELECTED bit is set */ + return (context_status & SDMA_GFX_CONTEXT_STATUS__SELECTED_MASK) != 0; +} + +static bool sdma_v4_4_2_ring_is_guilty(struct amdgpu_ring *ring) +{ + struct amdgpu_device *adev = ring->adev; + uint32_t instance_id = ring->me; + + return sdma_v4_4_2_is_queue_selected(adev, instance_id, false); +} + +static bool sdma_v4_4_2_page_ring_is_guilty(struct amdgpu_ring *ring) +{ + struct amdgpu_device *adev = ring->adev; + uint32_t instance_id = ring->me; + + if (!adev->sdma.has_page_queue) + return false; + + return sdma_v4_4_2_is_queue_selected(adev, instance_id, true); +} + static int sdma_v4_4_2_reset_queue(struct amdgpu_ring *ring, unsigned int vmid) { struct amdgpu_device *adev = ring->adev; @@ -2055,6 +2083,7 @@ static const struct amdgpu_ring_funcs sdma_v4_4_2_ring_funcs = { .emit_reg_wait = sdma_v4_4_2_ring_emit_reg_wait, .emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper, .reset = sdma_v4_4_2_reset_queue, + .is_guilty = sdma_v4_4_2_ring_is_guilty, }; static const struct amdgpu_ring_funcs sdma_v4_4_2_page_ring_funcs = { @@ -2086,6 +2115,7 @@ static const struct amdgpu_ring_funcs sdma_v4_4_2_page_ring_funcs = { .emit_wreg = sdma_v4_4_2_ring_emit_wreg, .emit_reg_wait = sdma_v4_4_2_ring_emit_reg_wait, .emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper, + .is_guilty = sdma_v4_4_2_page_ring_is_guilty, }; static void sdma_v4_4_2_set_ring_funcs(struct amdgpu_device *adev) From fdbfaaaae06bbf3074d309b03d3853281f6cf433 Mon Sep 17 00:00:00 2001 From: "Jesse.zhang@amd.com" Date: Thu, 20 Feb 2025 14:43:59 +0800 Subject: [PATCH 014/235] drm/amdgpu: Improve SDMA reset logic with guilty queue tracking This patch includes the remaining improvements to the SDMA reset logic: - Added `gfx_guilty` and `page_guilty` flags to track guilty queues. - Updated the reset and resume functions to handle the guilty state. - Cached the `rptr` before reset. v2: 1.replace the caller with a guilty bool. If the queue is the guilty one, set the rptr and wptr to the saved wptr value, else, set the rptr and wptr to the saved rptr value. (Alex) 2. cache the rptr before the reset. (Alex) v3: Keeping intermediate variables like u64 rwptr simplifies resotre rptr/wptr.(Lijo) Suggested-by: Alex Deucher Suggested-by: Jiadong Zhu Signed-off-by: Jesse Zhang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c | 6 ++- drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h | 3 ++ drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c | 66 +++++++++++++++++++----- 3 files changed, 61 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c index 9f26da7e7e34..42a7b86e41c3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c @@ -475,6 +475,10 @@ void amdgpu_sdma_register_on_reset_callbacks(struct amdgpu_device *adev, struct if (!funcs) return; + /* Ensure the reset_callback_list is initialized */ + if (!adev->sdma.reset_callback_list.next) { + INIT_LIST_HEAD(&adev->sdma.reset_callback_list); + } /* Initialize the list node in the callback structure */ INIT_LIST_HEAD(&funcs->list); @@ -517,7 +521,7 @@ int amdgpu_sdma_reset_engine(struct amdgpu_device *adev, uint32_t instance_id, b */ if (!amdgpu_ring_sched_ready(gfx_ring)) { drm_sched_wqueue_stop(&gfx_ring->sched); - gfx_sched_stopped = true;; + gfx_sched_stopped = true; } if (adev->sdma.has_page_queue && !amdgpu_ring_sched_ready(page_ring)) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h index dd4bf2e103e5..965169320065 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h @@ -126,6 +126,9 @@ struct amdgpu_sdma { uint32_t *ip_dump; uint32_t supported_reset; struct list_head reset_callback_list; + /* track guilty state of GFX and PAGE queues */ + bool gfx_guilty; + bool page_guilty; }; /* diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c index 4ef828df8e56..0f76e2f955eb 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c @@ -671,11 +671,12 @@ static uint32_t sdma_v4_4_2_rb_cntl(struct amdgpu_ring *ring, uint32_t rb_cntl) * @adev: amdgpu_device pointer * @i: instance to resume * @restore: used to restore wptr when restart + * @guilty: boolean indicating whether this queue is the guilty one (caused the timeout/error) * * Set up the gfx DMA ring buffers and enable them. * Returns 0 for success, error for failure. */ -static void sdma_v4_4_2_gfx_resume(struct amdgpu_device *adev, unsigned int i, bool restore) +static void sdma_v4_4_2_gfx_resume(struct amdgpu_device *adev, unsigned int i, bool restore, bool guilty) { struct amdgpu_ring *ring = &adev->sdma.instance[i].ring; u32 rb_cntl, ib_cntl, wptr_poll_cntl; @@ -683,6 +684,7 @@ static void sdma_v4_4_2_gfx_resume(struct amdgpu_device *adev, unsigned int i, b u32 doorbell; u32 doorbell_offset; u64 wptr_gpu_addr; + u64 rwptr; wb_offset = (ring->rptr_offs * 4); @@ -708,12 +710,20 @@ static void sdma_v4_4_2_gfx_resume(struct amdgpu_device *adev, unsigned int i, b /* before programing wptr to a less value, need set minor_ptr_update first */ WREG32_SDMA(i, regSDMA_GFX_MINOR_PTR_UPDATE, 1); + /* For the guilty queue, set RPTR to the current wptr to skip bad commands, + * It is not a guilty queue, restore cache_rptr and continue execution. + */ + if (guilty) + rwptr = ring->wptr; + else + rwptr = ring->cached_rptr; + /* Initialize the ring buffer's read and write pointers */ if (restore) { - WREG32_SDMA(i, regSDMA_GFX_RB_RPTR, lower_32_bits(ring->wptr << 2)); - WREG32_SDMA(i, regSDMA_GFX_RB_RPTR_HI, upper_32_bits(ring->wptr << 2)); - WREG32_SDMA(i, regSDMA_GFX_RB_WPTR, lower_32_bits(ring->wptr << 2)); - WREG32_SDMA(i, regSDMA_GFX_RB_WPTR_HI, upper_32_bits(ring->wptr << 2)); + WREG32_SDMA(i, regSDMA_GFX_RB_RPTR, lower_32_bits(rwptr << 2)); + WREG32_SDMA(i, regSDMA_GFX_RB_RPTR_HI, upper_32_bits(rwptr << 2)); + WREG32_SDMA(i, regSDMA_GFX_RB_WPTR, lower_32_bits(rwptr << 2)); + WREG32_SDMA(i, regSDMA_GFX_RB_WPTR_HI, upper_32_bits(rwptr << 2)); } else { WREG32_SDMA(i, regSDMA_GFX_RB_RPTR, 0); WREG32_SDMA(i, regSDMA_GFX_RB_RPTR_HI, 0); @@ -768,11 +778,12 @@ static void sdma_v4_4_2_gfx_resume(struct amdgpu_device *adev, unsigned int i, b * @adev: amdgpu_device pointer * @i: instance to resume * @restore: boolean to say restore needed or not + * @guilty: boolean indicating whether this queue is the guilty one (caused the timeout/error) * * Set up the page DMA ring buffers and enable them. * Returns 0 for success, error for failure. */ -static void sdma_v4_4_2_page_resume(struct amdgpu_device *adev, unsigned int i, bool restore) +static void sdma_v4_4_2_page_resume(struct amdgpu_device *adev, unsigned int i, bool restore, bool guilty) { struct amdgpu_ring *ring = &adev->sdma.instance[i].page; u32 rb_cntl, ib_cntl, wptr_poll_cntl; @@ -780,6 +791,7 @@ static void sdma_v4_4_2_page_resume(struct amdgpu_device *adev, unsigned int i, u32 doorbell; u32 doorbell_offset; u64 wptr_gpu_addr; + u64 rwptr; wb_offset = (ring->rptr_offs * 4); @@ -787,12 +799,20 @@ static void sdma_v4_4_2_page_resume(struct amdgpu_device *adev, unsigned int i, rb_cntl = sdma_v4_4_2_rb_cntl(ring, rb_cntl); WREG32_SDMA(i, regSDMA_PAGE_RB_CNTL, rb_cntl); + /* For the guilty queue, set RPTR to the current wptr to skip bad commands, + * It is not a guilty queue, restore cache_rptr and continue execution. + */ + if (guilty) + rwptr = ring->wptr; + else + rwptr = ring->cached_rptr; + /* Initialize the ring buffer's read and write pointers */ if (restore) { - WREG32_SDMA(i, regSDMA_GFX_RB_RPTR, lower_32_bits(ring->wptr << 2)); - WREG32_SDMA(i, regSDMA_GFX_RB_RPTR_HI, upper_32_bits(ring->wptr << 2)); - WREG32_SDMA(i, regSDMA_GFX_RB_WPTR, lower_32_bits(ring->wptr << 2)); - WREG32_SDMA(i, regSDMA_GFX_RB_WPTR_HI, upper_32_bits(ring->wptr << 2)); + WREG32_SDMA(i, regSDMA_PAGE_RB_RPTR, lower_32_bits(rwptr << 2)); + WREG32_SDMA(i, regSDMA_PAGE_RB_RPTR_HI, upper_32_bits(rwptr << 2)); + WREG32_SDMA(i, regSDMA_PAGE_RB_WPTR, lower_32_bits(rwptr << 2)); + WREG32_SDMA(i, regSDMA_PAGE_RB_WPTR_HI, upper_32_bits(rwptr << 2)); } else { WREG32_SDMA(i, regSDMA_PAGE_RB_RPTR, 0); WREG32_SDMA(i, regSDMA_PAGE_RB_RPTR_HI, 0); @@ -968,9 +988,9 @@ static int sdma_v4_4_2_inst_start(struct amdgpu_device *adev, uint32_t temp; WREG32_SDMA(i, regSDMA_SEM_WAIT_FAIL_TIMER_CNTL, 0); - sdma_v4_4_2_gfx_resume(adev, i, restore); + sdma_v4_4_2_gfx_resume(adev, i, restore, adev->sdma.gfx_guilty); if (adev->sdma.has_page_queue) - sdma_v4_4_2_page_resume(adev, i, restore); + sdma_v4_4_2_page_resume(adev, i, restore, adev->sdma.page_guilty); /* set utc l1 enable flag always to 1 */ temp = RREG32_SDMA(i, regSDMA_CNTL); @@ -1480,7 +1500,9 @@ static int sdma_v4_4_2_sw_init(struct amdgpu_ip_block *ip_block) r = amdgpu_sdma_sysfs_reset_mask_init(adev); if (r) return r; - INIT_LIST_HEAD(&adev->sdma.reset_callback_list); + /* Initialize guilty flags for GFX and PAGE queues */ + adev->sdma.gfx_guilty = false; + adev->sdma.page_guilty = false; return r; } @@ -1644,11 +1666,29 @@ static int sdma_v4_4_2_reset_queue(struct amdgpu_ring *ring, unsigned int vmid) static int sdma_v4_4_2_stop_queue(struct amdgpu_device *adev, uint32_t instance_id) { u32 inst_mask; + uint64_t rptr; struct amdgpu_ring *ring = &adev->sdma.instance[instance_id].ring; if (amdgpu_sriov_vf(adev)) return -EINVAL; + /* Check if this queue is the guilty one */ + adev->sdma.gfx_guilty = sdma_v4_4_2_is_queue_selected(adev, instance_id, false); + if (adev->sdma.has_page_queue) + adev->sdma.page_guilty = sdma_v4_4_2_is_queue_selected(adev, instance_id, true); + + /* Cache the rptr before reset, after the reset, + * all of the registers will be reset to 0 + */ + rptr = amdgpu_ring_get_rptr(ring); + ring->cached_rptr = rptr; + /* Cache the rptr for the page queue if it exists */ + if (adev->sdma.has_page_queue) { + struct amdgpu_ring *page_ring = &adev->sdma.instance[instance_id].page; + rptr = amdgpu_ring_get_rptr(page_ring); + page_ring->cached_rptr = rptr; + } + /* stop queue */ inst_mask = 1 << ring->me; sdma_v4_4_2_inst_gfx_stop(adev, inst_mask); From 82252544921e3180389dc62efd0ca15eb2012898 Mon Sep 17 00:00:00 2001 From: "Jesse.zhang@amd.com" Date: Thu, 13 Feb 2025 13:28:51 +0800 Subject: [PATCH 015/235] drm/amdgpu: Add reset function pointer for SDMA v4.4.2 page ring This patch adds a reset function pointer to the SDMA v4.4.2 page ring functionality. The new function pointer `reset` is set to `sdma_v4_4_2_reset_queue`, which is responsible for resetting the SDMA queue. Changes: - Add `reset` function pointer to `sdma_v4_4_2_page_ring_funcs`. Signed-off-by: Jesse Zhang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c index 0f76e2f955eb..4fa688e00f5e 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c @@ -2155,6 +2155,7 @@ static const struct amdgpu_ring_funcs sdma_v4_4_2_page_ring_funcs = { .emit_wreg = sdma_v4_4_2_ring_emit_wreg, .emit_reg_wait = sdma_v4_4_2_ring_emit_reg_wait, .emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper, + .reset = sdma_v4_4_2_reset_queue, .is_guilty = sdma_v4_4_2_page_ring_is_guilty, }; From d190e4d0f7b52bdb2b5bd8c3dcfbcd7877a0dc53 Mon Sep 17 00:00:00 2001 From: "Jesse.zhang@amd.com" Date: Fri, 21 Feb 2025 14:02:05 +0800 Subject: [PATCH 016/235] drm/amd/pm: add support for checking SDMA reset capability This patch introduces a new function to check if the SMU supports resetting the SDMA engine. This capability check ensures that the driver does not attempt to reset the SDMA engine on hardware that does not support it. The following changes are included: - New function `amdgpu_dpm_reset_sdma_is_supported` to check SDMA reset support at the AMDGPU driver level. - New function `smu_reset_sdma_is_supported` to check SDMA reset support at the SMU level. - Implementation of `smu_v13_0_6_reset_sdma_is_supported` for the specific SMU version v13.0.6. - Updated `smu_v13_0_6_reset_sdma` to use the new capability check before attempting to reset the SDMA engine. v2: change smu_reset_sdma_is_supported type to bool (Tim) Signed-off-by: Vitaly Prosyak Signed-off-by: Jesse Zhang Reviewed-by: Tim Huang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 23 +++++++++++++++++++ drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h | 1 + drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 17 ++++++++++++++ drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h | 5 ++++ .../drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c | 23 ++++++++++++++++++- 5 files changed, 68 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c index faae9bf48aa4..7c4ff12269d9 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c @@ -722,6 +722,29 @@ int amdgpu_dpm_send_rma_reason(struct amdgpu_device *adev) return ret; } +/** + * amdgpu_dpm_reset_sdma_is_supported - Check if SDMA reset is supported + * @adev: amdgpu_device pointer + * + * This function checks if the SMU supports resetting the SDMA engine. + * It returns false if the hardware does not support software SMU or + * if the feature is not supported. + */ +bool amdgpu_dpm_reset_sdma_is_supported(struct amdgpu_device *adev) +{ + struct smu_context *smu = adev->powerplay.pp_handle; + bool ret; + + if (!is_support_sw_smu(adev)) + return false; + + mutex_lock(&adev->pm.mutex); + ret = smu_reset_sdma_is_supported(smu); + mutex_unlock(&adev->pm.mutex); + + return ret; +} + int amdgpu_dpm_reset_sdma(struct amdgpu_device *adev, uint32_t inst_mask) { struct smu_context *smu = adev->powerplay.pp_handle; diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h index 1f5ac7e0230d..9fb26b5c8ae7 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h @@ -603,5 +603,6 @@ int amdgpu_dpm_set_pm_policy(struct amdgpu_device *adev, int policy_type, ssize_t amdgpu_dpm_get_pm_policy_info(struct amdgpu_device *adev, enum pp_pm_policy p_type, char *buf); int amdgpu_dpm_reset_sdma(struct amdgpu_device *adev, uint32_t inst_mask); +bool amdgpu_dpm_reset_sdma_is_supported(struct amdgpu_device *adev); #endif diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 0b32c6cf6924..d71c8c58caa4 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -3907,6 +3907,23 @@ int smu_send_rma_reason(struct smu_context *smu) return ret; } +/** + * smu_reset_sdma_is_supported - Check if SDMA reset is supported by SMU + * @smu: smu_context pointer + * + * This function checks if the SMU supports resetting the SDMA engine. + * It returns true if supported, false otherwise. + */ +bool smu_reset_sdma_is_supported(struct smu_context *smu) +{ + bool ret = false; + + if (smu->ppt_funcs && smu->ppt_funcs->reset_sdma_is_supported) + ret = smu->ppt_funcs->reset_sdma_is_supported(smu); + + return ret; +} + int smu_reset_sdma(struct smu_context *smu, uint32_t inst_mask) { int ret = 0; diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h index 3630593bce61..3ba169639f54 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h @@ -1376,6 +1376,10 @@ struct pptable_funcs { * @reset_sdma: message SMU to soft reset sdma instance. */ int (*reset_sdma)(struct smu_context *smu, uint32_t inst_mask); + /** + * @reset_sdma_is_supported: Check if support resets the SDMA engine. + */ + bool (*reset_sdma_is_supported)(struct smu_context *smu); /** * @get_ecc_table: message SMU to get ECC INFO table. @@ -1637,6 +1641,7 @@ int smu_send_hbm_bad_pages_num(struct smu_context *smu, uint32_t size); int smu_send_hbm_bad_channel_flag(struct smu_context *smu, uint32_t size); int smu_send_rma_reason(struct smu_context *smu); int smu_reset_sdma(struct smu_context *smu, uint32_t inst_mask); +bool smu_reset_sdma_is_supported(struct smu_context *smu); int smu_set_pm_policy(struct smu_context *smu, enum pp_pm_policy p_type, int level); ssize_t smu_get_pm_policy_info(struct smu_context *smu, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c index 9f2de69f53b2..9f276f393b81 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c @@ -2902,11 +2902,31 @@ static int smu_v13_0_6_send_rma_reason(struct smu_context *smu) return ret; } +/** + * smu_v13_0_6_reset_sdma_is_supported - Check if SDMA reset is supported + * @smu: smu_context pointer + * + * This function checks if the SMU supports resetting the SDMA engine. + * It returns false if the capability is not supported. + */ +static bool smu_v13_0_6_reset_sdma_is_supported(struct smu_context *smu) +{ + bool ret = true; + + if (!smu_v13_0_6_cap_supported(smu, SMU_CAP(SDMA_RESET))) { + dev_info(smu->adev->dev, + "SDMA reset capability is not supported\n"); + ret = false; + } + + return ret; +} + static int smu_v13_0_6_reset_sdma(struct smu_context *smu, uint32_t inst_mask) { int ret = 0; - if (!smu_v13_0_6_cap_supported(smu, SMU_CAP(SDMA_RESET))) + if (!smu_v13_0_6_reset_sdma_is_supported(smu)) return -EOPNOTSUPP; ret = smu_cmn_send_smc_msg_with_param(smu, @@ -3590,6 +3610,7 @@ static const struct pptable_funcs smu_v13_0_6_ppt_funcs = { .send_hbm_bad_pages_num = smu_v13_0_6_smu_send_hbm_bad_page_num, .send_rma_reason = smu_v13_0_6_send_rma_reason, .reset_sdma = smu_v13_0_6_reset_sdma, + .reset_sdma_is_supported = smu_v13_0_6_reset_sdma_is_supported, }; void smu_v13_0_6_set_ppt_funcs(struct smu_context *smu) From c94943b0863ef3b8e88769f0805f715c8247b2bf Mon Sep 17 00:00:00 2001 From: "Jesse.zhang@amd.com" Date: Fri, 21 Feb 2025 10:26:52 +0800 Subject: [PATCH 017/235] drm/amdgpu: Update amdgpu_job_timedout to check if the ring is guilty This patch updates the `amdgpu_job_timedout` function to check if the ring is actually guilty of causing the timeout. If not, it skips error handling and fence completion. v2: move the is_guilty check down into the queue reset area (Alex) v3: need to call is_guilty before reset (Alex) v4: squash in is_guilty logic fixes (Alex) Signed-off-by: Alex Deucher Signed-off-by: Jesse Zhang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c index 100f04475943..abfbbc6babe7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c @@ -130,29 +130,45 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job) amdgpu_vm_put_task_info(ti); } - dma_fence_set_error(&s_job->s_fence->finished, -ETIME); - /* attempt a per ring reset */ if (amdgpu_gpu_recovery && ring->funcs->reset) { + bool is_guilty; + dev_err(adev->dev, "Starting %s ring reset\n", s_job->sched->name); /* stop the scheduler, but don't mess with the * bad job yet because if ring reset fails * we'll fall back to full GPU reset. */ drm_sched_wqueue_stop(&ring->sched); + + /* for engine resets, we need to reset the engine, + * but individual queues may be unaffected. + * check here to make sure the accounting is correct. + */ + if (ring->funcs->is_guilty) + is_guilty = ring->funcs->is_guilty(ring); + else + is_guilty = true; + + if (is_guilty) + dma_fence_set_error(&s_job->s_fence->finished, -ETIME); + r = amdgpu_ring_reset(ring, job->vmid); if (!r) { if (amdgpu_ring_sched_ready(ring)) drm_sched_stop(&ring->sched, s_job); - atomic_inc(&ring->adev->gpu_reset_counter); - amdgpu_fence_driver_force_completion(ring); + if (is_guilty) { + atomic_inc(&ring->adev->gpu_reset_counter); + amdgpu_fence_driver_force_completion(ring); + } if (amdgpu_ring_sched_ready(ring)) drm_sched_start(&ring->sched, 0); goto exit; } dev_err(adev->dev, "Ring %s reset failure\n", ring->sched.name); } + dma_fence_set_error(&s_job->s_fence->finished, -ETIME); if (amdgpu_device_should_recover_gpu(ring->adev)) { struct amdgpu_reset_context reset_context; From e2b3f95b47ed08b6ce8b9d64dbbbb79989ff3705 Mon Sep 17 00:00:00 2001 From: Asad Kamal Date: Mon, 10 Feb 2025 15:56:51 +0800 Subject: [PATCH 018/235] drm/amd/pm: Update pmfw headers for smu_v13_0_12 Update pmfw headers for smu_v13_0_12 new messages & metrics table. Static metrics table for frequency added, Separate metrics table for smu_v13_0_12 added. Signed-off-by: Asad Kamal Reviewed-by: Lijo Lazar Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- .../pm/swsmu/inc/pmfw_if/smu_v13_0_12_pmfw.h | 147 +++++++++++++++++- .../pm/swsmu/inc/pmfw_if/smu_v13_0_12_ppsmc.h | 143 +++++++++++++++++ 2 files changed, 288 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_12_ppsmc.h diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_12_pmfw.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_12_pmfw.h index 4a1256d29d62..d7505cfc433a 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_12_pmfw.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_12_pmfw.h @@ -38,6 +38,13 @@ #define NUM_SOC_P2S_TABLES 6 #define NUM_GFX_P2S_TABLES 8 #define NUM_PSM_DIDT_THRESHOLDS 3 +#define NUM_XVMIN_VMIN_THRESHOLDS 3 + +#define PRODUCT_MODEL_NUMBER_LEN 20 +#define PRODUCT_NAME_LEN 64 +#define PRODUCT_SERIAL_LEN 20 +#define PRODUCT_MANUFACTURER_NAME_LEN 32 +#define PRODUCT_FRU_ID_LEN 32 typedef enum { /*0*/ FEATURE_DATA_CALCULATION = 0, @@ -85,11 +92,11 @@ typedef enum { //enum for MPIO PCIe gen speed msgs typedef enum { + PCIE_LINK_SPEED_INDEX_TABLE_RESERVED, PCIE_LINK_SPEED_INDEX_TABLE_GEN1, PCIE_LINK_SPEED_INDEX_TABLE_GEN2, PCIE_LINK_SPEED_INDEX_TABLE_GEN3, PCIE_LINK_SPEED_INDEX_TABLE_GEN4, - PCIE_LINK_SPEED_INDEX_TABLE_GEN4_ESM, PCIE_LINK_SPEED_INDEX_TABLE_GEN5, PCIE_LINK_SPEED_INDEX_TABLE_COUNT } PCIE_LINK_SPEED_INDEX_TABLE_e; @@ -126,13 +133,149 @@ typedef enum { GFX_DVM_MARGIN_COUNT } GFX_DVM_MARGIN_e; -#define SMU_VF_METRICS_TABLE_VERSION 0x3 +#define SMU_METRICS_TABLE_VERSION 0x12 + +typedef struct __attribute__((packed, aligned(4))) { + uint64_t AccumulationCounter; + + //TEMPERATURE + uint32_t MaxSocketTemperature; + uint32_t MaxVrTemperature; + uint32_t MaxHbmTemperature; + uint64_t MaxSocketTemperatureAcc; + uint64_t MaxVrTemperatureAcc; + uint64_t MaxHbmTemperatureAcc; + + //POWER + uint32_t SocketPowerLimit; + uint32_t SocketPower; + + //ENERGY + uint64_t Timestamp; + uint64_t SocketEnergyAcc; + uint64_t XcdEnergyAcc; + uint64_t AidEnergyAcc; + uint64_t HbmEnergyAcc; + + //FREQUENCY + uint32_t GfxclkFrequencyLimit; + uint32_t FclkFrequency; + uint32_t UclkFrequency; + uint32_t SocclkFrequency[4]; + uint32_t VclkFrequency[4]; + uint32_t DclkFrequency[4]; + uint32_t LclkFrequency[4]; + uint64_t GfxclkFrequencyAcc[8]; + + //FREQUENCY RANGE + uint32_t MaxLclkDpmRange; + uint32_t MinLclkDpmRange; + + //XGMI + uint32_t XgmiWidth; + uint32_t XgmiBitrate; + uint64_t XgmiReadBandwidthAcc[8]; + uint64_t XgmiWriteBandwidthAcc[8]; + + //ACTIVITY + uint32_t SocketGfxBusy; + uint32_t DramBandwidthUtilization; + uint64_t SocketGfxBusyAcc; + uint64_t DramBandwidthAcc; + uint32_t MaxDramBandwidth; + uint64_t DramBandwidthUtilizationAcc; + uint64_t PcieBandwidthAcc[4]; + + //THROTTLERS + uint32_t ProchotResidencyAcc; + uint32_t PptResidencyAcc; + uint32_t SocketThmResidencyAcc; + uint32_t VrThmResidencyAcc; + uint32_t HbmThmResidencyAcc; + uint32_t GfxLockXCDMak; + + // New Items at end to maintain driver compatibility + uint32_t GfxclkFrequency[8]; + + //XGMI Data tranfser size + uint64_t XgmiReadDataSizeAcc[8];//in KByte + uint64_t XgmiWriteDataSizeAcc[8];//in KByte + + //PCIE BW Data and error count + uint32_t PcieBandwidth[4]; + uint32_t PCIeL0ToRecoveryCountAcc; // The Pcie counter itself is accumulated + uint32_t PCIenReplayAAcc; // The Pcie counter itself is accumulated + uint32_t PCIenReplayARolloverCountAcc; // The Pcie counter itself is accumulated + uint32_t PCIeNAKSentCountAcc; // The Pcie counter itself is accumulated + uint32_t PCIeNAKReceivedCountAcc; // The Pcie counter itself is accumulated + + // VCN/JPEG ACTIVITY + uint32_t VcnBusy[4]; + uint32_t JpegBusy[40]; + + // PCIE LINK Speed and width + uint32_t PCIeLinkSpeed; + uint32_t PCIeLinkWidth; + + // PER XCD ACTIVITY + uint32_t GfxBusy[8]; + uint64_t GfxBusyAcc[8]; + + //PCIE BW Data and error count + uint32_t PCIeOtherEndRecoveryAcc; // The Pcie counter itself is accumulated + + //Total App Clock Counter + uint64_t GfxclkBelowHostLimitPptAcc[8]; + uint64_t GfxclkBelowHostLimitThmAcc[8]; + uint64_t GfxclkBelowHostLimitTotalAcc[8]; + uint64_t GfxclkLowUtilizationAcc[8]; +} MetricsTable_t; + +#define SMU_VF_METRICS_TABLE_MASK (1 << 31) +#define SMU_VF_METRICS_TABLE_VERSION (0x6 | SMU_VF_METRICS_TABLE_MASK) typedef struct __attribute__((packed, aligned(4))) { uint32_t AccumulationCounter; uint32_t InstGfxclk_TargFreq; uint64_t AccGfxclk_TargFreq; uint64_t AccGfxRsmuDpm_Busy; + uint64_t AccGfxclkBelowHostLimitPpt; + uint64_t AccGfxclkBelowHostLimitThm; + uint64_t AccGfxclkBelowHostLimitTotal; + uint64_t AccGfxclkLowUtilization; } VfMetricsTable_t; +/* FRU product information */ +typedef struct __attribute__((packed, aligned(4))) { + uint8_t ModelNumber[PRODUCT_MODEL_NUMBER_LEN]; + uint8_t Name[PRODUCT_NAME_LEN]; + uint8_t Serial[PRODUCT_SERIAL_LEN]; + uint8_t ManufacturerName[PRODUCT_MANUFACTURER_NAME_LEN]; + uint8_t FruId[PRODUCT_FRU_ID_LEN]; +} FRUProductInfo_t; + +#pragma pack(push, 4) +typedef struct { + //FRU PRODUCT INFO + FRUProductInfo_t ProductInfo; + + //POWER + uint32_t MaxSocketPowerLimit; + + //FREQUENCY RANGE + uint32_t MaxGfxclkFrequency; + uint32_t MinGfxclkFrequency; + uint32_t FclkFrequencyTable[4]; + uint32_t UclkFrequencyTable[4]; + uint32_t SocclkFrequencyTable[4]; + uint32_t VclkFrequencyTable[4]; + uint32_t DclkFrequencyTable[4]; + uint32_t LclkFrequencyTable[4]; + + //PSNs + uint64_t PublicSerialNumber_AID[4]; + uint64_t PublicSerialNumber_XCD[8]; +} StaticMetricsTable_t; +#pragma pack(pop) + #endif diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_12_ppsmc.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_12_ppsmc.h new file mode 100644 index 000000000000..e1f490b6ce64 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_12_ppsmc.h @@ -0,0 +1,143 @@ +/* + * Copyright 2021 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef SMU_13_0_12_PPSMC_H +#define SMU_13_0_12_PPSMC_H + +// SMU Response Codes: +#define PPSMC_Result_OK 0x1 +#define PPSMC_Result_Failed 0xFF +#define PPSMC_Result_UnknownCmd 0xFE +#define PPSMC_Result_CmdRejectedPrereq 0xFD +#define PPSMC_Result_CmdRejectedBusy 0xFC + +// Message Definitions: +#define PPSMC_MSG_TestMessage 0x1 +#define PPSMC_MSG_GetSmuVersion 0x2 +#define PPSMC_MSG_GfxDriverReset 0x3 +#define PPSMC_MSG_GetDriverIfVersion 0x4 +#define PPSMC_MSG_EnableAllSmuFeatures 0x5 +#define PPSMC_MSG_DisableAllSmuFeatures 0x6 +#define PPSMC_MSG_RequestI2cTransaction 0x7 +#define PPSMC_MSG_GetMetricsVersion 0x8 +#define PPSMC_MSG_GetMetricsTable 0x9 +#define PPSMC_MSG_GetEccInfoTable 0xA +#define PPSMC_MSG_GetEnabledSmuFeaturesLow 0xB +#define PPSMC_MSG_GetEnabledSmuFeaturesHigh 0xC +#define PPSMC_MSG_SetDriverDramAddrHigh 0xD +#define PPSMC_MSG_SetDriverDramAddrLow 0xE +#define PPSMC_MSG_SetToolsDramAddrHigh 0xF +#define PPSMC_MSG_SetToolsDramAddrLow 0x10 +#define PPSMC_MSG_SetSystemVirtualDramAddrHigh 0x11 +#define PPSMC_MSG_SetSystemVirtualDramAddrLow 0x12 +#define PPSMC_MSG_SetSoftMinByFreq 0x13 +#define PPSMC_MSG_SetSoftMaxByFreq 0x14 +#define PPSMC_MSG_GetMinDpmFreq 0x15 +#define PPSMC_MSG_GetMaxDpmFreq 0x16 +#define PPSMC_MSG_GetDpmFreqByIndex 0x17 +#define PPSMC_MSG_SetPptLimit 0x18 +#define PPSMC_MSG_GetPptLimit 0x19 +#define PPSMC_MSG_DramLogSetDramAddrHigh 0x1A +#define PPSMC_MSG_DramLogSetDramAddrLow 0x1B +#define PPSMC_MSG_DramLogSetDramSize 0x1C +#define PPSMC_MSG_GetDebugData 0x1D +#define PPSMC_MSG_HeavySBR 0x1E +#define PPSMC_MSG_SetNumBadHbmPagesRetired 0x1F +#define PPSMC_MSG_DFCstateControl 0x20 +#define PPSMC_MSG_GetGmiPwrDnHyst 0x21 +#define PPSMC_MSG_SetGmiPwrDnHyst 0x22 +#define PPSMC_MSG_GmiPwrDnControl 0x23 +#define PPSMC_MSG_EnterGfxoff 0x24 +#define PPSMC_MSG_ExitGfxoff 0x25 +#define PPSMC_MSG_EnableDeterminism 0x26 +#define PPSMC_MSG_DisableDeterminism 0x27 +#define PPSMC_MSG_DumpSTBtoDram 0x28 +#define PPSMC_MSG_STBtoDramLogSetDramAddrHigh 0x29 +#define PPSMC_MSG_STBtoDramLogSetDramAddrLow 0x2A +#define PPSMC_MSG_STBtoDramLogSetDramSize 0x2B +#define PPSMC_MSG_SetSystemVirtualSTBtoDramAddrHigh 0x2C +#define PPSMC_MSG_SetSystemVirtualSTBtoDramAddrLow 0x2D +#define PPSMC_MSG_GfxDriverResetRecovery 0x2E +#define PPSMC_MSG_TriggerVFFLR 0x2F +#define PPSMC_MSG_SetSoftMinGfxClk 0x30 +#define PPSMC_MSG_SetSoftMaxGfxClk 0x31 +#define PPSMC_MSG_GetMinGfxDpmFreq 0x32 +#define PPSMC_MSG_GetMaxGfxDpmFreq 0x33 +#define PPSMC_MSG_PrepareForDriverUnload 0x34 +#define PPSMC_MSG_ReadThrottlerLimit 0x35 +#define PPSMC_MSG_QueryValidMcaCount 0x36 +#define PPSMC_MSG_McaBankDumpDW 0x37 +#define PPSMC_MSG_GetCTFLimit 0x38 +#define PPSMC_MSG_ClearMcaOnRead 0x39 +#define PPSMC_MSG_QueryValidMcaCeCount 0x3A +#define PPSMC_MSG_McaBankCeDumpDW 0x3B +#define PPSMC_MSG_SelectPLPDMode 0x40 +#define PPSMC_MSG_PmLogReadSample 0x41 +#define PPSMC_MSG_PmLogGetTableVersion 0x42 +#define PPSMC_MSG_RmaDueToBadPageThreshold 0x43 +#define PPSMC_MSG_SetThrottlingPolicy 0x44 +#define PPSMC_MSG_SetPhaseDetectCSBWThreshold 0x45 +#define PPSMC_MSG_SetPhaseDetectFreqHigh 0x46 +#define PPSMC_MSG_SetPhaseDetectFreqLow 0x47 +#define PPSMC_MSG_SetPhaseDetectDownHysterisis 0x48 +#define PPSMC_MSG_SetPhaseDetectAlphaX1e6 0x49 +#define PPSMC_MSG_SetPhaseDetectOnOff 0x4A +#define PPSMC_MSG_GetPhaseDetectResidency 0x4B +#define PPSMC_MSG_UpdatePccWaitDecMaxStr 0x4C +#define PPSMC_MSG_ResetSDMA 0x4D +#define PPSMC_MSG_GetRasTableVersion 0x4E +#define PPSMC_MSG_GetRmaStatus 0x4F +#define PPSMC_MSG_GetErrorCount 0x50 +#define PPSMC_MSG_GetBadPageCount 0x51 +#define PPSMC_MSG_GetBadPageInfo 0x52 +#define PPSMC_MSG_GetBadPagePaAddrLoHi 0x53 +#define PPSMC_MSG_SetTimestampLoHi 0x54 +#define PPSMC_MSG_GetTimestampLoHi 0x55 +#define PPSMC_MSG_GetRasPolicy 0x56 +#define PPSMC_MSG_DumpErrorRecord 0x57 +#define PPSMC_MSG_EraseRasTable 0x58 +#define PPSMC_MSG_GetStaticMetricsTable 0x59 +#define PPSMC_Message_Count 0x5A + +//PPSMC Reset Types for driver msg argument +#define PPSMC_RESET_TYPE_DRIVER_MODE_1_RESET 0x1 +#define PPSMC_RESET_TYPE_DRIVER_MODE_2_RESET 0x2 +#define PPSMC_RESET_TYPE_DRIVER_MODE_3_RESET 0x3 + +//PPSMC Reset Types for driver msg argument +#define PPSMC_THROTTLING_LIMIT_TYPE_SOCKET 0x1 +#define PPSMC_THROTTLING_LIMIT_TYPE_HBM 0x2 + +//CTF/Throttle Limit types +#define PPSMC_AID_THM_TYPE 0x1 +#define PPSMC_CCD_THM_TYPE 0x2 +#define PPSMC_XCD_THM_TYPE 0x3 +#define PPSMC_HBM_THM_TYPE 0x4 + +//PLPD modes +#define PPSMC_PLPD_MODE_DEFAULT 0x1 +#define PPSMC_PLPD_MODE_OPTIMIZED 0x2 + +typedef uint32_t PPSMC_Result; +typedef uint32_t PPSMC_MSG; + +#endif From 6c565218ed965160cde4a37ce0650b5c94b6241e Mon Sep 17 00:00:00 2001 From: Asad Kamal Date: Tue, 11 Feb 2025 00:17:37 +0800 Subject: [PATCH 019/235] drm/amd/pm: Add GetStaticMetricTable message Add GetStaticMetricTable message for smu_v13_0_12 Signed-off-by: Asad Kamal Reviewed-by: Lijo Lazar Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h | 3 +- drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h | 1 + .../drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c | 58 +++++++++++++++++++ .../drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c | 3 +- 4 files changed, 63 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h index 9ccd5a1986d3..9c8468fb203a 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h @@ -276,7 +276,8 @@ __SMU_DUMMY_MAP(SetThrottlingPolicy), \ __SMU_DUMMY_MAP(MALLPowerController), \ __SMU_DUMMY_MAP(MALLPowerState), \ - __SMU_DUMMY_MAP(ResetSDMA), + __SMU_DUMMY_MAP(ResetSDMA), \ + __SMU_DUMMY_MAP(GetStaticMetricsTable), #undef __SMU_DUMMY_MAP #define __SMU_DUMMY_MAP(type) SMU_MSG_##type diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h index 31166974746f..609a04c75129 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h @@ -308,5 +308,6 @@ int smu_v13_0_get_boot_freq_by_index(struct smu_context *smu, void smu_v13_0_interrupt_work(struct smu_context *smu); bool smu_v13_0_12_is_dpm_running(struct smu_context *smu); extern const struct cmn2asic_mapping smu_v13_0_12_feature_mask_map[]; +extern const struct cmn2asic_msg_mapping smu_v13_0_12_message_map[]; #endif #endif diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c index 86852e738837..5ad5dd879e81 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c @@ -28,6 +28,7 @@ #include "amdgpu_smu.h" #include "smu_v13_0_12_pmfw.h" #include "smu_v13_0_6_ppt.h" +#include "smu_v13_0_12_ppsmc.h" #include "smu_v13_0.h" #include "amdgpu_xgmi.h" #include @@ -72,6 +73,63 @@ const struct cmn2asic_mapping smu_v13_0_12_feature_mask_map[SMU_FEATURE_COUNT] = SMU_13_0_12_FEA_MAP(SMU_FEATURE_XGMI_PER_LINK_PWR_DWN_BIT, FEATURE_XGMI_PER_LINK_PWR_DOWN), }; +// clang-format off +const struct cmn2asic_msg_mapping smu_v13_0_12_message_map[SMU_MSG_MAX_COUNT] = { + MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 0), + MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion, 1), + MSG_MAP(GetDriverIfVersion, PPSMC_MSG_GetDriverIfVersion, 1), + MSG_MAP(EnableAllSmuFeatures, PPSMC_MSG_EnableAllSmuFeatures, 0), + MSG_MAP(DisableAllSmuFeatures, PPSMC_MSG_DisableAllSmuFeatures, 0), + MSG_MAP(RequestI2cTransaction, PPSMC_MSG_RequestI2cTransaction, 0), + MSG_MAP(GetMetricsTable, PPSMC_MSG_GetMetricsTable, 1), + MSG_MAP(GetMetricsVersion, PPSMC_MSG_GetMetricsVersion, 1), + MSG_MAP(GetEnabledSmuFeaturesHigh, PPSMC_MSG_GetEnabledSmuFeaturesHigh, 1), + MSG_MAP(GetEnabledSmuFeaturesLow, PPSMC_MSG_GetEnabledSmuFeaturesLow, 1), + MSG_MAP(SetDriverDramAddrHigh, PPSMC_MSG_SetDriverDramAddrHigh, 1), + MSG_MAP(SetDriverDramAddrLow, PPSMC_MSG_SetDriverDramAddrLow, 1), + MSG_MAP(SetToolsDramAddrHigh, PPSMC_MSG_SetToolsDramAddrHigh, 0), + MSG_MAP(SetToolsDramAddrLow, PPSMC_MSG_SetToolsDramAddrLow, 0), + MSG_MAP(SetSoftMinByFreq, PPSMC_MSG_SetSoftMinByFreq, 0), + MSG_MAP(SetSoftMaxByFreq, PPSMC_MSG_SetSoftMaxByFreq, 1), + MSG_MAP(GetMinDpmFreq, PPSMC_MSG_GetMinDpmFreq, 1), + MSG_MAP(GetMaxDpmFreq, PPSMC_MSG_GetMaxDpmFreq, 1), + MSG_MAP(GetDpmFreqByIndex, PPSMC_MSG_GetDpmFreqByIndex, 1), + MSG_MAP(SetPptLimit, PPSMC_MSG_SetPptLimit, 0), + MSG_MAP(GetPptLimit, PPSMC_MSG_GetPptLimit, 1), + MSG_MAP(GfxDeviceDriverReset, PPSMC_MSG_GfxDriverReset, SMU_MSG_RAS_PRI), + MSG_MAP(DramLogSetDramAddrHigh, PPSMC_MSG_DramLogSetDramAddrHigh, 0), + MSG_MAP(DramLogSetDramAddrLow, PPSMC_MSG_DramLogSetDramAddrLow, 0), + MSG_MAP(DramLogSetDramSize, PPSMC_MSG_DramLogSetDramSize, 0), + MSG_MAP(GetDebugData, PPSMC_MSG_GetDebugData, 0), + MSG_MAP(SetNumBadHbmPagesRetired, PPSMC_MSG_SetNumBadHbmPagesRetired, 0), + MSG_MAP(DFCstateControl, PPSMC_MSG_DFCstateControl, 0), + MSG_MAP(GetGmiPwrDnHyst, PPSMC_MSG_GetGmiPwrDnHyst, 0), + MSG_MAP(SetGmiPwrDnHyst, PPSMC_MSG_SetGmiPwrDnHyst, 0), + MSG_MAP(GmiPwrDnControl, PPSMC_MSG_GmiPwrDnControl, 0), + MSG_MAP(EnterGfxoff, PPSMC_MSG_EnterGfxoff, 0), + MSG_MAP(ExitGfxoff, PPSMC_MSG_ExitGfxoff, 0), + MSG_MAP(EnableDeterminism, PPSMC_MSG_EnableDeterminism, 0), + MSG_MAP(DisableDeterminism, PPSMC_MSG_DisableDeterminism, 0), + MSG_MAP(GfxDriverResetRecovery, PPSMC_MSG_GfxDriverResetRecovery, 0), + MSG_MAP(GetMinGfxclkFrequency, PPSMC_MSG_GetMinGfxDpmFreq, 1), + MSG_MAP(GetMaxGfxclkFrequency, PPSMC_MSG_GetMaxGfxDpmFreq, 1), + MSG_MAP(SetSoftMinGfxclk, PPSMC_MSG_SetSoftMinGfxClk, 1), + MSG_MAP(SetSoftMaxGfxClk, PPSMC_MSG_SetSoftMaxGfxClk, 1), + MSG_MAP(PrepareMp1ForUnload, PPSMC_MSG_PrepareForDriverUnload, 0), + MSG_MAP(GetCTFLimit, PPSMC_MSG_GetCTFLimit, 0), + MSG_MAP(GetThermalLimit, PPSMC_MSG_ReadThrottlerLimit, 0), + MSG_MAP(ClearMcaOnRead, PPSMC_MSG_ClearMcaOnRead, 0), + MSG_MAP(QueryValidMcaCount, PPSMC_MSG_QueryValidMcaCount, SMU_MSG_RAS_PRI), + MSG_MAP(QueryValidMcaCeCount, PPSMC_MSG_QueryValidMcaCeCount, SMU_MSG_RAS_PRI), + MSG_MAP(McaBankDumpDW, PPSMC_MSG_McaBankDumpDW, SMU_MSG_RAS_PRI), + MSG_MAP(McaBankCeDumpDW, PPSMC_MSG_McaBankCeDumpDW, SMU_MSG_RAS_PRI), + MSG_MAP(SelectPLPDMode, PPSMC_MSG_SelectPLPDMode, 0), + MSG_MAP(RmaDueToBadPageThreshold, PPSMC_MSG_RmaDueToBadPageThreshold, 0), + MSG_MAP(SetThrottlingPolicy, PPSMC_MSG_SetThrottlingPolicy, 0), + MSG_MAP(ResetSDMA, PPSMC_MSG_ResetSDMA, 0), + MSG_MAP(GetStaticMetricsTable, PPSMC_MSG_GetStaticMetricsTable, 1), +}; + static int smu_v13_0_12_get_enabled_mask(struct smu_context *smu, uint64_t *feature_mask) { diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c index 9f276f393b81..c43fce62df1c 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c @@ -3616,7 +3616,8 @@ static const struct pptable_funcs smu_v13_0_6_ppt_funcs = { void smu_v13_0_6_set_ppt_funcs(struct smu_context *smu) { smu->ppt_funcs = &smu_v13_0_6_ppt_funcs; - smu->message_map = smu_v13_0_6_message_map; + smu->message_map = (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(13, 0, 12)) ? + smu_v13_0_12_message_map : smu_v13_0_6_message_map; smu->clock_map = smu_v13_0_6_clk_map; smu->feature_map = (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(13, 0, 12)) ? smu_v13_0_12_feature_mask_map : smu_v13_0_6_feature_mask_map; From 95eebc05a72942582669f3ae675d7185dc275205 Mon Sep 17 00:00:00 2001 From: Asad Kamal Date: Tue, 11 Feb 2025 00:03:18 +0800 Subject: [PATCH 020/235] drm/amd/pm: Fetch static metrics table Fetch clock frequency table from static metrics table for smu_v13_0_12 v2: Move PPTable definition, remove unnecessary checks for getting static metrics table(Lijo) Signed-off-by: Asad Kamal Reviewed-by: Lijo Lazar Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h | 6 ++ .../drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c | 70 +++++++++++++++++++ .../drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c | 29 +++----- .../drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.h | 16 +++++ 4 files changed, 101 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h index 609a04c75129..4dc3b37d52b9 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h @@ -53,6 +53,10 @@ #define SMU_13_VCLK_SHIFT 16 +#define SMUQ10_TO_UINT(x) ((x) >> 10) +#define SMUQ10_FRAC(x) ((x) & 0x3ff) +#define SMUQ10_ROUND(x) ((SMUQ10_TO_UINT(x)) + ((SMUQ10_FRAC(x)) >= 0x200)) + extern const int pmfw_decoded_link_speed[5]; extern const int pmfw_decoded_link_width[7]; @@ -307,6 +311,8 @@ int smu_v13_0_get_boot_freq_by_index(struct smu_context *smu, void smu_v13_0_interrupt_work(struct smu_context *smu); bool smu_v13_0_12_is_dpm_running(struct smu_context *smu); +int smu_v13_0_12_get_max_metrics_size(void); +int smu_v13_0_12_setup_driver_pptable(struct smu_context *smu); extern const struct cmn2asic_mapping smu_v13_0_12_feature_mask_map[]; extern const struct cmn2asic_msg_mapping smu_v13_0_12_message_map[]; #endif diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c index 5ad5dd879e81..1555fb954487 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c @@ -145,6 +145,76 @@ static int smu_v13_0_12_get_enabled_mask(struct smu_context *smu, return ret; } +int smu_v13_0_12_get_max_metrics_size(void) +{ + return sizeof(StaticMetricsTable_t); +} + +static int smu_v13_0_12_get_static_metrics_table(struct smu_context *smu) +{ + struct smu_table_context *smu_table = &smu->smu_table; + uint32_t table_size = smu_table->tables[SMU_TABLE_SMU_METRICS].size; + struct smu_table *table = &smu_table->driver_table; + int ret; + + ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetStaticMetricsTable, NULL); + if (ret) { + dev_info(smu->adev->dev, + "Failed to export static metrics table!\n"); + return ret; + } + + amdgpu_asic_invalidate_hdp(smu->adev, NULL); + memcpy(smu_table->metrics_table, table->cpu_addr, table_size); + + return 0; +} + +int smu_v13_0_12_setup_driver_pptable(struct smu_context *smu) +{ + struct smu_table_context *smu_table = &smu->smu_table; + StaticMetricsTable_t *static_metrics = (StaticMetricsTable_t *)smu_table->metrics_table; + struct PPTable_t *pptable = + (struct PPTable_t *)smu_table->driver_pptable; + int ret, i; + + if (!pptable->Init) { + ret = smu_v13_0_12_get_static_metrics_table(smu); + if (ret) + return ret; + + pptable->MaxSocketPowerLimit = + SMUQ10_ROUND(static_metrics->MaxSocketPowerLimit); + pptable->MaxGfxclkFrequency = + SMUQ10_ROUND(static_metrics->MaxGfxclkFrequency); + pptable->MinGfxclkFrequency = + SMUQ10_ROUND(static_metrics->MinGfxclkFrequency); + + for (i = 0; i < 4; ++i) { + pptable->FclkFrequencyTable[i] = + SMUQ10_ROUND(static_metrics->FclkFrequencyTable[i]); + pptable->UclkFrequencyTable[i] = + SMUQ10_ROUND(static_metrics->UclkFrequencyTable[i]); + pptable->SocclkFrequencyTable[i] = + SMUQ10_ROUND(static_metrics->SocclkFrequencyTable[i]); + pptable->VclkFrequencyTable[i] = + SMUQ10_ROUND(static_metrics->VclkFrequencyTable[i]); + pptable->DclkFrequencyTable[i] = + SMUQ10_ROUND(static_metrics->DclkFrequencyTable[i]); + pptable->LclkFrequencyTable[i] = + SMUQ10_ROUND(static_metrics->LclkFrequencyTable[i]); + } + + /* use AID0 serial number by default */ + pptable->PublicSerialNumber_AID = + static_metrics->PublicSerialNumber_AID[0]; + + pptable->Init = true; + } + + return 0; +} + bool smu_v13_0_12_is_dpm_running(struct smu_context *smu) { int ret; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c index c43fce62df1c..c3e0da680cf8 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c @@ -116,6 +116,7 @@ enum smu_v13_0_6_caps { SMU_CAP(RMA_MSG), SMU_CAP(ACA_SYND), SMU_CAP(SDMA_RESET), + SMU_CAP(STATIC_METRICS), SMU_CAP(ALL), }; @@ -252,25 +253,6 @@ static const uint8_t smu_v13_0_6_throttler_map[] = { [THROTTLER_PROCHOT_BIT] = (SMU_THROTTLER_PROCHOT_GFX_BIT), }; -struct PPTable_t { - uint32_t MaxSocketPowerLimit; - uint32_t MaxGfxclkFrequency; - uint32_t MinGfxclkFrequency; - uint32_t FclkFrequencyTable[4]; - uint32_t UclkFrequencyTable[4]; - uint32_t SocclkFrequencyTable[4]; - uint32_t VclkFrequencyTable[4]; - uint32_t DclkFrequencyTable[4]; - uint32_t LclkFrequencyTable[4]; - uint32_t MaxLclkDpmRange; - uint32_t MinLclkDpmRange; - uint64_t PublicSerialNumber_AID; - bool Init; -}; - -#define SMUQ10_TO_UINT(x) ((x) >> 10) -#define SMUQ10_FRAC(x) ((x) & 0x3ff) -#define SMUQ10_ROUND(x) ((SMUQ10_TO_UINT(x)) + ((SMUQ10_FRAC(x)) >= 0x200)) #define GET_GPU_METRIC_FIELD(field, version) ((version == METRICS_VERSION_V0) ?\ (metrics_v0->field) : (metrics_v2->field)) #define GET_METRIC_FIELD(field, version) ((version == METRICS_VERSION_V1) ?\ @@ -368,6 +350,9 @@ static void smu_v13_0_12_init_caps(struct smu_context *smu) if (fw_ver >= 0x00561700) smu_v13_0_6_cap_set(smu, SMU_CAP(SDMA_RESET)); + + if (fw_ver >= 0x00561E00) + smu_v13_0_6_cap_set(smu, SMU_CAP(STATIC_METRICS)); } static void smu_v13_0_6_init_caps(struct smu_context *smu) @@ -523,13 +508,14 @@ static int smu_v13_0_6_tables_init(struct smu_context *smu) struct smu_table_context *smu_table = &smu->smu_table; struct smu_table *tables = smu_table->tables; struct amdgpu_device *adev = smu->adev; + int gpu_metrcs_size = METRICS_TABLE_SIZE; if (!(adev->flags & AMD_IS_APU)) SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU13_TOOL_SIZE, PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, - METRICS_TABLE_SIZE, + max(gpu_metrcs_size, smu_v13_0_12_get_max_metrics_size()), PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM | AMDGPU_GEM_DOMAIN_GTT); @@ -776,6 +762,9 @@ static int smu_v13_0_6_setup_driver_pptable(struct smu_context *smu) int ret, i, retry = 100; uint32_t table_version; + if (smu_v13_0_6_cap_supported(smu, SMU_CAP(STATIC_METRICS))) + return smu_v13_0_12_setup_driver_pptable(smu); + /* Store one-time values in driver PPTable */ if (!pptable->Init) { while (--retry) { diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.h b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.h index 717fe669882e..83745909e564 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.h +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.h @@ -35,6 +35,22 @@ typedef enum { /*3*/ NUM_METRICS = 3 } METRICS_LIST_e; +struct PPTable_t { + uint32_t MaxSocketPowerLimit; + uint32_t MaxGfxclkFrequency; + uint32_t MinGfxclkFrequency; + uint32_t FclkFrequencyTable[4]; + uint32_t UclkFrequencyTable[4]; + uint32_t SocclkFrequencyTable[4]; + uint32_t VclkFrequencyTable[4]; + uint32_t DclkFrequencyTable[4]; + uint32_t LclkFrequencyTable[4]; + uint32_t MaxLclkDpmRange; + uint32_t MinLclkDpmRange; + uint64_t PublicSerialNumber_AID; + bool Init; +}; + extern void smu_v13_0_6_set_ppt_funcs(struct smu_context *smu); #endif From 25907304cfce5244fb4a8aa2ca5ec884e823b7c5 Mon Sep 17 00:00:00 2001 From: Asad Kamal Date: Wed, 12 Feb 2025 16:00:41 +0800 Subject: [PATCH 021/235] drm/amd/pm: Fetch fru product info for smu_v13_0_12 Fetch fru product info for smu_v13_0_12 from static metrics table v2: Field by field copy for fru info(Lijo) Signed-off-by: Asad Kamal Reviewed-by: Lijo Lazar Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- .../gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c | 9 ++++++ .../drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c | 31 +++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c index 89109eb2ce16..1ae88c459da5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c @@ -31,6 +31,7 @@ #define FRU_EEPROM_MADDR_6 0x60000 #define FRU_EEPROM_MADDR_8 0x80000 +#define FRU_EEPROM_MADDR_INV 0xFFFFF static bool is_fru_eeprom_supported(struct amdgpu_device *adev, u32 *fru_addr) { @@ -104,6 +105,10 @@ static bool is_fru_eeprom_supported(struct amdgpu_device *adev, u32 *fru_addr) if (fru_addr) *fru_addr = FRU_EEPROM_MADDR_8; return true; + case IP_VERSION(13, 0, 12): + if (fru_addr) + *fru_addr = FRU_EEPROM_MADDR_INV; + return true; default: return false; } @@ -120,6 +125,10 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev) if (!is_fru_eeprom_supported(adev, &fru_addr)) return 0; + /* FRU data avaialble, but no direct EEPROM access */ + if (fru_addr == FRU_EEPROM_MADDR_INV) + return 0; + if (!adev->fru_info) { adev->fru_info = kzalloc(sizeof(*adev->fru_info), GFP_KERNEL); if (!adev->fru_info) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c index 1555fb954487..e153062adf77 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c @@ -31,6 +31,7 @@ #include "smu_v13_0_12_ppsmc.h" #include "smu_v13_0.h" #include "amdgpu_xgmi.h" +#include "amdgpu_fru_eeprom.h" #include #include "smu_cmn.h" @@ -145,6 +146,33 @@ static int smu_v13_0_12_get_enabled_mask(struct smu_context *smu, return ret; } +static int smu_v13_0_12_fru_get_product_info(struct smu_context *smu, + StaticMetricsTable_t *static_metrics) +{ + struct amdgpu_fru_info *fru_info; + struct amdgpu_device *adev = smu->adev; + + if (!adev->fru_info) { + adev->fru_info = kzalloc(sizeof(*adev->fru_info), GFP_KERNEL); + if (!adev->fru_info) + return -ENOMEM; + } + + fru_info = adev->fru_info; + strscpy(fru_info->product_number, static_metrics->ProductInfo.ModelNumber, + sizeof(fru_info->product_number)); + strscpy(fru_info->product_name, static_metrics->ProductInfo.Name, + sizeof(fru_info->product_name)); + strscpy(fru_info->serial, static_metrics->ProductInfo.Serial, + sizeof(fru_info->serial)); + strscpy(fru_info->manufacturer_name, static_metrics->ProductInfo.ManufacturerName, + sizeof(fru_info->manufacturer_name)); + strscpy(fru_info->fru_id, static_metrics->ProductInfo.FruId, + sizeof(fru_info->fru_id)); + + return 0; +} + int smu_v13_0_12_get_max_metrics_size(void) { return sizeof(StaticMetricsTable_t); @@ -208,6 +236,9 @@ int smu_v13_0_12_setup_driver_pptable(struct smu_context *smu) /* use AID0 serial number by default */ pptable->PublicSerialNumber_AID = static_metrics->PublicSerialNumber_AID[0]; + ret = smu_v13_0_12_fru_get_product_info(smu, static_metrics); + if (ret) + return ret; pptable->Init = true; } From 5235053f443cef4210606e5fb71f99b915a9723d Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 17 Feb 2025 10:55:05 -0500 Subject: [PATCH 022/235] drm/amdgpu: disable BAR resize on Dell G5 SE There was a quirk added to add a workaround for a Sapphire RX 5600 XT Pulse that didn't allow BAR resizing. However, the quirk caused a regression with runtime pm on Dell laptops using those chips, rather than narrowing the scope of the resizing quirk, add a quirk to prevent amdgpu from resizing the BAR on those Dell platforms unless runtime pm is disabled. v2: update commit message, add runpm check Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/1707 Fixes: 907830b0fc9e ("PCI: Add a REBAR size quirk for Sapphire RX 5600 XT Pulse") Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index c8ceea01a221..7b60646c6ad2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1662,6 +1662,13 @@ int amdgpu_device_resize_fb_bar(struct amdgpu_device *adev) if (amdgpu_sriov_vf(adev)) return 0; + /* resizing on Dell G5 SE platforms causes problems with runtime pm */ + if ((amdgpu_runtime_pm != 0) && + adev->pdev->vendor == PCI_VENDOR_ID_ATI && + adev->pdev->device == 0x731f && + adev->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL) + return 0; + /* PCI_EXT_CAP_ID_VNDR extended capability is located at 0x100 */ if (!pci_find_ext_capability(adev->pdev, PCI_EXT_CAP_ID_VNDR)) DRM_WARN("System can't access extended configuration space, please check!!\n"); From c19390ca9094dfcbc16d96b233a409c01e21d85b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 11 Feb 2025 15:38:20 -0500 Subject: [PATCH 023/235] MAINTAINERS: update amdgpu maintainers list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Xinhui's email is no longer valid. Reviewed-by: Christian König Signed-off-by: Alex Deucher --- MAINTAINERS | 1 - 1 file changed, 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 896a307fa065..b3363c0c34e3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -19607,7 +19607,6 @@ F: drivers/net/wireless/quantenna RADEON and AMDGPU DRM DRIVERS M: Alex Deucher M: Christian König -M: Xinhui Pan L: amd-gfx@lists.freedesktop.org S: Supported B: https://gitlab.freedesktop.org/drm/amd/-/issues From a1addcf8499a566496847f1e36e1cf0b4ad72a26 Mon Sep 17 00:00:00 2001 From: Aurabindo Pillai Date: Fri, 21 Feb 2025 09:45:12 -0500 Subject: [PATCH 024/235] drm/amd/display: fix an indent issue in DML21 Remove extraneous tab and newline in dml2_core_dcn4.c that was reported by the bot Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202502211920.txUfwtSj-lkp@intel.com/ Fixes: 70839da6360 ("drm/amd/display: Add new DCN401 sources") Signed-off-by: Aurabindo Pillai Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4.c index 3664980d1574..0f4ada64461e 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4.c @@ -141,9 +141,8 @@ bool core_dcn4_initialize(struct dml2_core_initialize_in_out *in_out) core->clean_me_up.mode_lib.ip.subvp_fw_processing_delay_us = core_dcn4_ip_caps_base.subvp_pstate_allow_width_us; core->clean_me_up.mode_lib.ip.subvp_swath_height_margin_lines = core_dcn4_ip_caps_base.subvp_swath_height_margin_lines; } else { - memcpy(&core->clean_me_up.mode_lib.ip, &core_dcn4_ip_caps_base, sizeof(struct dml2_core_ip_params)); + memcpy(&core->clean_me_up.mode_lib.ip, &core_dcn4_ip_caps_base, sizeof(struct dml2_core_ip_params)); patch_ip_params_with_ip_caps(&core->clean_me_up.mode_lib.ip, in_out->ip_caps); - core->clean_me_up.mode_lib.ip.imall_supported = false; } From da120ed561e2f47556f63638842e6d6ddb8d8216 Mon Sep 17 00:00:00 2001 From: Sathishkumar S Date: Tue, 18 Feb 2025 23:26:37 +0530 Subject: [PATCH 025/235] drm/amdgpu: Per-instance init func for JPEG5_0_1 Add helper functions to handle per-instance and per-core initialization and deinitialization in JPEG5_0_1. Signed-off-by: Sathishkumar S Reviewed-by: Leo Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c | 150 +++++++++++------------ 1 file changed, 69 insertions(+), 81 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c index 5d4e2a09acca..e6412195e467 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c @@ -326,11 +326,10 @@ static int jpeg_v5_0_1_resume(struct amdgpu_ip_block *ip_block) return r; } -static int jpeg_v5_0_1_disable_antihang(struct amdgpu_device *adev, int inst_idx) +static void jpeg_v5_0_1_init_inst(struct amdgpu_device *adev, int i) { - int jpeg_inst; + int jpeg_inst = GET_INST(JPEG, i); - jpeg_inst = GET_INST(JPEG, inst_idx); /* disable anti hang mechanism */ WREG32_P(SOC15_REG_OFFSET(JPEG, jpeg_inst, regUVD_JPEG_POWER_STATUS), 0, ~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK); @@ -339,20 +338,75 @@ static int jpeg_v5_0_1_disable_antihang(struct amdgpu_device *adev, int inst_idx WREG32_P(SOC15_REG_OFFSET(JPEG, jpeg_inst, regUVD_JPEG_POWER_STATUS), 0, ~UVD_JPEG_POWER_STATUS__JPEG_PG_MODE_MASK); - return 0; + /* MJPEG global tiling registers */ + WREG32_SOC15(JPEG, 0, regJPEG_DEC_GFX10_ADDR_CONFIG, + adev->gfx.config.gb_addr_config); + + /* enable JMI channel */ + WREG32_P(SOC15_REG_OFFSET(JPEG, jpeg_inst, regUVD_JMI_CNTL), 0, + ~UVD_JMI_CNTL__SOFT_RESET_MASK); } -static int jpeg_v5_0_1_enable_antihang(struct amdgpu_device *adev, int inst_idx) +static void jpeg_v5_0_1_deinit_inst(struct amdgpu_device *adev, int i) { - int jpeg_inst; + int jpeg_inst = GET_INST(JPEG, i); + /* reset JMI */ + WREG32_P(SOC15_REG_OFFSET(JPEG, jpeg_inst, regUVD_JMI_CNTL), + UVD_JMI_CNTL__SOFT_RESET_MASK, + ~UVD_JMI_CNTL__SOFT_RESET_MASK); - jpeg_inst = GET_INST(JPEG, inst_idx); /* enable anti hang mechanism */ WREG32_P(SOC15_REG_OFFSET(JPEG, jpeg_inst, regUVD_JPEG_POWER_STATUS), UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK, - ~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK); + ~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK); +} - return 0; +static void jpeg_v5_0_1_init_jrbc(struct amdgpu_ring *ring) +{ + struct amdgpu_device *adev = ring->adev; + u32 reg, data, mask; + int jpeg_inst = GET_INST(JPEG, ring->me); + int reg_offset = ring->pipe ? jpeg_v5_0_1_core_reg_offset(ring->pipe) : 0; + + /* enable System Interrupt for JRBC */ + reg = SOC15_REG_OFFSET(JPEG, jpeg_inst, regJPEG_SYS_INT_EN); + if (ring->pipe < AMDGPU_MAX_JPEG_RINGS_4_0_3) { + data = JPEG_SYS_INT_EN__DJRBC0_MASK << ring->pipe; + mask = ~(JPEG_SYS_INT_EN__DJRBC0_MASK << ring->pipe); + WREG32_P(reg, data, mask); + } else { + data = JPEG_SYS_INT_EN__DJRBC0_MASK << (ring->pipe+12); + mask = ~(JPEG_SYS_INT_EN__DJRBC0_MASK << (ring->pipe+12)); + WREG32_P(reg, data, mask); + } + + WREG32_SOC15_OFFSET(JPEG, jpeg_inst, + regUVD_LMI_JRBC_RB_VMID, + reg_offset, 0); + WREG32_SOC15_OFFSET(JPEG, jpeg_inst, + regUVD_JRBC_RB_CNTL, + reg_offset, + (0x00000001L | 0x00000002L)); + WREG32_SOC15_OFFSET(JPEG, jpeg_inst, + regUVD_LMI_JRBC_RB_64BIT_BAR_LOW, + reg_offset, lower_32_bits(ring->gpu_addr)); + WREG32_SOC15_OFFSET(JPEG, jpeg_inst, + regUVD_LMI_JRBC_RB_64BIT_BAR_HIGH, + reg_offset, upper_32_bits(ring->gpu_addr)); + WREG32_SOC15_OFFSET(JPEG, jpeg_inst, + regUVD_JRBC_RB_RPTR, + reg_offset, 0); + WREG32_SOC15_OFFSET(JPEG, jpeg_inst, + regUVD_JRBC_RB_WPTR, + reg_offset, 0); + WREG32_SOC15_OFFSET(JPEG, jpeg_inst, + regUVD_JRBC_RB_CNTL, + reg_offset, 0x00000002L); + WREG32_SOC15_OFFSET(JPEG, jpeg_inst, + regUVD_JRBC_RB_SIZE, + reg_offset, ring->ring_size / 4); + ring->wptr = RREG32_SOC15_OFFSET(JPEG, jpeg_inst, regUVD_JRBC_RB_WPTR, + reg_offset); } /** @@ -365,69 +419,13 @@ static int jpeg_v5_0_1_enable_antihang(struct amdgpu_device *adev, int inst_idx) static int jpeg_v5_0_1_start(struct amdgpu_device *adev) { struct amdgpu_ring *ring; - int i, j, jpeg_inst, r; + int i, j; for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) { - jpeg_inst = GET_INST(JPEG, i); - - /* disable antihang */ - r = jpeg_v5_0_1_disable_antihang(adev, i); - if (r) - return r; - - /* MJPEG global tiling registers */ - WREG32_SOC15(JPEG, 0, regJPEG_DEC_GFX10_ADDR_CONFIG, - adev->gfx.config.gb_addr_config); - - /* enable JMI channel */ - WREG32_P(SOC15_REG_OFFSET(JPEG, jpeg_inst, regUVD_JMI_CNTL), 0, - ~UVD_JMI_CNTL__SOFT_RESET_MASK); - + jpeg_v5_0_1_init_inst(adev, i); for (j = 0; j < adev->jpeg.num_jpeg_rings; ++j) { - int reg_offset = (j ? jpeg_v5_0_1_core_reg_offset(j) : 0); - u32 reg, data, mask; - ring = &adev->jpeg.inst[i].ring_dec[j]; - - /* enable System Interrupt for JRBC */ - reg = SOC15_REG_OFFSET(JPEG, jpeg_inst, regJPEG_SYS_INT_EN); - if (j < AMDGPU_MAX_JPEG_RINGS_4_0_3) { - data = JPEG_SYS_INT_EN__DJRBC0_MASK << j; - mask = ~(JPEG_SYS_INT_EN__DJRBC0_MASK << j); - WREG32_P(reg, data, mask); - } else { - data = JPEG_SYS_INT_EN__DJRBC0_MASK << (j+12); - mask = ~(JPEG_SYS_INT_EN__DJRBC0_MASK << (j+12)); - WREG32_P(reg, data, mask); - } - - WREG32_SOC15_OFFSET(JPEG, jpeg_inst, - regUVD_LMI_JRBC_RB_VMID, - reg_offset, 0); - WREG32_SOC15_OFFSET(JPEG, jpeg_inst, - regUVD_JRBC_RB_CNTL, - reg_offset, - (0x00000001L | 0x00000002L)); - WREG32_SOC15_OFFSET(JPEG, jpeg_inst, - regUVD_LMI_JRBC_RB_64BIT_BAR_LOW, - reg_offset, lower_32_bits(ring->gpu_addr)); - WREG32_SOC15_OFFSET(JPEG, jpeg_inst, - regUVD_LMI_JRBC_RB_64BIT_BAR_HIGH, - reg_offset, upper_32_bits(ring->gpu_addr)); - WREG32_SOC15_OFFSET(JPEG, jpeg_inst, - regUVD_JRBC_RB_RPTR, - reg_offset, 0); - WREG32_SOC15_OFFSET(JPEG, jpeg_inst, - regUVD_JRBC_RB_WPTR, - reg_offset, 0); - WREG32_SOC15_OFFSET(JPEG, jpeg_inst, - regUVD_JRBC_RB_CNTL, - reg_offset, 0x00000002L); - WREG32_SOC15_OFFSET(JPEG, jpeg_inst, - regUVD_JRBC_RB_SIZE, - reg_offset, ring->ring_size / 4); - ring->wptr = RREG32_SOC15_OFFSET(JPEG, jpeg_inst, regUVD_JRBC_RB_WPTR, - reg_offset); + jpeg_v5_0_1_init_jrbc(ring); } } @@ -443,20 +441,10 @@ static int jpeg_v5_0_1_start(struct amdgpu_device *adev) */ static int jpeg_v5_0_1_stop(struct amdgpu_device *adev) { - int i, jpeg_inst, r; + int i; - for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) { - jpeg_inst = GET_INST(JPEG, i); - /* reset JMI */ - WREG32_P(SOC15_REG_OFFSET(JPEG, jpeg_inst, regUVD_JMI_CNTL), - UVD_JMI_CNTL__SOFT_RESET_MASK, - ~UVD_JMI_CNTL__SOFT_RESET_MASK); - - /* enable antihang */ - r = jpeg_v5_0_1_enable_antihang(adev, i); - if (r) - return r; - } + for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) + jpeg_v5_0_1_deinit_inst(adev, i); return 0; } From 9b71be8785e2849cd82b6aeab642b60cd6577966 Mon Sep 17 00:00:00 2001 From: Sathishkumar S Date: Tue, 18 Feb 2025 23:35:42 +0530 Subject: [PATCH 026/235] drm/amdgpu: Add core reset registers for JPEG5_0_1 Add core reset control register definitions and align all prior register definitions to end at 100 column length for uniformity. Signed-off-by: Sathishkumar S Reviewed-by: Leo Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.h | 128 ++++++++++++----------- 1 file changed, 68 insertions(+), 60 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.h b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.h index 9de3272ef47f..d5c63d8074ab 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.h +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.h @@ -26,65 +26,73 @@ extern const struct amdgpu_ip_block_version jpeg_v5_0_1_ip_block; -#define regUVD_JRBC0_UVD_JRBC_RB_WPTR 0x0640 -#define regUVD_JRBC0_UVD_JRBC_RB_WPTR_BASE_IDX 1 -#define regUVD_JRBC0_UVD_JRBC_STATUS 0x0649 -#define regUVD_JRBC0_UVD_JRBC_STATUS_BASE_IDX 1 -#define regUVD_JRBC0_UVD_JRBC_RB_RPTR 0x064a -#define regUVD_JRBC0_UVD_JRBC_RB_RPTR_BASE_IDX 1 -#define regUVD_JRBC1_UVD_JRBC_RB_WPTR 0x0000 -#define regUVD_JRBC1_UVD_JRBC_RB_WPTR_BASE_IDX 0 -#define regUVD_JRBC1_UVD_JRBC_STATUS 0x0009 -#define regUVD_JRBC1_UVD_JRBC_STATUS_BASE_IDX 0 -#define regUVD_JRBC1_UVD_JRBC_RB_RPTR 0x000a -#define regUVD_JRBC1_UVD_JRBC_RB_RPTR_BASE_IDX 0 -#define regUVD_JRBC2_UVD_JRBC_RB_WPTR 0x0040 -#define regUVD_JRBC2_UVD_JRBC_RB_WPTR_BASE_IDX 0 -#define regUVD_JRBC2_UVD_JRBC_STATUS 0x0049 -#define regUVD_JRBC2_UVD_JRBC_STATUS_BASE_IDX 0 -#define regUVD_JRBC2_UVD_JRBC_RB_RPTR 0x004a -#define regUVD_JRBC2_UVD_JRBC_RB_RPTR_BASE_IDX 0 -#define regUVD_JRBC3_UVD_JRBC_RB_WPTR 0x0080 -#define regUVD_JRBC3_UVD_JRBC_RB_WPTR_BASE_IDX 0 -#define regUVD_JRBC3_UVD_JRBC_STATUS 0x0089 -#define regUVD_JRBC3_UVD_JRBC_STATUS_BASE_IDX 0 -#define regUVD_JRBC3_UVD_JRBC_RB_RPTR 0x008a -#define regUVD_JRBC3_UVD_JRBC_RB_RPTR_BASE_IDX 0 -#define regUVD_JRBC4_UVD_JRBC_RB_WPTR 0x00c0 -#define regUVD_JRBC4_UVD_JRBC_RB_WPTR_BASE_IDX 0 -#define regUVD_JRBC4_UVD_JRBC_STATUS 0x00c9 -#define regUVD_JRBC4_UVD_JRBC_STATUS_BASE_IDX 0 -#define regUVD_JRBC4_UVD_JRBC_RB_RPTR 0x00ca -#define regUVD_JRBC4_UVD_JRBC_RB_RPTR_BASE_IDX 0 -#define regUVD_JRBC5_UVD_JRBC_RB_WPTR 0x0100 -#define regUVD_JRBC5_UVD_JRBC_RB_WPTR_BASE_IDX 0 -#define regUVD_JRBC5_UVD_JRBC_STATUS 0x0109 -#define regUVD_JRBC5_UVD_JRBC_STATUS_BASE_IDX 0 -#define regUVD_JRBC5_UVD_JRBC_RB_RPTR 0x010a -#define regUVD_JRBC5_UVD_JRBC_RB_RPTR_BASE_IDX 0 -#define regUVD_JRBC6_UVD_JRBC_RB_WPTR 0x0140 -#define regUVD_JRBC6_UVD_JRBC_RB_WPTR_BASE_IDX 0 -#define regUVD_JRBC6_UVD_JRBC_STATUS 0x0149 -#define regUVD_JRBC6_UVD_JRBC_STATUS_BASE_IDX 0 -#define regUVD_JRBC6_UVD_JRBC_RB_RPTR 0x014a -#define regUVD_JRBC6_UVD_JRBC_RB_RPTR_BASE_IDX 0 -#define regUVD_JRBC7_UVD_JRBC_RB_WPTR 0x0180 -#define regUVD_JRBC7_UVD_JRBC_RB_WPTR_BASE_IDX 0 -#define regUVD_JRBC7_UVD_JRBC_STATUS 0x0189 -#define regUVD_JRBC7_UVD_JRBC_STATUS_BASE_IDX 0 -#define regUVD_JRBC7_UVD_JRBC_RB_RPTR 0x018a -#define regUVD_JRBC7_UVD_JRBC_RB_RPTR_BASE_IDX 0 -#define regUVD_JRBC8_UVD_JRBC_RB_WPTR 0x01c0 -#define regUVD_JRBC8_UVD_JRBC_RB_WPTR_BASE_IDX 0 -#define regUVD_JRBC8_UVD_JRBC_STATUS 0x01c9 -#define regUVD_JRBC8_UVD_JRBC_STATUS_BASE_IDX 0 -#define regUVD_JRBC8_UVD_JRBC_RB_RPTR 0x01ca -#define regUVD_JRBC8_UVD_JRBC_RB_RPTR_BASE_IDX 0 -#define regUVD_JRBC9_UVD_JRBC_RB_WPTR 0x0440 -#define regUVD_JRBC9_UVD_JRBC_RB_WPTR_BASE_IDX 1 -#define regUVD_JRBC9_UVD_JRBC_STATUS 0x0449 -#define regUVD_JRBC9_UVD_JRBC_STATUS_BASE_IDX 1 -#define regUVD_JRBC9_UVD_JRBC_RB_RPTR 0x044a -#define regUVD_JRBC9_UVD_JRBC_RB_RPTR_BASE_IDX 1 +#define regUVD_JRBC0_UVD_JRBC_RB_WPTR 0x0640 +#define regUVD_JRBC0_UVD_JRBC_RB_WPTR_BASE_IDX 1 +#define regUVD_JRBC0_UVD_JRBC_STATUS 0x0649 +#define regUVD_JRBC0_UVD_JRBC_STATUS_BASE_IDX 1 +#define regUVD_JRBC0_UVD_JRBC_RB_RPTR 0x064a +#define regUVD_JRBC0_UVD_JRBC_RB_RPTR_BASE_IDX 1 +#define regUVD_JRBC1_UVD_JRBC_RB_WPTR 0x0000 +#define regUVD_JRBC1_UVD_JRBC_RB_WPTR_BASE_IDX 0 +#define regUVD_JRBC1_UVD_JRBC_STATUS 0x0009 +#define regUVD_JRBC1_UVD_JRBC_STATUS_BASE_IDX 0 +#define regUVD_JRBC1_UVD_JRBC_RB_RPTR 0x000a +#define regUVD_JRBC1_UVD_JRBC_RB_RPTR_BASE_IDX 0 +#define regUVD_JRBC2_UVD_JRBC_RB_WPTR 0x0040 +#define regUVD_JRBC2_UVD_JRBC_RB_WPTR_BASE_IDX 0 +#define regUVD_JRBC2_UVD_JRBC_STATUS 0x0049 +#define regUVD_JRBC2_UVD_JRBC_STATUS_BASE_IDX 0 +#define regUVD_JRBC2_UVD_JRBC_RB_RPTR 0x004a +#define regUVD_JRBC2_UVD_JRBC_RB_RPTR_BASE_IDX 0 +#define regUVD_JRBC3_UVD_JRBC_RB_WPTR 0x0080 +#define regUVD_JRBC3_UVD_JRBC_RB_WPTR_BASE_IDX 0 +#define regUVD_JRBC3_UVD_JRBC_STATUS 0x0089 +#define regUVD_JRBC3_UVD_JRBC_STATUS_BASE_IDX 0 +#define regUVD_JRBC3_UVD_JRBC_RB_RPTR 0x008a +#define regUVD_JRBC3_UVD_JRBC_RB_RPTR_BASE_IDX 0 +#define regUVD_JRBC4_UVD_JRBC_RB_WPTR 0x00c0 +#define regUVD_JRBC4_UVD_JRBC_RB_WPTR_BASE_IDX 0 +#define regUVD_JRBC4_UVD_JRBC_STATUS 0x00c9 +#define regUVD_JRBC4_UVD_JRBC_STATUS_BASE_IDX 0 +#define regUVD_JRBC4_UVD_JRBC_RB_RPTR 0x00ca +#define regUVD_JRBC4_UVD_JRBC_RB_RPTR_BASE_IDX 0 +#define regUVD_JRBC5_UVD_JRBC_RB_WPTR 0x0100 +#define regUVD_JRBC5_UVD_JRBC_RB_WPTR_BASE_IDX 0 +#define regUVD_JRBC5_UVD_JRBC_STATUS 0x0109 +#define regUVD_JRBC5_UVD_JRBC_STATUS_BASE_IDX 0 +#define regUVD_JRBC5_UVD_JRBC_RB_RPTR 0x010a +#define regUVD_JRBC5_UVD_JRBC_RB_RPTR_BASE_IDX 0 +#define regUVD_JRBC6_UVD_JRBC_RB_WPTR 0x0140 +#define regUVD_JRBC6_UVD_JRBC_RB_WPTR_BASE_IDX 0 +#define regUVD_JRBC6_UVD_JRBC_STATUS 0x0149 +#define regUVD_JRBC6_UVD_JRBC_STATUS_BASE_IDX 0 +#define regUVD_JRBC6_UVD_JRBC_RB_RPTR 0x014a +#define regUVD_JRBC6_UVD_JRBC_RB_RPTR_BASE_IDX 0 +#define regUVD_JRBC7_UVD_JRBC_RB_WPTR 0x0180 +#define regUVD_JRBC7_UVD_JRBC_RB_WPTR_BASE_IDX 0 +#define regUVD_JRBC7_UVD_JRBC_STATUS 0x0189 +#define regUVD_JRBC7_UVD_JRBC_STATUS_BASE_IDX 0 +#define regUVD_JRBC7_UVD_JRBC_RB_RPTR 0x018a +#define regUVD_JRBC7_UVD_JRBC_RB_RPTR_BASE_IDX 0 +#define regUVD_JRBC8_UVD_JRBC_RB_WPTR 0x01c0 +#define regUVD_JRBC8_UVD_JRBC_RB_WPTR_BASE_IDX 0 +#define regUVD_JRBC8_UVD_JRBC_STATUS 0x01c9 +#define regUVD_JRBC8_UVD_JRBC_STATUS_BASE_IDX 0 +#define regUVD_JRBC8_UVD_JRBC_RB_RPTR 0x01ca +#define regUVD_JRBC8_UVD_JRBC_RB_RPTR_BASE_IDX 0 +#define regUVD_JRBC9_UVD_JRBC_RB_WPTR 0x0440 +#define regUVD_JRBC9_UVD_JRBC_RB_WPTR_BASE_IDX 1 +#define regUVD_JRBC9_UVD_JRBC_STATUS 0x0449 +#define regUVD_JRBC9_UVD_JRBC_STATUS_BASE_IDX 1 +#define regUVD_JRBC9_UVD_JRBC_RB_RPTR 0x044a +#define regUVD_JRBC9_UVD_JRBC_RB_RPTR_BASE_IDX 1 +#define regUVD_JMI0_JPEG_LMI_DROP 0x0663 +#define regUVD_JMI0_JPEG_LMI_DROP_BASE_IDX 1 +#define regUVD_JMI0_UVD_JMI_CLIENT_STALL 0x067a +#define regUVD_JMI0_UVD_JMI_CLIENT_STALL_BASE_IDX 1 +#define regUVD_JMI0_UVD_JMI_CLIENT_CLEAN_STATUS 0x067b +#define regUVD_JMI0_UVD_JMI_CLIENT_CLEAN_STATUS_BASE_IDX 1 +#define regJPEG_CORE_RST_CTRL 0x072e +#define regJPEG_CORE_RST_CTRL_BASE_IDX 1 #endif /* __JPEG_V5_0_0_H__ */ From 0b4119d54b17618c2ddb04a2af5bf5ebe24121e3 Mon Sep 17 00:00:00 2001 From: Asad Kamal Date: Wed, 12 Feb 2025 16:34:03 +0800 Subject: [PATCH 027/235] drm/amd/pm: Use separate metrics table for smu_v13_0_12 Use separate metrics table for smu_v13_0_12 and fetch metrics data using that. v2: Fix jpeg busy indexing (Lijo) Signed-off-by: Asad Kamal Reviewed-by: Lijo Lazar Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h | 4 + .../drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c | 219 +++++++++++++++++- .../drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c | 9 +- 3 files changed, 230 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h index 4dc3b37d52b9..cd03caffe317 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h @@ -313,6 +313,10 @@ void smu_v13_0_interrupt_work(struct smu_context *smu); bool smu_v13_0_12_is_dpm_running(struct smu_context *smu); int smu_v13_0_12_get_max_metrics_size(void); int smu_v13_0_12_setup_driver_pptable(struct smu_context *smu); +int smu_v13_0_12_get_smu_metrics_data(struct smu_context *smu, + MetricsMember_t member, + uint32_t *value); +ssize_t smu_v13_0_12_get_gpu_metrics(struct smu_context *smu, void **table); extern const struct cmn2asic_mapping smu_v13_0_12_feature_mask_map[]; extern const struct cmn2asic_msg_mapping smu_v13_0_12_message_map[]; #endif diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c index e153062adf77..5e7e97d90805 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c @@ -56,6 +56,10 @@ (FEATURE_MASK(FEATURE_DATA_CALCULATION) | \ FEATURE_MASK(FEATURE_DPM_GFXCLK) | FEATURE_MASK(FEATURE_DPM_FCLK)) +#define NUM_JPEG_RINGS_FW 10 +#define NUM_JPEG_RINGS_GPU_METRICS(gpu_metrics) \ + (ARRAY_SIZE(gpu_metrics->xcp_stats[0].jpeg_busy) / 4) + const struct cmn2asic_mapping smu_v13_0_12_feature_mask_map[SMU_FEATURE_COUNT] = { SMU_13_0_12_FEA_MAP(SMU_FEATURE_DATA_CALCULATIONS_BIT, FEATURE_DATA_CALCULATION), SMU_13_0_12_FEA_MAP(SMU_FEATURE_DPM_GFXCLK_BIT, FEATURE_DPM_GFXCLK), @@ -175,7 +179,7 @@ static int smu_v13_0_12_fru_get_product_info(struct smu_context *smu, int smu_v13_0_12_get_max_metrics_size(void) { - return sizeof(StaticMetricsTable_t); + return max(sizeof(StaticMetricsTable_t), sizeof(MetricsTable_t)); } static int smu_v13_0_12_get_static_metrics_table(struct smu_context *smu) @@ -258,3 +262,216 @@ bool smu_v13_0_12_is_dpm_running(struct smu_context *smu) return !!(feature_enabled & SMC_DPM_FEATURE); } + +int smu_v13_0_12_get_smu_metrics_data(struct smu_context *smu, + MetricsMember_t member, + uint32_t *value) +{ + struct smu_table_context *smu_table = &smu->smu_table; + MetricsTable_t *metrics = (MetricsTable_t *)smu_table->metrics_table; + struct amdgpu_device *adev = smu->adev; + int ret = 0; + int xcc_id; + + /* For clocks with multiple instances, only report the first one */ + switch (member) { + case METRICS_CURR_GFXCLK: + case METRICS_AVERAGE_GFXCLK: + xcc_id = GET_INST(GC, 0); + *value = SMUQ10_ROUND(metrics->GfxclkFrequency[xcc_id]); + break; + case METRICS_CURR_SOCCLK: + case METRICS_AVERAGE_SOCCLK: + *value = SMUQ10_ROUND(metrics->SocclkFrequency[0]); + break; + case METRICS_CURR_UCLK: + case METRICS_AVERAGE_UCLK: + *value = SMUQ10_ROUND(metrics->UclkFrequency); + break; + case METRICS_CURR_VCLK: + *value = SMUQ10_ROUND(metrics->VclkFrequency[0]); + break; + case METRICS_CURR_DCLK: + *value = SMUQ10_ROUND(metrics->DclkFrequency[0]); + break; + case METRICS_CURR_FCLK: + *value = SMUQ10_ROUND(metrics->FclkFrequency); + break; + case METRICS_AVERAGE_GFXACTIVITY: + *value = SMUQ10_ROUND(metrics->SocketGfxBusy); + break; + case METRICS_AVERAGE_MEMACTIVITY: + *value = SMUQ10_ROUND(metrics->DramBandwidthUtilization); + break; + case METRICS_CURR_SOCKETPOWER: + *value = SMUQ10_ROUND(metrics->SocketPower) << 8; + break; + case METRICS_TEMPERATURE_HOTSPOT: + *value = SMUQ10_ROUND(metrics->MaxSocketTemperature) * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_TEMPERATURE_MEM: + *value = SMUQ10_ROUND(metrics->MaxHbmTemperature) * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + /* This is the max of all VRs and not just SOC VR. + * No need to define another data type for the same. + */ + case METRICS_TEMPERATURE_VRSOC: + *value = SMUQ10_ROUND(metrics->MaxVrTemperature) * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + default: + *value = UINT_MAX; + break; + } + + return ret; +} + +ssize_t smu_v13_0_12_get_gpu_metrics(struct smu_context *smu, void **table) +{ + struct smu_table_context *smu_table = &smu->smu_table; + struct gpu_metrics_v1_7 *gpu_metrics = + (struct gpu_metrics_v1_7 *)smu_table->gpu_metrics_table; + int ret = 0, xcc_id, inst, i, j, k, idx; + struct amdgpu_device *adev = smu->adev; + u8 num_jpeg_rings_gpu_metrics; + MetricsTable_t *metrics; + struct amdgpu_xcp *xcp; + u32 inst_mask; + + metrics = kzalloc(sizeof(MetricsTable_t), GFP_KERNEL); + memcpy(metrics, smu_table->metrics_table, sizeof(MetricsTable_t)); + + smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 7); + + gpu_metrics->temperature_hotspot = + SMUQ10_ROUND(metrics->MaxSocketTemperature); + /* Individual HBM stack temperature is not reported */ + gpu_metrics->temperature_mem = + SMUQ10_ROUND(metrics->MaxHbmTemperature); + /* Reports max temperature of all voltage rails */ + gpu_metrics->temperature_vrsoc = + SMUQ10_ROUND(metrics->MaxVrTemperature); + + gpu_metrics->average_gfx_activity = + SMUQ10_ROUND(metrics->SocketGfxBusy); + gpu_metrics->average_umc_activity = + SMUQ10_ROUND(metrics->DramBandwidthUtilization); + + gpu_metrics->mem_max_bandwidth = + SMUQ10_ROUND(metrics->MaxDramBandwidth); + + gpu_metrics->curr_socket_power = + SMUQ10_ROUND(metrics->SocketPower); + /* Energy counter reported in 15.259uJ (2^-16) units */ + gpu_metrics->energy_accumulator = metrics->SocketEnergyAcc; + + for (i = 0; i < MAX_GFX_CLKS; i++) { + xcc_id = GET_INST(GC, i); + if (xcc_id >= 0) + gpu_metrics->current_gfxclk[i] = + SMUQ10_ROUND(metrics->GfxclkFrequency[xcc_id]); + + if (i < MAX_CLKS) { + gpu_metrics->current_socclk[i] = + SMUQ10_ROUND(metrics->SocclkFrequency[i]); + inst = GET_INST(VCN, i); + if (inst >= 0) { + gpu_metrics->current_vclk0[i] = + SMUQ10_ROUND(metrics->VclkFrequency[inst]); + gpu_metrics->current_dclk0[i] = + SMUQ10_ROUND(metrics->DclkFrequency[inst]); + } + } + } + + gpu_metrics->current_uclk = SMUQ10_ROUND(metrics->UclkFrequency); + + /* Total accumulated cycle counter */ + gpu_metrics->accumulation_counter = metrics->AccumulationCounter; + + /* Accumulated throttler residencies */ + gpu_metrics->prochot_residency_acc = metrics->ProchotResidencyAcc; + gpu_metrics->ppt_residency_acc = metrics->PptResidencyAcc; + gpu_metrics->socket_thm_residency_acc = metrics->SocketThmResidencyAcc; + gpu_metrics->vr_thm_residency_acc = metrics->VrThmResidencyAcc; + gpu_metrics->hbm_thm_residency_acc = metrics->HbmThmResidencyAcc; + + /* Clock Lock Status. Each bit corresponds to each GFXCLK instance */ + gpu_metrics->gfxclk_lock_status = metrics->GfxLockXCDMak >> GET_INST(GC, 0); + + gpu_metrics->pcie_link_width = metrics->PCIeLinkWidth; + gpu_metrics->pcie_link_speed = + pcie_gen_to_speed(metrics->PCIeLinkSpeed); + gpu_metrics->pcie_bandwidth_acc = + SMUQ10_ROUND(metrics->PcieBandwidthAcc[0]); + gpu_metrics->pcie_bandwidth_inst = + SMUQ10_ROUND(metrics->PcieBandwidth[0]); + gpu_metrics->pcie_l0_to_recov_count_acc = metrics->PCIeL0ToRecoveryCountAcc; + gpu_metrics->pcie_replay_count_acc = metrics->PCIenReplayAAcc; + gpu_metrics->pcie_replay_rover_count_acc = + metrics->PCIenReplayARolloverCountAcc; + gpu_metrics->pcie_nak_sent_count_acc = metrics->PCIeNAKSentCountAcc; + gpu_metrics->pcie_nak_rcvd_count_acc = metrics->PCIeNAKReceivedCountAcc; + gpu_metrics->pcie_lc_perf_other_end_recovery = metrics->PCIeOtherEndRecoveryAcc; + + gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); + + gpu_metrics->gfx_activity_acc = SMUQ10_ROUND(metrics->SocketGfxBusyAcc); + gpu_metrics->mem_activity_acc = SMUQ10_ROUND(metrics->DramBandwidthUtilizationAcc); + + for (i = 0; i < NUM_XGMI_LINKS; i++) { + gpu_metrics->xgmi_read_data_acc[i] = + SMUQ10_ROUND(metrics->XgmiReadDataSizeAcc[i]); + gpu_metrics->xgmi_write_data_acc[i] = + SMUQ10_ROUND(metrics->XgmiWriteDataSizeAcc[i]); + ret = amdgpu_get_xgmi_link_status(adev, i); + if (ret >= 0) + gpu_metrics->xgmi_link_status[i] = ret; + } + + gpu_metrics->num_partition = adev->xcp_mgr->num_xcps; + + num_jpeg_rings_gpu_metrics = NUM_JPEG_RINGS_GPU_METRICS(gpu_metrics); + for_each_xcp(adev->xcp_mgr, xcp, i) { + amdgpu_xcp_get_inst_details(xcp, AMDGPU_XCP_VCN, &inst_mask); + idx = 0; + for_each_inst(k, inst_mask) { + /* Both JPEG and VCN has same instances */ + inst = GET_INST(VCN, k); + + for (j = 0; j < num_jpeg_rings_gpu_metrics; ++j) { + gpu_metrics->xcp_stats[i].jpeg_busy + [(idx * num_jpeg_rings_gpu_metrics) + j] = + SMUQ10_ROUND(metrics->JpegBusy + [(inst * NUM_JPEG_RINGS_FW) + j]); + } + gpu_metrics->xcp_stats[i].vcn_busy[idx] = + SMUQ10_ROUND(metrics->VcnBusy[inst]); + idx++; + } + + amdgpu_xcp_get_inst_details(xcp, AMDGPU_XCP_GFX, &inst_mask); + idx = 0; + for_each_inst(k, inst_mask) { + inst = GET_INST(GC, k); + gpu_metrics->xcp_stats[i].gfx_busy_inst[idx] = + SMUQ10_ROUND(metrics->GfxBusy[inst]); + gpu_metrics->xcp_stats[i].gfx_busy_acc[idx] = + SMUQ10_ROUND(metrics->GfxBusyAcc[inst]); + idx++; + } + } + + gpu_metrics->xgmi_link_width = SMUQ10_ROUND(metrics->XgmiWidth); + gpu_metrics->xgmi_link_speed = SMUQ10_ROUND(metrics->XgmiBitrate); + + gpu_metrics->firmware_timestamp = metrics->Timestamp; + + *table = (void *)gpu_metrics; + kfree(metrics); + + return sizeof(*gpu_metrics); +} diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c index c3e0da680cf8..76cc827f128c 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c @@ -515,7 +515,8 @@ static int smu_v13_0_6_tables_init(struct smu_context *smu) PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, - max(gpu_metrcs_size, smu_v13_0_12_get_max_metrics_size()), + max(gpu_metrcs_size, + smu_v13_0_12_get_max_metrics_size()), PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM | AMDGPU_GEM_DOMAIN_GTT); @@ -1145,6 +1146,9 @@ static int smu_v13_0_6_get_smu_metrics_data(struct smu_context *smu, if (ret) return ret; + if (smu_v13_0_6_cap_supported(smu, SMU_CAP(STATIC_METRICS))) + return smu_v13_0_12_get_smu_metrics_data(smu, member, value); + /* For clocks with multiple instances, only report the first one */ switch (member) { case METRICS_CURR_GFXCLK: @@ -2507,6 +2511,9 @@ static ssize_t smu_v13_0_6_get_gpu_metrics(struct smu_context *smu, void **table return ret; } + if (smu_v13_0_6_cap_supported(smu, SMU_CAP(STATIC_METRICS))) + return smu_v13_0_12_get_gpu_metrics(smu, table); + metrics_v1 = (MetricsTableV1_t *)metrics_v0; metrics_v2 = (MetricsTableV2_t *)metrics_v0; From 27b791514789844e80da990c456c2465325e0851 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 14 Feb 2025 12:32:30 -0500 Subject: [PATCH 028/235] drm/amdgpu/mes: keep enforce isolation up to date Re-send the mes message on resume to make sure the mes state is up to date. Fixes: 8521e3c5f058 ("drm/amd/amdgpu: limit single process inside MES") Acked-by: Srinivasan Shanmugam Signed-off-by: Alex Deucher Cc: Shaoyun Liu Cc: Srinivasan Shanmugam Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c | 13 ++++--------- drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c | 20 +++++++++++++++++++- drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h | 2 +- drivers/gpu/drm/amd/amdgpu/mes_v11_0.c | 4 ++++ drivers/gpu/drm/amd/amdgpu/mes_v12_0.c | 4 ++++ 5 files changed, 32 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c index b9bd6654f317..a194bf3347cb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c @@ -1665,24 +1665,19 @@ static ssize_t amdgpu_gfx_set_enforce_isolation(struct device *dev, } mutex_lock(&adev->enforce_isolation_mutex); - for (i = 0; i < num_partitions; i++) { - if (adev->enforce_isolation[i] && !partition_values[i]) { + if (adev->enforce_isolation[i] && !partition_values[i]) /* Going from enabled to disabled */ amdgpu_vmid_free_reserved(adev, AMDGPU_GFXHUB(i)); - if (adev->enable_mes && adev->gfx.enable_cleaner_shader) - amdgpu_mes_set_enforce_isolation(adev, i, false); - } else if (!adev->enforce_isolation[i] && partition_values[i]) { + else if (!adev->enforce_isolation[i] && partition_values[i]) /* Going from disabled to enabled */ amdgpu_vmid_alloc_reserved(adev, AMDGPU_GFXHUB(i)); - if (adev->enable_mes && adev->gfx.enable_cleaner_shader) - amdgpu_mes_set_enforce_isolation(adev, i, true); - } adev->enforce_isolation[i] = partition_values[i]; } - mutex_unlock(&adev->enforce_isolation_mutex); + amdgpu_mes_update_enforce_isolation(adev); + return count; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c index 32b27a1658e7..709c11cbeabd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c @@ -1681,7 +1681,8 @@ bool amdgpu_mes_suspend_resume_all_supported(struct amdgpu_device *adev) } /* Fix me -- node_id is used to identify the correct MES instances in the future */ -int amdgpu_mes_set_enforce_isolation(struct amdgpu_device *adev, uint32_t node_id, bool enable) +static int amdgpu_mes_set_enforce_isolation(struct amdgpu_device *adev, + uint32_t node_id, bool enable) { struct mes_misc_op_input op_input = {0}; int r; @@ -1703,6 +1704,23 @@ int amdgpu_mes_set_enforce_isolation(struct amdgpu_device *adev, uint32_t node_i return r; } +int amdgpu_mes_update_enforce_isolation(struct amdgpu_device *adev) +{ + int i, r = 0; + + if (adev->enable_mes && adev->gfx.enable_cleaner_shader) { + mutex_lock(&adev->enforce_isolation_mutex); + for (i = 0; i < (adev->xcp_mgr ? adev->xcp_mgr->num_xcps : 1); i++) { + if (adev->enforce_isolation[i]) + r |= amdgpu_mes_set_enforce_isolation(adev, i, true); + else + r |= amdgpu_mes_set_enforce_isolation(adev, i, false); + } + mutex_unlock(&adev->enforce_isolation_mutex); + } + return r; +} + #if defined(CONFIG_DEBUG_FS) static int amdgpu_debugfs_mes_event_log_show(struct seq_file *m, void *unused) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h index 5189a7ac65b3..68d640aaa2e1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h @@ -534,6 +534,6 @@ static inline void amdgpu_mes_unlock(struct amdgpu_mes *mes) bool amdgpu_mes_suspend_resume_all_supported(struct amdgpu_device *adev); -int amdgpu_mes_set_enforce_isolation(struct amdgpu_device *adev, uint32_t node_id, bool enable); +int amdgpu_mes_update_enforce_isolation(struct amdgpu_device *adev); #endif /* __AMDGPU_MES_H__ */ diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c index f57ec3613d21..cbe0dc9ca6d9 100644 --- a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c @@ -1647,6 +1647,10 @@ static int mes_v11_0_hw_init(struct amdgpu_ip_block *ip_block) goto failure; } + r = amdgpu_mes_update_enforce_isolation(adev); + if (r) + goto failure; + out: /* * Disable KIQ ring usage from the driver once MES is enabled. diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c index 494910380057..12ea344ee5d4 100644 --- a/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c @@ -1762,6 +1762,10 @@ static int mes_v12_0_hw_init(struct amdgpu_ip_block *ip_block) goto failure; } + r = amdgpu_mes_update_enforce_isolation(adev); + if (r) + goto failure; + out: /* * Disable KIQ ring usage from the driver once MES is enabled. From 28d05f0836dfc4479d81e664f345ce125ea921d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Almeida?= Date: Thu, 20 Feb 2025 13:27:48 -0300 Subject: [PATCH 029/235] drm/amdgpu: Log the creation of a coredump file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After a GPU reset happens, the driver creates a coredump file. However, the user might not be aware of it. Log the file creation the user can find more information about the device and add the file to bug reports. This is similar to what the xe driver does. Reviewed-by: Christian König Signed-off-by: André Almeida Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c index 824f9da5b6ce..7b50741dc097 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c @@ -364,5 +364,9 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check, dev_coredumpm(dev->dev, THIS_MODULE, coredump, 0, GFP_NOWAIT, amdgpu_devcoredump_read, amdgpu_devcoredump_free); + + drm_info(dev, "AMDGPU device coredump file has been created\n"); + drm_info(dev, "Check your /sys/class/drm/card%d/device/devcoredump/data\n", + dev->primary->index); } #endif From b7fd6528b5ad80eea66df6240f2399602d9fd388 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Almeida?= Date: Thu, 20 Feb 2025 13:27:49 -0300 Subject: [PATCH 030/235] drm/amdgpu: Log after a successful ring reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a ring reset happens, the kernel log shows only "amdgpu: Starting ring reset", but when it finishes nothing appears in the log. Explicitly write in the log that the reset has finished correctly. Reviewed-by: Christian König Signed-off-by: André Almeida Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c index abfbbc6babe7..c37bc683253a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c @@ -164,6 +164,7 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job) } if (amdgpu_ring_sched_ready(ring)) drm_sched_start(&ring->sched, 0); + dev_err(adev->dev, "Ring %s reset succeeded\n", ring->sched.name); goto exit; } dev_err(adev->dev, "Ring %s reset failure\n", ring->sched.name); From 9b3ef540397cfc356f10f504841b2e9d16e31286 Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Wed, 19 Feb 2025 11:46:19 -0700 Subject: [PATCH 031/235] MAINTAINERS: Change my role from Maintainer to Reviewer Reviewed-by: Harry Wentland Signed-off-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index b3363c0c34e3..498e1d07f0e3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1046,7 +1046,7 @@ F: drivers/crypto/ccp/hsti.* AMD DISPLAY CORE M: Harry Wentland M: Leo Li -M: Rodrigo Siqueira +R: Rodrigo Siqueira L: amd-gfx@lists.freedesktop.org S: Supported T: git https://gitlab.freedesktop.org/agd5f/linux.git From 62431979dd92e8b2df2ea4ef38f852511b4e2638 Mon Sep 17 00:00:00 2001 From: Sathishkumar S Date: Tue, 18 Feb 2025 23:36:48 +0530 Subject: [PATCH 032/235] drm/amdgpu: Add ring reset callback for JPEG5_0_1 Add ring reset function callback for JPEG5_0_1 to recover from job timeouts without a full gpu reset. Signed-off-by: Sathishkumar S Reviewed-by: Leo Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c | 50 ++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c index e6412195e467..6b8ef8e8c0eb 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c @@ -190,6 +190,13 @@ static int jpeg_v5_0_1_sw_init(struct amdgpu_ip_block *ip_block) if (r) return r; + if (!amdgpu_sriov_vf(adev)) { + adev->jpeg.supported_reset = AMDGPU_RESET_TYPE_PER_QUEUE; + r = amdgpu_jpeg_sysfs_reset_mask_init(adev); + if (r) + return r; + } + return 0; } @@ -209,6 +216,9 @@ static int jpeg_v5_0_1_sw_fini(struct amdgpu_ip_block *ip_block) if (r) return r; + if (!amdgpu_sriov_vf(adev)) + amdgpu_jpeg_sysfs_reset_mask_fini(adev); + r = amdgpu_jpeg_sw_fini(adev); return r; @@ -650,6 +660,45 @@ static int jpeg_v5_0_1_process_interrupt(struct amdgpu_device *adev, return 0; } +static void jpeg_v5_0_1_core_stall_reset(struct amdgpu_ring *ring) +{ + struct amdgpu_device *adev = ring->adev; + int jpeg_inst = GET_INST(JPEG, ring->me); + int reg_offset = ring->pipe ? jpeg_v5_0_1_core_reg_offset(ring->pipe) : 0; + + WREG32_SOC15_OFFSET(JPEG, jpeg_inst, + regUVD_JMI0_UVD_JMI_CLIENT_STALL, + reg_offset, 0x1F); + SOC15_WAIT_ON_RREG(JPEG, jpeg_inst, + regUVD_JMI0_UVD_JMI_CLIENT_CLEAN_STATUS, + 0x1F, 0x1F); + WREG32_SOC15_OFFSET(JPEG, jpeg_inst, + regUVD_JMI0_JPEG_LMI_DROP, + reg_offset, 0x1F); + WREG32_SOC15_OFFSET(JPEG, jpeg_inst, + regJPEG_CORE_RST_CTRL, + reg_offset, 1 << ring->pipe); + WREG32_SOC15_OFFSET(JPEG, jpeg_inst, + regUVD_JMI0_UVD_JMI_CLIENT_STALL, + reg_offset, 0x00); + WREG32_SOC15_OFFSET(JPEG, jpeg_inst, + regUVD_JMI0_JPEG_LMI_DROP, + reg_offset, 0x00); + WREG32_SOC15_OFFSET(JPEG, jpeg_inst, + regJPEG_CORE_RST_CTRL, + reg_offset, 0x00); +} + +static int jpeg_v5_0_1_ring_reset(struct amdgpu_ring *ring, unsigned int vmid) +{ + if (amdgpu_sriov_vf(ring->adev)) + return -EOPNOTSUPP; + + jpeg_v5_0_1_core_stall_reset(ring); + jpeg_v5_0_1_init_jrbc(ring); + return amdgpu_ring_test_helper(ring); +} + static const struct amd_ip_funcs jpeg_v5_0_1_ip_funcs = { .name = "jpeg_v5_0_1", .early_init = jpeg_v5_0_1_early_init, @@ -699,6 +748,7 @@ static const struct amdgpu_ring_funcs jpeg_v5_0_1_dec_ring_vm_funcs = { .emit_wreg = jpeg_v4_0_3_dec_ring_emit_wreg, .emit_reg_wait = jpeg_v4_0_3_dec_ring_emit_reg_wait, .emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper, + .reset = jpeg_v5_0_1_ring_reset, }; static void jpeg_v5_0_1_set_dec_ring_funcs(struct amdgpu_device *adev) From 289387d0dbf806bd59063ab93d94f48cd4c75c7c Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Wed, 19 Feb 2025 11:46:20 -0700 Subject: [PATCH 033/235] mailmap: Add entry for Rodrigo Siqueira Map all of my previously used email addresses to my @igalia.com address. Acked-by: Harry Wentland Signed-off-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- .mailmap | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.mailmap b/.mailmap index ae0adc499f4a..28fa0e9bc95f 100644 --- a/.mailmap +++ b/.mailmap @@ -608,6 +608,8 @@ Richard Leitner Richard Leitner Robert Foss Rocky Liao +Rodrigo Siqueira +Rodrigo Siqueira Roman Gushchin Roman Gushchin Roman Gushchin From 9d8af72fe73f00b74ac1ace6201ab7030d765d54 Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Wed, 19 Feb 2025 21:23:18 +0000 Subject: [PATCH 034/235] drm/amdgpu: Remove unused nbif_v6_3_1_sriov_funcs The nbif_v6_3_1_sriov_funcs instance of amdgpu_nbio_funcs was added in commit 894c6d3522d1 ("drm/amdgpu: Add nbif v6_3_1 ip block support") but has remained unused. Alex has confirmed it wasn't needed. Remove it, together with the four unused stub functions: nbif_v6_3_1_sriov_ih_doorbell_range nbif_v6_3_1_sriov_gc_doorbell_init nbif_v6_3_1_sriov_vcn_doorbell_range nbif_v6_3_1_sriov_sdma_doorbell_range Signed-off-by: Dr. David Alan Gilbert Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/nbif_v6_3_1.c | 46 ------------------------ drivers/gpu/drm/amd/amdgpu/nbif_v6_3_1.h | 1 - 2 files changed, 47 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/nbif_v6_3_1.c b/drivers/gpu/drm/amd/amdgpu/nbif_v6_3_1.c index 9900fe5c3bc3..9b4025c39e44 100644 --- a/drivers/gpu/drm/amd/amdgpu/nbif_v6_3_1.c +++ b/drivers/gpu/drm/amd/amdgpu/nbif_v6_3_1.c @@ -473,52 +473,6 @@ const struct amdgpu_nbio_funcs nbif_v6_3_1_funcs = { }; -static void nbif_v6_3_1_sriov_ih_doorbell_range(struct amdgpu_device *adev, - bool use_doorbell, int doorbell_index) -{ -} - -static void nbif_v6_3_1_sriov_sdma_doorbell_range(struct amdgpu_device *adev, - int instance, bool use_doorbell, - int doorbell_index, - int doorbell_size) -{ -} - -static void nbif_v6_3_1_sriov_vcn_doorbell_range(struct amdgpu_device *adev, - bool use_doorbell, - int doorbell_index, int instance) -{ -} - -static void nbif_v6_3_1_sriov_gc_doorbell_init(struct amdgpu_device *adev) -{ -} - -const struct amdgpu_nbio_funcs nbif_v6_3_1_sriov_funcs = { - .get_hdp_flush_req_offset = nbif_v6_3_1_get_hdp_flush_req_offset, - .get_hdp_flush_done_offset = nbif_v6_3_1_get_hdp_flush_done_offset, - .get_pcie_index_offset = nbif_v6_3_1_get_pcie_index_offset, - .get_pcie_data_offset = nbif_v6_3_1_get_pcie_data_offset, - .get_rev_id = nbif_v6_3_1_get_rev_id, - .mc_access_enable = nbif_v6_3_1_mc_access_enable, - .get_memsize = nbif_v6_3_1_get_memsize, - .sdma_doorbell_range = nbif_v6_3_1_sriov_sdma_doorbell_range, - .vcn_doorbell_range = nbif_v6_3_1_sriov_vcn_doorbell_range, - .gc_doorbell_init = nbif_v6_3_1_sriov_gc_doorbell_init, - .enable_doorbell_aperture = nbif_v6_3_1_enable_doorbell_aperture, - .enable_doorbell_selfring_aperture = nbif_v6_3_1_enable_doorbell_selfring_aperture, - .ih_doorbell_range = nbif_v6_3_1_sriov_ih_doorbell_range, - .update_medium_grain_clock_gating = nbif_v6_3_1_update_medium_grain_clock_gating, - .update_medium_grain_light_sleep = nbif_v6_3_1_update_medium_grain_light_sleep, - .get_clockgating_state = nbif_v6_3_1_get_clockgating_state, - .ih_control = nbif_v6_3_1_ih_control, - .init_registers = nbif_v6_3_1_init_registers, - .remap_hdp_registers = nbif_v6_3_1_remap_hdp_registers, - .get_rom_offset = nbif_v6_3_1_get_rom_offset, - .set_reg_remap = nbif_v6_3_1_set_reg_remap, -}; - static int nbif_v6_3_1_set_ras_err_event_athub_irq_state(struct amdgpu_device *adev, struct amdgpu_irq_src *src, unsigned type, diff --git a/drivers/gpu/drm/amd/amdgpu/nbif_v6_3_1.h b/drivers/gpu/drm/amd/amdgpu/nbif_v6_3_1.h index 9ac4831d39e1..3afec715a9fe 100644 --- a/drivers/gpu/drm/amd/amdgpu/nbif_v6_3_1.h +++ b/drivers/gpu/drm/amd/amdgpu/nbif_v6_3_1.h @@ -28,7 +28,6 @@ extern const struct nbio_hdp_flush_reg nbif_v6_3_1_hdp_flush_reg; extern const struct amdgpu_nbio_funcs nbif_v6_3_1_funcs; -extern const struct amdgpu_nbio_funcs nbif_v6_3_1_sriov_funcs; extern struct amdgpu_nbio_ras nbif_v6_3_1_ras; #endif From 81262b1656feb3813e3d917ab78824df6831e69e Mon Sep 17 00:00:00 2001 From: Melissa Wen Date: Sat, 15 Feb 2025 18:15:47 -0300 Subject: [PATCH 035/235] drm/amd/display: restore edid reading from a given i2c adapter When switching to drm_edid, we slightly changed how to get edid by removing the possibility of getting them from dc_link when in aux transaction mode. As MST doesn't initialize the connector with `drm_connector_init_with_ddc()`, restore the original behavior to avoid functional changes. v2: - Fix build warning of unchecked dereference (kernel test bot) CC: Alex Hung CC: Mario Limonciello CC: Roman Li CC: Aurabindo Pillai Fixes: 48edb2a4256e ("drm/amd/display: switch amdgpu_dm_connector to use struct drm_edid") Reviewed-by: Alex Hung Signed-off-by: Melissa Wen Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 009e2696f2c8..e3df652bb74e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -7295,8 +7295,14 @@ static void amdgpu_dm_connector_funcs_force(struct drm_connector *connector) struct dc_link *dc_link = aconnector->dc_link; struct dc_sink *dc_em_sink = aconnector->dc_em_sink; const struct drm_edid *drm_edid; + struct i2c_adapter *ddc; - drm_edid = drm_edid_read(connector); + if (dc_link && dc_link->aux_mode) + ddc = &aconnector->dm_dp_aux.aux.ddc; + else + ddc = &aconnector->i2c->base; + + drm_edid = drm_edid_read_ddc(connector, ddc); drm_edid_connector_update(connector, drm_edid); if (!drm_edid) { DRM_ERROR("No EDID found on connector: %s.\n", connector->name); @@ -7341,14 +7347,21 @@ static int get_modes(struct drm_connector *connector) static void create_eml_sink(struct amdgpu_dm_connector *aconnector) { struct drm_connector *connector = &aconnector->base; + struct dc_link *dc_link = aconnector->dc_link; struct dc_sink_init_data init_params = { .link = aconnector->dc_link, .sink_signal = SIGNAL_TYPE_VIRTUAL }; const struct drm_edid *drm_edid; const struct edid *edid; + struct i2c_adapter *ddc; - drm_edid = drm_edid_read(connector); + if (dc_link && dc_link->aux_mode) + ddc = &aconnector->dm_dp_aux.aux.ddc; + else + ddc = &aconnector->i2c->base; + + drm_edid = drm_edid_read_ddc(connector, ddc); drm_edid_connector_update(connector, drm_edid); if (!drm_edid) { DRM_ERROR("No EDID found on connector: %s.\n", connector->name); From a101fa705d016d46463dd4ce488671369c922bc2 Mon Sep 17 00:00:00 2001 From: Aurabindo Pillai Date: Fri, 21 Feb 2025 14:19:12 -0500 Subject: [PATCH 036/235] MAINTAINERS: Update AMDGPU DML maintainers info Chaitanya is no longer with AMD, and the responsibility has been taken over by Austin. Signed-off-by: Aurabindo Pillai Acked-by: Alex Deucher Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 498e1d07f0e3..27e75c615e06 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1053,7 +1053,7 @@ T: git https://gitlab.freedesktop.org/agd5f/linux.git F: drivers/gpu/drm/amd/display/ AMD DISPLAY CORE - DML -M: Chaitanya Dhere +M: Austin Zheng M: Jun Lei S: Supported F: drivers/gpu/drm/amd/display/dc/dml/ From abefe9fcfbb6705b26ce1b71eb38a76c33291414 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 17 Feb 2025 09:53:25 +0000 Subject: [PATCH 037/235] drm/amd/display: Fix spelling mistake "oustanding" -> "outstanding" There is a spelling mistake in max_oustanding_when_urgent_expected, fix it. Signed-off-by: Colin Ian King Signed-off-by: Alex Deucher --- .../dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c | 6 +++--- .../dc/dml2/dml21/src/dml2_core/dml2_core_shared_types.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c index 78c93a502518..4c33d99ca7e8 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c @@ -5058,7 +5058,7 @@ static void CalculateExtraLatency( double HostVMInefficiencyFactorPrefetch, unsigned int HostVMMinPageSize, enum dml2_qos_param_type qos_type, - bool max_oustanding_when_urgent_expected, + bool max_outstanding_when_urgent_expected, unsigned int max_outstanding_requests, unsigned int request_size_bytes_luma[], unsigned int request_size_bytes_chroma[], @@ -5106,7 +5106,7 @@ static void CalculateExtraLatency( if (qos_type == dml2_qos_param_type_dcn4x) { *ExtraLatency_sr = dchub_arb_to_ret_delay / DCFCLK; *ExtraLatency = *ExtraLatency_sr; - if (max_oustanding_when_urgent_expected) + if (max_outstanding_when_urgent_expected) *ExtraLatency = *ExtraLatency + (ROBBufferSizeInKByte * 1024 - max_outstanding_requests * max_request_size_bytes) / ReturnBW; } else { *ExtraLatency_sr = dchub_arb_to_ret_delay / DCFCLK + RoundTripPingLatencyCycles / FabricClock + ReorderingBytes / ReturnBW; @@ -5121,7 +5121,7 @@ static void CalculateExtraLatency( dml2_printf("DML::%s: qos_type=%u\n", __func__, qos_type); dml2_printf("DML::%s: hostvm_mode=%u\n", __func__, hostvm_mode); dml2_printf("DML::%s: Tex_trips=%u\n", __func__, Tex_trips); - dml2_printf("DML::%s: max_oustanding_when_urgent_expected=%u\n", __func__, max_oustanding_when_urgent_expected); + dml2_printf("DML::%s: max_outstanding_when_urgent_expected=%u\n", __func__, max_outstanding_when_urgent_expected); dml2_printf("DML::%s: FabricClock=%f\n", __func__, FabricClock); dml2_printf("DML::%s: DCFCLK=%f\n", __func__, DCFCLK); dml2_printf("DML::%s: ReturnBW=%f\n", __func__, ReturnBW); diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_shared_types.h b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_shared_types.h index dfe54112a9c6..4e502f0a6d20 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_shared_types.h +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_shared_types.h @@ -1571,7 +1571,7 @@ struct dml2_core_calcs_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport_param unsigned int *DSTYAfterScaler; bool UnboundedRequestEnabled; unsigned int CompressedBufferSizeInkByte; - bool max_oustanding_when_urgent_expected; + bool max_outstanding_when_urgent_expected; unsigned int max_outstanding_requests; unsigned int max_request_size_bytes; unsigned int *meta_row_height_l; From dc84a21f5f8d6930219237008295ae6d60e894ca Mon Sep 17 00:00:00 2001 From: Tom Chung Date: Thu, 6 Feb 2025 11:30:17 +0800 Subject: [PATCH 038/235] drm/amd/display: Revert "Disable PSR-SU on some OLED panel" This reverts commit c31b41f1cb32450d8ac176eef9bda979760040e7. We planning to disable the PSR-SU and fallback to PSR1 for all eDP panels not only for specific eDP panel temporarily. Reviewed-by: Sun peng Li Signed-off-by: Tom Chung Signed-off-by: Roman Li Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c index 104f03868266..45858bf1523d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c @@ -30,23 +30,6 @@ #include "amdgpu_dm.h" #include "modules/power/power_helpers.h" -static bool is_specific_oled_panel(struct dc_link *link) -{ - if (!link->dpcd_sink_ext_caps.bits.oled) - return false; - - /* Disable PSR-SU for some OLED panels to avoid glitches */ - if (link->dpcd_caps.sink_dev_id == 0xBA4159) { - uint8_t sink_dev_id_str1[] = {'4', '0', 'C', 'U', '1'}; - - if (!memcmp(link->dpcd_caps.sink_dev_id_str, sink_dev_id_str1, - sizeof(sink_dev_id_str1))) - return true; - } - - return false; -} - static bool link_supports_psrsu(struct dc_link *link) { struct dc *dc = link->ctx->dc; @@ -57,9 +40,6 @@ static bool link_supports_psrsu(struct dc_link *link) if (dc->ctx->dce_version < DCN_VERSION_3_1) return false; - if (is_specific_oled_panel(link)) - return false; - if (!is_psr_su_specific_panel(link)) return false; From 6deeefb820d0efb0b36753622fb982d03b37b3ad Mon Sep 17 00:00:00 2001 From: Tom Chung Date: Thu, 6 Feb 2025 11:31:23 +0800 Subject: [PATCH 039/235] drm/amd/display: Disable PSR-SU on eDP panels [Why] PSR-SU may cause some glitching randomly on several panels. [How] Temporarily disable the PSR-SU and fallback to PSR1 for all eDP panels. Link: https://gitlab.freedesktop.org/drm/amd/-/issues/3388 Cc: Mario Limonciello Cc: Alex Deucher Reviewed-by: Sun peng Li Signed-off-by: Tom Chung Signed-off-by: Roman Li Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c index 45858bf1523d..e140b7a04d72 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c @@ -54,7 +54,8 @@ static bool link_supports_psrsu(struct dc_link *link) if (amdgpu_dc_debug_mask & DC_DISABLE_PSR_SU) return false; - return dc_dmub_check_min_version(dc->ctx->dmub_srv->dmub); + /* Temporarily disable PSR-SU to avoid glitches */ + return false; } /* From d8075f5a6d9d5e387967a65b583c5ec63bba5008 Mon Sep 17 00:00:00 2001 From: Alex Hung Date: Tue, 11 Feb 2025 13:43:48 -0700 Subject: [PATCH 040/235] drm/amd/display: update incorrect cursor buffer size [WHAT & HOW] Fix the incorrect value of the cursor_buffer_size. Signed-off-by: Alex Hung Reviewed-by: Zaeem Mohamed Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4.c index 0f4ada64461e..bb863c8c6b39 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4.c @@ -44,7 +44,7 @@ struct dml2_core_ip_params core_dcn4_ip_caps_base = { .dppclk_delay_scl_lb_only = 16, .dppclk_delay_cnvc_formatter = 28, .dppclk_delay_cnvc_cursor = 6, - .cursor_buffer_size = 42, + .cursor_buffer_size = 24, .cursor_chunk_size = 2, .dispclk_delay_subtotal = 125, .max_inter_dcn_tile_repeaters = 8, From 97b05c8c2e1e0390f4447dc9cc5ec131dd54ca02 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Fri, 24 Jan 2025 09:59:37 -0500 Subject: [PATCH 041/235] drm/amd/display: Apply DCN35 DML2 state policy for DCN36 too [Why] DCN36 should inherit the same policy as DCN35 for DML2. [How] Add it to the list of checks in translation helper. Signed-off-by: Nicholas Kazlauskas Reviewed-by: Zaeem Mohamed Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c index f829d5ac7c8e..2061d43b92e1 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c @@ -557,6 +557,7 @@ void dml2_init_soc_states(struct dml2_context *dml2, const struct dc *in_dc, } if (dml2->v20.dml_core_ctx.project == dml_project_dcn35 || + dml2->v20.dml_core_ctx.project == dml_project_dcn36 || dml2->v20.dml_core_ctx.project == dml_project_dcn351) { int max_dcfclk_mhz = 0, max_dispclk_mhz = 0, max_dppclk_mhz = 0, max_phyclk_mhz = 0, max_dtbclk_mhz = 0, max_fclk_mhz = 0, max_uclk_mhz = 0, max_socclk_mhz = 0; From 86f06bcbb54e93f3c7b5e22ae37e72882b74c4b0 Mon Sep 17 00:00:00 2001 From: Samson Tam Date: Tue, 7 Jan 2025 14:16:04 -0500 Subject: [PATCH 042/235] drm/amd/display: Fix mismatch type comparison in custom_float [Why & How] Passing uint into uchar function param. Pass uint instead Signed-off-by: Samson Tam Reviewed-by: Alvin Lee Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/sspl/spl_fixpt31_32.c | 2 +- drivers/gpu/drm/amd/display/dc/sspl/spl_fixpt31_32.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/sspl/spl_fixpt31_32.c b/drivers/gpu/drm/amd/display/dc/sspl/spl_fixpt31_32.c index 131f1e3949d3..52d97918a3bd 100644 --- a/drivers/gpu/drm/amd/display/dc/sspl/spl_fixpt31_32.c +++ b/drivers/gpu/drm/amd/display/dc/sspl/spl_fixpt31_32.c @@ -346,7 +346,7 @@ struct spl_fixed31_32 spl_fixpt_exp(struct spl_fixed31_32 arg) if (m > 0) return spl_fixpt_shl( spl_fixed31_32_exp_from_taylor_series(r), - (unsigned char)m); + (unsigned int)m); else return spl_fixpt_div_int( spl_fixed31_32_exp_from_taylor_series(r), diff --git a/drivers/gpu/drm/amd/display/dc/sspl/spl_fixpt31_32.h b/drivers/gpu/drm/amd/display/dc/sspl/spl_fixpt31_32.h index ed2647f9a099..9f349ffe9148 100644 --- a/drivers/gpu/drm/amd/display/dc/sspl/spl_fixpt31_32.h +++ b/drivers/gpu/drm/amd/display/dc/sspl/spl_fixpt31_32.h @@ -189,7 +189,7 @@ static inline struct spl_fixed31_32 spl_fixpt_clamp( * @brief * result = arg << shift */ -static inline struct spl_fixed31_32 spl_fixpt_shl(struct spl_fixed31_32 arg, unsigned char shift) +static inline struct spl_fixed31_32 spl_fixpt_shl(struct spl_fixed31_32 arg, unsigned int shift) { SPL_ASSERT(((arg.value >= 0) && (arg.value <= LLONG_MAX >> shift)) || ((arg.value < 0) && (arg.value >= ~(LLONG_MAX >> shift)))); @@ -203,7 +203,7 @@ static inline struct spl_fixed31_32 spl_fixpt_shl(struct spl_fixed31_32 arg, uns * @brief * result = arg >> shift */ -static inline struct spl_fixed31_32 spl_fixpt_shr(struct spl_fixed31_32 arg, unsigned char shift) +static inline struct spl_fixed31_32 spl_fixpt_shr(struct spl_fixed31_32 arg, unsigned int shift) { bool negative = arg.value < 0; From fba4d19f3731483ee8565f9e9bb7ed9fc89479e8 Mon Sep 17 00:00:00 2001 From: Navid Assadian Date: Mon, 20 Jan 2025 12:35:23 -0500 Subject: [PATCH 043/235] drm/amd/display: Add opp recout adjustment [Why] For subsampled YUV output formats, more pixels can get fetched and be used for scaling. [How] Add the adjustment to the calculated recout, so the viewport covers the corresponding pixels on the source plane. Signed-off-by: Navid Assadian Reviewed-by: Samson Tam Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/sspl/dc_spl.c | 31 +++++++++++++++---- .../drm/amd/display/dc/sspl/dc_spl_types.h | 10 ++++++ 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/sspl/dc_spl.c b/drivers/gpu/drm/amd/display/dc/sspl/dc_spl.c index 31495c9978b0..72a79288ab79 100644 --- a/drivers/gpu/drm/amd/display/dc/sspl/dc_spl.c +++ b/drivers/gpu/drm/amd/display/dc/sspl/dc_spl.c @@ -76,6 +76,21 @@ static struct spl_rect shift_rec(const struct spl_rect *rec_in, int x, int y) return rec_out; } +static void spl_opp_adjust_rect(struct spl_rect *rec, const struct spl_opp_adjust *adjust) +{ + if ((rec->x + adjust->x) >= 0) + rec->x += adjust->x; + + if ((rec->y + adjust->y) >= 0) + rec->y += adjust->y; + + if ((rec->width + adjust->width) >= 1) + rec->width += adjust->width; + + if ((rec->height + adjust->height) >= 1) + rec->height += adjust->height; +} + static struct spl_rect calculate_plane_rec_in_timing_active( struct spl_in *spl_in, const struct spl_rect *rec_in) @@ -723,13 +738,15 @@ static void spl_handle_3d_recout(struct spl_in *spl_in, struct spl_rect *recout) } } -static void spl_clamp_viewport(struct spl_rect *viewport) +static void spl_clamp_viewport(struct spl_rect *viewport, int min_viewport_size) { + if (min_viewport_size == 0) + min_viewport_size = MIN_VIEWPORT_SIZE; /* Clamp minimum viewport size */ - if (viewport->height < MIN_VIEWPORT_SIZE) - viewport->height = MIN_VIEWPORT_SIZE; - if (viewport->width < MIN_VIEWPORT_SIZE) - viewport->width = MIN_VIEWPORT_SIZE; + if (viewport->height < min_viewport_size) + viewport->height = min_viewport_size; + if (viewport->width < min_viewport_size) + viewport->width = min_viewport_size; } static enum scl_mode spl_get_dscl_mode(const struct spl_in *spl_in, @@ -1764,6 +1781,8 @@ static bool spl_calculate_number_of_taps(struct spl_in *spl_in, struct spl_scrat spl_calculate_recout(spl_in, spl_scratch, spl_out); /* depends on pixel format */ spl_calculate_scaling_ratios(spl_in, spl_scratch, spl_out); + /* Adjust recout for opp if needed */ + spl_opp_adjust_rect(&spl_scratch->scl_data.recout, &spl_in->basic_in.opp_recout_adjust); /* depends on scaling ratios and recout, does not calculate offset yet */ spl_calculate_viewport_size(spl_in, spl_scratch); @@ -1800,7 +1819,7 @@ bool spl_calculate_scaler_params(struct spl_in *spl_in, struct spl_out *spl_out) // Handle 3d recout spl_handle_3d_recout(spl_in, &spl_scratch.scl_data.recout); // Clamp - spl_clamp_viewport(&spl_scratch.scl_data.viewport); + spl_clamp_viewport(&spl_scratch.scl_data.viewport, spl_in->min_viewport_size); // Save all calculated parameters in dscl_prog_data structure to program hw registers spl_set_dscl_prog_data(spl_in, &spl_scratch, spl_out, enable_easf_v, enable_easf_h, enable_isharp); diff --git a/drivers/gpu/drm/amd/display/dc/sspl/dc_spl_types.h b/drivers/gpu/drm/amd/display/dc/sspl/dc_spl_types.h index 467af9dd90de..0130673ceee6 100644 --- a/drivers/gpu/drm/amd/display/dc/sspl/dc_spl_types.h +++ b/drivers/gpu/drm/amd/display/dc/sspl/dc_spl_types.h @@ -427,6 +427,14 @@ struct spl_out { // SPL inputs +// opp extra adjustment for rect +struct spl_opp_adjust { + int x; + int y; + int width; + int height; +}; + // Basic input information struct basic_in { enum spl_pixel_format format; // Pixel Format @@ -444,6 +452,7 @@ struct basic_in { } num_slices_recout_width; } num_h_slices_recout_width_align; int mpc_h_slice_index; // previous mpc_combine_v - split_idx + struct spl_opp_adjust opp_recout_adjust; // Inputs for adaptive scaler - TODO enum spl_transfer_func_type tf_type; /* Transfer function type */ enum spl_transfer_func_predefined tf_predefined_type; /* Transfer function predefined type */ @@ -535,6 +544,7 @@ struct spl_in { bool is_hdr_on; int h_active; int v_active; + int min_viewport_size; int sdr_white_level_nits; enum sharpen_policy sharpen_policy; }; From 26873260d394b1e33cdd720154aedf0af95327f9 Mon Sep 17 00:00:00 2001 From: "Assadian, Navid" Date: Thu, 19 Dec 2024 17:19:09 -0500 Subject: [PATCH 044/235] drm/amd/display: Fix mismatch type comparison The mismatch type comparison/assignment may cause data loss. Since the values are always non-negative, it is safe to use unsigned variables to resolve the mismatch. Signed-off-by: Navid Assadian Reviewed-by: Joshua Aberback Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/sspl/dc_spl.c | 4 ++-- drivers/gpu/drm/amd/display/dc/sspl/dc_spl_types.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/sspl/dc_spl.c b/drivers/gpu/drm/amd/display/dc/sspl/dc_spl.c index 72a79288ab79..3d85732cc0f5 100644 --- a/drivers/gpu/drm/amd/display/dc/sspl/dc_spl.c +++ b/drivers/gpu/drm/amd/display/dc/sspl/dc_spl.c @@ -944,8 +944,8 @@ static bool spl_get_optimal_number_of_taps( bool *enable_isharp) { int num_part_y, num_part_c; - int max_taps_y, max_taps_c; - int min_taps_y, min_taps_c; + unsigned int max_taps_y, max_taps_c; + unsigned int min_taps_y, min_taps_c; enum lb_memory_config lb_config; bool skip_easf = false; bool is_subsampled = spl_is_subsampled_format(spl_in->basic_in.format); diff --git a/drivers/gpu/drm/amd/display/dc/sspl/dc_spl_types.h b/drivers/gpu/drm/amd/display/dc/sspl/dc_spl_types.h index 0130673ceee6..1c3949b24611 100644 --- a/drivers/gpu/drm/amd/display/dc/sspl/dc_spl_types.h +++ b/drivers/gpu/drm/amd/display/dc/sspl/dc_spl_types.h @@ -493,7 +493,7 @@ struct spl_sharpness_range { }; struct adaptive_sharpness { bool enable; - int sharpness_level; + unsigned int sharpness_level; struct spl_sharpness_range sharpness_range; }; enum linear_light_scaling { // convert it in translation logic From 0d3004647631aedb713251525a99784661574767 Mon Sep 17 00:00:00 2001 From: Samson Tam Date: Tue, 21 Jan 2025 11:01:47 -0500 Subject: [PATCH 045/235] drm/amd/display: fix check for identity ratio [Why] IDENTITY_RATIO check uses 2 bits for integer, which only allows checking downscale ratios up to 3. But we support up to 6x downscale [How] Update IDENTITY_RATIO to check 3 bits for integer Add ASSERT to catch if we downscale more than 6x Signed-off-by: Samson Tam Reviewed-by: Jun Lei Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/sspl/dc_spl.c | 21 +++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/sspl/dc_spl.c b/drivers/gpu/drm/amd/display/dc/sspl/dc_spl.c index 3d85732cc0f5..047f05ab0181 100644 --- a/drivers/gpu/drm/amd/display/dc/sspl/dc_spl.c +++ b/drivers/gpu/drm/amd/display/dc/sspl/dc_spl.c @@ -8,7 +8,7 @@ #include "dc_spl_isharp_filters.h" #include "spl_debug.h" -#define IDENTITY_RATIO(ratio) (spl_fixpt_u2d19(ratio) == (1 << 19)) +#define IDENTITY_RATIO(ratio) (spl_fixpt_u3d19(ratio) == (1 << 19)) #define MIN_VIEWPORT_SIZE 12 static bool spl_is_yuv420(enum spl_pixel_format format) @@ -887,6 +887,8 @@ static bool spl_get_isharp_en(struct spl_in *spl_in, static void spl_get_taps_non_adaptive_scaler( struct spl_scratch *spl_scratch, const struct spl_taps *in_taps) { + bool check_max_downscale = false; + if (in_taps->h_taps == 0) { if (spl_fixpt_ceil(spl_scratch->scl_data.ratios.horz) > 1) spl_scratch->scl_data.taps.h_taps = spl_min(2 * spl_fixpt_ceil( @@ -926,6 +928,23 @@ static void spl_get_taps_non_adaptive_scaler( else spl_scratch->scl_data.taps.h_taps_c = in_taps->h_taps_c; + + /* + * Max downscale supported is 6.0x. Add ASSERT to catch if go beyond that + */ + check_max_downscale = spl_fixpt_le(spl_scratch->scl_data.ratios.horz, + spl_fixpt_from_fraction(6, 1)); + SPL_ASSERT(check_max_downscale); + check_max_downscale = spl_fixpt_le(spl_scratch->scl_data.ratios.vert, + spl_fixpt_from_fraction(6, 1)); + SPL_ASSERT(check_max_downscale); + check_max_downscale = spl_fixpt_le(spl_scratch->scl_data.ratios.horz_c, + spl_fixpt_from_fraction(6, 1)); + SPL_ASSERT(check_max_downscale); + check_max_downscale = spl_fixpt_le(spl_scratch->scl_data.ratios.vert_c, + spl_fixpt_from_fraction(6, 1)); + SPL_ASSERT(check_max_downscale); + if (IDENTITY_RATIO(spl_scratch->scl_data.ratios.horz)) spl_scratch->scl_data.taps.h_taps = 1; if (IDENTITY_RATIO(spl_scratch->scl_data.ratios.vert)) From 259eacbfcf66c52384bf4e194fd34939b6007265 Mon Sep 17 00:00:00 2001 From: Samson Tam Date: Tue, 7 Jan 2025 14:17:15 -0500 Subject: [PATCH 046/235] drm/amd/display: Fix unit test failure [Why] Some of unit tests use large scaling ratio such that when we calculate optimal number of taps, max_taps is negative. Then in recent change, we changed max_taps to uint instead of int so now max_taps wraps and is positive. This change changed the behaviour from returning back false to return true and breaks unit test check [How] Add check to prevent max_taps from wrapping and set to 0 instead Signed-off-by: Samson Tam Reviewed-by: Alvin Lee Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/sspl/dc_spl.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/sspl/dc_spl.c b/drivers/gpu/drm/amd/display/dc/sspl/dc_spl.c index 047f05ab0181..ad77cef57ac7 100644 --- a/drivers/gpu/drm/amd/display/dc/sspl/dc_spl.c +++ b/drivers/gpu/drm/amd/display/dc/sspl/dc_spl.c @@ -1026,12 +1026,18 @@ static bool spl_get_optimal_number_of_taps( lb_config, &num_part_y, &num_part_c); /* MAX_V_TAPS = MIN (NUM_LINES - MAX(CEILING(V_RATIO,1)-2, 0), 8) */ if (spl_fixpt_ceil(spl_scratch->scl_data.ratios.vert) > 2) - max_taps_y = num_part_y - (spl_fixpt_ceil(spl_scratch->scl_data.ratios.vert) - 2); + if ((spl_fixpt_ceil(spl_scratch->scl_data.ratios.vert) - 2) > num_part_y) + max_taps_y = 0; + else + max_taps_y = num_part_y - (spl_fixpt_ceil(spl_scratch->scl_data.ratios.vert) - 2); else max_taps_y = num_part_y; if (spl_fixpt_ceil(spl_scratch->scl_data.ratios.vert_c) > 2) - max_taps_c = num_part_c - (spl_fixpt_ceil(spl_scratch->scl_data.ratios.vert_c) - 2); + if ((spl_fixpt_ceil(spl_scratch->scl_data.ratios.vert_c) - 2) > num_part_c) + max_taps_c = 0; + else + max_taps_c = num_part_c - (spl_fixpt_ceil(spl_scratch->scl_data.ratios.vert_c) - 2); else max_taps_c = num_part_c; From 0fe2df4498db493ad400a67eb0e7e76fcaf7c3be Mon Sep 17 00:00:00 2001 From: Navid Assadian Date: Mon, 20 Jan 2025 12:35:07 -0500 Subject: [PATCH 047/235] drm/amd/display: Add SPL namespace [Why] In order to avoid component conflicts, spl namespace is needed. [How] Adding SPL namespace to the public API os that each user of SPL can have their own namespace. Signed-off-by: Navid Assadian Reviewed-by: Samson Tam Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/sspl/dc_spl.c | 4 ++-- drivers/gpu/drm/amd/display/dc/sspl/dc_spl.h | 16 ++++++++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/sspl/dc_spl.c b/drivers/gpu/drm/amd/display/dc/sspl/dc_spl.c index ad77cef57ac7..8d80bce0738a 100644 --- a/drivers/gpu/drm/amd/display/dc/sspl/dc_spl.c +++ b/drivers/gpu/drm/amd/display/dc/sspl/dc_spl.c @@ -1819,7 +1819,7 @@ static bool spl_calculate_number_of_taps(struct spl_in *spl_in, struct spl_scrat } /* Calculate scaler parameters */ -bool spl_calculate_scaler_params(struct spl_in *spl_in, struct spl_out *spl_out) +bool SPL_NAMESPACE(spl_calculate_scaler_params(struct spl_in *spl_in, struct spl_out *spl_out)) { bool res = false; bool enable_easf_v = false; @@ -1884,7 +1884,7 @@ bool spl_calculate_scaler_params(struct spl_in *spl_in, struct spl_out *spl_out) } /* External interface to get number of taps only */ -bool spl_get_number_of_taps(struct spl_in *spl_in, struct spl_out *spl_out) +bool SPL_NAMESPACE(spl_get_number_of_taps(struct spl_in *spl_in, struct spl_out *spl_out)) { bool res = false; bool enable_easf_v = false; diff --git a/drivers/gpu/drm/amd/display/dc/sspl/dc_spl.h b/drivers/gpu/drm/amd/display/dc/sspl/dc_spl.h index 02a2d6725ed5..145961803a92 100644 --- a/drivers/gpu/drm/amd/display/dc/sspl/dc_spl.h +++ b/drivers/gpu/drm/amd/display/dc/sspl/dc_spl.h @@ -9,10 +9,22 @@ #define BLACK_OFFSET_RGB_Y 0x0 #define BLACK_OFFSET_CBCR 0x8000 +#ifndef SPL_PFX_ +#define SPL_PFX_ +#endif + +#define SPL_EXPAND2(a, b) a##b +#define SPL_EXPAND(a, b) SPL_EXPAND2(a, b) +#define SPL_NAMESPACE(symbol) SPL_EXPAND(SPL_PFX_, symbol) + +#ifdef __cplusplus +extern "C" { +#endif + /* SPL interfaces */ -bool spl_calculate_scaler_params(struct spl_in *spl_in, struct spl_out *spl_out); +bool SPL_NAMESPACE(spl_calculate_scaler_params(struct spl_in *spl_in, struct spl_out *spl_out)); -bool spl_get_number_of_taps(struct spl_in *spl_in, struct spl_out *spl_out); +bool SPL_NAMESPACE(spl_get_number_of_taps(struct spl_in *spl_in, struct spl_out *spl_out)); #endif /* __DC_SPL_H__ */ From d295786840166074e3d5d3ba3e0d854b21749510 Mon Sep 17 00:00:00 2001 From: Peichen Huang Date: Fri, 17 Jan 2025 10:48:11 +0800 Subject: [PATCH 048/235] drm/amd/display: replace dio encoder access [WHY] replace dio encoder access to work with new dio encoder assignment. [HOW} 1. before validation, access dio encoder by get_temp_dio_link_enc() 2. after validation, access dio encoder through pipe_ctx->link_res Reviewed-by: Wenjing Liu Reviewed-by: Meenakshikumar Somasundaram Signed-off-by: Peichen Huang Signed-off-by: Zaeem Mohamed Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- .../amd/display/dc/hwss/dce110/dce110_hwseq.c | 5 +- .../amd/display/dc/hwss/dcn20/dcn20_hwseq.c | 5 +- .../amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 5 +- drivers/gpu/drm/amd/display/dc/inc/resource.h | 5 ++ .../amd/display/dc/link/hwss/link_hwss_dio.c | 66 ++++++++++++++++--- .../hwss/link_hwss_dio_fixed_vs_pe_retimer.c | 5 +- .../amd/display/dc/link/hwss/link_hwss_dpia.c | 20 ++++-- .../gpu/drm/amd/display/dc/link/link_dpms.c | 15 +++-- .../dc/link/protocols/link_dp_capability.c | 21 ++++-- .../dc/link/protocols/link_dp_capability.h | 1 + .../display/dc/link/protocols/link_dp_phy.c | 16 +++-- .../display/dc/link/protocols/link_dp_phy.h | 3 +- .../dc/link/protocols/link_dp_training.c | 20 ++++-- .../dc/link/protocols/link_dp_training.h | 2 + .../protocols/link_dp_training_128b_132b.c | 4 +- .../protocols/link_dp_training_128b_132b.h | 1 + .../link/protocols/link_dp_training_8b_10b.c | 5 +- .../link/protocols/link_dp_training_8b_10b.h | 3 +- .../link/protocols/link_dp_training_auxless.c | 1 + .../dc/link/protocols/link_dp_training_dpia.c | 1 + .../dc/resource/dcn20/dcn20_resource.c | 5 +- .../dc/resource/dcn401/dcn401_resource.c | 5 +- 23 files changed, 161 insertions(+), 55 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 7eb91612b60d..0bd3e7c072a1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -5191,7 +5191,7 @@ void get_audio_check(struct audio_info *aud_modes, } } -static struct link_encoder *get_temp_dio_link_enc( +struct link_encoder *get_temp_dio_link_enc( const struct resource_context *res_ctx, const struct resource_pool *const pool, const struct dc_link *link) diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c index 8280e3652171..9c9947fc5d44 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c @@ -1153,9 +1153,12 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) struct timing_generator *tg = pipe_ctx->stream_res.tg; struct dtbclk_dto_params dto_params = {0}; int dp_hpo_inst; - struct link_encoder *link_enc = link_enc_cfg_get_link_enc(pipe_ctx->stream->link); + struct link_encoder *link_enc = pipe_ctx->link_res.dio_link_enc; struct stream_encoder *stream_enc = pipe_ctx->stream_res.stream_enc; + if (!dc->config.unify_link_enc_assignment) + link_enc = link_enc_cfg_get_link_enc(link); + if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal)) { pipe_ctx->stream_res.stream_enc->funcs->stop_hdmi_info_packets( pipe_ctx->stream_res.stream_enc); diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c index b158eb1045a1..a5a3e0823e21 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c @@ -3020,9 +3020,12 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx) enum phyd32clk_clock_source phyd32clk; int dp_hpo_inst; - struct link_encoder *link_enc = link_enc_cfg_get_link_enc(pipe_ctx->stream->link); + struct link_encoder *link_enc = pipe_ctx->link_res.dio_link_enc; struct stream_encoder *stream_enc = pipe_ctx->stream_res.stream_enc; + if (!dc->config.unify_link_enc_assignment) + link_enc = link_enc_cfg_get_link_enc(link); + if (dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { dto_params.otg_inst = tg->inst; dto_params.pixclk_khz = pipe_ctx->stream->timing.pix_clk_100hz / 10; diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c index c4a37a95e812..39668d8cc13a 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c @@ -927,9 +927,12 @@ void dcn401_enable_stream(struct pipe_ctx *pipe_ctx) int dp_hpo_inst = 0; unsigned int tmds_div = PIXEL_RATE_DIV_NA; unsigned int unused_div = PIXEL_RATE_DIV_NA; - struct link_encoder *link_enc = link_enc_cfg_get_link_enc(pipe_ctx->stream->link); + struct link_encoder *link_enc = pipe_ctx->link_res.dio_link_enc; struct stream_encoder *stream_enc = pipe_ctx->stream_res.stream_enc; + if (!dc->config.unify_link_enc_assignment) + link_enc = link_enc_cfg_get_link_enc(link); + dcn401_enable_stream_calc(pipe_ctx, &dp_hpo_inst, &phyd32clk, &tmds_div, &early_control); diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index 042e04f924a2..9458187b834d 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -647,4 +647,9 @@ void resource_init_common_dml2_callbacks(struct dc *dc, struct dml2_configuratio int resource_calculate_det_for_stream(struct dc_state *state, struct pipe_ctx *otg_master); bool resource_is_hpo_acquired(struct dc_state *context); + +struct link_encoder *get_temp_dio_link_enc( + const struct resource_context *res_ctx, + const struct resource_pool *const pool, + const struct dc_link *link); #endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c index 06faa461067b..4a3578a9586e 100644 --- a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c +++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c @@ -48,9 +48,16 @@ void set_dio_throttled_vcp_size(struct pipe_ctx *pipe_ctx, void setup_dio_stream_encoder(struct pipe_ctx *pipe_ctx) { - struct link_encoder *link_enc = link_enc_cfg_get_link_enc(pipe_ctx->stream->link); + struct link_encoder *link_enc = pipe_ctx->link_res.dio_link_enc; struct stream_encoder *stream_enc = pipe_ctx->stream_res.stream_enc; + if (!pipe_ctx->stream->ctx->dc->config.unify_link_enc_assignment) + link_enc = link_enc_cfg_get_link_enc(pipe_ctx->stream->link); + if (!link_enc) { + ASSERT(link_enc); + return; + } + link_enc->funcs->connect_dig_be_to_fe(link_enc, pipe_ctx->stream_res.stream_enc->id, true); if (dc_is_dp_signal(pipe_ctx->stream->signal)) @@ -71,9 +78,16 @@ void setup_dio_stream_encoder(struct pipe_ctx *pipe_ctx) void reset_dio_stream_encoder(struct pipe_ctx *pipe_ctx) { - struct link_encoder *link_enc = link_enc_cfg_get_link_enc(pipe_ctx->stream->link); + struct link_encoder *link_enc = pipe_ctx->link_res.dio_link_enc; struct stream_encoder *stream_enc = pipe_ctx->stream_res.stream_enc; + if (!pipe_ctx->stream->ctx->dc->config.unify_link_enc_assignment) + link_enc = link_enc_cfg_get_link_enc(pipe_ctx->stream->link); + if (!link_enc) { + ASSERT(link_enc); + return; + } + if (!stream_enc) return; @@ -142,7 +156,14 @@ void enable_dio_dp_link_output(struct dc_link *link, enum clock_source_id clock_source, const struct dc_link_settings *link_settings) { - struct link_encoder *link_enc = link_enc_cfg_get_link_enc(link); + struct link_encoder *link_enc = link_res->dio_link_enc; + + if (!link->dc->config.unify_link_enc_assignment) + link_enc = link_enc_cfg_get_link_enc(link); + if (!link_enc) { + ASSERT(link_enc); + return; + } if (dc_is_dp_sst_signal(signal)) link_enc->funcs->enable_dp_output( @@ -162,11 +183,16 @@ void disable_dio_link_output(struct dc_link *link, const struct link_resource *link_res, enum signal_type signal) { - struct link_encoder *link_enc = link_enc_cfg_get_link_enc(link); + struct link_encoder *link_enc = link_res->dio_link_enc; - if (link_enc != NULL) - link_enc->funcs->disable_output(link_enc, signal); + if (!link->dc->config.unify_link_enc_assignment) + link_enc = link_enc_cfg_get_link_enc(link); + if (!link_enc) { + ASSERT(link_enc); + return; + } + link_enc->funcs->disable_output(link_enc, signal); link->dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_LINK_PHY); } @@ -175,7 +201,14 @@ void set_dio_dp_link_test_pattern(struct dc_link *link, const struct link_resource *link_res, struct encoder_set_dp_phy_pattern_param *tp_params) { - struct link_encoder *link_enc = link_enc_cfg_get_link_enc(link); + struct link_encoder *link_enc = link_res->dio_link_enc; + + if (!link->dc->config.unify_link_enc_assignment) + link_enc = link_enc_cfg_get_link_enc(link); + if (!link_enc) { + ASSERT(link_enc); + return; + } link_enc->funcs->dp_set_phy_pattern(link_enc, tp_params); link->dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_SET_SOURCE_PATTERN); @@ -186,7 +219,14 @@ void set_dio_dp_lane_settings(struct dc_link *link, const struct dc_link_settings *link_settings, const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]) { - struct link_encoder *link_enc = link_enc_cfg_get_link_enc(link); + struct link_encoder *link_enc = link_res->dio_link_enc; + + if (!link->dc->config.unify_link_enc_assignment) + link_enc = link_enc_cfg_get_link_enc(link); + if (!link_enc) { + ASSERT(link_enc); + return; + } link_enc->funcs->dp_set_lane_settings(link_enc, link_settings, lane_settings); } @@ -195,9 +235,15 @@ void update_dio_stream_allocation_table(struct dc_link *link, const struct link_resource *link_res, const struct link_mst_stream_allocation_table *table) { - struct link_encoder *link_enc = link_enc_cfg_get_link_enc(link); + struct link_encoder *link_enc = link_res->dio_link_enc; + + if (!link->dc->config.unify_link_enc_assignment) + link_enc = link_enc_cfg_get_link_enc(link); + if (!link_enc) { + ASSERT(link_enc); + return; + } - ASSERT(link_enc); link_enc->funcs->update_mst_stream_allocation_table(link_enc, table); } diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio_fixed_vs_pe_retimer.c b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio_fixed_vs_pe_retimer.c index a6d1d7641ab4..e1dff4e3f446 100644 --- a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio_fixed_vs_pe_retimer.c +++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio_fixed_vs_pe_retimer.c @@ -127,7 +127,10 @@ static void set_dio_fixed_vs_pe_retimer_dp_link_test_pattern(struct dc_link *lin const struct link_resource *link_res, struct encoder_set_dp_phy_pattern_param *tp_params) { - struct link_encoder *link_enc = link_enc_cfg_get_link_enc(link); + struct link_encoder *link_enc = link_res->dio_link_enc; + + if (!link->dc->config.unify_link_enc_assignment) + link_enc = link_enc_cfg_get_link_enc(link); if (!set_dio_fixed_vs_pe_retimer_dp_link_test_pattern_override( link, link_res, tp_params, get_dio_link_hwss())) { diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dpia.c b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dpia.c index 36adf95744fe..81d5085e322f 100644 --- a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dpia.c +++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dpia.c @@ -35,12 +35,15 @@ static void update_dpia_stream_allocation_table(struct dc_link *link, const struct link_resource *link_res, const struct link_mst_stream_allocation_table *table) { - struct link_encoder *link_enc = link_enc_cfg_get_link_enc(link); + struct link_encoder *link_enc = link_res->dio_link_enc; static enum dc_status status; uint8_t mst_alloc_slots = 0, prev_mst_slots_in_use = 0xFF; int i; DC_LOGGER_INIT(link->ctx->logger); + if (!link->dc->config.unify_link_enc_assignment) + link_enc = link_enc_cfg_get_link_enc(link); + for (i = 0; i < table->stream_count; i++) mst_alloc_slots += table->stream_allocations[i].slot_count; @@ -61,7 +64,10 @@ static void set_dio_dpia_link_test_pattern(struct dc_link *link, if (tp_params->dp_phy_pattern != DP_TEST_PATTERN_VIDEO_MODE) return; - struct link_encoder *link_enc = link_enc_cfg_get_link_enc(link); + struct link_encoder *link_enc = link_res->dio_link_enc; + + if (!link->dc->config.unify_link_enc_assignment) + link_enc = link_enc_cfg_get_link_enc(link); if (!link_enc) return; @@ -83,7 +89,10 @@ static void enable_dpia_link_output(struct dc_link *link, enum clock_source_id clock_source, const struct dc_link_settings *link_settings) { - struct link_encoder *link_enc = link_enc_cfg_get_link_enc(link); + struct link_encoder *link_enc = link_res->dio_link_enc; + + if (!link->dc->config.unify_link_enc_assignment) + link_enc = link_enc_cfg_get_link_enc(link); if (link_enc != NULL) { if (link->dc->config.enable_dpia_pre_training && link_enc->funcs->enable_dpia_output) { @@ -119,7 +128,10 @@ static void disable_dpia_link_output(struct dc_link *link, const struct link_resource *link_res, enum signal_type signal) { - struct link_encoder *link_enc = link_enc_cfg_get_link_enc(link); + struct link_encoder *link_enc = link_res->dio_link_enc; + + if (!link->dc->config.unify_link_enc_assignment) + link_enc = link_enc_cfg_get_link_enc(link); if (link_enc != NULL) { if (link->dc->config.enable_dpia_pre_training && link_enc->funcs->disable_dpia_output) { diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c index ec7de9c01fab..321fd1785370 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c @@ -652,15 +652,15 @@ static void write_i2c_redriver_setting( static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off) { struct cp_psp *cp_psp = &pipe_ctx->stream->ctx->cp_psp; - struct link_encoder *link_enc = NULL; + struct link_encoder *link_enc = pipe_ctx->link_res.dio_link_enc; struct cp_psp_stream_config config = {0}; enum dp_panel_mode panel_mode = dp_get_panel_mode(pipe_ctx->stream->link); if (cp_psp == NULL || cp_psp->funcs.update_stream_config == NULL) return; - - link_enc = link_enc_cfg_get_link_enc(pipe_ctx->stream->link); + if (!pipe_ctx->stream->ctx->dc->config.unify_link_enc_assignment) + link_enc = link_enc_cfg_get_link_enc(pipe_ctx->stream->link); ASSERT(link_enc); if (link_enc == NULL) return; @@ -1924,7 +1924,7 @@ static void disable_link_dp(struct dc_link *link, if (link_dp_get_encoding_format(&link_settings) == DP_8b_10b_ENCODING) { - dp_set_fec_enable(link, false); + dp_set_fec_enable(link, link_res, false); dp_set_fec_ready(link, link_res, false); } } @@ -2122,7 +2122,7 @@ static enum dc_status enable_link_dp(struct dc_state *state, fec_enable = true; if (link_dp_get_encoding_format(link_settings) == DP_8b_10b_ENCODING) - dp_set_fec_enable(link, fec_enable); + dp_set_fec_enable(link, &pipe_ctx->link_res, fec_enable); // during mode set we do DP_SET_POWER off then on, aux writes are lost if (link->dpcd_sink_ext_caps.bits.oled == 1 || @@ -2461,7 +2461,7 @@ void link_set_dpms_on( struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->sink->link; enum dc_status status; - struct link_encoder *link_enc; + struct link_encoder *link_enc = pipe_ctx->link_res.dio_link_enc; enum otg_out_mux_dest otg_out_dest = OUT_MUX_DIO; struct vpg *vpg = pipe_ctx->stream_res.stream_enc->vpg; const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res); @@ -2486,7 +2486,8 @@ void link_set_dpms_on( } } - link_enc = link_enc_cfg_get_link_enc(link); + if (!dc->config.unify_link_enc_assignment) + link_enc = link_enc_cfg_get_link_enc(link); ASSERT(link_enc); if (!dc_is_virtual_signal(pipe_ctx->stream->signal) diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c index e3e7fcb07f19..f6e0868507f7 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c @@ -330,9 +330,12 @@ bool dp_is_fec_supported(const struct dc_link *link) /* TODO - use asic cap instead of link_enc->features * we no longer know which link enc to use for this link before commit */ - struct link_encoder *link_enc = NULL; + struct resource_context *res_ctx = &link->dc->current_state->res_ctx; + struct resource_pool *res_pool = link->dc->res_pool; + struct link_encoder *link_enc = get_temp_dio_link_enc(res_ctx, res_pool, link); - link_enc = link_enc_cfg_get_link_enc(link); + if (!link->dc->config.unify_link_enc_assignment) + link_enc = link_enc_cfg_get_link_enc(link); ASSERT(link_enc); return (dc_is_dp_signal(link->connector_signal) && link_enc && @@ -2093,14 +2096,17 @@ void detect_edp_sink_caps(struct dc_link *link) bool dp_get_max_link_enc_cap(const struct dc_link *link, struct dc_link_settings *max_link_enc_cap) { - struct link_encoder *link_enc = NULL; + struct resource_context *res_ctx = &link->dc->current_state->res_ctx; + struct resource_pool *res_pool = link->dc->res_pool; + struct link_encoder *link_enc = get_temp_dio_link_enc(res_ctx, res_pool, link); if (!max_link_enc_cap) { DC_LOG_ERROR("%s: Could not return max link encoder caps", __func__); return false; } - link_enc = link_enc_cfg_get_link_enc(link); + if (!link->dc->config.unify_link_enc_assignment) + link_enc = link_enc_cfg_get_link_enc(link); ASSERT(link_enc); if (link_enc && link_enc->funcs->get_max_link_cap) { @@ -2128,10 +2134,13 @@ struct dc_link_settings dp_get_max_link_cap(struct dc_link *link) struct dc_link_settings max_link_cap = {0}; enum dc_link_rate lttpr_max_link_rate; enum dc_link_rate cable_max_link_rate; - struct link_encoder *link_enc = NULL; + struct resource_context *res_ctx = &link->dc->current_state->res_ctx; + struct resource_pool *res_pool = link->dc->res_pool; + struct link_encoder *link_enc = get_temp_dio_link_enc(res_ctx, res_pool, link); bool is_uhbr13_5_supported = true; - link_enc = link_enc_cfg_get_link_enc(link); + if (!link->dc->config.unify_link_enc_assignment) + link_enc = link_enc_cfg_get_link_enc(link); ASSERT(link_enc); /* get max link encoder capability */ diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.h index 8f0ce97f2362..0ce0af3ddbeb 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.h +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.h @@ -67,6 +67,7 @@ bool dp_is_128b_132b_signal(struct pipe_ctx *pipe_ctx); /* Initialize output parameter lt_settings. */ void dp_decide_training_settings( struct dc_link *link, + const struct link_resource *link_res, const struct dc_link_settings *link_setting, struct link_training_settings *lt_settings); diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c index c27ffec5d84f..49521ac4b0e8 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c @@ -142,11 +142,12 @@ enum dc_status dp_set_fec_ready(struct dc_link *link, const struct link_resource * if the sink supports it and leave it enabled on link. * If FEC is not supported, disable it. */ - struct link_encoder *link_enc = NULL; + struct link_encoder *link_enc = link_res->dio_link_enc; enum dc_status status = DC_OK; uint8_t fec_config = 0; - link_enc = link_enc_cfg_get_link_enc(link); + if (!link->dc->config.unify_link_enc_assignment) + link_enc = link_enc_cfg_get_link_enc(link); ASSERT(link_enc); if (link_enc->funcs->fec_set_ready == NULL) return DC_NOT_SUPPORTED; @@ -176,13 +177,14 @@ enum dc_status dp_set_fec_ready(struct dc_link *link, const struct link_resource return status; } -void dp_set_fec_enable(struct dc_link *link, bool enable) +void dp_set_fec_enable(struct dc_link *link, const struct link_resource *link_res, bool enable) { - struct link_encoder *link_enc = NULL; + struct link_encoder *link_enc = link_res->dio_link_enc; - link_enc = link_enc_cfg_get_link_enc(link); - ASSERT(link_enc); - if (link_enc->funcs->fec_set_enable == NULL) + if (!link->dc->config.unify_link_enc_assignment) + link_enc = link_enc_cfg_get_link_enc(link); + + if (link_enc == NULL || link_enc->funcs == NULL || link_enc->funcs->fec_set_enable == NULL) return; if (enable && dp_should_enable_fec(link)) { diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.h index 1eb0619d6710..ab1c1f8f1f8b 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.h +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.h @@ -52,7 +52,8 @@ void dp_set_drive_settings( enum dc_status dp_set_fec_ready(struct dc_link *link, const struct link_resource *link_res, bool ready); -void dp_set_fec_enable(struct dc_link *link, bool enable); +void dp_set_fec_enable(struct dc_link *link, + const struct link_resource *link_res, bool enable); void dpcd_write_rx_power_ctrl(struct dc_link *link, bool on); diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c index 751c18e592ea..40ac17ba9479 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c @@ -801,19 +801,23 @@ enum dc_dp_training_pattern decide_cr_training_pattern( } enum dc_dp_training_pattern decide_eq_training_pattern(struct dc_link *link, + const struct link_resource *link_res, const struct dc_link_settings *link_settings) { - struct link_encoder *link_enc; + struct link_encoder *link_enc = link_res->dio_link_enc; struct encoder_feature_support *enc_caps; struct dpcd_caps *rx_caps = &link->dpcd_caps; enum dc_dp_training_pattern pattern = DP_TRAINING_PATTERN_SEQUENCE_2; - link_enc = link_enc_cfg_get_link_enc(link); - ASSERT(link_enc); - enc_caps = &link_enc->features; - switch (link_dp_get_encoding_format(link_settings)) { case DP_8b_10b_ENCODING: + if (!link->dc->config.unify_link_enc_assignment) + link_enc = link_enc_cfg_get_link_enc(link); + + if (!link_enc) + break; + + enc_caps = &link_enc->features; if (enc_caps->flags.bits.IS_TPS4_CAPABLE && rx_caps->max_down_spread.bits.TPS4_SUPPORTED) pattern = DP_TRAINING_PATTERN_SEQUENCE_4; @@ -886,13 +890,14 @@ void dp_decide_lane_settings( void dp_decide_training_settings( struct dc_link *link, + const struct link_resource *link_res, const struct dc_link_settings *link_settings, struct link_training_settings *lt_settings) { if (link_dp_get_encoding_format(link_settings) == DP_8b_10b_ENCODING) - decide_8b_10b_training_settings(link, link_settings, lt_settings); + decide_8b_10b_training_settings(link, link_res, link_settings, lt_settings); else if (link_dp_get_encoding_format(link_settings) == DP_128b_132b_ENCODING) - decide_128b_132b_training_settings(link, link_settings, lt_settings); + decide_128b_132b_training_settings(link, link_res, link_settings, lt_settings); } @@ -1556,6 +1561,7 @@ enum link_training_result dp_perform_link_training( /* decide training settings */ dp_decide_training_settings( link, + link_res, link_settings, <_settings); diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.h index 0b18aa35c33c..574b083e0936 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.h +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.h @@ -104,6 +104,7 @@ void start_clock_recovery_pattern_early(struct dc_link *link, void dp_decide_training_settings( struct dc_link *link, + const struct link_resource *link_res, const struct dc_link_settings *link_settings, struct link_training_settings *lt_settings); @@ -117,6 +118,7 @@ enum dc_dp_training_pattern decide_cr_training_pattern( const struct dc_link_settings *link_settings); enum dc_dp_training_pattern decide_eq_training_pattern(struct dc_link *link, + const struct link_resource *link_res, const struct dc_link_settings *link_settings); enum lttpr_mode dp_decide_lttpr_mode(struct dc_link *link, diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_128b_132b.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_128b_132b.c index db87cfe37b5c..11565f187ac7 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_128b_132b.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_128b_132b.c @@ -204,6 +204,7 @@ enum link_training_result dp_perform_128b_132b_link_training( struct link_training_settings legacy_settings; decide_8b_10b_training_settings(link, + link_res, <_settings->link_settings, &legacy_settings); return dp_perform_8b_10b_link_training(link, link_res, &legacy_settings); @@ -227,6 +228,7 @@ enum link_training_result dp_perform_128b_132b_link_training( } void decide_128b_132b_training_settings(struct dc_link *link, + const struct link_resource *link_res, const struct dc_link_settings *link_settings, struct link_training_settings *lt_settings) { @@ -238,7 +240,7 @@ void decide_128b_132b_training_settings(struct dc_link *link, LINK_SPREAD_05_DOWNSPREAD_30KHZ; lt_settings->pattern_for_cr = decide_cr_training_pattern(link_settings); - lt_settings->pattern_for_eq = decide_eq_training_pattern(link, link_settings); + lt_settings->pattern_for_eq = decide_eq_training_pattern(link, link_res, link_settings); lt_settings->eq_pattern_time = 2500; lt_settings->eq_wait_time_limit = 400000; lt_settings->eq_loop_count_limit = 20; diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_128b_132b.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_128b_132b.h index 2147f24efc8b..901a42edafa1 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_128b_132b.h +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_128b_132b.h @@ -34,6 +34,7 @@ enum link_training_result dp_perform_128b_132b_link_training( struct link_training_settings *lt_settings); void decide_128b_132b_training_settings(struct dc_link *link, + const struct link_resource *link_res, const struct dc_link_settings *link_settings, struct link_training_settings *lt_settings); diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.c index ae95ec48e572..34d2e097ca2e 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.c @@ -93,7 +93,8 @@ static uint32_t get_eq_training_aux_rd_interval( } void decide_8b_10b_training_settings( - struct dc_link *link, + struct dc_link *link, + const struct link_resource *link_res, const struct dc_link_settings *link_setting, struct link_training_settings *lt_settings) { @@ -115,7 +116,7 @@ void decide_8b_10b_training_settings( LINK_SPREAD_DISABLED : LINK_SPREAD_05_DOWNSPREAD_30KHZ; lt_settings->eq_pattern_time = get_eq_training_aux_rd_interval(link, link_setting); lt_settings->pattern_for_cr = decide_cr_training_pattern(link_setting); - lt_settings->pattern_for_eq = decide_eq_training_pattern(link, link_setting); + lt_settings->pattern_for_eq = decide_eq_training_pattern(link, link_res, link_setting); lt_settings->enhanced_framing = 1; lt_settings->should_set_fec_ready = true; lt_settings->disallow_per_lane_settings = true; diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.h index d26de15ce954..ea0de701d83f 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.h +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.h @@ -54,7 +54,8 @@ enum link_training_result perform_8b_10b_channel_equalization_sequence( enum lttpr_mode dp_decide_8b_10b_lttpr_mode(struct dc_link *link); void decide_8b_10b_training_settings( - struct dc_link *link, + struct dc_link *link, + const struct link_resource *link_res, const struct dc_link_settings *link_setting, struct link_training_settings *lt_settings); diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_auxless.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_auxless.c index 4c6b886a9da8..f99d26290bc0 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_auxless.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_auxless.c @@ -39,6 +39,7 @@ bool dp_perform_link_training_skip_aux( dp_decide_training_settings( link, + link_res, link_setting, <_settings); override_training_settings( diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c index 39e4b7dc9588..6e2d08cfc546 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c @@ -110,6 +110,7 @@ static enum link_training_result dpia_configure_link( dp_decide_training_settings( link, + link_res, link_setting, lt_settings); diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c index 5c6dc710e96c..e4eca3e32c1b 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c @@ -1220,7 +1220,7 @@ static void get_pixel_clock_parameters( struct pipe_ctx *odm_pipe; int opp_cnt = 1; struct dc_link *link = stream->link; - struct link_encoder *link_enc = NULL; + struct link_encoder *link_enc = pipe_ctx->link_res.dio_link_enc; struct dc *dc = pipe_ctx->stream->ctx->dc; struct dce_hwseq *hws = dc->hwseq; @@ -1229,7 +1229,8 @@ static void get_pixel_clock_parameters( pixel_clk_params->requested_pix_clk_100hz = stream->timing.pix_clk_100hz; - link_enc = link_enc_cfg_get_link_enc(link); + if (!dc->config.unify_link_enc_assignment) + link_enc = link_enc_cfg_get_link_enc(link); if (link_enc) pixel_clk_params->encoder_object_id = link_enc->id; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c index 4e842f29d4c4..7436dfbdf927 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c @@ -1666,12 +1666,13 @@ static void dcn401_build_pipe_pix_clk_params(struct pipe_ctx *pipe_ctx) { const struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->link; - struct link_encoder *link_enc = NULL; + struct link_encoder *link_enc = pipe_ctx->link_res.dio_link_enc; struct pixel_clk_params *pixel_clk_params = &pipe_ctx->stream_res.pix_clk_params; pixel_clk_params->requested_pix_clk_100hz = stream->timing.pix_clk_100hz; - link_enc = link_enc_cfg_get_link_enc(link); + if (!pipe_ctx->stream->ctx->dc->config.unify_link_enc_assignment) + link_enc = link_enc_cfg_get_link_enc(link); if (link_enc) pixel_clk_params->encoder_object_id = link_enc->id; From f6d17270d18a6a6753fff046330483d43f8405e4 Mon Sep 17 00:00:00 2001 From: Yilin Chen Date: Fri, 7 Feb 2025 15:26:19 -0500 Subject: [PATCH 049/235] drm/amd/display: add a quirk to enable eDP0 on DP1 [why] some board designs have eDP0 connected to DP1, need a way to enable support_edp0_on_dp1 flag, otherwise edp related features cannot work [how] do a dmi check during dm initialization to identify systems that require support_edp0_on_dp1. Optimize quirk table with callback functions to set quirk entries, retrieve_dmi_info can set quirks according to quirk entries Cc: Mario Limonciello Reviewed-by: Mario Limonciello Reviewed-by: Nicholas Kazlauskas Signed-off-by: Yilin Chen Signed-off-by: Zaeem Mohamed Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 69 +++++++++++++++++-- 1 file changed, 62 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index e3df652bb74e..b27fa9738cac 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1625,75 +1625,130 @@ static bool dm_should_disable_stutter(struct pci_dev *pdev) return false; } -static const struct dmi_system_id hpd_disconnect_quirk_table[] = { +struct amdgpu_dm_quirks { + bool aux_hpd_discon; + bool support_edp0_on_dp1; +}; + +static struct amdgpu_dm_quirks quirk_entries = { + .aux_hpd_discon = false, + .support_edp0_on_dp1 = false +}; + +static int edp0_on_dp1_callback(const struct dmi_system_id *id) +{ + quirk_entries.support_edp0_on_dp1 = true; + return 0; +} + +static int aux_hpd_discon_callback(const struct dmi_system_id *id) +{ + quirk_entries.aux_hpd_discon = true; + return 0; +} + +static const struct dmi_system_id dmi_quirk_table[] = { { + .callback = aux_hpd_discon_callback, .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "Precision 3660"), }, }, { + .callback = aux_hpd_discon_callback, .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "Precision 3260"), }, }, { + .callback = aux_hpd_discon_callback, .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "Precision 3460"), }, }, { + .callback = aux_hpd_discon_callback, .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex Tower Plus 7010"), }, }, { + .callback = aux_hpd_discon_callback, .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex Tower 7010"), }, }, { + .callback = aux_hpd_discon_callback, .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex SFF Plus 7010"), }, }, { + .callback = aux_hpd_discon_callback, .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex SFF 7010"), }, }, { + .callback = aux_hpd_discon_callback, .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex Micro Plus 7010"), }, }, { + .callback = aux_hpd_discon_callback, .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex Micro 7010"), }, }, + { + .callback = edp0_on_dp1_callback, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Elite mt645 G8 Mobile Thin Client"), + }, + }, + { + .callback = edp0_on_dp1_callback, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook 665 16 inch G11 Notebook PC"), + }, + }, {} /* TODO: refactor this from a fixed table to a dynamic option */ }; -static void retrieve_dmi_info(struct amdgpu_display_manager *dm) +static void retrieve_dmi_info(struct amdgpu_display_manager *dm, struct dc_init_data *init_data) { - const struct dmi_system_id *dmi_id; + int dmi_id; + struct drm_device *dev = dm->ddev; dm->aux_hpd_discon_quirk = false; + init_data->flags.support_edp0_on_dp1 = false; - dmi_id = dmi_first_match(hpd_disconnect_quirk_table); - if (dmi_id) { + dmi_id = dmi_check_system(dmi_quirk_table); + + if (!dmi_id) + return; + + if (quirk_entries.aux_hpd_discon) { dm->aux_hpd_discon_quirk = true; - DRM_INFO("aux_hpd_discon_quirk attached\n"); + drm_info(dev, "aux_hpd_discon_quirk attached\n"); + } + if (quirk_entries.support_edp0_on_dp1) { + init_data->flags.support_edp0_on_dp1 = true; + drm_info(dev, "aux_hpd_discon_quirk attached\n"); } } @@ -2002,7 +2057,7 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) if (amdgpu_ip_version(adev, DCE_HWIP, 0) >= IP_VERSION(3, 0, 0)) init_data.num_virtual_links = 1; - retrieve_dmi_info(&adev->dm); + retrieve_dmi_info(&adev->dm, &init_data); if (adev->dm.bb_from_dmub) init_data.bb_from_dmub = adev->dm.bb_from_dmub; From 02a2793ab27e3aa3f345f4e7761005e5c9e3ebd4 Mon Sep 17 00:00:00 2001 From: "Patel, Swapnil" Date: Sun, 9 Feb 2025 11:42:23 -0500 Subject: [PATCH 050/235] drm/amd/display: Refactor DCN4x and related code [why & how] Refactor existing code related to DCN4x for better code sharing with other modules. Reviewed-by: Charlene Liu Signed-off-by: Swapnil Patel Signed-off-by: Zaeem Mohamed Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../amd/display/dc/dccg/dcn20/dcn20_dccg.h | 94 ++++---- .../amd/display/dc/dccg/dcn401/dcn401_dccg.c | 2 +- .../amd/display/dc/dccg/dcn401/dcn401_dccg.h | 5 +- .../dc/dio/dcn401/dcn401_dio_stream_encoder.c | 2 +- .../dc/dio/dcn401/dcn401_dio_stream_encoder.h | 5 + .../drm/amd/display/dc/dml2/dml2_wrapper.c | 3 +- .../amd/display/dc/dpp/dcn401/dcn401_dpp.h | 148 ++++++------ .../dc/hpo/dcn31/dcn31_hpo_dp_link_encoder.c | 10 +- .../dc/hpo/dcn31/dcn31_hpo_dp_link_encoder.h | 6 + .../dc/hpo/dcn32/dcn32_hpo_dp_link_encoder.h | 3 + .../drm/amd/display/dc/hwss/dce/dce_hwseq.h | 1 + .../amd/display/dc/mpc/dcn401/dcn401_mpc.h | 31 ++- .../amd/display/dc/optc/dcn10/dcn10_optc.h | 221 +++++++++--------- 13 files changed, 282 insertions(+), 249 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn20/dcn20_dccg.h b/drivers/gpu/drm/amd/display/dc/dccg/dcn20/dcn20_dccg.h index 160c299419b7..a9b88f5e0c04 100644 --- a/drivers/gpu/drm/amd/display/dc/dccg/dcn20/dcn20_dccg.h +++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn20/dcn20_dccg.h @@ -379,53 +379,55 @@ struct dccg_mask { DCCG401_REG_FIELD_LIST(uint32_t) }; +#define DCCG_REG_VARIABLE_LIST \ + uint32_t DPPCLK_DTO_CTRL; \ + uint32_t DPPCLK_DTO_PARAM[6]; \ + uint32_t REFCLK_CNTL; \ + uint32_t DISPCLK_FREQ_CHANGE_CNTL; \ + uint32_t OTG_PIXEL_RATE_CNTL[MAX_PIPES]; \ + uint32_t HDMICHARCLK_CLOCK_CNTL[6]; \ + uint32_t PHYASYMCLK_CLOCK_CNTL; \ + uint32_t PHYBSYMCLK_CLOCK_CNTL; \ + uint32_t PHYCSYMCLK_CLOCK_CNTL; \ + uint32_t PHYDSYMCLK_CLOCK_CNTL; \ + uint32_t PHYESYMCLK_CLOCK_CNTL; \ + uint32_t DTBCLK_DTO_MODULO[MAX_PIPES]; \ + uint32_t DTBCLK_DTO_PHASE[MAX_PIPES]; \ + uint32_t DCCG_AUDIO_DTBCLK_DTO_MODULO; \ + uint32_t DCCG_AUDIO_DTBCLK_DTO_PHASE; \ + uint32_t DCCG_AUDIO_DTO_SOURCE; \ + uint32_t DPSTREAMCLK_CNTL; \ + uint32_t HDMISTREAMCLK_CNTL; \ + uint32_t SYMCLK32_SE_CNTL; \ + uint32_t SYMCLK32_LE_CNTL; \ + uint32_t DENTIST_DISPCLK_CNTL; \ + uint32_t DSCCLK_DTO_CTRL; \ + uint32_t DSCCLK0_DTO_PARAM; \ + uint32_t DSCCLK1_DTO_PARAM; \ + uint32_t DSCCLK2_DTO_PARAM; \ + uint32_t DSCCLK3_DTO_PARAM; \ + uint32_t DPSTREAMCLK_ROOT_GATE_DISABLE; \ + uint32_t DPSTREAMCLK_GATE_DISABLE; \ + uint32_t DCCG_GATE_DISABLE_CNTL; \ + uint32_t DCCG_GATE_DISABLE_CNTL2; \ + uint32_t DCCG_GATE_DISABLE_CNTL3; \ + uint32_t HDMISTREAMCLK0_DTO_PARAM; \ + uint32_t DCCG_GATE_DISABLE_CNTL4; \ + uint32_t OTG_PIXEL_RATE_DIV; \ + uint32_t DTBCLK_P_CNTL; \ + uint32_t DPPCLK_CTRL; \ + uint32_t DCCG_GATE_DISABLE_CNTL5; \ + uint32_t DCCG_GATE_DISABLE_CNTL6; \ + uint32_t DCCG_GLOBAL_FGCG_REP_CNTL; \ + uint32_t SYMCLKA_CLOCK_ENABLE; \ + uint32_t SYMCLKB_CLOCK_ENABLE; \ + uint32_t SYMCLKC_CLOCK_ENABLE; \ + uint32_t SYMCLKD_CLOCK_ENABLE; \ + uint32_t SYMCLKE_CLOCK_ENABLE; \ + uint32_t DP_DTO_MODULO[MAX_PIPES]; \ + uint32_t DP_DTO_PHASE[MAX_PIPES] struct dccg_registers { - uint32_t DPPCLK_DTO_CTRL; - uint32_t DPPCLK_DTO_PARAM[6]; - uint32_t REFCLK_CNTL; - uint32_t DISPCLK_FREQ_CHANGE_CNTL; - uint32_t OTG_PIXEL_RATE_CNTL[MAX_PIPES]; - uint32_t HDMICHARCLK_CLOCK_CNTL[6]; - uint32_t PHYASYMCLK_CLOCK_CNTL; - uint32_t PHYBSYMCLK_CLOCK_CNTL; - uint32_t PHYCSYMCLK_CLOCK_CNTL; - uint32_t PHYDSYMCLK_CLOCK_CNTL; - uint32_t PHYESYMCLK_CLOCK_CNTL; - uint32_t DTBCLK_DTO_MODULO[MAX_PIPES]; - uint32_t DTBCLK_DTO_PHASE[MAX_PIPES]; - uint32_t DCCG_AUDIO_DTBCLK_DTO_MODULO; - uint32_t DCCG_AUDIO_DTBCLK_DTO_PHASE; - uint32_t DCCG_AUDIO_DTO_SOURCE; - uint32_t DPSTREAMCLK_CNTL; - uint32_t HDMISTREAMCLK_CNTL; - uint32_t SYMCLK32_SE_CNTL; - uint32_t SYMCLK32_LE_CNTL; - uint32_t DENTIST_DISPCLK_CNTL; - uint32_t DSCCLK_DTO_CTRL; - uint32_t DSCCLK0_DTO_PARAM; - uint32_t DSCCLK1_DTO_PARAM; - uint32_t DSCCLK2_DTO_PARAM; - uint32_t DSCCLK3_DTO_PARAM; - uint32_t DPSTREAMCLK_ROOT_GATE_DISABLE; - uint32_t DPSTREAMCLK_GATE_DISABLE; - uint32_t DCCG_GATE_DISABLE_CNTL; - uint32_t DCCG_GATE_DISABLE_CNTL2; - uint32_t DCCG_GATE_DISABLE_CNTL3; - uint32_t HDMISTREAMCLK0_DTO_PARAM; - uint32_t DCCG_GATE_DISABLE_CNTL4; - uint32_t OTG_PIXEL_RATE_DIV; - uint32_t DTBCLK_P_CNTL; - uint32_t DPPCLK_CTRL; - uint32_t DCCG_GATE_DISABLE_CNTL5; - uint32_t DCCG_GATE_DISABLE_CNTL6; - uint32_t DCCG_GLOBAL_FGCG_REP_CNTL; - uint32_t SYMCLKA_CLOCK_ENABLE; - uint32_t SYMCLKB_CLOCK_ENABLE; - uint32_t SYMCLKC_CLOCK_ENABLE; - uint32_t SYMCLKD_CLOCK_ENABLE; - uint32_t SYMCLKE_CLOCK_ENABLE; - uint32_t DP_DTO_MODULO[MAX_PIPES]; - uint32_t DP_DTO_PHASE[MAX_PIPES]; + DCCG_REG_VARIABLE_LIST; }; struct dcn_dccg { diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c index 332094ad2b05..ffd172231fdf 100644 --- a/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c +++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c @@ -531,7 +531,7 @@ static void dccg401_enable_dpstreamclk(struct dccg *dccg, int otg_inst, int dp_h DPSTREAMCLK_ROOT_GATE_DISABLE, 1); } -static void dccg401_disable_dpstreamclk(struct dccg *dccg, int dp_hpo_inst) +void dccg401_disable_dpstreamclk(struct dccg *dccg, int dp_hpo_inst) { struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.h b/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.h index b9905c73e754..55e8718aad22 100644 --- a/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.h +++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.h @@ -208,6 +208,8 @@ void dccg401_enable_symclk32_le( void dccg401_disable_symclk32_le( struct dccg *dccg, int hpo_le_inst); +void dccg401_disable_dpstreamclk(struct dccg *dccg, int dp_hpo_inst); +void dccg401_set_dto_dscclk(struct dccg *dccg, uint32_t inst); void dccg401_set_ref_dscclk(struct dccg *dccg, uint32_t dsc_inst); void dccg401_set_src_sel( @@ -228,14 +230,11 @@ void dccg401_set_dp_dto( const struct dp_dto_params *params); void dccg401_enable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, uint32_t link_enc_inst); void dccg401_disable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, uint32_t link_enc_inst); - void dccg401_set_dto_dscclk(struct dccg *dccg, uint32_t inst); void dccg401_set_dtbclk_p_src( struct dccg *dccg, enum streamclk_source src, uint32_t otg_inst); - - struct dccg *dccg401_create( struct dc_context *ctx, const struct dccg_registers *regs, diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c index 4bab180e1938..d5fa551dd3c9 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c @@ -100,7 +100,7 @@ void enc401_stream_encoder_dvi_set_stream_attribute( } /* setup stream encoder in hdmi mode */ -static void enc401_stream_encoder_hdmi_set_stream_attribute( +void enc401_stream_encoder_hdmi_set_stream_attribute( struct stream_encoder *enc, struct dc_crtc_timing *crtc_timing, int actual_pix_clk_khz, diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.h index 25cc8f72d8d3..d6b00cd246b1 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.h @@ -232,4 +232,9 @@ void enc401_stream_encoder_map_to_link( uint32_t stream_enc_inst, uint32_t link_enc_inst); void enc401_read_state(struct stream_encoder *enc, struct enc_state *s); +void enc401_stream_encoder_hdmi_set_stream_attribute( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + int actual_pix_clk_khz, + bool enable_audio); #endif /* __DC_DIO_STREAM_ENCODER_DCN401_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c index 45584e2f5dfe..939ee0708bd2 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c @@ -33,7 +33,6 @@ #include "dml2_dc_resource_mgmt.h" #include "dml21_wrapper.h" - static void initialize_dml2_ip_params(struct dml2_context *dml2, const struct dc *in_dc, struct ip_params_st *out) { if (dml2->config.use_native_soc_bb_construction) @@ -792,7 +791,7 @@ bool dml2_create(const struct dc *in_dc, const struct dml2_configuration_options // TODO : Temporarily add DCN_VERSION_3_2 for N-1 validation. Remove DCN_VERSION_3_2 after N-1 validation phase is complete. if ((in_dc->debug.using_dml21) && (in_dc->ctx->dce_version == DCN_VERSION_4_01 - )) + )) return dml21_create(in_dc, dml2, config); // Allocate Mode Lib Ctx diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.h b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.h index 4bc85aaf17da..ecaa976e1f52 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.h @@ -567,80 +567,82 @@ type ISHARP_NLDELTA_SCLIP_PIVOT_N; \ type ISHARP_NLDELTA_SCLIP_SLOPE_N +#define DPP_REG_VARIABLE_LIST_DCN401 \ + DPP_DCN3_REG_VARIABLE_LIST_COMMON; \ + uint32_t CURSOR0_FP_SCALE_BIAS_G_Y; \ + uint32_t CURSOR0_FP_SCALE_BIAS_RB_CRCB; \ + uint32_t CUR0_MATRIX_MODE; \ + uint32_t CUR0_MATRIX_C11_C12_A; \ + uint32_t CUR0_MATRIX_C13_C14_A; \ + uint32_t CUR0_MATRIX_C21_C22_A; \ + uint32_t CUR0_MATRIX_C23_C24_A; \ + uint32_t CUR0_MATRIX_C31_C32_A; \ + uint32_t CUR0_MATRIX_C33_C34_A; \ + uint32_t CUR0_MATRIX_C11_C12_B; \ + uint32_t CUR0_MATRIX_C13_C14_B; \ + uint32_t CUR0_MATRIX_C21_C22_B; \ + uint32_t CUR0_MATRIX_C23_C24_B; \ + uint32_t CUR0_MATRIX_C31_C32_B; \ + uint32_t CUR0_MATRIX_C33_C34_B; \ + uint32_t DSCL_SC_MODE; \ + uint32_t DSCL_EASF_H_MODE; \ + uint32_t DSCL_EASF_H_BF_CNTL; \ + uint32_t DSCL_EASF_H_RINGEST_EVENTAP_REDUCE; \ + uint32_t DSCL_EASF_H_RINGEST_EVENTAP_GAIN; \ + uint32_t DSCL_EASF_H_BF_FINAL_MAX_MIN; \ + uint32_t DSCL_EASF_H_BF1_PWL_SEG0; \ + uint32_t DSCL_EASF_H_BF1_PWL_SEG1; \ + uint32_t DSCL_EASF_H_BF1_PWL_SEG2; \ + uint32_t DSCL_EASF_H_BF1_PWL_SEG3; \ + uint32_t DSCL_EASF_H_BF1_PWL_SEG4; \ + uint32_t DSCL_EASF_H_BF1_PWL_SEG5; \ + uint32_t DSCL_EASF_H_BF1_PWL_SEG6; \ + uint32_t DSCL_EASF_H_BF1_PWL_SEG7; \ + uint32_t DSCL_EASF_H_BF3_PWL_SEG0; \ + uint32_t DSCL_EASF_H_BF3_PWL_SEG1; \ + uint32_t DSCL_EASF_H_BF3_PWL_SEG2; \ + uint32_t DSCL_EASF_H_BF3_PWL_SEG3; \ + uint32_t DSCL_EASF_H_BF3_PWL_SEG4; \ + uint32_t DSCL_EASF_H_BF3_PWL_SEG5; \ + uint32_t DSCL_EASF_V_MODE; \ + uint32_t DSCL_EASF_V_BF_CNTL; \ + uint32_t DSCL_EASF_V_RINGEST_3TAP_CNTL1; \ + uint32_t DSCL_EASF_V_RINGEST_3TAP_CNTL2; \ + uint32_t DSCL_EASF_V_RINGEST_3TAP_CNTL3; \ + uint32_t DSCL_EASF_V_RINGEST_EVENTAP_REDUCE; \ + uint32_t DSCL_EASF_V_RINGEST_EVENTAP_GAIN; \ + uint32_t DSCL_EASF_V_BF_FINAL_MAX_MIN; \ + uint32_t DSCL_EASF_V_BF1_PWL_SEG0; \ + uint32_t DSCL_EASF_V_BF1_PWL_SEG1; \ + uint32_t DSCL_EASF_V_BF1_PWL_SEG2; \ + uint32_t DSCL_EASF_V_BF1_PWL_SEG3; \ + uint32_t DSCL_EASF_V_BF1_PWL_SEG4; \ + uint32_t DSCL_EASF_V_BF1_PWL_SEG5; \ + uint32_t DSCL_EASF_V_BF1_PWL_SEG6; \ + uint32_t DSCL_EASF_V_BF1_PWL_SEG7; \ + uint32_t DSCL_EASF_V_BF3_PWL_SEG0; \ + uint32_t DSCL_EASF_V_BF3_PWL_SEG1; \ + uint32_t DSCL_EASF_V_BF3_PWL_SEG2; \ + uint32_t DSCL_EASF_V_BF3_PWL_SEG3; \ + uint32_t DSCL_EASF_V_BF3_PWL_SEG4; \ + uint32_t DSCL_EASF_V_BF3_PWL_SEG5; \ + uint32_t DSCL_SC_MATRIX_C0C1; \ + uint32_t DSCL_SC_MATRIX_C2C3; \ + uint32_t ISHARP_MODE; \ + uint32_t ISHARP_NOISEDET_THRESHOLD; \ + uint32_t ISHARP_NOISE_GAIN_PWL; \ + uint32_t ISHARP_LBA_PWL_SEG0; \ + uint32_t ISHARP_LBA_PWL_SEG1; \ + uint32_t ISHARP_LBA_PWL_SEG2; \ + uint32_t ISHARP_LBA_PWL_SEG3; \ + uint32_t ISHARP_LBA_PWL_SEG4; \ + uint32_t ISHARP_LBA_PWL_SEG5; \ + uint32_t ISHARP_DELTA_CTRL; \ + uint32_t ISHARP_DELTA_DATA; \ + uint32_t ISHARP_DELTA_INDEX; \ + uint32_t ISHARP_NLDELTA_SOFT_CLIP struct dcn401_dpp_registers { - DPP_DCN3_REG_VARIABLE_LIST_COMMON; - uint32_t CURSOR0_FP_SCALE_BIAS_G_Y; - uint32_t CURSOR0_FP_SCALE_BIAS_RB_CRCB; - uint32_t CUR0_MATRIX_MODE; - uint32_t CUR0_MATRIX_C11_C12_A; - uint32_t CUR0_MATRIX_C13_C14_A; - uint32_t CUR0_MATRIX_C21_C22_A; - uint32_t CUR0_MATRIX_C23_C24_A; - uint32_t CUR0_MATRIX_C31_C32_A; - uint32_t CUR0_MATRIX_C33_C34_A; - uint32_t CUR0_MATRIX_C11_C12_B; - uint32_t CUR0_MATRIX_C13_C14_B; - uint32_t CUR0_MATRIX_C21_C22_B; - uint32_t CUR0_MATRIX_C23_C24_B; - uint32_t CUR0_MATRIX_C31_C32_B; - uint32_t CUR0_MATRIX_C33_C34_B; - uint32_t DSCL_SC_MODE; - uint32_t DSCL_EASF_H_MODE; - uint32_t DSCL_EASF_H_BF_CNTL; - uint32_t DSCL_EASF_H_RINGEST_EVENTAP_REDUCE; - uint32_t DSCL_EASF_H_RINGEST_EVENTAP_GAIN; - uint32_t DSCL_EASF_H_BF_FINAL_MAX_MIN; - uint32_t DSCL_EASF_H_BF1_PWL_SEG0; - uint32_t DSCL_EASF_H_BF1_PWL_SEG1; - uint32_t DSCL_EASF_H_BF1_PWL_SEG2; - uint32_t DSCL_EASF_H_BF1_PWL_SEG3; - uint32_t DSCL_EASF_H_BF1_PWL_SEG4; - uint32_t DSCL_EASF_H_BF1_PWL_SEG5; - uint32_t DSCL_EASF_H_BF1_PWL_SEG6; - uint32_t DSCL_EASF_H_BF1_PWL_SEG7; - uint32_t DSCL_EASF_H_BF3_PWL_SEG0; - uint32_t DSCL_EASF_H_BF3_PWL_SEG1; - uint32_t DSCL_EASF_H_BF3_PWL_SEG2; - uint32_t DSCL_EASF_H_BF3_PWL_SEG3; - uint32_t DSCL_EASF_H_BF3_PWL_SEG4; - uint32_t DSCL_EASF_H_BF3_PWL_SEG5; - uint32_t DSCL_EASF_V_MODE; - uint32_t DSCL_EASF_V_BF_CNTL; - uint32_t DSCL_EASF_V_RINGEST_3TAP_CNTL1; - uint32_t DSCL_EASF_V_RINGEST_3TAP_CNTL2; - uint32_t DSCL_EASF_V_RINGEST_3TAP_CNTL3; - uint32_t DSCL_EASF_V_RINGEST_EVENTAP_REDUCE; - uint32_t DSCL_EASF_V_RINGEST_EVENTAP_GAIN; - uint32_t DSCL_EASF_V_BF_FINAL_MAX_MIN; - uint32_t DSCL_EASF_V_BF1_PWL_SEG0; - uint32_t DSCL_EASF_V_BF1_PWL_SEG1; - uint32_t DSCL_EASF_V_BF1_PWL_SEG2; - uint32_t DSCL_EASF_V_BF1_PWL_SEG3; - uint32_t DSCL_EASF_V_BF1_PWL_SEG4; - uint32_t DSCL_EASF_V_BF1_PWL_SEG5; - uint32_t DSCL_EASF_V_BF1_PWL_SEG6; - uint32_t DSCL_EASF_V_BF1_PWL_SEG7; - uint32_t DSCL_EASF_V_BF3_PWL_SEG0; - uint32_t DSCL_EASF_V_BF3_PWL_SEG1; - uint32_t DSCL_EASF_V_BF3_PWL_SEG2; - uint32_t DSCL_EASF_V_BF3_PWL_SEG3; - uint32_t DSCL_EASF_V_BF3_PWL_SEG4; - uint32_t DSCL_EASF_V_BF3_PWL_SEG5; - uint32_t DSCL_SC_MATRIX_C0C1; - uint32_t DSCL_SC_MATRIX_C2C3; - uint32_t ISHARP_MODE; - uint32_t ISHARP_NOISEDET_THRESHOLD; - uint32_t ISHARP_NOISE_GAIN_PWL; - uint32_t ISHARP_LBA_PWL_SEG0; - uint32_t ISHARP_LBA_PWL_SEG1; - uint32_t ISHARP_LBA_PWL_SEG2; - uint32_t ISHARP_LBA_PWL_SEG3; - uint32_t ISHARP_LBA_PWL_SEG4; - uint32_t ISHARP_LBA_PWL_SEG5; - uint32_t ISHARP_DELTA_CTRL; - uint32_t ISHARP_DELTA_DATA; - uint32_t ISHARP_DELTA_INDEX; - uint32_t ISHARP_NLDELTA_SOFT_CLIP; + DPP_REG_VARIABLE_LIST_DCN401; }; struct dcn401_dpp_shift { diff --git a/drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_link_encoder.c b/drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_link_encoder.c index 03b4ac2f1991..0d2ae21abbdd 100644 --- a/drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_link_encoder.c @@ -262,7 +262,7 @@ void dcn31_hpo_dp_link_enc_set_link_test_pattern( } } -static void fill_stream_allocation_row_info( +void dcn31_fill_stream_allocation_row_info( const struct link_mst_stream_allocation *stream_allocation, uint32_t *src, uint32_t *slots) @@ -296,7 +296,7 @@ void dcn31_hpo_dp_link_enc_update_stream_allocation_table( /* we should clean-up table each time */ if (table->stream_count >= 1) { - fill_stream_allocation_row_info( + dcn31_fill_stream_allocation_row_info( &table->stream_allocations[0], &src, &slots); @@ -310,7 +310,7 @@ void dcn31_hpo_dp_link_enc_update_stream_allocation_table( SAT_SLOT_COUNT, slots); if (table->stream_count >= 2) { - fill_stream_allocation_row_info( + dcn31_fill_stream_allocation_row_info( &table->stream_allocations[1], &src, &slots); @@ -324,7 +324,7 @@ void dcn31_hpo_dp_link_enc_update_stream_allocation_table( SAT_SLOT_COUNT, slots); if (table->stream_count >= 3) { - fill_stream_allocation_row_info( + dcn31_fill_stream_allocation_row_info( &table->stream_allocations[2], &src, &slots); @@ -338,7 +338,7 @@ void dcn31_hpo_dp_link_enc_update_stream_allocation_table( SAT_SLOT_COUNT, slots); if (table->stream_count >= 4) { - fill_stream_allocation_row_info( + dcn31_fill_stream_allocation_row_info( &table->stream_allocations[3], &src, &slots); diff --git a/drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_link_encoder.h b/drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_link_encoder.h index 51f5781325e8..40859660e4dc 100644 --- a/drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_link_encoder.h @@ -226,4 +226,10 @@ void dcn31_hpo_dp_link_enc_set_ffe( const struct dc_link_settings *link_settings, uint8_t ffe_preset); + +void dcn31_fill_stream_allocation_row_info( + const struct link_mst_stream_allocation *stream_allocation, + uint32_t *src, + uint32_t *slots); + #endif // __DAL_DCN31_HPO_LINK_ENCODER_H__ diff --git a/drivers/gpu/drm/amd/display/dc/hpo/dcn32/dcn32_hpo_dp_link_encoder.h b/drivers/gpu/drm/amd/display/dc/hpo/dcn32/dcn32_hpo_dp_link_encoder.h index 48ef3d29b370..bea4e1a8ff90 100644 --- a/drivers/gpu/drm/amd/display/dc/hpo/dcn32/dcn32_hpo_dp_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/hpo/dcn32/dcn32_hpo_dp_link_encoder.h @@ -62,4 +62,7 @@ void hpo_dp_link_encoder32_construct(struct dcn31_hpo_dp_link_encoder *enc31, const struct dcn31_hpo_dp_link_encoder_shift *hpo_le_shift, const struct dcn31_hpo_dp_link_encoder_mask *hpo_le_mask); +bool dcn32_hpo_dp_link_enc_is_in_alt_mode( + struct hpo_dp_link_encoder *enc); + #endif // __DAL_DCN32_HPO_DP_LINK_ENCODER_H__ diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dce/dce_hwseq.h index 09049aa3c4f3..f66a38f43a09 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/hwss/dce/dce_hwseq.h @@ -1244,6 +1244,7 @@ struct dce_hwseq_registers { type DOMAIN24_PGFSM_PWR_STATUS; \ type DOMAIN25_PGFSM_PWR_STATUS; \ type DOMAIN_DESIRED_PWR_STATE; + struct dce_hwseq_shift { HWSEQ_REG_FIELD_LIST(uint8_t) HWSEQ_DCN_REG_FIELD_LIST(uint8_t) diff --git a/drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.h b/drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.h index 9267cdf88e9a..ce6fbcf14d7a 100644 --- a/drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.h +++ b/drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.h @@ -63,8 +63,7 @@ uint32_t MPC_MCM_SECOND_GAMUT_REMAP_C31_C32_B[MAX_MPCC]; \ uint32_t MPC_MCM_SECOND_GAMUT_REMAP_C33_C34_B[MAX_MPCC]; \ uint32_t MPCC_MCM_3DLUT_FAST_LOAD_SELECT[MAX_MPCC]; \ - uint32_t MPCC_MCM_3DLUT_FAST_LOAD_STATUS[MAX_MPCC]; \ - uint32_t MPCC_CONTROL2[MAX_MPCC] + uint32_t MPCC_MCM_3DLUT_FAST_LOAD_STATUS[MAX_MPCC]; #define MPC_COMMON_MASK_SH_LIST_DCN4_01(mask_sh) \ MPC_COMMON_MASK_SH_LIST_DCN32(mask_sh), \ @@ -184,7 +183,7 @@ struct dcn401_mpc_mask { }; struct dcn401_mpc_registers { - MPC_REG_VARIABLE_LIST_DCN4_01; + MPC_REG_VARIABLE_LIST_DCN4_01 }; struct dcn401_mpc { @@ -236,7 +235,29 @@ void mpc401_get_gamut_remap( struct mpc *mpc, int mpcc_id, struct mpc_grph_gamut_adjustment *adjust); -void mpc401_update_3dlut_fast_load_select(struct mpc *mpc, int mpcc_id, int hubp_idx); -void mpc401_get_3dlut_fast_load_status(struct mpc *mpc, int mpcc_id, uint32_t *done, uint32_t *soft_underflow, uint32_t *hard_underflow); + +void mpc401_update_3dlut_fast_load_select( + struct mpc *mpc, + int mpcc_id, + int hubp_idx); + +void mpc401_get_3dlut_fast_load_status( + struct mpc *mpc, + int mpcc_id, + uint32_t *done, + uint32_t *soft_underflow, + uint32_t *hard_underflow); + +void mpc401_update_3dlut_fast_load_select( + struct mpc *mpc, + int mpcc_id, + int hubp_idx); + +void mpc401_get_3dlut_fast_load_status( + struct mpc *mpc, + int mpcc_id, + uint32_t *done, + uint32_t *soft_underflow, + uint32_t *hard_underflow); #endif diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h b/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h index a6d4dbe82c13..8b2a8455eb56 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h @@ -104,120 +104,115 @@ SRI(OTG_MANUAL_FLOW_CONTROL, OTG, inst) +#define OPTC_REG_VARIABLE_LIST_DCN \ + uint32_t OTG_GLOBAL_CONTROL1; \ + uint32_t OTG_GLOBAL_CONTROL2; \ + uint32_t OTG_VERT_SYNC_CONTROL; \ + uint32_t OTG_MASTER_UPDATE_MODE; \ + uint32_t OTG_GSL_CONTROL; \ + uint32_t OTG_VSTARTUP_PARAM; \ + uint32_t OTG_VUPDATE_PARAM; \ + uint32_t OTG_VREADY_PARAM; \ + uint32_t OTG_BLANK_CONTROL; \ + uint32_t OTG_MASTER_UPDATE_LOCK; \ + uint32_t OTG_GLOBAL_CONTROL0; \ + uint32_t OTG_DOUBLE_BUFFER_CONTROL; \ + uint32_t OTG_H_TOTAL; \ + uint32_t OTG_H_BLANK_START_END; \ + uint32_t OTG_H_SYNC_A; \ + uint32_t OTG_H_SYNC_A_CNTL; \ + uint32_t OTG_H_TIMING_CNTL; \ + uint32_t OTG_V_TOTAL; \ + uint32_t OTG_V_BLANK_START_END; \ + uint32_t OTG_V_SYNC_A; \ + uint32_t OTG_V_SYNC_A_CNTL; \ + uint32_t OTG_INTERLACE_CONTROL; \ + uint32_t OTG_CONTROL; \ + uint32_t OTG_STEREO_CONTROL; \ + uint32_t OTG_3D_STRUCTURE_CONTROL; \ + uint32_t OTG_STEREO_STATUS; \ + uint32_t OTG_V_TOTAL_MAX; \ + uint32_t OTG_V_TOTAL_MID; \ + uint32_t OTG_V_TOTAL_MIN; \ + uint32_t OTG_V_TOTAL_CONTROL; \ + uint32_t OTG_V_COUNT_STOP_CONTROL; \ + uint32_t OTG_V_COUNT_STOP_CONTROL2; \ + uint32_t OTG_TRIGA_CNTL; \ + uint32_t OTG_TRIGA_MANUAL_TRIG; \ + uint32_t OTG_MANUAL_FLOW_CONTROL; \ + uint32_t OTG_FORCE_COUNT_NOW_CNTL; \ + uint32_t OTG_STATIC_SCREEN_CONTROL; \ + uint32_t OTG_STATUS_FRAME_COUNT; \ + uint32_t OTG_STATUS; \ + uint32_t OTG_STATUS_POSITION; \ + uint32_t OTG_NOM_VERT_POSITION; \ + uint32_t OTG_BLACK_COLOR; \ + uint32_t OTG_TEST_PATTERN_PARAMETERS; \ + uint32_t OTG_TEST_PATTERN_CONTROL; \ + uint32_t OTG_TEST_PATTERN_COLOR; \ + uint32_t OTG_CLOCK_CONTROL; \ + uint32_t OTG_VERTICAL_INTERRUPT0_CONTROL; \ + uint32_t OTG_VERTICAL_INTERRUPT0_POSITION; \ + uint32_t OTG_VERTICAL_INTERRUPT1_CONTROL; \ + uint32_t OTG_VERTICAL_INTERRUPT1_POSITION; \ + uint32_t OTG_VERTICAL_INTERRUPT2_CONTROL; \ + uint32_t OTG_VERTICAL_INTERRUPT2_POSITION; \ + uint32_t OPTC_INPUT_CLOCK_CONTROL; \ + uint32_t OPTC_DATA_SOURCE_SELECT; \ + uint32_t OPTC_MEMORY_CONFIG; \ + uint32_t OPTC_INPUT_GLOBAL_CONTROL; \ + uint32_t CONTROL; \ + uint32_t OTG_GSL_WINDOW_X; \ + uint32_t OTG_GSL_WINDOW_Y; \ + uint32_t OTG_VUPDATE_KEEPOUT; \ + uint32_t OTG_CRC_CNTL; \ + uint32_t OTG_CRC_CNTL2; \ + uint32_t OTG_CRC0_DATA_RG; \ + uint32_t OTG_CRC0_DATA_B; \ + uint32_t OTG_CRC1_DATA_B; \ + uint32_t OTG_CRC2_DATA_B; \ + uint32_t OTG_CRC3_DATA_B; \ + uint32_t OTG_CRC1_DATA_RG; \ + uint32_t OTG_CRC2_DATA_RG; \ + uint32_t OTG_CRC3_DATA_RG; \ + uint32_t OTG_CRC0_WINDOWA_X_CONTROL; \ + uint32_t OTG_CRC0_WINDOWA_Y_CONTROL; \ + uint32_t OTG_CRC0_WINDOWB_X_CONTROL; \ + uint32_t OTG_CRC0_WINDOWB_Y_CONTROL; \ + uint32_t OTG_CRC1_WINDOWA_X_CONTROL; \ + uint32_t OTG_CRC1_WINDOWA_Y_CONTROL; \ + uint32_t OTG_CRC1_WINDOWB_X_CONTROL; \ + uint32_t OTG_CRC1_WINDOWB_Y_CONTROL; \ + uint32_t GSL_SOURCE_SELECT; \ + uint32_t DWB_SOURCE_SELECT; \ + uint32_t OTG_DSC_START_POSITION; \ + uint32_t OPTC_DATA_FORMAT_CONTROL; \ + uint32_t OPTC_BYTES_PER_PIXEL; \ + uint32_t OPTC_WIDTH_CONTROL; \ + uint32_t OTG_DRR_CONTROL; \ + uint32_t OTG_BLANK_DATA_COLOR; \ + uint32_t OTG_BLANK_DATA_COLOR_EXT; \ + uint32_t OTG_DRR_TRIGGER_WINDOW; \ + uint32_t OTG_M_CONST_DTO0; \ + uint32_t OTG_M_CONST_DTO1; \ + uint32_t OTG_DRR_V_TOTAL_CHANGE; \ + uint32_t OTG_GLOBAL_CONTROL4; \ + uint32_t OTG_CRC0_WINDOWA_X_CONTROL_READBACK; \ + uint32_t OTG_CRC0_WINDOWA_Y_CONTROL_READBACK; \ + uint32_t OTG_CRC0_WINDOWB_X_CONTROL_READBACK; \ + uint32_t OTG_CRC0_WINDOWB_Y_CONTROL_READBACK; \ + uint32_t OTG_CRC1_WINDOWA_X_CONTROL_READBACK; \ + uint32_t OTG_CRC1_WINDOWA_Y_CONTROL_READBACK; \ + uint32_t OTG_CRC1_WINDOWB_X_CONTROL_READBACK; \ + uint32_t OTG_CRC1_WINDOWB_Y_CONTROL_READBACK; \ + uint32_t OPTC_CLOCK_CONTROL; \ + uint32_t OPTC_WIDTH_CONTROL2; \ + uint32_t OTG_PSTATE_REGISTER; \ + uint32_t OTG_PIPE_UPDATE_STATUS; \ + uint32_t INTERRUPT_DEST + struct dcn_optc_registers { - uint32_t OTG_GLOBAL_CONTROL1; - uint32_t OTG_GLOBAL_CONTROL2; - uint32_t OTG_VERT_SYNC_CONTROL; - uint32_t OTG_MASTER_UPDATE_MODE; - uint32_t OTG_GSL_CONTROL; - uint32_t OTG_VSTARTUP_PARAM; - uint32_t OTG_VUPDATE_PARAM; - uint32_t OTG_VREADY_PARAM; - uint32_t OTG_BLANK_CONTROL; - uint32_t OTG_MASTER_UPDATE_LOCK; - uint32_t OTG_GLOBAL_CONTROL0; - uint32_t OTG_DOUBLE_BUFFER_CONTROL; - uint32_t OTG_H_TOTAL; - uint32_t OTG_H_BLANK_START_END; - uint32_t OTG_H_SYNC_A; - uint32_t OTG_H_SYNC_A_CNTL; - uint32_t OTG_H_TIMING_CNTL; - uint32_t OTG_V_TOTAL; - uint32_t OTG_V_BLANK_START_END; - uint32_t OTG_V_SYNC_A; - uint32_t OTG_V_SYNC_A_CNTL; - uint32_t OTG_INTERLACE_CONTROL; - uint32_t OTG_CONTROL; - uint32_t OTG_STEREO_CONTROL; - uint32_t OTG_3D_STRUCTURE_CONTROL; - uint32_t OTG_STEREO_STATUS; - uint32_t OTG_V_TOTAL_MAX; - uint32_t OTG_V_TOTAL_MID; - uint32_t OTG_V_TOTAL_MIN; - uint32_t OTG_V_TOTAL_CONTROL; - uint32_t OTG_V_COUNT_STOP_CONTROL; - uint32_t OTG_V_COUNT_STOP_CONTROL2; - uint32_t OTG_TRIGA_CNTL; - uint32_t OTG_TRIGA_MANUAL_TRIG; - uint32_t OTG_MANUAL_FLOW_CONTROL; - uint32_t OTG_FORCE_COUNT_NOW_CNTL; - uint32_t OTG_STATIC_SCREEN_CONTROL; - uint32_t OTG_STATUS_FRAME_COUNT; - uint32_t OTG_STATUS; - uint32_t OTG_STATUS_POSITION; - uint32_t OTG_NOM_VERT_POSITION; - uint32_t OTG_BLACK_COLOR; - uint32_t OTG_TEST_PATTERN_PARAMETERS; - uint32_t OTG_TEST_PATTERN_CONTROL; - uint32_t OTG_TEST_PATTERN_COLOR; - uint32_t OTG_CLOCK_CONTROL; - uint32_t OTG_VERTICAL_INTERRUPT0_CONTROL; - uint32_t OTG_VERTICAL_INTERRUPT0_POSITION; - uint32_t OTG_VERTICAL_INTERRUPT1_CONTROL; - uint32_t OTG_VERTICAL_INTERRUPT1_POSITION; - uint32_t OTG_VERTICAL_INTERRUPT2_CONTROL; - uint32_t OTG_VERTICAL_INTERRUPT2_POSITION; - uint32_t OPTC_INPUT_CLOCK_CONTROL; - uint32_t OPTC_DATA_SOURCE_SELECT; - uint32_t OPTC_MEMORY_CONFIG; - uint32_t OPTC_INPUT_GLOBAL_CONTROL; - uint32_t CONTROL; - uint32_t OTG_GSL_WINDOW_X; - uint32_t OTG_GSL_WINDOW_Y; - uint32_t OTG_VUPDATE_KEEPOUT; - uint32_t OTG_CRC_CNTL; - uint32_t OTG_CRC_CNTL2; - uint32_t OTG_CRC0_DATA_RG; - uint32_t OTG_CRC1_DATA_RG; - uint32_t OTG_CRC2_DATA_RG; - uint32_t OTG_CRC3_DATA_RG; - uint32_t OTG_CRC0_DATA_B; - uint32_t OTG_CRC1_DATA_B; - uint32_t OTG_CRC2_DATA_B; - uint32_t OTG_CRC3_DATA_B; - uint32_t OTG_CRC0_DATA_R; - uint32_t OTG_CRC1_DATA_R; - uint32_t OTG_CRC2_DATA_R; - uint32_t OTG_CRC3_DATA_R; - uint32_t OTG_CRC0_DATA_G; - uint32_t OTG_CRC1_DATA_G; - uint32_t OTG_CRC2_DATA_G; - uint32_t OTG_CRC3_DATA_G; - uint32_t OTG_CRC0_WINDOWA_X_CONTROL; - uint32_t OTG_CRC0_WINDOWA_Y_CONTROL; - uint32_t OTG_CRC0_WINDOWB_X_CONTROL; - uint32_t OTG_CRC0_WINDOWB_Y_CONTROL; - uint32_t OTG_CRC1_WINDOWA_X_CONTROL; - uint32_t OTG_CRC1_WINDOWA_Y_CONTROL; - uint32_t OTG_CRC1_WINDOWB_X_CONTROL; - uint32_t OTG_CRC1_WINDOWB_Y_CONTROL; - uint32_t GSL_SOURCE_SELECT; - uint32_t DWB_SOURCE_SELECT; - uint32_t OTG_DSC_START_POSITION; - uint32_t OPTC_DATA_FORMAT_CONTROL; - uint32_t OPTC_BYTES_PER_PIXEL; - uint32_t OPTC_WIDTH_CONTROL; - uint32_t OTG_DRR_CONTROL; - uint32_t OTG_BLANK_DATA_COLOR; - uint32_t OTG_BLANK_DATA_COLOR_EXT; - uint32_t OTG_DRR_TRIGGER_WINDOW; - uint32_t OTG_M_CONST_DTO0; - uint32_t OTG_M_CONST_DTO1; - uint32_t OTG_DRR_V_TOTAL_CHANGE; - uint32_t OTG_GLOBAL_CONTROL4; - uint32_t OTG_CRC0_WINDOWA_X_CONTROL_READBACK; - uint32_t OTG_CRC0_WINDOWA_Y_CONTROL_READBACK; - uint32_t OTG_CRC0_WINDOWB_X_CONTROL_READBACK; - uint32_t OTG_CRC0_WINDOWB_Y_CONTROL_READBACK; - uint32_t OTG_CRC1_WINDOWA_X_CONTROL_READBACK; - uint32_t OTG_CRC1_WINDOWA_Y_CONTROL_READBACK; - uint32_t OTG_CRC1_WINDOWB_X_CONTROL_READBACK; - uint32_t OTG_CRC1_WINDOWB_Y_CONTROL_READBACK; - uint32_t OPTC_CLOCK_CONTROL; - uint32_t OPTC_WIDTH_CONTROL2; - uint32_t OTG_PSTATE_REGISTER; - uint32_t OTG_PIPE_UPDATE_STATUS; - uint32_t INTERRUPT_DEST; + OPTC_REG_VARIABLE_LIST_DCN; }; #define TG_COMMON_MASK_SH_LIST_DCN(mask_sh)\ From ab021b9f3194c16bb766eec084d22529e503f2c5 Mon Sep 17 00:00:00 2001 From: Rafal Ostrowski Date: Wed, 12 Feb 2025 08:08:07 +0100 Subject: [PATCH 051/235] drm/amd/display: ACPI Re-timer Programming [Why] We must implement an ACPI re-timer programming interface and notify ACPI driver whenever a PHY transition is about to take place. Because some trace lengths on certain platforms are very long, then a re-timer may need to be programmed whenever a PHY transition takes place. The implementation of this re-timer programming interface will notify ACPI driver that PHY transition is taking place and it will trigger the re-timer as needed. First we need to gather retimer information from ACPI interface. Then, in the PRE case, the re-timer interface needs to be called before we call transmitter ENABLE. In the POST case, it has to be called after we call transmitter DISABLE. [How] Implemented ACPI retimer programming interface. Reviewed-by: Alvin Lee Signed-off-by: Rafal Ostrowski Signed-off-by: Zaeem Mohamed Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 7 +++ .../drm/amd/display/dc/bios/command_table2.c | 47 +++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dc.h | 2 + drivers/gpu/drm/amd/display/dc/dm_services.h | 7 +++ .../drm/amd/display/dc/dm_services_types.h | 26 ++++++++++ 5 files changed, 89 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index b27fa9738cac..d0af935557c4 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -12717,3 +12717,10 @@ bool dm_execute_dmub_cmd_list(const struct dc_context *ctx, unsigned int count, { return dc_dmub_srv_cmd_run_list(ctx->dmub_srv, count, cmd, wait_type); } + +void dm_acpi_process_phy_transition_interlock( + const struct dc_context *ctx, + struct dm_process_phy_transition_init_params process_phy_transition_init_params) +{ + // Not yet implemented +} diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c index 7d18f372ce7a..2c96a5e64567 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c @@ -210,6 +210,7 @@ static enum bp_result encoder_control_fallback( ****************************************************************************** *****************************************************************************/ + static enum bp_result transmitter_control_v1_6( struct bios_parser *bp, struct bp_transmitter_control *cntl); @@ -325,6 +326,21 @@ static void transmitter_control_dmcub_v1_7( dc_wake_and_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); } +static struct dc_link *get_link_by_phy_id(struct dc *p_dc, uint32_t phy_id) +{ + struct dc_link *link = NULL; + + // Get Transition Bitmask from dc_link structure associated with PHY + for (uint8_t link_id = 0; link_id < MAX_LINKS; link_id++) { + if (phy_id == p_dc->links[link_id]->link_enc->transmitter) { + link = p_dc->links[link_id]; + break; + } + } + + return link; +} + static enum bp_result transmitter_control_v1_7( struct bios_parser *bp, struct bp_transmitter_control *cntl) @@ -363,7 +379,37 @@ static enum bp_result transmitter_control_v1_7( if (bp->base.ctx->dc->ctx->dmub_srv && bp->base.ctx->dc->debug.dmub_command_table) { + struct dm_process_phy_transition_init_params process_phy_transition_init_params = {0}; + struct dc_link *link = get_link_by_phy_id(bp->base.ctx->dc, dig_v1_7.phyid); + bool is_phy_transition_interlock_allowed = false; + uint8_t action = dig_v1_7.action; + + if (link) { + if (link->phy_transition_bitmask && + (action == TRANSMITTER_CONTROL_ENABLE || action == TRANSMITTER_CONTROL_DISABLE)) { + is_phy_transition_interlock_allowed = true; + + // Prepare input parameters for processing ACPI retimers + process_phy_transition_init_params.action = action; + process_phy_transition_init_params.display_port_lanes_count = cntl->lanes_number; + process_phy_transition_init_params.phy_id = dig_v1_7.phyid; + process_phy_transition_init_params.signal = cntl->signal; + process_phy_transition_init_params.sym_clock_10khz = dig_v1_7.symclk_units.symclk_10khz; + process_phy_transition_init_params.display_port_link_rate = link->cur_link_settings.link_rate; + process_phy_transition_init_params.transition_bitmask = link->phy_transition_bitmask; + } + } + + // Handle PRE_OFF_TO_ON: Process ACPI PHY Transition Interlock + if (is_phy_transition_interlock_allowed && action == TRANSMITTER_CONTROL_ENABLE) + dm_acpi_process_phy_transition_interlock(bp->base.ctx, process_phy_transition_init_params); + transmitter_control_dmcub_v1_7(bp->base.ctx->dmub_srv, &dig_v1_7); + + // Handle POST_ON_TO_OFF: Process ACPI PHY Transition Interlock + if (is_phy_transition_interlock_allowed && action == TRANSMITTER_CONTROL_DISABLE) + dm_acpi_process_phy_transition_interlock(bp->base.ctx, process_phy_transition_init_params); + return BP_RESULT_OK; } @@ -1046,3 +1092,4 @@ void dal_firmware_parser_init_cmd_tbl(struct bios_parser *bp) init_enable_lvtma_control(bp); } + diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 5e96913bcab1..f76884fe86e3 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -1083,6 +1083,7 @@ struct dc_debug_options { unsigned int enable_oled_edp_power_up_opt; bool enable_hblank_borrow; bool force_subvp_df_throttle; + uint32_t acpi_transition_bitmasks[MAX_PIPES]; }; @@ -1806,6 +1807,7 @@ struct dc_link { struct dc_panel_config panel_config; struct phy_state phy_state; + uint32_t phy_transition_bitmask; // BW ALLOCATON USB4 ONLY struct dc_dpia_bw_alloc dpia_bw_alloc_config; bool skip_implict_edp_power_control; diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index f81e5a4e1d6d..7b9c22c45453 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -290,6 +290,13 @@ void dm_trace_smu_delay(uint32_t delay, struct dc_context *ctx); bool dm_execute_dmub_cmd(const struct dc_context *ctx, union dmub_rb_cmd *cmd, enum dm_dmub_wait_type wait_type); bool dm_execute_dmub_cmd_list(const struct dc_context *ctx, unsigned int count, union dmub_rb_cmd *cmd, enum dm_dmub_wait_type wait_type); +/* + * ACPI Interfaces + */ +void dm_acpi_process_phy_transition_interlock( + const struct dc_context *ctx, + struct dm_process_phy_transition_init_params process_phy_transition_init_params); + /* * Debug and verification hooks */ diff --git a/drivers/gpu/drm/amd/display/dc/dm_services_types.h b/drivers/gpu/drm/amd/display/dc/dm_services_types.h index facf269c4326..bf63da266a18 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services_types.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services_types.h @@ -275,4 +275,30 @@ enum dm_dmub_wait_type { DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY, }; +enum dm_acpi_transition_link_type { + hdmi_tmds, + hdmi_frl, + dp_8b_10b, + dp_128b_132b, + none +}; + +struct dm_process_phy_transition_init_params { + uint32_t phy_id; + uint8_t action; + uint32_t sym_clock_10khz; + enum signal_type signal; + enum dc_lane_count display_port_lanes_count; + enum dc_link_rate display_port_link_rate; + uint32_t transition_bitmask; + uint8_t hdmi_frl_num_lanes; +}; + +struct dm_process_phy_transition_input_params { + uint32_t phy_id; + uint32_t transition_id; + uint32_t phy_configuration; + uint32_t data_rate; +}; + #endif From ba93dddfc92084a1e28ea447ec4f8315f3d8d3fd Mon Sep 17 00:00:00 2001 From: Aurabindo Pillai Date: Mon, 20 Jan 2025 15:27:23 -0500 Subject: [PATCH 052/235] drm/amd/display: Temporarily disable hostvm on DCN31 With HostVM enabled, DCN31 fails to pass validation for 3x4k60. Some Linux userspace does not downgrade one of the monitors to 4k30, and the result is that the monitor does not light up. Disable it until the bandwidth calculation failure is resolved. Reviewed-by: Sun peng Li Signed-off-by: Aurabindo Pillai Signed-off-by: Zaeem Mohamed Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c index 911bd60d4fbc..3c42ba8566cf 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c @@ -890,7 +890,7 @@ static const struct dc_debug_options debug_defaults_drv = { .disable_z10 = true, .enable_legacy_fast_update = true, .enable_z9_disable_interface = true, /* Allow support for the PMFW interface for disable Z9*/ - .dml_hostvm_override = DML_HOSTVM_NO_OVERRIDE, + .dml_hostvm_override = DML_HOSTVM_OVERRIDE_FALSE, .using_dml2 = false, }; From 23ef388a84c72b0614a6c10f866ffeac7e807719 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Thu, 13 Feb 2025 12:37:10 -0500 Subject: [PATCH 053/235] drm/amd/display: fix dcn4x init failed [why] failed due to cmdtable not created. switch atombios cmdtable as default. Reviewed-by: Alvin Lee Signed-off-by: Charlene Liu Signed-off-by: Zaeem Mohamed Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/command_table2.c | 9 --------- .../gpu/drm/amd/display/dc/bios/command_table_helper2.c | 3 +-- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c index 2c96a5e64567..2c645dffec18 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c @@ -101,7 +101,6 @@ static void init_dig_encoder_control(struct bios_parser *bp) bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v1_5; break; default: - dm_output_to_console("Don't have dig_encoder_control for v%d\n", version); bp->cmd_tbl.dig_encoder_control = encoder_control_fallback; break; } @@ -239,7 +238,6 @@ static void init_transmitter_control(struct bios_parser *bp) bp->cmd_tbl.transmitter_control = transmitter_control_v1_7; break; default: - dm_output_to_console("Don't have transmitter_control for v%d\n", crev); bp->cmd_tbl.transmitter_control = transmitter_control_fallback; break; } @@ -454,8 +452,6 @@ static void init_set_pixel_clock(struct bios_parser *bp) bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v7; break; default: - dm_output_to_console("Don't have set_pixel_clock for v%d\n", - BIOS_CMD_TABLE_PARA_REVISION(setpixelclock)); bp->cmd_tbl.set_pixel_clock = set_pixel_clock_fallback; break; } @@ -600,7 +596,6 @@ static void init_set_crtc_timing(struct bios_parser *bp) set_crtc_using_dtd_timing_v3; break; default: - dm_output_to_console("Don't have set_crtc_timing for v%d\n", dtd_version); bp->cmd_tbl.set_crtc_timing = NULL; break; } @@ -717,8 +712,6 @@ static void init_enable_crtc(struct bios_parser *bp) bp->cmd_tbl.enable_crtc = enable_crtc_v1; break; default: - dm_output_to_console("Don't have enable_crtc for v%d\n", - BIOS_CMD_TABLE_PARA_REVISION(enablecrtc)); bp->cmd_tbl.enable_crtc = NULL; break; } @@ -910,8 +903,6 @@ static void init_set_dce_clock(struct bios_parser *bp) bp->cmd_tbl.set_dce_clock = set_dce_clock_v2_1; break; default: - dm_output_to_console("Don't have set_dce_clock for v%d\n", - BIOS_CMD_TABLE_PARA_REVISION(setdceclock)); bp->cmd_tbl.set_dce_clock = NULL; break; } diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c index bad4e4711b4f..268e2414b34f 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c @@ -88,8 +88,7 @@ bool dal_bios_parser_init_cmd_tbl_helper2( return true; default: - /* Unsupported DCE */ - BREAK_TO_DEBUGGER(); + *h = dal_cmd_tbl_helper_dce112_get_table2(); return false; } } From 7c6518c1c73199a230b5fc55ddfed3e5b9dc3290 Mon Sep 17 00:00:00 2001 From: Michael Strauss Date: Fri, 24 Jan 2025 15:02:27 -0500 Subject: [PATCH 054/235] drm/amd/display: Update FIXED_VS Link Rate Toggle Workaround Usage [WHY] Previously the 128b/132b LTTPR support DPCD field was used to decide if FIXED_VS training sequence required a rate toggle before initiating LT. When running DP2.1 4.9.x.x compliance tests, emulated LTTPRs can report no-128b/132b support which is then forwarded by the FIXED_VS retimer. As a result this test exposes the rate toggle again, erroneously causing failures as certain compliance sinks don't expect this behaviour. [HOW] Add new DPCD register defines/reads to read LTTPR IEEE OUI and device ID. Decide whether to perform the rate toggle based on the LTTPR's IEEE OUI which guarantees that we only perform the toggle on affected retimers. Reviewed-by: Wenjing Liu Signed-off-by: Michael Strauss Signed-off-by: Zaeem Mohamed Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_dp_types.h | 8 ++++++++ .../display/dc/link/protocols/link_dp_capability.c | 12 ++++++++++-- .../protocols/link_dp_training_fixed_vs_pe_retimer.c | 3 ++- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h index ae6e2d8552ac..8bb628ab7855 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h @@ -1128,6 +1128,8 @@ struct dc_lttpr_caps { union dp_128b_132b_supported_lttpr_link_rates supported_128b_132b_rates; union dp_alpm_lttpr_cap alpm; uint8_t aux_rd_interval[MAX_REPEATER_CNT - 1]; + uint8_t lttpr_ieee_oui[3]; + uint8_t lttpr_device_id[6]; }; struct dc_dongle_dfp_cap_ext { @@ -1391,6 +1393,12 @@ struct dp_trace { #ifndef DP_BRANCH_VENDOR_SPECIFIC_START #define DP_BRANCH_VENDOR_SPECIFIC_START 0x50C #endif +#ifndef DP_LTTPR_IEEE_OUI +#define DP_LTTPR_IEEE_OUI 0xF003D +#endif +#ifndef DP_LTTPR_DEVICE_ID +#define DP_LTTPR_DEVICE_ID 0xF0040 +#endif /** USB4 DPCD BW Allocation Registers Chapter 10.7 **/ #ifndef DP_TUNNELING_CAPABILITIES #define DP_TUNNELING_CAPABILITIES 0xE000D /* 1.4a */ diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c index f6e0868507f7..0785c030f6a6 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c @@ -1575,10 +1575,18 @@ enum dc_status dp_retrieve_lttpr_cap(struct dc_link *link) /* Attempt to train in LTTPR transparent mode if repeater count exceeds 8. */ is_lttpr_present = dp_is_lttpr_present(link); - if (is_lttpr_present) + DC_LOG_DC("is_lttpr_present = %d\n", is_lttpr_present); + + if (is_lttpr_present) { CONN_DATA_DETECT(link, lttpr_dpcd_data, sizeof(lttpr_dpcd_data), "LTTPR Caps: "); - DC_LOG_DC("is_lttpr_present = %d\n", is_lttpr_present); + core_link_read_dpcd(link, DP_LTTPR_IEEE_OUI, link->dpcd_caps.lttpr_caps.lttpr_ieee_oui, sizeof(link->dpcd_caps.lttpr_caps.lttpr_ieee_oui)); + CONN_DATA_DETECT(link, link->dpcd_caps.lttpr_caps.lttpr_ieee_oui, sizeof(link->dpcd_caps.lttpr_caps.lttpr_ieee_oui), "LTTPR IEEE OUI: "); + + core_link_read_dpcd(link, DP_LTTPR_DEVICE_ID, link->dpcd_caps.lttpr_caps.lttpr_device_id, sizeof(link->dpcd_caps.lttpr_caps.lttpr_device_id)); + CONN_DATA_DETECT(link, link->dpcd_caps.lttpr_caps.lttpr_device_id, sizeof(link->dpcd_caps.lttpr_caps.lttpr_device_id), "LTTPR Device ID: "); + } + return status; } diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.c index ccf8096dde29..ce174ce5579c 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.c @@ -270,7 +270,8 @@ enum link_training_result dp_perform_fixed_vs_pe_training_sequence( rate = get_dpcd_link_rate(<_settings->link_settings); - if (!link->dpcd_caps.lttpr_caps.main_link_channel_coding.bits.DP_128b_132b_SUPPORTED) { + // Only perform toggle if FIXED_VS LTTPR reports no IEEE OUI + if (memcmp("\x0,\x0,\x0", &link->dpcd_caps.lttpr_caps.lttpr_ieee_oui[0], 3) == 0) { /* Vendor specific: Toggle link rate */ toggle_rate = (rate == 0x6) ? 0xA : 0x6; From 02a940da2ccc0cc0299811379580852b405a0ea2 Mon Sep 17 00:00:00 2001 From: Yihan Zhu Date: Wed, 12 Feb 2025 15:17:56 -0500 Subject: [PATCH 055/235] drm/amd/display: handle max_downscale_src_width fail check [WHY] If max_downscale_src_width check fails, we exit early from TAP calculation and left a NULL value to the scaling data structure to cause the zero divide in the DML validation. [HOW] Call set default TAP calculation before early exit in get_optimal_number_of_taps due to max downscale limit exceed. Reviewed-by: Samson Tam Signed-off-by: Yihan Zhu Signed-off-by: Zaeem Mohamed Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c index 40acebd13e46..abf439e743f2 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c @@ -425,11 +425,6 @@ bool dpp3_get_optimal_number_of_taps( int min_taps_y, min_taps_c; enum lb_memory_config lb_config; - if (scl_data->viewport.width > scl_data->h_active && - dpp->ctx->dc->debug.max_downscale_src_width != 0 && - scl_data->viewport.width > dpp->ctx->dc->debug.max_downscale_src_width) - return false; - /* * Set default taps if none are provided * From programming guide: taps = min{ ceil(2*H_RATIO,1), 8} for downscaling @@ -467,6 +462,12 @@ bool dpp3_get_optimal_number_of_taps( else scl_data->taps.h_taps_c = in_taps->h_taps_c; + // Avoid null data in the scl data with this early return, proceed non-adaptive calcualtion first + if (scl_data->viewport.width > scl_data->h_active && + dpp->ctx->dc->debug.max_downscale_src_width != 0 && + scl_data->viewport.width > dpp->ctx->dc->debug.max_downscale_src_width) + return false; + /*Ensure we can support the requested number of vtaps*/ min_taps_y = dc_fixpt_ceil(scl_data->ratios.vert); min_taps_c = dc_fixpt_ceil(scl_data->ratios.vert_c); From 35079e7eeed349fe10831cd596b9e279d793f958 Mon Sep 17 00:00:00 2001 From: Krunoslav Kovac Date: Thu, 13 Feb 2025 19:14:59 -0500 Subject: [PATCH 056/235] drm/amd/display: Remove unused header [Why] Removes unused header Reviewed-by: Samson Tam Signed-off-by: Krunoslav Kovac Signed-off-by: Zaeem Mohamed Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/sspl/dc_spl.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/sspl/dc_spl.c b/drivers/gpu/drm/amd/display/dc/sspl/dc_spl.c index 8d80bce0738a..28348734d900 100644 --- a/drivers/gpu/drm/amd/display/dc/sspl/dc_spl.c +++ b/drivers/gpu/drm/amd/display/dc/sspl/dc_spl.c @@ -3,7 +3,6 @@ // Copyright 2024 Advanced Micro Devices, Inc. #include "dc_spl.h" -#include "dc_spl_scl_filters.h" #include "dc_spl_scl_easf_filters.h" #include "dc_spl_isharp_filters.h" #include "spl_debug.h" From 50f040c53ea9b26b32b8cf06724c24a99a6a4498 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Thu, 13 Feb 2025 17:40:29 -0500 Subject: [PATCH 057/235] drm/amd/display: Increase halt timeout for DMCUB to 1s [Why] If we soft reset before halt finishes and there are outstanding memory transactions then the memory interface may produce unexpected results, such as out of order transactions when the firmware next runs. These can manifest as random or unexpected load/store violations. [How] Increase the timeout before soft reset to ensure the DMCUB has quiesced. Reviewed-by: Dillon Varone Signed-off-by: Nicholas Kazlauskas Signed-off-by: Zaeem Mohamed Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c | 15 ++++++++++----- drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c | 2 +- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c index 3d0bba602b53..1fac75dfc650 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c @@ -83,8 +83,8 @@ static inline void dmub_dcn31_translate_addr(const union dmub_addr *addr_in, void dmub_dcn31_reset(struct dmub_srv *dmub) { union dmub_gpint_data_register cmd; - const uint32_t timeout = 100; - uint32_t in_reset, scratch, i, pwait_mode; + const uint32_t timeout = 1000000; + uint32_t in_reset, is_enabled, scratch, i, pwait_mode; REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &in_reset); @@ -125,9 +125,14 @@ void dmub_dcn31_reset(struct dmub_srv *dmub) /* Force reset in case we timed out, DMCUB is likely hung. */ } - REG_UPDATE(DMCUB_CNTL2, DMCUB_SOFT_RESET, 1); - REG_UPDATE(DMCUB_CNTL, DMCUB_ENABLE, 0); - REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 1); + REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_enabled); + + if (is_enabled) { + REG_UPDATE(DMCUB_CNTL2, DMCUB_SOFT_RESET, 1); + REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 1); + REG_UPDATE(DMCUB_CNTL, DMCUB_ENABLE, 0); + } + REG_WRITE(DMCUB_INBOX1_RPTR, 0); REG_WRITE(DMCUB_INBOX1_WPTR, 0); REG_WRITE(DMCUB_OUTBOX1_RPTR, 0); diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c index e5e77bd3c31e..652173b10401 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c @@ -88,7 +88,7 @@ static inline void dmub_dcn35_translate_addr(const union dmub_addr *addr_in, void dmub_dcn35_reset(struct dmub_srv *dmub) { union dmub_gpint_data_register cmd; - const uint32_t timeout = 100; + const uint32_t timeout = 1000000; uint32_t in_reset, is_enabled, scratch, i, pwait_mode; REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &in_reset); From 8adeff83a3b07fa6d0958ed51e1b38ba7469e448 Mon Sep 17 00:00:00 2001 From: Mike Katsnelson Date: Thu, 13 Feb 2025 11:52:32 -0500 Subject: [PATCH 058/235] drm/amd/display: stop DML2 from removing pipes based on planes [Why] Transitioning from low to high resolutions at high refresh rates caused grey corruption. During the transition state, there is a period where plane size is based on low resultion state and ODM slices are based on high resoultion state, causing the entire plane to be contained in one ODM slice. DML2 would turn off the pipe for the ODM slice with no plane, causing an underflow since the pixel rate for the higher resolution cannot be supported on one pipe. This change stops DML2 from turning off pipes that are mapped to an ODM slice with no plane. This is possible to do without negative consequences because pipes can now take the minimum viewport and draw with zero recout size, removing the need to have the pipe turned off. [How] In map_pipes_from_plane(), remove "check" that skips ODM slices that are not covered by the plane. This prevents the pipes for those ODM slices from being freed. Reviewed-by: Ovidiu Bunea Signed-off-by: Mike Katsnelson Signed-off-by: Zaeem Mohamed Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../display/dc/dml2/dml2_dc_resource_mgmt.c | 26 ------------------- 1 file changed, 26 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c index 1ed21c1b86a5..a966abd40788 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c @@ -532,26 +532,6 @@ static void calculate_odm_slices(const struct dc_stream_state *stream, unsigned odm_slice_end_x[odm_factor - 1] = stream->src.width - 1; } -static bool is_plane_in_odm_slice(const struct dc_plane_state *plane, unsigned int slice_index, unsigned int *odm_slice_end_x, unsigned int num_slices) -{ - unsigned int slice_start_x, slice_end_x; - - if (slice_index == 0) - slice_start_x = 0; - else - slice_start_x = odm_slice_end_x[slice_index - 1] + 1; - - slice_end_x = odm_slice_end_x[slice_index]; - - if (plane->clip_rect.x + plane->clip_rect.width < slice_start_x) - return false; - - if (plane->clip_rect.x > slice_end_x) - return false; - - return true; -} - static void add_odm_slice_to_odm_tree(struct dml2_context *ctx, struct dc_state *state, struct dc_pipe_mapping_scratch *scratch, @@ -791,12 +771,6 @@ static void map_pipes_for_plane(struct dml2_context *ctx, struct dc_state *state sort_pipes_for_splitting(&scratch->pipe_pool); for (odm_slice_index = 0; odm_slice_index < scratch->odm_info.odm_factor; odm_slice_index++) { - // We build the tree for one ODM slice at a time. - // Each ODM slice shares a common OPP - if (!is_plane_in_odm_slice(plane, odm_slice_index, scratch->odm_info.odm_slice_end_x, scratch->odm_info.odm_factor)) { - continue; - } - // Now we have a list of all pipes to be used for this plane/stream, now setup the tree. scratch->odm_info.next_higher_pipe_for_odm_slice[odm_slice_index] = add_plane_to_blend_tree(ctx, state, plane, From f3dde2ff7fcaacd77884502e8f572f2328e9c745 Mon Sep 17 00:00:00 2001 From: Roman Li Date: Wed, 12 Feb 2025 14:49:36 -0500 Subject: [PATCH 059/235] drm/amd/display: Fix HPD after gpu reset [Why] DC is not using amdgpu_irq_get/put to manage the HPD interrupt refcounts. So when amdgpu_irq_gpu_reset_resume_helper() reprograms all of the IRQs, HPD gets disabled. [How] Use amdgpu_irq_get/put() for HPD init/fini in DM in order to sync refcounts Cc: Mario Limonciello Cc: Alex Deucher Reviewed-by: Mario Limonciello Reviewed-by: Aurabindo Pillai Signed-off-by: Roman Li Signed-off-by: Zaeem Mohamed Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c index 3390f0d8420a..c4a7fd453e5f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c @@ -894,6 +894,7 @@ void amdgpu_dm_hpd_init(struct amdgpu_device *adev) struct drm_device *dev = adev_to_drm(adev); struct drm_connector *connector; struct drm_connector_list_iter iter; + int i; drm_connector_list_iter_begin(dev, &iter); drm_for_each_connector_iter(connector, &iter) { @@ -920,6 +921,12 @@ void amdgpu_dm_hpd_init(struct amdgpu_device *adev) } } drm_connector_list_iter_end(&iter); + + /* Update reference counts for HPDs */ + for (i = DC_IRQ_SOURCE_HPD1; i <= adev->mode_info.num_hpd; i++) { + if (amdgpu_irq_get(adev, &adev->hpd_irq, i - DC_IRQ_SOURCE_HPD1)) + drm_err(dev, "DM_IRQ: Failed get HPD for source=%d)!\n", i); + } } /** @@ -935,6 +942,7 @@ void amdgpu_dm_hpd_fini(struct amdgpu_device *adev) struct drm_device *dev = adev_to_drm(adev); struct drm_connector *connector; struct drm_connector_list_iter iter; + int i; drm_connector_list_iter_begin(dev, &iter); drm_for_each_connector_iter(connector, &iter) { @@ -960,4 +968,10 @@ void amdgpu_dm_hpd_fini(struct amdgpu_device *adev) } } drm_connector_list_iter_end(&iter); + + /* Update reference counts for HPDs */ + for (i = DC_IRQ_SOURCE_HPD1; i <= adev->mode_info.num_hpd; i++) { + if (amdgpu_irq_put(adev, &adev->hpd_irq, i - DC_IRQ_SOURCE_HPD1)) + drm_err(dev, "DM_IRQ: Failed put HPD for source=%d!\n", i); + } } From d7dc4917ae8147836a4eaecb5f64892d18dcbef8 Mon Sep 17 00:00:00 2001 From: Taimur Hassan Date: Sun, 16 Feb 2025 15:06:06 -0500 Subject: [PATCH 060/235] drm/amd/display: [FW Promotion] Release 0.0.255.0 Reviewed-by: Leo Li Signed-off-by: Taimur Hassan Signed-off-by: Zaeem Mohamed Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index 8cf89aed024b..f84bbc033e64 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -160,6 +160,13 @@ #define dmub_memset(dest, val, bytes) memset((dest), (val), (bytes)) #endif +/** + * OS/FW agnostic memcmp + */ +#ifndef dmub_memcmp +#define dmub_memcmp(lhs, rhs, bytes) memcmp((lhs), (rhs), (bytes)) +#endif + /** * OS/FW agnostic udelay */ @@ -1460,6 +1467,11 @@ enum dmub_cmd_type { */ DMUB_CMD__PSP = 88, + /** + * Command type used for all Fused IO commands. + */ + DMUB_CMD__FUSED_IO = 89, + DMUB_CMD__VBIOS = 128, }; @@ -1491,6 +1503,10 @@ enum dmub_out_cmd_type { * Command type used for HPD redetect notification */ DMUB_OUT_CMD__HPD_SENSE_NOTIFY = 6, + /** + * Command type used for Fused IO notification + */ + DMUB_OUT_CMD__FUSED_IO = 7, }; /* DMUB_CMD__DPIA command sub-types. */ @@ -5325,6 +5341,63 @@ struct dmub_rb_cmd_get_usbc_cable_id { } data; }; +enum dmub_cmd_fused_io_sub_type { + DMUB_CMD__FUSED_IO_EXECUTE = 0, + DMUB_CMD__FUSED_IO_ABORT = 1, +}; + +enum dmub_cmd_fused_request_type { + FUSED_REQUEST_READ, + FUSED_REQUEST_WRITE, + FUSED_REQUEST_POLL, +}; + +enum dmub_cmd_fused_request_status { + FUSED_REQUEST_STATUS_SUCCESS, + FUSED_REQUEST_STATUS_BEGIN, + FUSED_REQUEST_STATUS_SUBMIT, + FUSED_REQUEST_STATUS_REPLY, + FUSED_REQUEST_STATUS_POLL, + FUSED_REQUEST_STATUS_ABORTED, + FUSED_REQUEST_STATUS_FAILED = 0x80, + FUSED_REQUEST_STATUS_INVALID, + FUSED_REQUEST_STATUS_BUSY, + FUSED_REQUEST_STATUS_TIMEOUT, + FUSED_REQUEST_STATUS_POLL_TIMEOUT, +}; + +struct dmub_cmd_fused_request { + uint8_t status; + uint8_t type : 2; + uint8_t _reserved0 : 3; + uint8_t poll_mask_msb : 3; // Number of MSB to zero out from last byte before comparing + uint8_t identifier; + uint8_t _reserved1; + uint32_t timeout_us; + union dmub_cmd_fused_request_location { + struct dmub_cmd_fused_request_location_i2c { + uint8_t is_aux : 1; // False + uint8_t ddc_line : 3; + uint8_t _reserved0 : 4; + uint8_t address; + uint8_t offset; + uint8_t length; + } i2c; + struct dmub_cmd_fused_request_location_aux { + uint32_t is_aux : 1; // True + uint32_t ddc_line : 3; + uint32_t address : 20; + uint32_t length : 8; // Automatically split into 16B transactions + } aux; + } u; + uint8_t buffer[0x30]; // Read: out, write: in, poll: expected +}; + +struct dmub_rb_cmd_fused_io { + struct dmub_cmd_header header; + struct dmub_cmd_fused_request request; +}; + /** * Command type of a DMUB_CMD__SECURE_DISPLAY command */ @@ -5738,6 +5811,8 @@ union dmub_rb_cmd { struct dmub_rb_cmd_fams2_drr_update fams2_drr_update; struct dmub_rb_cmd_fams2_flip fams2_flip; + + struct dmub_rb_cmd_fused_io fused_io; }; /** @@ -5768,6 +5843,7 @@ union dmub_rb_out_cmd { * HPD sense notification command. */ struct dmub_rb_cmd_hpd_sense_notify hpd_sense_notify; + struct dmub_rb_cmd_fused_io fused_io; }; #pragma pack(pop) From 9655a16031789d43c21084027fe5a76393c189b1 Mon Sep 17 00:00:00 2001 From: Taimur Hassan Date: Sun, 16 Feb 2025 16:27:26 -0500 Subject: [PATCH 061/235] drm/amd/display: Promote DAL to 3.2.322 - Disable PSR-SU on eDP panels - Fix HPD after GPU reset - Fixes on dcn4x init, DML2 state policy on DCN36 - Various minor logic fixes Reviewed-by: Leo Li Signed-off-by: Taimur Hassan Signed-off-by: Zaeem Mohamed Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index f76884fe86e3..f646f537a3dc 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -53,7 +53,7 @@ struct aux_payload; struct set_config_cmd_payload; struct dmub_notification; -#define DC_VER "3.2.321" +#define DC_VER "3.2.322" /** * MAX_SURFACES - representative of the upper bound of surfaces that can be piped to a single CRTC From 6f0e68b8c76df15f4af5846e4c8d49b15a550196 Mon Sep 17 00:00:00 2001 From: Jonathan Kim Date: Fri, 21 Feb 2025 09:39:27 -0500 Subject: [PATCH 062/235] drm/amdkfd: enable cooperative launch on gfx12 Even though GWS no longer exists, to maintain runtime usage for cooperative launch, SW set legacy GWS size. Signed-off-by: Jonathan Kim Acked-by: Mukul Joshi Reviewed-by: Harish Kasiviswanathan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_device.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index 9d20e169ec4a..095e73790dc4 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -590,9 +590,13 @@ static int kfd_gws_init(struct kfd_node *node) && kfd->mec2_fw_version >= 0x6b) || (KFD_GC_VERSION(node) >= IP_VERSION(11, 0, 0) && KFD_GC_VERSION(node) < IP_VERSION(12, 0, 0) - && mes_rev >= 68)))) + && mes_rev >= 68) || + (KFD_GC_VERSION(node) >= IP_VERSION(12, 0, 0))))) { + if (KFD_GC_VERSION(node) >= IP_VERSION(12, 0, 0)) + node->adev->gds.gws_size = 64; ret = amdgpu_amdkfd_alloc_gws(node->adev, node->adev->gds.gws_size, &node->gws); + } return ret; } From 9424a5bf0836347b737ab27da2c22111abf0ede2 Mon Sep 17 00:00:00 2001 From: Jonathan Kim Date: Mon, 10 Feb 2025 13:15:48 -0500 Subject: [PATCH 063/235] drm/amdgpu: simplify xgmi peer info calls Deprecate KFD XGMI peer info calls in favour of calling directly from simplified XGMI peer info functions. Signed-off-by: Jonathan Kim Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 42 --------------- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h | 5 -- drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c | 61 ++++++++++++++++++---- drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h | 24 +++++++-- drivers/gpu/drm/amd/amdkfd/kfd_crat.c | 27 ++++++---- 5 files changed, 87 insertions(+), 72 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c index 0312231b703e..4cec3a873995 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c @@ -555,48 +555,6 @@ int amdgpu_amdkfd_get_dmabuf_info(struct amdgpu_device *adev, int dma_buf_fd, return r; } -uint8_t amdgpu_amdkfd_get_xgmi_hops_count(struct amdgpu_device *dst, - struct amdgpu_device *src) -{ - struct amdgpu_device *peer_adev = src; - struct amdgpu_device *adev = dst; - int ret = amdgpu_xgmi_get_hops_count(adev, peer_adev); - - if (ret < 0) { - DRM_ERROR("amdgpu: failed to get xgmi hops count between node %d and %d. ret = %d\n", - adev->gmc.xgmi.physical_node_id, - peer_adev->gmc.xgmi.physical_node_id, ret); - ret = 0; - } - return (uint8_t)ret; -} - -int amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(struct amdgpu_device *dst, - struct amdgpu_device *src, - bool is_min) -{ - struct amdgpu_device *adev = dst, *peer_adev; - int num_links; - - if (amdgpu_ip_version(adev, GC_HWIP, 0) < IP_VERSION(9, 4, 2)) - return 0; - - if (src) - peer_adev = src; - - /* num links returns 0 for indirect peers since indirect route is unknown. */ - num_links = is_min ? 1 : amdgpu_xgmi_get_num_links(adev, peer_adev); - if (num_links < 0) { - DRM_ERROR("amdgpu: failed to get xgmi num links between node %d and %d. ret = %d\n", - adev->gmc.xgmi.physical_node_id, - peer_adev->gmc.xgmi.physical_node_id, num_links); - num_links = 0; - } - - /* Aldebaran xGMI DPM is defeatured so assume x16 x 25Gbps for bandwidth. */ - return (num_links * 16 * 25000)/BITS_PER_BYTE; -} - int amdgpu_amdkfd_get_pcie_bandwidth_mbytes(struct amdgpu_device *adev, bool is_min) { int num_lanes_shift = (is_min ? ffs(adev->pm.pcie_mlw_mask) : diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h index 55d539967695..b6ca41859b53 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h @@ -254,11 +254,6 @@ int amdgpu_amdkfd_get_dmabuf_info(struct amdgpu_device *adev, int dma_buf_fd, uint64_t *bo_size, void *metadata_buffer, size_t buffer_size, uint32_t *metadata_size, uint32_t *flags, int8_t *xcp_id); -uint8_t amdgpu_amdkfd_get_xgmi_hops_count(struct amdgpu_device *dst, - struct amdgpu_device *src); -int amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(struct amdgpu_device *dst, - struct amdgpu_device *src, - bool is_min); int amdgpu_amdkfd_get_pcie_bandwidth_mbytes(struct amdgpu_device *adev, bool is_min); int amdgpu_amdkfd_send_close_event_drain_irq(struct amdgpu_device *adev, uint32_t *payload); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c index c98b6b35cfdf..49da137d42c9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c @@ -818,28 +818,69 @@ int amdgpu_xgmi_update_topology(struct amdgpu_hive_info *hive, struct amdgpu_dev * num_hops[2:0] = number of hops */ int amdgpu_xgmi_get_hops_count(struct amdgpu_device *adev, - struct amdgpu_device *peer_adev) + struct amdgpu_device *peer_adev) { struct psp_xgmi_topology_info *top = &adev->psp.xgmi_context.top_info; uint8_t num_hops_mask = 0x7; int i; + if (!adev->gmc.xgmi.supported) + return 0; + for (i = 0 ; i < top->num_nodes; ++i) if (top->nodes[i].node_id == peer_adev->gmc.xgmi.node_id) return top->nodes[i].num_hops & num_hops_mask; - return -EINVAL; + + dev_err(adev->dev, "Failed to get xgmi hops count for peer %d.\n", + peer_adev->gmc.xgmi.physical_node_id); + + return 0; } -int amdgpu_xgmi_get_num_links(struct amdgpu_device *adev, - struct amdgpu_device *peer_adev) +int amdgpu_xgmi_get_bandwidth(struct amdgpu_device *adev, struct amdgpu_device *peer_adev, + enum amdgpu_xgmi_bw_mode bw_mode, enum amdgpu_xgmi_bw_unit bw_unit, + uint32_t *min_bw, uint32_t *max_bw) { - struct psp_xgmi_topology_info *top = &adev->psp.xgmi_context.top_info; - int i; + bool peer_mode = bw_mode == AMDGPU_XGMI_BW_MODE_PER_PEER; + int unit_scale = bw_unit == AMDGPU_XGMI_BW_UNIT_MBYTES ? 1000 : 1; + int speed = 25, num_lanes = 16, num_links = !peer_mode ? 1 : -1; - for (i = 0 ; i < top->num_nodes; ++i) - if (top->nodes[i].node_id == peer_adev->gmc.xgmi.node_id) - return top->nodes[i].num_links; - return -EINVAL; + if (!(min_bw && max_bw)) + return -EINVAL; + + *min_bw = 0; + *max_bw = 0; + + if (!adev->gmc.xgmi.supported) + return -ENODATA; + + if (peer_mode && !peer_adev) + return -EINVAL; + + if (peer_mode) { + struct psp_xgmi_topology_info *top = &adev->psp.xgmi_context.top_info; + int i; + + for (i = 0 ; i < top->num_nodes; ++i) { + if (top->nodes[i].node_id != peer_adev->gmc.xgmi.node_id) + continue; + + num_links = top->nodes[i].num_links; + break; + } + } + + if (num_links == -1) { + dev_err(adev->dev, "Failed to get number of xgmi links for peer %d.\n", + peer_adev->gmc.xgmi.physical_node_id); + } else if (num_links) { + int per_link_bw = (speed * num_lanes * unit_scale)/BITS_PER_BYTE; + + *min_bw = per_link_bw; + *max_bw = num_links * per_link_bw; + } + + return 0; } bool amdgpu_xgmi_get_is_sharing_enabled(struct amdgpu_device *adev, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h index d1282b4c6348..924da0bec509 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h @@ -55,6 +55,22 @@ struct amdgpu_pcs_ras_field { uint32_t pcs_err_shift; }; +/** + * Bandwidth range reporting comes in two modes. + * + * PER_LINK - range for any xgmi link + * PER_PEER - range of max of single xgmi link to max of multiple links based on source peer + */ +enum amdgpu_xgmi_bw_mode { + AMDGPU_XGMI_BW_MODE_PER_LINK = 0, + AMDGPU_XGMI_BW_MODE_PER_PEER +}; + +enum amdgpu_xgmi_bw_unit { + AMDGPU_XGMI_BW_UNIT_GBYTES = 0, + AMDGPU_XGMI_BW_UNIT_MBYTES +}; + extern struct amdgpu_xgmi_ras xgmi_ras; struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev); void amdgpu_put_xgmi_hive(struct amdgpu_hive_info *hive); @@ -62,10 +78,10 @@ int amdgpu_xgmi_update_topology(struct amdgpu_hive_info *hive, struct amdgpu_dev int amdgpu_xgmi_add_device(struct amdgpu_device *adev); int amdgpu_xgmi_remove_device(struct amdgpu_device *adev); int amdgpu_xgmi_set_pstate(struct amdgpu_device *adev, int pstate); -int amdgpu_xgmi_get_hops_count(struct amdgpu_device *adev, - struct amdgpu_device *peer_adev); -int amdgpu_xgmi_get_num_links(struct amdgpu_device *adev, - struct amdgpu_device *peer_adev); +int amdgpu_xgmi_get_hops_count(struct amdgpu_device *adev, struct amdgpu_device *peer_adev); +int amdgpu_xgmi_get_bandwidth(struct amdgpu_device *adev, struct amdgpu_device *peer_adev, + enum amdgpu_xgmi_bw_mode bw_mode, enum amdgpu_xgmi_bw_unit bw_unit, + uint32_t *min_bw, uint32_t *max_bw); bool amdgpu_xgmi_get_is_sharing_enabled(struct amdgpu_device *adev, struct amdgpu_device *peer_adev); uint64_t amdgpu_xgmi_get_relative_phy_addr(struct amdgpu_device *adev, diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c index 70b3ae0b74fe..4a7180b46b71 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c @@ -2133,9 +2133,6 @@ static int kfd_fill_gpu_direct_io_link_to_cpu(int *avail_size, bool ext_cpu = KFD_GC_VERSION(kdev) != IP_VERSION(9, 4, 3); int mem_bw = 819200, weight = ext_cpu ? KFD_CRAT_XGMI_WEIGHT : KFD_CRAT_INTRA_SOCKET_WEIGHT; - uint32_t bandwidth = ext_cpu ? amdgpu_amdkfd_get_xgmi_bandwidth_mbytes( - kdev->adev, NULL, true) : mem_bw; - /* * with host gpu xgmi link, host can access gpu memory whether * or not pcie bar type is large, so always create bidirectional @@ -2144,8 +2141,16 @@ static int kfd_fill_gpu_direct_io_link_to_cpu(int *avail_size, sub_type_hdr->flags |= CRAT_IOLINK_FLAGS_BI_DIRECTIONAL; sub_type_hdr->io_interface_type = CRAT_IOLINK_TYPE_XGMI; sub_type_hdr->weight_xgmi = weight; - sub_type_hdr->minimum_bandwidth_mbs = bandwidth; - sub_type_hdr->maximum_bandwidth_mbs = bandwidth; + if (ext_cpu) { + amdgpu_xgmi_get_bandwidth(kdev->adev, NULL, + AMDGPU_XGMI_BW_MODE_PER_LINK, + AMDGPU_XGMI_BW_UNIT_MBYTES, + &sub_type_hdr->minimum_bandwidth_mbs, + &sub_type_hdr->maximum_bandwidth_mbs); + } else { + sub_type_hdr->minimum_bandwidth_mbs = mem_bw; + sub_type_hdr->maximum_bandwidth_mbs = mem_bw; + } } else { sub_type_hdr->io_interface_type = CRAT_IOLINK_TYPE_PCIEXPRESS; sub_type_hdr->minimum_bandwidth_mbs = @@ -2198,12 +2203,12 @@ static int kfd_fill_gpu_xgmi_link_to_gpu(int *avail_size, if (use_ta_info) { sub_type_hdr->weight_xgmi = KFD_CRAT_XGMI_WEIGHT * - amdgpu_amdkfd_get_xgmi_hops_count(kdev->adev, peer_kdev->adev); - sub_type_hdr->maximum_bandwidth_mbs = - amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(kdev->adev, - peer_kdev->adev, false); - sub_type_hdr->minimum_bandwidth_mbs = sub_type_hdr->maximum_bandwidth_mbs ? - amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(kdev->adev, NULL, true) : 0; + amdgpu_xgmi_get_hops_count(kdev->adev, peer_kdev->adev); + amdgpu_xgmi_get_bandwidth(kdev->adev, peer_kdev->adev, + AMDGPU_XGMI_BW_MODE_PER_PEER, + AMDGPU_XGMI_BW_UNIT_MBYTES, + &sub_type_hdr->minimum_bandwidth_mbs, + &sub_type_hdr->maximum_bandwidth_mbs); } else { bool is_single_hop = kdev->kfd == peer_kdev->kfd; int weight = is_single_hop ? KFD_CRAT_INTRA_SOCKET_WEIGHT : From 700e535db4ccd5ae0c0514f7d9a5fd9c98eb3855 Mon Sep 17 00:00:00 2001 From: Mangesh Gadre Date: Fri, 21 Feb 2025 17:38:21 +0800 Subject: [PATCH 064/235] drm/amd/pm: handling of set performance level display performance level when set not supported Signed-off-by: Mangesh Gadre Reviewed-by: Lijo Lazar Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 7 ++++++- drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index d71c8c58caa4..37ba84898bd5 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -2315,7 +2315,12 @@ static int smu_adjust_power_state_dynamic(struct smu_context *smu, if (smu_dpm_ctx->dpm_level != level) { ret = smu_asic_set_performance_level(smu, level); if (ret) { - dev_err(smu->adev->dev, "Failed to set performance level!"); + if (ret == -EOPNOTSUPP) + dev_info(smu->adev->dev, "set performance level %d not supported", + level); + else + dev_err(smu->adev->dev, "Failed to set performance level %d", + level); return ret; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c index 76cc827f128c..1e1d8989c77a 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c @@ -1940,7 +1940,7 @@ static int smu_v13_0_6_set_performance_level(struct smu_context *smu, break; } - return -EINVAL; + return -EOPNOTSUPP; } static int smu_v13_0_6_set_soft_freq_limited_range(struct smu_context *smu, From ce615fe328450b761eeb71c046072aeca3099f3d Mon Sep 17 00:00:00 2001 From: Xiang Liu Date: Mon, 24 Feb 2025 21:10:24 +0800 Subject: [PATCH 065/235] drm/amdgpu: Check if CPER enabled when generating CPER In the case of CPER disabled, generating CPER will cause kernel NULL pointer dereference without checking. Signed-off-by: Xiang Liu Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c | 3 +++ drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 5 +++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c index d11593cd1922..ffd4c64e123c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c @@ -392,6 +392,9 @@ static void aca_banks_generate_cper(struct amdgpu_device *adev, struct aca_bank_node *node; struct aca_bank *bank; + if (!adev->cper.enabled) + return; + if (!banks || !count) { dev_warn(adev->dev, "fail to generate cper records\n"); return; diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c index 7c4ff12269d9..81e9b443ca0a 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c @@ -716,8 +716,9 @@ int amdgpu_dpm_send_rma_reason(struct amdgpu_device *adev) ret = smu_send_rma_reason(smu); mutex_unlock(&adev->pm.mutex); - if (amdgpu_cper_generate_bp_threshold_record(adev)) - dev_warn(adev->dev, "fail to generate bad page threshold cper records\n"); + if (adev->cper.enabled) + if (amdgpu_cper_generate_bp_threshold_record(adev)) + dev_warn(adev->dev, "fail to generate bad page threshold cper records\n"); return ret; } From f2510355fba808972253a8d8729f05e064c89321 Mon Sep 17 00:00:00 2001 From: ganglxie Date: Mon, 24 Feb 2025 11:17:33 +0800 Subject: [PATCH 066/235] drm/amdgpu: Save nps to eeprom nps info saved together with bad page makes bad page parsing more efficient Signed-off-by: ganglxie Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 8 ++++++-- drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h | 7 +++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c index 83b54efcaa87..87fcdda3ec61 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c @@ -852,6 +852,7 @@ int amdgpu_ras_eeprom_append(struct amdgpu_ras_eeprom_control *control, { struct amdgpu_device *adev = to_amdgpu_device(control); int res, i; + uint64_t nps = AMDGPU_NPS1_PARTITION_MODE; if (!__is_ras_eeprom_supported(adev)) return 0; @@ -865,9 +866,12 @@ int amdgpu_ras_eeprom_append(struct amdgpu_ras_eeprom_control *control, return -EINVAL; } + if (adev->gmc.gmc_funcs->query_mem_partition_mode) + nps = adev->gmc.gmc_funcs->query_mem_partition_mode(adev); + /* set the new channel index flag */ for (i = 0; i < num; i++) - record[i].retired_page |= UMC_CHANNEL_IDX_V2; + record[i].retired_page |= (nps << UMC_NPS_SHIFT); mutex_lock(&control->ras_tbl_mutex); @@ -881,7 +885,7 @@ int amdgpu_ras_eeprom_append(struct amdgpu_ras_eeprom_control *control, /* clear channel index flag, the flag is only saved on eeprom */ for (i = 0; i < num; i++) - record[i].retired_page &= ~UMC_CHANNEL_IDX_V2; + record[i].retired_page &= ~(nps << UMC_NPS_SHIFT); return res; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h index a4a7e61817aa..857693bcd8d4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h @@ -71,6 +71,13 @@ */ #define UMC_CHANNEL_IDX_V2 BIT_ULL(47) +/* + * save nps value to eeprom_table_record.retired_page[47:40], + * the channel index flag above will be retired. + */ +#define UMC_NPS_SHIFT 40 +#define UMC_NPS_MASK 0xffULL + typedef int (*umc_func)(struct amdgpu_device *adev, uint32_t node_inst, uint32_t umc_inst, uint32_t ch_inst, void *data); From ff930483af93753cc3ba252e13f3cd92e505f0f0 Mon Sep 17 00:00:00 2001 From: Xiang Liu Date: Mon, 24 Feb 2025 23:01:06 +0800 Subject: [PATCH 067/235] drm/amdgpu: Set CPER enabled flag after ring initiailized Setting cper.enabled to be true only after cper ring is successfully created. Signed-off-by: Xiang Liu Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c index 20c474a32852..5b6bdabb8012 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c @@ -538,15 +538,23 @@ static int amdgpu_cper_ring_init(struct amdgpu_device *adev) int amdgpu_cper_init(struct amdgpu_device *adev) { + int r; + if (!amdgpu_aca_is_enabled(adev)) return 0; + r = amdgpu_cper_ring_init(adev); + if (r) { + dev_err(adev->dev, "fail to initiailize cper ring, r = %d\n", r); + return r; + } + mutex_init(&adev->cper.cper_lock); adev->cper.enabled = true; adev->cper.max_count = CPER_MAX_ALLOWED_COUNT; - return amdgpu_cper_ring_init(adev); + return 0; } int amdgpu_cper_fini(struct amdgpu_device *adev) From e4e6ae41cc9d96f253383e1ef2b705387f45a132 Mon Sep 17 00:00:00 2001 From: "Jesse.zhang@amd.com" Date: Fri, 21 Feb 2025 18:18:07 +0800 Subject: [PATCH 068/235] drm/amdgpu: update SDMA sysfs reset mask in late_init - Added `sdma_v4_4_2_update_reset_mask` function to update the reset mask. - update the sysfs reset mask to the `late_init` stage to ensure that the SMU initialization and capability setup are completed before checking the SDMA reset capability. - For IP versions 9.4.3 and 9.4.4, enable per-queue reset if the MEC firmware version is at least 0xb0 and PMFW supports queue reset. - Add a TODO comment for future support of per-queue reset for IP version 9.5.0. This change ensures that per-queue reset is only enabled when the MEC and PMFW support it. v2: fix ip version (9.5.4 -> 9.5.0)(Lijo) Suggested-by: Jonathan Kim Signed-off-by: Vitaly Prosyak Signed-off-by: Jesse Zhang Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c | 37 +++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c index 4fa688e00f5e..ba43c8f46f45 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c @@ -107,6 +107,7 @@ static void sdma_v4_4_2_set_vm_pte_funcs(struct amdgpu_device *adev); static void sdma_v4_4_2_set_irq_funcs(struct amdgpu_device *adev); static void sdma_v4_4_2_set_ras_funcs(struct amdgpu_device *adev); static void sdma_v4_4_2_set_engine_reset_funcs(struct amdgpu_device *adev); +static void sdma_v4_4_2_update_reset_mask(struct amdgpu_device *adev); static u32 sdma_v4_4_2_get_reg_offset(struct amdgpu_device *adev, u32 instance, u32 offset) @@ -1374,6 +1375,12 @@ static int sdma_v4_4_2_late_init(struct amdgpu_ip_block *ip_block) if (!amdgpu_persistent_edc_harvesting_supported(adev)) amdgpu_ras_reset_error_count(adev, AMDGPU_RAS_BLOCK__SDMA); + /* The initialization is done in the late_init stage to ensure that the SMU + * initialization and capability setup are completed before we check the SDMA + * reset capability + */ + sdma_v4_4_2_update_reset_mask(adev); + return 0; } @@ -1481,7 +1488,6 @@ static int sdma_v4_4_2_sw_init(struct amdgpu_ip_block *ip_block) } } - /* TODO: Add queue reset mask when FW fully supports it */ adev->sdma.supported_reset = amdgpu_get_soft_full_reset_mask(&adev->sdma.instance[0].ring); @@ -2328,6 +2334,35 @@ static void sdma_v4_4_2_set_vm_pte_funcs(struct amdgpu_device *adev) adev->vm_manager.vm_pte_num_scheds = adev->sdma.num_instances; } +/** + * sdma_v4_4_2_update_reset_mask - update reset mask for SDMA + * @adev: Pointer to the AMDGPU device structure + * + * This function update reset mask for SDMA and sets the supported + * reset types based on the IP version and firmware versions. + * + */ +static void sdma_v4_4_2_update_reset_mask(struct amdgpu_device *adev) +{ + + /* + * the user queue relies on MEC fw and pmfw when the sdma queue do reset. + * it needs to check both of them at here to skip old mec and pmfw. + */ + switch (amdgpu_ip_version(adev, GC_HWIP, 0)) { + case IP_VERSION(9, 4, 3): + case IP_VERSION(9, 4, 4): + if ((adev->gfx.mec_fw_version >= 0xb0) && amdgpu_dpm_reset_sdma_is_supported(adev)) + adev->sdma.supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE; + break; + case IP_VERSION(9, 5, 0): + /*TODO: enable the queue reset flag until fw supported */ + default: + break; + } + +} + const struct amdgpu_ip_block_version sdma_v4_4_2_ip_block = { .type = AMD_IP_BLOCK_TYPE_SDMA, .major = 4, From e6aae1db41e501f9b553ba3289c599e657de04d8 Mon Sep 17 00:00:00 2001 From: Asad Kamal Date: Sat, 22 Feb 2025 18:11:35 +0800 Subject: [PATCH 069/235] drm/amd/pm: Get metrics table version for smu_v13_0_12 Get metrics table version for smu_v13_0_12 and populate pm_metrics Signed-off-by: Asad Kamal Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c index 5e7e97d90805..5e80b9aabfc9 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c @@ -208,6 +208,7 @@ int smu_v13_0_12_setup_driver_pptable(struct smu_context *smu) StaticMetricsTable_t *static_metrics = (StaticMetricsTable_t *)smu_table->metrics_table; struct PPTable_t *pptable = (struct PPTable_t *)smu_table->driver_pptable; + uint32_t table_version; int ret, i; if (!pptable->Init) { @@ -215,6 +216,13 @@ int smu_v13_0_12_setup_driver_pptable(struct smu_context *smu) if (ret) return ret; + ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetMetricsVersion, + &table_version); + if (ret) + return ret; + smu_table->tables[SMU_TABLE_SMU_METRICS].version = + table_version; + pptable->MaxSocketPowerLimit = SMUQ10_ROUND(static_metrics->MaxSocketPowerLimit); pptable->MaxGfxclkFrequency = From 0153d27673ac5c122d2437c1e573923963abd181 Mon Sep 17 00:00:00 2001 From: ganglxie Date: Mon, 24 Feb 2025 15:03:05 +0800 Subject: [PATCH 070/235] drm/amdgpu: Refine bad page adding bad page adding can be simpler with nps info Signed-off-by: ganglxie Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 196 +++++++++++++----------- 1 file changed, 104 insertions(+), 92 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 3c3312bbfee8..f0349094f8c9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -2799,20 +2799,100 @@ static int amdgpu_ras_mca2pa(struct amdgpu_device *adev, return -EINVAL; } +static int __amdgpu_ras_restore_bad_pages(struct amdgpu_device *adev, + struct eeprom_table_record *bps, int count) +{ + int j; + struct amdgpu_ras *con = amdgpu_ras_get_context(adev); + struct ras_err_handler_data *data = con->eh_data; + + for (j = 0; j < count; j++) { + if (amdgpu_ras_check_bad_page_unlock(con, + bps[j].retired_page << AMDGPU_GPU_PAGE_SHIFT)) + continue; + + if (!data->space_left && + amdgpu_ras_realloc_eh_data_space(adev, data, 256)) { + return -ENOMEM; + } + + amdgpu_ras_reserve_page(adev, bps[j].retired_page); + + memcpy(&data->bps[data->count], &(bps[j]), + sizeof(struct eeprom_table_record)); + data->count++; + data->space_left--; + } + + return 0; +} + +static int __amdgpu_ras_convert_rec_array_from_rom(struct amdgpu_device *adev, + struct eeprom_table_record *bps, struct ras_err_data *err_data, + enum amdgpu_memory_partition nps) +{ + int i = 0; + enum amdgpu_memory_partition save_nps; + + save_nps = (bps[0].retired_page >> UMC_NPS_SHIFT) & UMC_NPS_MASK; + + for (i = 0; i < adev->umc.retire_unit; i++) + bps[i].retired_page &= ~(UMC_NPS_MASK << UMC_NPS_SHIFT); + + if (save_nps) { + if (save_nps == nps) { + if (amdgpu_umc_pages_in_a_row(adev, err_data, + bps[0].retired_page << AMDGPU_GPU_PAGE_SHIFT)) + return -EINVAL; + } else { + if (amdgpu_ras_mca2pa_by_idx(adev, &bps[0], err_data)) + return -EINVAL; + } + } else { + if (amdgpu_ras_mca2pa(adev, &bps[0], err_data)) { + if (nps == AMDGPU_NPS1_PARTITION_MODE) + memcpy(err_data->err_addr, bps, + sizeof(struct eeprom_table_record) * adev->umc.retire_unit); + else + return -EOPNOTSUPP; + } + } + + return __amdgpu_ras_restore_bad_pages(adev, err_data->err_addr, adev->umc.retire_unit); +} + +static int __amdgpu_ras_convert_rec_from_rom(struct amdgpu_device *adev, + struct eeprom_table_record *bps, struct ras_err_data *err_data, + enum amdgpu_memory_partition nps) +{ + enum amdgpu_memory_partition save_nps; + + save_nps = (bps->retired_page >> UMC_NPS_SHIFT) & UMC_NPS_MASK; + bps->retired_page &= ~(UMC_NPS_MASK << UMC_NPS_SHIFT); + + if (save_nps == nps) { + if (amdgpu_umc_pages_in_a_row(adev, err_data, + bps->retired_page << AMDGPU_GPU_PAGE_SHIFT)) + return -EINVAL; + } else { + if (amdgpu_ras_mca2pa_by_idx(adev, bps, err_data)) + return -EINVAL; + } + return __amdgpu_ras_restore_bad_pages(adev, err_data->err_addr, + adev->umc.retire_unit); +} + /* it deal with vram only. */ int amdgpu_ras_add_bad_pages(struct amdgpu_device *adev, struct eeprom_table_record *bps, int pages, bool from_rom) { struct amdgpu_ras *con = amdgpu_ras_get_context(adev); - struct ras_err_handler_data *data; struct ras_err_data err_data; - struct eeprom_table_record *err_rec; struct amdgpu_ras_eeprom_control *control = &adev->psp.ras_context.ras->eeprom_control; enum amdgpu_memory_partition nps = AMDGPU_NPS1_PARTITION_MODE; int ret = 0; - uint32_t i, j, loop_cnt = 1; - bool find_pages_per_pa = false; + uint32_t i; if (!con || !con->eh_data || !bps || pages <= 0) return 0; @@ -2823,114 +2903,46 @@ int amdgpu_ras_add_bad_pages(struct amdgpu_device *adev, sizeof(struct eeprom_table_record), GFP_KERNEL); if (!err_data.err_addr) { dev_warn(adev->dev, "Failed to alloc UMC error address record in mca2pa conversion!\n"); - ret = -ENOMEM; - goto out; + return -ENOMEM; } - err_rec = err_data.err_addr; - loop_cnt = adev->umc.retire_unit; if (adev->gmc.gmc_funcs->query_mem_partition_mode) nps = adev->gmc.gmc_funcs->query_mem_partition_mode(adev); } mutex_lock(&con->recovery_lock); - data = con->eh_data; - if (!data) { - /* Returning 0 as the absence of eh_data is acceptable */ - goto free; - } - for (i = 0; i < pages; i++) { - if (from_rom && - control->rec_type == AMDGPU_RAS_EEPROM_REC_MCA) { - if (!find_pages_per_pa) { - if (amdgpu_ras_mca2pa_by_idx(adev, &bps[i], &err_data)) { - if (!i && nps == AMDGPU_NPS1_PARTITION_MODE) { - /* may use old RAS TA, use PA to find pages in - * one row - */ - if (amdgpu_umc_pages_in_a_row(adev, &err_data, - bps[i].retired_page << - AMDGPU_GPU_PAGE_SHIFT)) { - ret = -EINVAL; - goto free; - } else { - find_pages_per_pa = true; - } - } else { - /* unsupported cases */ - ret = -EOPNOTSUPP; + if (from_rom) { + for (i = 0; i < pages; i++) { + if (control->ras_num_recs - i >= adev->umc.retire_unit) { + if ((bps[i].address == bps[i + 1].address) && + (bps[i].mem_channel == bps[i + 1].mem_channel)) { + //deal with retire_unit records a time + ret = __amdgpu_ras_convert_rec_array_from_rom(adev, + &bps[i], &err_data, nps); + if (ret) goto free; - } - } - } else { - if (amdgpu_umc_pages_in_a_row(adev, &err_data, - bps[i].retired_page << AMDGPU_GPU_PAGE_SHIFT)) { - ret = -EINVAL; - goto free; - } - } - } else { - if (from_rom && !find_pages_per_pa) { - if (bps[i].retired_page & UMC_CHANNEL_IDX_V2) { - /* bad page in any NPS mode in eeprom */ - if (amdgpu_ras_mca2pa_by_idx(adev, &bps[i], &err_data)) { - ret = -EINVAL; - goto free; - } - } else { - /* legacy bad page in eeprom, generated only in - * NPS1 mode - */ - if (amdgpu_ras_mca2pa(adev, &bps[i], &err_data)) { - /* old RAS TA or ASICs which don't support to - * convert addrss via mca address - */ - if (!i && nps == AMDGPU_NPS1_PARTITION_MODE) { - find_pages_per_pa = true; - err_rec = &bps[i]; - loop_cnt = 1; - } else { - /* non-nps1 mode, old RAS TA - * can't support it - */ - ret = -EOPNOTSUPP; - goto free; - } - } - } - - if (!find_pages_per_pa) i += (adev->umc.retire_unit - 1); + } else { + break; + } } else { - err_rec = &bps[i]; + break; } } - - for (j = 0; j < loop_cnt; j++) { - if (amdgpu_ras_check_bad_page_unlock(con, - err_rec[j].retired_page << AMDGPU_GPU_PAGE_SHIFT)) - continue; - - if (!data->space_left && - amdgpu_ras_realloc_eh_data_space(adev, data, 256)) { - ret = -ENOMEM; + for (; i < pages; i++) { + ret = __amdgpu_ras_convert_rec_from_rom(adev, + &bps[i], &err_data, nps); + if (ret) goto free; - } - - amdgpu_ras_reserve_page(adev, err_rec[j].retired_page); - - memcpy(&data->bps[data->count], &(err_rec[j]), - sizeof(struct eeprom_table_record)); - data->count++; - data->space_left--; } + } else { + ret = __amdgpu_ras_restore_bad_pages(adev, bps, pages); } free: if (from_rom) kfree(err_data.err_addr); -out: mutex_unlock(&con->recovery_lock); return ret; From a8f921a10a8c2e2b209ad9ed1f1b7f48192c30aa Mon Sep 17 00:00:00 2001 From: ganglxie Date: Mon, 24 Feb 2025 15:06:51 +0800 Subject: [PATCH 071/235] drm/amdgpu: Change page/record number calculation based on nps save only one record to save eeprom space,and bad_page_num = pa_rec_num + mca_rec_num*16 Signed-off-by: ganglxie Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 49 +++++++++---------- .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 17 +++---- .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h | 20 +++----- 3 files changed, 35 insertions(+), 51 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index f0349094f8c9..493dd004d6fa 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -2981,24 +2981,14 @@ int amdgpu_ras_save_bad_pages(struct amdgpu_device *adev, /* only new entries are saved */ if (save_count > 0) { - if (control->rec_type == AMDGPU_RAS_EEPROM_REC_PA) { + for (i = 0; i < unit_num; i++) { if (amdgpu_ras_eeprom_append(control, - &data->bps[control->ras_num_recs], - save_count)) { + &data->bps[bad_page_num + i * adev->umc.retire_unit], + 1)) { dev_err(adev->dev, "Failed to save EEPROM table data!"); return -EIO; } - } else { - for (i = 0; i < unit_num; i++) { - if (amdgpu_ras_eeprom_append(control, - &data->bps[bad_page_num + i * adev->umc.retire_unit], - 1)) { - dev_err(adev->dev, "Failed to save EEPROM table data!"); - return -EIO; - } - } } - dev_info(adev->dev, "Saved %d pages to EEPROM table.\n", save_count); } @@ -3014,7 +3004,7 @@ static int amdgpu_ras_load_bad_pages(struct amdgpu_device *adev) struct amdgpu_ras_eeprom_control *control = &adev->psp.ras_context.ras->eeprom_control; struct eeprom_table_record *bps; - int ret; + int ret, i = 0; /* no bad page record, skip eeprom access */ if (control->ras_num_recs == 0 || amdgpu_bad_page_threshold == 0) @@ -3028,13 +3018,23 @@ static int amdgpu_ras_load_bad_pages(struct amdgpu_device *adev) if (ret) { dev_err(adev->dev, "Failed to load EEPROM table records!"); } else { - if (control->ras_num_recs > 1 && - adev->umc.ras && adev->umc.ras->convert_ras_err_addr) { - if ((bps[0].address == bps[1].address) && - (bps[0].mem_channel == bps[1].mem_channel)) - control->rec_type = AMDGPU_RAS_EEPROM_REC_PA; - else - control->rec_type = AMDGPU_RAS_EEPROM_REC_MCA; + if (adev->umc.ras && adev->umc.ras->convert_ras_err_addr) { + for (i = 0; i < control->ras_num_recs; i++) { + if ((control->ras_num_recs - i) >= adev->umc.retire_unit) { + if ((bps[i].address == bps[i + 1].address) && + (bps[i].mem_channel == bps[i + 1].mem_channel)) { + control->ras_num_pa_recs += adev->umc.retire_unit; + i += (adev->umc.retire_unit - 1); + } else { + control->ras_num_mca_recs += + (control->ras_num_recs - i); + break; + } + } else { + control->ras_num_mca_recs += (control->ras_num_recs - i); + break; + } + } } ret = amdgpu_ras_eeprom_check(control); @@ -3440,12 +3440,7 @@ int amdgpu_ras_init_badpage_info(struct amdgpu_device *adev) return ret; if (!adev->umc.ras || !adev->umc.ras->convert_ras_err_addr) - control->rec_type = AMDGPU_RAS_EEPROM_REC_PA; - - /* default status is MCA storage */ - if (control->ras_num_recs <= 1 && - adev->umc.ras && adev->umc.ras->convert_ras_err_addr) - control->rec_type = AMDGPU_RAS_EEPROM_REC_MCA; + control->ras_num_pa_recs = control->ras_num_recs; if (control->ras_num_recs) { ret = amdgpu_ras_load_bad_pages(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c index 87fcdda3ec61..ab27cecb5519 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c @@ -727,11 +727,9 @@ amdgpu_ras_eeprom_append_table(struct amdgpu_ras_eeprom_control *control, - control->ras_fri) % control->ras_max_record_count; - if (control->rec_type == AMDGPU_RAS_EEPROM_REC_PA) - control->ras_num_bad_pages = control->ras_num_recs; - else - control->ras_num_bad_pages = - control->ras_num_recs * adev->umc.retire_unit; + control->ras_num_mca_recs += num; + control->ras_num_bad_pages += num * adev->umc.retire_unit; + Out: kfree(buf); return res; @@ -1396,6 +1394,8 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control) } control->ras_fri = RAS_OFFSET_TO_INDEX(control, hdr->first_rec_offset); + control->ras_num_mca_recs = 0; + control->ras_num_pa_recs = 0; return 0; } @@ -1416,11 +1416,8 @@ int amdgpu_ras_eeprom_check(struct amdgpu_ras_eeprom_control *control) if (!__get_eeprom_i2c_addr(adev, control)) return -EINVAL; - if (control->rec_type == AMDGPU_RAS_EEPROM_REC_PA) - control->ras_num_bad_pages = control->ras_num_recs; - else - control->ras_num_bad_pages = - control->ras_num_recs * adev->umc.retire_unit; + control->ras_num_bad_pages = control->ras_num_pa_recs + + control->ras_num_mca_recs * adev->umc.retire_unit; if (hdr->header == RAS_TABLE_HDR_VAL) { DRM_DEBUG_DRIVER("Found existing EEPROM table with %d records", diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h index 81d55cb7b397..13f7eda9a696 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h @@ -43,19 +43,6 @@ enum amdgpu_ras_eeprom_err_type { AMDGPU_RAS_EEPROM_ERR_COUNT, }; -/* - * one UMC MCA address could map to multiply physical address (PA), - * such as 1:16, we use eeprom_table_record.address to store MCA - * address and use eeprom_table_record.retired_page to save PA. - * - * AMDGPU_RAS_EEPROM_REC_PA: one record store one PA - * AMDGPU_RAS_EEPROM_REC_MCA: one record store one MCA address - */ -enum amdgpu_ras_eeprom_rec_type { - AMDGPU_RAS_EEPROM_REC_PA, - AMDGPU_RAS_EEPROM_REC_MCA, -}; - struct amdgpu_ras_eeprom_table_header { uint32_t header; uint32_t version; @@ -100,6 +87,12 @@ struct amdgpu_ras_eeprom_control { */ u32 ras_num_bad_pages; + /* Number of records store mca address */ + u32 ras_num_mca_recs; + + /* Number of records store physical address */ + u32 ras_num_pa_recs; + /* First record index to read, 0-based. * Range is [0, num_recs-1]. This is * an absolute index, starting right after @@ -120,7 +113,6 @@ struct amdgpu_ras_eeprom_control { /* Record channel info which occurred bad pages */ u32 bad_channel_bitmap; - enum amdgpu_ras_eeprom_rec_type rec_type; }; /* From 7c62aacc3b452f73a1284198c81551035fac6d71 Mon Sep 17 00:00:00 2001 From: Pierre-Eric Pelloux-Prayer Date: Thu, 20 Feb 2025 14:41:59 +0100 Subject: [PATCH 072/235] drm/amdgpu: init return value in amdgpu_ttm_clear_buffer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise an uninitialized value can be returned if amdgpu_res_cleared returns true for all regions. Possibly closes: https://gitlab.freedesktop.org/drm/amd/-/issues/3812 Fixes: a68c7eaa7a8f ("drm/amdgpu: Enable clear page functionality") Signed-off-by: Pierre-Eric Pelloux-Prayer Acked-by: Alex Deucher Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index bcb4bcc4ab75..53b71e9d8076 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -2295,7 +2295,7 @@ int amdgpu_ttm_clear_buffer(struct amdgpu_bo *bo, struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring; struct amdgpu_res_cursor cursor; u64 addr; - int r; + int r = 0; if (!adev->mman.buffer_funcs_enabled) return -EINVAL; From 59f9c2c9f6f87c640d82a9751647d2eb1c4f0095 Mon Sep 17 00:00:00 2001 From: Srinivasan Shanmugam Date: Mon, 24 Feb 2025 17:26:22 +0530 Subject: [PATCH 073/235] drm/amdgpu: Fix correct parameter desc for VCN idle check functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the kdoc for the following VCN idle check functions by updating the parameter description from 'handle' to 'ip_block': - vcn_v4_0_is_idle - vcn_v4_0_3_is_idle - vcn_v4_0_5_is_idle - vcn_v5_0_1_is_idle Fixes the below with gcc W=1: drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c:935: warning: Function parameter or struct member 'ip_block' not described in 'vcn_v5_0_1_is_idle' drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c:935: warning: Excess function parameter 'handle' description in 'vcn_v5_0_1_is_idle' drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c:1972: warning: Function parameter or struct member 'ip_block' not described in 'vcn_v4_0_is_idle' drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c:1972: warning: Excess function parameter 'handle' description in 'vcn_v4_0_is_idle' drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c:1583: warning: Function parameter or struct member 'ip_block' not described in 'vcn_v4_0_3_is_idle' drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c:1583: warning: Excess function parameter 'handle' description in 'vcn_v4_0_3_is_idle' drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c:1200: warning: Function parameter or struct member 'ip_block' not described in 'vcn_v5_0_0_is_idle' drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c:1200: warning: Excess function parameter 'handle' description in 'vcn_v5_0_0_is_idle' drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c:1460: warning: Function parameter or struct member 'ip_block' not described in 'vcn_v4_0_5_is_idle' drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c:1460: warning: Excess function parameter 'handle' description in 'vcn_v4_0_5_is_idle' Cc: Christian König Cc: Alex Deucher Signed-off-by: Srinivasan Shanmugam Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c | 2 +- drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c | 2 +- drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c index fe539f7957f0..0dd844243531 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c @@ -1964,7 +1964,7 @@ static void vcn_v4_0_set_unified_ring_funcs(struct amdgpu_device *adev) /** * vcn_v4_0_is_idle - check VCN block is idle * - * @handle: amdgpu_device pointer + * @ip_block: Pointer to the amdgpu_ip_block structure * * Check whether VCN block is idle */ diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c index dda5ee187948..c936bd08963e 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c @@ -1575,7 +1575,7 @@ static void vcn_v4_0_3_set_unified_ring_funcs(struct amdgpu_device *adev) /** * vcn_v4_0_3_is_idle - check VCN block is idle * - * @handle: amdgpu_device pointer + * @ip_block: Pointer to the amdgpu_ip_block structure * * Check whether VCN block is idle */ diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c index a482658cbf86..5e6ad825cc47 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c @@ -1452,7 +1452,7 @@ static void vcn_v4_0_5_set_unified_ring_funcs(struct amdgpu_device *adev) /** * vcn_v4_0_5_is_idle - check VCN block is idle * - * @handle: amdgpu_device pointer + * @ip_block: Pointer to the amdgpu_ip_block structure * * Check whether VCN block is idle */ diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c index 721c29f52451..40f36c9a4132 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c @@ -927,7 +927,7 @@ static void vcn_v5_0_1_set_unified_ring_funcs(struct amdgpu_device *adev) /** * vcn_v5_0_1_is_idle - check VCN block is idle * - * @handle: amdgpu_device pointer + * @ip_block: Pointer to the amdgpu_ip_block structure * * Check whether VCN block is idle */ From dab993bf151359e4e4d045c5469f34333e88e359 Mon Sep 17 00:00:00 2001 From: Tao Zhou Date: Tue, 25 Feb 2025 19:18:12 +0800 Subject: [PATCH 074/235] drm/amdgpu: increase AMDGPU_MAX_RINGS Increase it since a cper ring is introduced. Signed-off-by: Tao Zhou Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h index 52f7a9a79e7b..b4fd1e17205e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h @@ -37,7 +37,7 @@ struct amdgpu_job; struct amdgpu_vm; /* max number of rings */ -#define AMDGPU_MAX_RINGS 132 +#define AMDGPU_MAX_RINGS 133 #define AMDGPU_MAX_HWIP_RINGS 64 #define AMDGPU_MAX_GFX_RINGS 2 #define AMDGPU_MAX_SW_GFX_RINGS 2 From dae870019866b247a7796359c4327ade3170faa4 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 24 Feb 2025 11:13:27 -0500 Subject: [PATCH 075/235] drm/amdgpu/vcn2.5: fix VCN stop logic Need to make sure we call amdgpu_dpm_enable_vcn() in vcn_v2_5_stop() at the end if there are errors or DPG is enabled. Fixes: ebc25499de12 ("drm/amdgpu/vcn2.5: split code along instances") Reviewed-by: Boyuan Zhang Suggested-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c index a6726afcf89c..e36e2a5676df 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c @@ -1414,13 +1414,15 @@ static int vcn_v2_5_stop(struct amdgpu_device *adev, int i) if (adev->vcn.harvest_config & (1 << i)) return 0; - if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) - return vcn_v2_5_stop_dpg_mode(adev, i); + if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) { + r = vcn_v2_5_stop_dpg_mode(adev, i); + goto done; + } /* wait for vcn idle */ r = SOC15_WAIT_ON_RREG(VCN, i, mmUVD_STATUS, UVD_STATUS__IDLE, 0x7); if (r) - return r; + goto done; tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK | UVD_LMI_STATUS__READ_CLEAN_MASK | @@ -1428,7 +1430,7 @@ static int vcn_v2_5_stop(struct amdgpu_device *adev, int i) UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK; r = SOC15_WAIT_ON_RREG(VCN, i, mmUVD_LMI_STATUS, tmp, tmp); if (r) - return r; + goto done; /* block LMI UMC channel */ tmp = RREG32_SOC15(VCN, i, mmUVD_LMI_CTRL2); @@ -1439,7 +1441,7 @@ static int vcn_v2_5_stop(struct amdgpu_device *adev, int i) UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK; r = SOC15_WAIT_ON_RREG(VCN, i, mmUVD_LMI_STATUS, tmp, tmp); if (r) - return r; + goto done; /* block VCPU register access */ WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_RB_ARB_CTRL), @@ -1465,10 +1467,11 @@ static int vcn_v2_5_stop(struct amdgpu_device *adev, int i) UVD_POWER_STATUS__UVD_POWER_STATUS_MASK, ~UVD_POWER_STATUS__UVD_POWER_STATUS_MASK); +done: if (adev->pm.dpm_enabled) amdgpu_dpm_enable_vcn(adev, false, i); - return 0; + return r; } static int vcn_v2_5_pause_dpg_mode(struct amdgpu_device *adev, From d39f1bb57741ff6e34dd3c2937d5cddfed8a499c Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 13 Nov 2024 11:47:49 -0500 Subject: [PATCH 076/235] drm/amdgpu/vcn3.0: split code along instances Split the code on a per instance basis. This will allow us to use the per instance functions in the future to handle more things per instance. v2: squash in fix for stop() from Boyuan Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 431 +++++++++++++------------- 1 file changed, 212 insertions(+), 219 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c index f75f996d929e..ec42a456c541 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c @@ -1134,192 +1134,186 @@ static int vcn_v3_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo return 0; } -static int vcn_v3_0_start(struct amdgpu_device *adev) +static int vcn_v3_0_start(struct amdgpu_device *adev, int i) { volatile struct amdgpu_fw_shared *fw_shared; struct amdgpu_ring *ring; uint32_t rb_bufsz, tmp; - int i, j, k, r; + int j, k, r; - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { - if (adev->pm.dpm_enabled) - amdgpu_dpm_enable_vcn(adev, true, i); - } + if (adev->vcn.harvest_config & (1 << i)) + return 0; - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { - if (adev->vcn.harvest_config & (1 << i)) - continue; + if (adev->pm.dpm_enabled) + amdgpu_dpm_enable_vcn(adev, true, i); - if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) { - r = vcn_v3_0_start_dpg_mode(adev, i, adev->vcn.indirect_sram); - continue; - } + if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) + return vcn_v3_0_start_dpg_mode(adev, i, adev->vcn.indirect_sram); - /* disable VCN power gating */ - vcn_v3_0_disable_static_power_gating(adev, i); + /* disable VCN power gating */ + vcn_v3_0_disable_static_power_gating(adev, i); - /* set VCN status busy */ - tmp = RREG32_SOC15(VCN, i, mmUVD_STATUS) | UVD_STATUS__UVD_BUSY; - WREG32_SOC15(VCN, i, mmUVD_STATUS, tmp); + /* set VCN status busy */ + tmp = RREG32_SOC15(VCN, i, mmUVD_STATUS) | UVD_STATUS__UVD_BUSY; + WREG32_SOC15(VCN, i, mmUVD_STATUS, tmp); - /*SW clock gating */ - vcn_v3_0_disable_clock_gating(adev, i); + /* SW clock gating */ + vcn_v3_0_disable_clock_gating(adev, i); - /* enable VCPU clock */ - WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL), - UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK); + /* enable VCPU clock */ + WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL), + UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK); - /* disable master interrupt */ - WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_MASTINT_EN), 0, - ~UVD_MASTINT_EN__VCPU_EN_MASK); + /* disable master interrupt */ + WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_MASTINT_EN), 0, + ~UVD_MASTINT_EN__VCPU_EN_MASK); - /* enable LMI MC and UMC channels */ - WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_LMI_CTRL2), 0, - ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK); + /* enable LMI MC and UMC channels */ + WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_LMI_CTRL2), 0, + ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK); - tmp = RREG32_SOC15(VCN, i, mmUVD_SOFT_RESET); - tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK; - tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK; - WREG32_SOC15(VCN, i, mmUVD_SOFT_RESET, tmp); + tmp = RREG32_SOC15(VCN, i, mmUVD_SOFT_RESET); + tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK; + tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK; + WREG32_SOC15(VCN, i, mmUVD_SOFT_RESET, tmp); - /* setup mmUVD_LMI_CTRL */ - tmp = RREG32_SOC15(VCN, i, mmUVD_LMI_CTRL); - WREG32_SOC15(VCN, i, mmUVD_LMI_CTRL, tmp | - UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK | - UVD_LMI_CTRL__MASK_MC_URGENT_MASK | - UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK | - UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK); + /* setup mmUVD_LMI_CTRL */ + tmp = RREG32_SOC15(VCN, i, mmUVD_LMI_CTRL); + WREG32_SOC15(VCN, i, mmUVD_LMI_CTRL, tmp | + UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK | + UVD_LMI_CTRL__MASK_MC_URGENT_MASK | + UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK | + UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK); - /* setup mmUVD_MPC_CNTL */ - tmp = RREG32_SOC15(VCN, i, mmUVD_MPC_CNTL); - tmp &= ~UVD_MPC_CNTL__REPLACEMENT_MODE_MASK; - tmp |= 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT; - WREG32_SOC15(VCN, i, mmUVD_MPC_CNTL, tmp); + /* setup mmUVD_MPC_CNTL */ + tmp = RREG32_SOC15(VCN, i, mmUVD_MPC_CNTL); + tmp &= ~UVD_MPC_CNTL__REPLACEMENT_MODE_MASK; + tmp |= 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT; + WREG32_SOC15(VCN, i, mmUVD_MPC_CNTL, tmp); - /* setup UVD_MPC_SET_MUXA0 */ - WREG32_SOC15(VCN, i, mmUVD_MPC_SET_MUXA0, - ((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) | - (0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) | - (0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) | - (0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT))); + /* setup UVD_MPC_SET_MUXA0 */ + WREG32_SOC15(VCN, i, mmUVD_MPC_SET_MUXA0, + ((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) | + (0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) | + (0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) | + (0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT))); - /* setup UVD_MPC_SET_MUXB0 */ - WREG32_SOC15(VCN, i, mmUVD_MPC_SET_MUXB0, - ((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) | - (0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) | - (0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) | - (0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT))); + /* setup UVD_MPC_SET_MUXB0 */ + WREG32_SOC15(VCN, i, mmUVD_MPC_SET_MUXB0, + ((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) | + (0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) | + (0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) | + (0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT))); - /* setup mmUVD_MPC_SET_MUX */ - WREG32_SOC15(VCN, i, mmUVD_MPC_SET_MUX, - ((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) | - (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) | - (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT))); + /* setup mmUVD_MPC_SET_MUX */ + WREG32_SOC15(VCN, i, mmUVD_MPC_SET_MUX, + ((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) | + (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) | + (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT))); - vcn_v3_0_mc_resume(adev, i); + vcn_v3_0_mc_resume(adev, i); - /* VCN global tiling registers */ - WREG32_SOC15(VCN, i, mmUVD_GFX10_ADDR_CONFIG, - adev->gfx.config.gb_addr_config); + /* VCN global tiling registers */ + WREG32_SOC15(VCN, i, mmUVD_GFX10_ADDR_CONFIG, + adev->gfx.config.gb_addr_config); - /* unblock VCPU register access */ - WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_RB_ARB_CTRL), 0, - ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK); + /* unblock VCPU register access */ + WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_RB_ARB_CTRL), 0, + ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK); - /* release VCPU reset to boot */ - WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL), 0, - ~UVD_VCPU_CNTL__BLK_RST_MASK); + /* release VCPU reset to boot */ + WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL), 0, + ~UVD_VCPU_CNTL__BLK_RST_MASK); - for (j = 0; j < 10; ++j) { - uint32_t status; + for (j = 0; j < 10; ++j) { + uint32_t status; - for (k = 0; k < 100; ++k) { - status = RREG32_SOC15(VCN, i, mmUVD_STATUS); - if (status & 2) - break; - mdelay(10); - } - r = 0; + for (k = 0; k < 100; ++k) { + status = RREG32_SOC15(VCN, i, mmUVD_STATUS); if (status & 2) break; - - DRM_ERROR("VCN[%d] decode not responding, trying to reset the VCPU!!!\n", i); - WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL), - UVD_VCPU_CNTL__BLK_RST_MASK, - ~UVD_VCPU_CNTL__BLK_RST_MASK); mdelay(10); - WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL), 0, - ~UVD_VCPU_CNTL__BLK_RST_MASK); - - mdelay(10); - r = -1; } + r = 0; + if (status & 2) + break; - if (r) { - DRM_ERROR("VCN[%d] decode not responding, giving up!!!\n", i); - return r; - } + DRM_ERROR("VCN[%d] decode not responding, trying to reset the VCPU!!!\n", i); + WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL), + UVD_VCPU_CNTL__BLK_RST_MASK, + ~UVD_VCPU_CNTL__BLK_RST_MASK); + mdelay(10); + WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL), 0, + ~UVD_VCPU_CNTL__BLK_RST_MASK); - /* enable master interrupt */ - WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_MASTINT_EN), - UVD_MASTINT_EN__VCPU_EN_MASK, - ~UVD_MASTINT_EN__VCPU_EN_MASK); + mdelay(10); + r = -1; + } - /* clear the busy bit of VCN_STATUS */ - WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_STATUS), 0, - ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT)); + if (r) { + DRM_ERROR("VCN[%d] decode not responding, giving up!!!\n", i); + return r; + } - WREG32_SOC15(VCN, i, mmUVD_LMI_RBC_RB_VMID, 0); + /* enable master interrupt */ + WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_MASTINT_EN), + UVD_MASTINT_EN__VCPU_EN_MASK, + ~UVD_MASTINT_EN__VCPU_EN_MASK); - ring = &adev->vcn.inst[i].ring_dec; - /* force RBC into idle state */ - rb_bufsz = order_base_2(ring->ring_size); - tmp = REG_SET_FIELD(0, UVD_RBC_RB_CNTL, RB_BUFSZ, rb_bufsz); - tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_BLKSZ, 1); - tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_NO_FETCH, 1); - tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_NO_UPDATE, 1); - tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_RPTR_WR_EN, 1); - WREG32_SOC15(VCN, i, mmUVD_RBC_RB_CNTL, tmp); + /* clear the busy bit of VCN_STATUS */ + WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_STATUS), 0, + ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT)); - fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; - fw_shared->multi_queue.decode_queue_mode |= cpu_to_le32(FW_QUEUE_RING_RESET); + WREG32_SOC15(VCN, i, mmUVD_LMI_RBC_RB_VMID, 0); - /* programm the RB_BASE for ring buffer */ - WREG32_SOC15(VCN, i, mmUVD_LMI_RBC_RB_64BIT_BAR_LOW, - lower_32_bits(ring->gpu_addr)); - WREG32_SOC15(VCN, i, mmUVD_LMI_RBC_RB_64BIT_BAR_HIGH, - upper_32_bits(ring->gpu_addr)); + ring = &adev->vcn.inst[i].ring_dec; + /* force RBC into idle state */ + rb_bufsz = order_base_2(ring->ring_size); + tmp = REG_SET_FIELD(0, UVD_RBC_RB_CNTL, RB_BUFSZ, rb_bufsz); + tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_BLKSZ, 1); + tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_NO_FETCH, 1); + tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_NO_UPDATE, 1); + tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_RPTR_WR_EN, 1); + WREG32_SOC15(VCN, i, mmUVD_RBC_RB_CNTL, tmp); - /* Initialize the ring buffer's read and write pointers */ - WREG32_SOC15(VCN, i, mmUVD_RBC_RB_RPTR, 0); + fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; + fw_shared->multi_queue.decode_queue_mode |= cpu_to_le32(FW_QUEUE_RING_RESET); - WREG32_SOC15(VCN, i, mmUVD_SCRATCH2, 0); - ring->wptr = RREG32_SOC15(VCN, i, mmUVD_RBC_RB_RPTR); - WREG32_SOC15(VCN, i, mmUVD_RBC_RB_WPTR, - lower_32_bits(ring->wptr)); - fw_shared->rb.wptr = lower_32_bits(ring->wptr); - fw_shared->multi_queue.decode_queue_mode &= cpu_to_le32(~FW_QUEUE_RING_RESET); + /* programm the RB_BASE for ring buffer */ + WREG32_SOC15(VCN, i, mmUVD_LMI_RBC_RB_64BIT_BAR_LOW, + lower_32_bits(ring->gpu_addr)); + WREG32_SOC15(VCN, i, mmUVD_LMI_RBC_RB_64BIT_BAR_HIGH, + upper_32_bits(ring->gpu_addr)); - if (amdgpu_ip_version(adev, UVD_HWIP, 0) != - IP_VERSION(3, 0, 33)) { - fw_shared->multi_queue.encode_generalpurpose_queue_mode |= cpu_to_le32(FW_QUEUE_RING_RESET); - ring = &adev->vcn.inst[i].ring_enc[0]; - WREG32_SOC15(VCN, i, mmUVD_RB_RPTR, lower_32_bits(ring->wptr)); - WREG32_SOC15(VCN, i, mmUVD_RB_WPTR, lower_32_bits(ring->wptr)); - WREG32_SOC15(VCN, i, mmUVD_RB_BASE_LO, ring->gpu_addr); - WREG32_SOC15(VCN, i, mmUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr)); - WREG32_SOC15(VCN, i, mmUVD_RB_SIZE, ring->ring_size / 4); - fw_shared->multi_queue.encode_generalpurpose_queue_mode &= cpu_to_le32(~FW_QUEUE_RING_RESET); + /* Initialize the ring buffer's read and write pointers */ + WREG32_SOC15(VCN, i, mmUVD_RBC_RB_RPTR, 0); - fw_shared->multi_queue.encode_lowlatency_queue_mode |= cpu_to_le32(FW_QUEUE_RING_RESET); - ring = &adev->vcn.inst[i].ring_enc[1]; - WREG32_SOC15(VCN, i, mmUVD_RB_RPTR2, lower_32_bits(ring->wptr)); - WREG32_SOC15(VCN, i, mmUVD_RB_WPTR2, lower_32_bits(ring->wptr)); - WREG32_SOC15(VCN, i, mmUVD_RB_BASE_LO2, ring->gpu_addr); - WREG32_SOC15(VCN, i, mmUVD_RB_BASE_HI2, upper_32_bits(ring->gpu_addr)); - WREG32_SOC15(VCN, i, mmUVD_RB_SIZE2, ring->ring_size / 4); - fw_shared->multi_queue.encode_lowlatency_queue_mode &= cpu_to_le32(~FW_QUEUE_RING_RESET); - } + WREG32_SOC15(VCN, i, mmUVD_SCRATCH2, 0); + ring->wptr = RREG32_SOC15(VCN, i, mmUVD_RBC_RB_RPTR); + WREG32_SOC15(VCN, i, mmUVD_RBC_RB_WPTR, + lower_32_bits(ring->wptr)); + fw_shared->rb.wptr = lower_32_bits(ring->wptr); + fw_shared->multi_queue.decode_queue_mode &= cpu_to_le32(~FW_QUEUE_RING_RESET); + + if (amdgpu_ip_version(adev, UVD_HWIP, 0) != + IP_VERSION(3, 0, 33)) { + fw_shared->multi_queue.encode_generalpurpose_queue_mode |= cpu_to_le32(FW_QUEUE_RING_RESET); + ring = &adev->vcn.inst[i].ring_enc[0]; + WREG32_SOC15(VCN, i, mmUVD_RB_RPTR, lower_32_bits(ring->wptr)); + WREG32_SOC15(VCN, i, mmUVD_RB_WPTR, lower_32_bits(ring->wptr)); + WREG32_SOC15(VCN, i, mmUVD_RB_BASE_LO, ring->gpu_addr); + WREG32_SOC15(VCN, i, mmUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr)); + WREG32_SOC15(VCN, i, mmUVD_RB_SIZE, ring->ring_size / 4); + fw_shared->multi_queue.encode_generalpurpose_queue_mode &= cpu_to_le32(~FW_QUEUE_RING_RESET); + + fw_shared->multi_queue.encode_lowlatency_queue_mode |= cpu_to_le32(FW_QUEUE_RING_RESET); + ring = &adev->vcn.inst[i].ring_enc[1]; + WREG32_SOC15(VCN, i, mmUVD_RB_RPTR2, lower_32_bits(ring->wptr)); + WREG32_SOC15(VCN, i, mmUVD_RB_WPTR2, lower_32_bits(ring->wptr)); + WREG32_SOC15(VCN, i, mmUVD_RB_BASE_LO2, ring->gpu_addr); + WREG32_SOC15(VCN, i, mmUVD_RB_BASE_HI2, upper_32_bits(ring->gpu_addr)); + WREG32_SOC15(VCN, i, mmUVD_RB_SIZE2, ring->ring_size / 4); + fw_shared->multi_queue.encode_lowlatency_queue_mode &= cpu_to_le32(~FW_QUEUE_RING_RESET); } return 0; @@ -1565,81 +1559,78 @@ static int vcn_v3_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx) return 0; } -static int vcn_v3_0_stop(struct amdgpu_device *adev) +static int vcn_v3_0_stop(struct amdgpu_device *adev, int i) { uint32_t tmp; - int i, r = 0; + int r = 0; - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { - if (adev->vcn.harvest_config & (1 << i)) - continue; + if (adev->vcn.harvest_config & (1 << i)) + return 0; - if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) { - r = vcn_v3_0_stop_dpg_mode(adev, i); - continue; - } - - /* wait for vcn idle */ - r = SOC15_WAIT_ON_RREG(VCN, i, mmUVD_STATUS, UVD_STATUS__IDLE, 0x7); - if (r) - return r; - - tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK | - UVD_LMI_STATUS__READ_CLEAN_MASK | - UVD_LMI_STATUS__WRITE_CLEAN_MASK | - UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK; - r = SOC15_WAIT_ON_RREG(VCN, i, mmUVD_LMI_STATUS, tmp, tmp); - if (r) - return r; - - /* disable LMI UMC channel */ - tmp = RREG32_SOC15(VCN, i, mmUVD_LMI_CTRL2); - tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK; - WREG32_SOC15(VCN, i, mmUVD_LMI_CTRL2, tmp); - tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK| - UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK; - r = SOC15_WAIT_ON_RREG(VCN, i, mmUVD_LMI_STATUS, tmp, tmp); - if (r) - return r; - - /* block VCPU register access */ - WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_RB_ARB_CTRL), - UVD_RB_ARB_CTRL__VCPU_DIS_MASK, - ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK); - - /* reset VCPU */ - WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL), - UVD_VCPU_CNTL__BLK_RST_MASK, - ~UVD_VCPU_CNTL__BLK_RST_MASK); - - /* disable VCPU clock */ - WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL), 0, - ~(UVD_VCPU_CNTL__CLK_EN_MASK)); - - /* apply soft reset */ - tmp = RREG32_SOC15(VCN, i, mmUVD_SOFT_RESET); - tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK; - WREG32_SOC15(VCN, i, mmUVD_SOFT_RESET, tmp); - tmp = RREG32_SOC15(VCN, i, mmUVD_SOFT_RESET); - tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK; - WREG32_SOC15(VCN, i, mmUVD_SOFT_RESET, tmp); - - /* clear status */ - WREG32_SOC15(VCN, i, mmUVD_STATUS, 0); - - /* apply HW clock gating */ - vcn_v3_0_enable_clock_gating(adev, i); - - /* enable VCN power gating */ - vcn_v3_0_enable_static_power_gating(adev, i); + if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) { + r = vcn_v3_0_stop_dpg_mode(adev, i); + goto done; } - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { - if (adev->pm.dpm_enabled) - amdgpu_dpm_enable_vcn(adev, false, i); - } + /* wait for vcn idle */ + r = SOC15_WAIT_ON_RREG(VCN, i, mmUVD_STATUS, UVD_STATUS__IDLE, 0x7); + if (r) + goto done; - return 0; + tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK | + UVD_LMI_STATUS__READ_CLEAN_MASK | + UVD_LMI_STATUS__WRITE_CLEAN_MASK | + UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK; + r = SOC15_WAIT_ON_RREG(VCN, i, mmUVD_LMI_STATUS, tmp, tmp); + if (r) + goto done; + + /* disable LMI UMC channel */ + tmp = RREG32_SOC15(VCN, i, mmUVD_LMI_CTRL2); + tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK; + WREG32_SOC15(VCN, i, mmUVD_LMI_CTRL2, tmp); + tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK| + UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK; + r = SOC15_WAIT_ON_RREG(VCN, i, mmUVD_LMI_STATUS, tmp, tmp); + if (r) + goto done; + + /* block VCPU register access */ + WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_RB_ARB_CTRL), + UVD_RB_ARB_CTRL__VCPU_DIS_MASK, + ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK); + + /* reset VCPU */ + WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL), + UVD_VCPU_CNTL__BLK_RST_MASK, + ~UVD_VCPU_CNTL__BLK_RST_MASK); + + /* disable VCPU clock */ + WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL), 0, + ~(UVD_VCPU_CNTL__CLK_EN_MASK)); + + /* apply soft reset */ + tmp = RREG32_SOC15(VCN, i, mmUVD_SOFT_RESET); + tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK; + WREG32_SOC15(VCN, i, mmUVD_SOFT_RESET, tmp); + tmp = RREG32_SOC15(VCN, i, mmUVD_SOFT_RESET); + tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK; + WREG32_SOC15(VCN, i, mmUVD_SOFT_RESET, tmp); + + /* clear status */ + WREG32_SOC15(VCN, i, mmUVD_STATUS, 0); + + /* apply HW clock gating */ + vcn_v3_0_enable_clock_gating(adev, i); + + /* enable VCN power gating */ + vcn_v3_0_enable_static_power_gating(adev, i); + +done: + if (adev->pm.dpm_enabled) + amdgpu_dpm_enable_vcn(adev, false, i); + + return r; } static int vcn_v3_0_pause_dpg_mode(struct amdgpu_device *adev, @@ -2163,7 +2154,7 @@ static int vcn_v3_0_set_powergating_state(struct amdgpu_ip_block *ip_block, enum amd_powergating_state state) { struct amdgpu_device *adev = ip_block->adev; - int ret; + int ret = 0, i; /* for SRIOV, guest should not control VCN Power-gating * MMSCH FW should control Power-gating and clock-gating @@ -2177,10 +2168,12 @@ static int vcn_v3_0_set_powergating_state(struct amdgpu_ip_block *ip_block, if (state == adev->vcn.cur_state) return 0; - if (state == AMD_PG_STATE_GATE) - ret = vcn_v3_0_stop(adev); - else - ret = vcn_v3_0_start(adev); + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { + if (state == AMD_PG_STATE_GATE) + ret |= vcn_v3_0_stop(adev, i); + else + ret |= vcn_v3_0_start(adev, i); + } if (!ret) adev->vcn.cur_state = state; From f4cd7a85db75d78f7cb907de785b1140e8b8b8aa Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 13 Nov 2024 12:01:44 -0500 Subject: [PATCH 077/235] drm/amdgpu/vcn4.0: split code along instances Split the code on a per instance basis. This will allow us to use the per instance functions in the future to handle more things per instance. v2: squash in fix for stop() from Boyuan Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c | 462 +++++++++++++------------- 1 file changed, 229 insertions(+), 233 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c index 0dd844243531..c99c121faac0 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c @@ -1087,183 +1087,178 @@ static int vcn_v4_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo * vcn_v4_0_start - VCN start * * @adev: amdgpu_device pointer + * @i: instance to start * * Start VCN block */ -static int vcn_v4_0_start(struct amdgpu_device *adev) +static int vcn_v4_0_start(struct amdgpu_device *adev, int i) { volatile struct amdgpu_vcn4_fw_shared *fw_shared; struct amdgpu_ring *ring; uint32_t tmp; - int i, j, k, r; + int j, k, r; - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { - if (adev->pm.dpm_enabled) - amdgpu_dpm_enable_vcn(adev, true, i); - } + if (adev->vcn.harvest_config & (1 << i)) + return 0; - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { - if (adev->vcn.harvest_config & (1 << i)) - continue; + if (adev->pm.dpm_enabled) + amdgpu_dpm_enable_vcn(adev, true, i); - fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; + fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; - if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) { - r = vcn_v4_0_start_dpg_mode(adev, i, adev->vcn.indirect_sram); - continue; + if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) + return vcn_v4_0_start_dpg_mode(adev, i, adev->vcn.indirect_sram); + + /* disable VCN power gating */ + vcn_v4_0_disable_static_power_gating(adev, i); + + /* set VCN status busy */ + tmp = RREG32_SOC15(VCN, i, regUVD_STATUS) | UVD_STATUS__UVD_BUSY; + WREG32_SOC15(VCN, i, regUVD_STATUS, tmp); + + /*SW clock gating */ + vcn_v4_0_disable_clock_gating(adev, i); + + /* enable VCPU clock */ + WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), + UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK); + + /* disable master interrupt */ + WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN), 0, + ~UVD_MASTINT_EN__VCPU_EN_MASK); + + /* enable LMI MC and UMC channels */ + WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_LMI_CTRL2), 0, + ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK); + + tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET); + tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK; + tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK; + WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp); + + /* setup regUVD_LMI_CTRL */ + tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL); + WREG32_SOC15(VCN, i, regUVD_LMI_CTRL, tmp | + UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK | + UVD_LMI_CTRL__MASK_MC_URGENT_MASK | + UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK | + UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK); + + /* setup regUVD_MPC_CNTL */ + tmp = RREG32_SOC15(VCN, i, regUVD_MPC_CNTL); + tmp &= ~UVD_MPC_CNTL__REPLACEMENT_MODE_MASK; + tmp |= 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT; + WREG32_SOC15(VCN, i, regUVD_MPC_CNTL, tmp); + + /* setup UVD_MPC_SET_MUXA0 */ + WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUXA0, + ((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) | + (0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) | + (0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) | + (0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT))); + + /* setup UVD_MPC_SET_MUXB0 */ + WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUXB0, + ((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) | + (0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) | + (0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) | + (0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT))); + + /* setup UVD_MPC_SET_MUX */ + WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUX, + ((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) | + (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) | + (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT))); + + vcn_v4_0_mc_resume(adev, i); + + /* VCN global tiling registers */ + WREG32_SOC15(VCN, i, regUVD_GFX10_ADDR_CONFIG, + adev->gfx.config.gb_addr_config); + + /* unblock VCPU register access */ + WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL), 0, + ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK); + + /* release VCPU reset to boot */ + WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0, + ~UVD_VCPU_CNTL__BLK_RST_MASK); + + for (j = 0; j < 10; ++j) { + uint32_t status; + + for (k = 0; k < 100; ++k) { + status = RREG32_SOC15(VCN, i, regUVD_STATUS); + if (status & 2) + break; + mdelay(10); + if (amdgpu_emu_mode == 1) + msleep(1); } - /* disable VCN power gating */ - vcn_v4_0_disable_static_power_gating(adev, i); - - /* set VCN status busy */ - tmp = RREG32_SOC15(VCN, i, regUVD_STATUS) | UVD_STATUS__UVD_BUSY; - WREG32_SOC15(VCN, i, regUVD_STATUS, tmp); - - /*SW clock gating */ - vcn_v4_0_disable_clock_gating(adev, i); - - /* enable VCPU clock */ - WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), - UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK); - - /* disable master interrupt */ - WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN), 0, - ~UVD_MASTINT_EN__VCPU_EN_MASK); - - /* enable LMI MC and UMC channels */ - WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_LMI_CTRL2), 0, - ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK); - - tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET); - tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK; - tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK; - WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp); - - /* setup regUVD_LMI_CTRL */ - tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL); - WREG32_SOC15(VCN, i, regUVD_LMI_CTRL, tmp | - UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK | - UVD_LMI_CTRL__MASK_MC_URGENT_MASK | - UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK | - UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK); - - /* setup regUVD_MPC_CNTL */ - tmp = RREG32_SOC15(VCN, i, regUVD_MPC_CNTL); - tmp &= ~UVD_MPC_CNTL__REPLACEMENT_MODE_MASK; - tmp |= 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT; - WREG32_SOC15(VCN, i, regUVD_MPC_CNTL, tmp); - - /* setup UVD_MPC_SET_MUXA0 */ - WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUXA0, - ((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) | - (0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) | - (0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) | - (0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT))); - - /* setup UVD_MPC_SET_MUXB0 */ - WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUXB0, - ((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) | - (0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) | - (0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) | - (0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT))); - - /* setup UVD_MPC_SET_MUX */ - WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUX, - ((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) | - (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) | - (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT))); - - vcn_v4_0_mc_resume(adev, i); - - /* VCN global tiling registers */ - WREG32_SOC15(VCN, i, regUVD_GFX10_ADDR_CONFIG, - adev->gfx.config.gb_addr_config); - - /* unblock VCPU register access */ - WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL), 0, - ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK); - - /* release VCPU reset to boot */ - WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0, - ~UVD_VCPU_CNTL__BLK_RST_MASK); - - for (j = 0; j < 10; ++j) { - uint32_t status; - - for (k = 0; k < 100; ++k) { - status = RREG32_SOC15(VCN, i, regUVD_STATUS); - if (status & 2) - break; - mdelay(10); - if (amdgpu_emu_mode == 1) - msleep(1); - } - - if (amdgpu_emu_mode == 1) { - r = -1; - if (status & 2) { - r = 0; - break; - } - } else { + if (amdgpu_emu_mode == 1) { + r = -1; + if (status & 2) { r = 0; - if (status & 2) - break; - - dev_err(adev->dev, "VCN[%d] is not responding, trying to reset the VCPU!!!\n", i); - WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), - UVD_VCPU_CNTL__BLK_RST_MASK, - ~UVD_VCPU_CNTL__BLK_RST_MASK); - mdelay(10); - WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0, - ~UVD_VCPU_CNTL__BLK_RST_MASK); - - mdelay(10); - r = -1; + break; } + } else { + r = 0; + if (status & 2) + break; + + dev_err(adev->dev, "VCN[%d] is not responding, trying to reset the VCPU!!!\n", i); + WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), + UVD_VCPU_CNTL__BLK_RST_MASK, + ~UVD_VCPU_CNTL__BLK_RST_MASK); + mdelay(10); + WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0, + ~UVD_VCPU_CNTL__BLK_RST_MASK); + + mdelay(10); + r = -1; } - - if (r) { - dev_err(adev->dev, "VCN[%d] is not responding, giving up!!!\n", i); - return r; - } - - /* enable master interrupt */ - WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN), - UVD_MASTINT_EN__VCPU_EN_MASK, - ~UVD_MASTINT_EN__VCPU_EN_MASK); - - /* clear the busy bit of VCN_STATUS */ - WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_STATUS), 0, - ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT)); - - ring = &adev->vcn.inst[i].ring_enc[0]; - WREG32_SOC15(VCN, i, regVCN_RB1_DB_CTRL, - ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT | - VCN_RB1_DB_CTRL__EN_MASK); - - WREG32_SOC15(VCN, i, regUVD_RB_BASE_LO, ring->gpu_addr); - WREG32_SOC15(VCN, i, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr)); - WREG32_SOC15(VCN, i, regUVD_RB_SIZE, ring->ring_size / 4); - - tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE); - tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK); - WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp); - fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET; - WREG32_SOC15(VCN, i, regUVD_RB_RPTR, 0); - WREG32_SOC15(VCN, i, regUVD_RB_WPTR, 0); - - tmp = RREG32_SOC15(VCN, i, regUVD_RB_RPTR); - WREG32_SOC15(VCN, i, regUVD_RB_WPTR, tmp); - ring->wptr = RREG32_SOC15(VCN, i, regUVD_RB_WPTR); - - tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE); - tmp |= VCN_RB_ENABLE__RB1_EN_MASK; - WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp); - fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF); } + if (r) { + dev_err(adev->dev, "VCN[%d] is not responding, giving up!!!\n", i); + return r; + } + + /* enable master interrupt */ + WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN), + UVD_MASTINT_EN__VCPU_EN_MASK, + ~UVD_MASTINT_EN__VCPU_EN_MASK); + + /* clear the busy bit of VCN_STATUS */ + WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_STATUS), 0, + ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT)); + + ring = &adev->vcn.inst[i].ring_enc[0]; + WREG32_SOC15(VCN, i, regVCN_RB1_DB_CTRL, + ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT | + VCN_RB1_DB_CTRL__EN_MASK); + + WREG32_SOC15(VCN, i, regUVD_RB_BASE_LO, ring->gpu_addr); + WREG32_SOC15(VCN, i, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr)); + WREG32_SOC15(VCN, i, regUVD_RB_SIZE, ring->ring_size / 4); + + tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE); + tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK); + WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp); + fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET; + WREG32_SOC15(VCN, i, regUVD_RB_RPTR, 0); + WREG32_SOC15(VCN, i, regUVD_RB_WPTR, 0); + + tmp = RREG32_SOC15(VCN, i, regUVD_RB_RPTR); + WREG32_SOC15(VCN, i, regUVD_RB_WPTR, tmp); + ring->wptr = RREG32_SOC15(VCN, i, regUVD_RB_WPTR); + + tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE); + tmp |= VCN_RB_ENABLE__RB1_EN_MASK; + WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp); + fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF); + return 0; } @@ -1549,86 +1544,85 @@ static void vcn_v4_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx) * vcn_v4_0_stop - VCN stop * * @adev: amdgpu_device pointer + * @i: instance to stop * * Stop VCN block */ -static int vcn_v4_0_stop(struct amdgpu_device *adev) +static int vcn_v4_0_stop(struct amdgpu_device *adev, int i) { volatile struct amdgpu_vcn4_fw_shared *fw_shared; uint32_t tmp; - int i, r = 0; + int r = 0; - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { - if (adev->vcn.harvest_config & (1 << i)) - continue; + if (adev->vcn.harvest_config & (1 << i)) + return 0; - fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; - fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF; + fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; + fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF; - if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) { - vcn_v4_0_stop_dpg_mode(adev, i); - continue; - } - - /* wait for vcn idle */ - r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_STATUS, UVD_STATUS__IDLE, 0x7); - if (r) - return r; - - tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK | - UVD_LMI_STATUS__READ_CLEAN_MASK | - UVD_LMI_STATUS__WRITE_CLEAN_MASK | - UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK; - r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp); - if (r) - return r; - - /* disable LMI UMC channel */ - tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL2); - tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK; - WREG32_SOC15(VCN, i, regUVD_LMI_CTRL2, tmp); - tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK | - UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK; - r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp); - if (r) - return r; - - /* block VCPU register access */ - WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL), - UVD_RB_ARB_CTRL__VCPU_DIS_MASK, - ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK); - - /* reset VCPU */ - WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), - UVD_VCPU_CNTL__BLK_RST_MASK, - ~UVD_VCPU_CNTL__BLK_RST_MASK); - - /* disable VCPU clock */ - WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0, - ~(UVD_VCPU_CNTL__CLK_EN_MASK)); - - /* apply soft reset */ - tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET); - tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK; - WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp); - tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET); - tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK; - WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp); - - /* clear status */ - WREG32_SOC15(VCN, i, regUVD_STATUS, 0); - - /* apply HW clock gating */ - vcn_v4_0_enable_clock_gating(adev, i); - - /* enable VCN power gating */ - vcn_v4_0_enable_static_power_gating(adev, i); + if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) { + vcn_v4_0_stop_dpg_mode(adev, i); + r = 0; + goto done; } - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { - if (adev->pm.dpm_enabled) - amdgpu_dpm_enable_vcn(adev, false, i); - } + /* wait for vcn idle */ + r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_STATUS, UVD_STATUS__IDLE, 0x7); + if (r) + goto done; + + tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK | + UVD_LMI_STATUS__READ_CLEAN_MASK | + UVD_LMI_STATUS__WRITE_CLEAN_MASK | + UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK; + r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp); + if (r) + goto done; + + /* disable LMI UMC channel */ + tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL2); + tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK; + WREG32_SOC15(VCN, i, regUVD_LMI_CTRL2, tmp); + tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK | + UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK; + r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp); + if (r) + goto done; + + /* block VCPU register access */ + WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL), + UVD_RB_ARB_CTRL__VCPU_DIS_MASK, + ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK); + + /* reset VCPU */ + WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), + UVD_VCPU_CNTL__BLK_RST_MASK, + ~UVD_VCPU_CNTL__BLK_RST_MASK); + + /* disable VCPU clock */ + WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0, + ~(UVD_VCPU_CNTL__CLK_EN_MASK)); + + /* apply soft reset */ + tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET); + tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK; + WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp); + tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET); + tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK; + WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp); + + /* clear status */ + WREG32_SOC15(VCN, i, regUVD_STATUS, 0); + + /* apply HW clock gating */ + vcn_v4_0_enable_clock_gating(adev, i); + + /* enable VCN power gating */ + vcn_v4_0_enable_static_power_gating(adev, i); + +done: + if (adev->pm.dpm_enabled) + amdgpu_dpm_enable_vcn(adev, false, i); return 0; } @@ -2051,7 +2045,7 @@ static int vcn_v4_0_set_powergating_state(struct amdgpu_ip_block *ip_block, enum amd_powergating_state state) { struct amdgpu_device *adev = ip_block->adev; - int ret; + int ret = 0, i; /* for SRIOV, guest should not control VCN Power-gating * MMSCH FW should control Power-gating and clock-gating @@ -2065,10 +2059,12 @@ static int vcn_v4_0_set_powergating_state(struct amdgpu_ip_block *ip_block, if (state == adev->vcn.cur_state) return 0; - if (state == AMD_PG_STATE_GATE) - ret = vcn_v4_0_stop(adev); - else - ret = vcn_v4_0_start(adev); + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { + if (state == AMD_PG_STATE_GATE) + ret |= vcn_v4_0_stop(adev, i); + else + ret |= vcn_v4_0_start(adev, i); + } if (!ret) adev->vcn.cur_state = state; From 5826d5a5d5c5548a11fbc503d9a0bdee8af310d2 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 13 Nov 2024 12:13:15 -0500 Subject: [PATCH 078/235] drm/amdgpu/vcn4.0.3: split code along instances Split the code on a per instance basis. This will allow us to use the per instance functions in the future to handle more things per instance. v2: squash in fix for stop() from Boyuan Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c | 407 ++++++++++++------------ 1 file changed, 203 insertions(+), 204 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c index c936bd08963e..00b94d01cd4c 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c @@ -1117,172 +1117,169 @@ static int vcn_v4_0_3_start_sriov(struct amdgpu_device *adev) * vcn_v4_0_3_start - VCN start * * @adev: amdgpu_device pointer + * @i: instance to start * * Start VCN block */ -static int vcn_v4_0_3_start(struct amdgpu_device *adev) +static int vcn_v4_0_3_start(struct amdgpu_device *adev, int i) { volatile struct amdgpu_vcn4_fw_shared *fw_shared; struct amdgpu_ring *ring; - int i, j, k, r, vcn_inst; + int j, k, r, vcn_inst; uint32_t tmp; - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { - if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) { - r = vcn_v4_0_3_start_dpg_mode(adev, i, adev->vcn.indirect_sram); - continue; - } + if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) + return vcn_v4_0_3_start_dpg_mode(adev, i, adev->vcn.indirect_sram); - vcn_inst = GET_INST(VCN, i); - /* set VCN status busy */ - tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_STATUS) | - UVD_STATUS__UVD_BUSY; - WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, tmp); + vcn_inst = GET_INST(VCN, i); + /* set VCN status busy */ + tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_STATUS) | + UVD_STATUS__UVD_BUSY; + WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, tmp); - /*SW clock gating */ - vcn_v4_0_3_disable_clock_gating(adev, i); + /* SW clock gating */ + vcn_v4_0_3_disable_clock_gating(adev, i); - /* enable VCPU clock */ - WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), - UVD_VCPU_CNTL__CLK_EN_MASK, - ~UVD_VCPU_CNTL__CLK_EN_MASK); + /* enable VCPU clock */ + WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), + UVD_VCPU_CNTL__CLK_EN_MASK, + ~UVD_VCPU_CNTL__CLK_EN_MASK); - /* disable master interrupt */ - WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_MASTINT_EN), 0, - ~UVD_MASTINT_EN__VCPU_EN_MASK); + /* disable master interrupt */ + WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_MASTINT_EN), 0, + ~UVD_MASTINT_EN__VCPU_EN_MASK); - /* enable LMI MC and UMC channels */ - WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_LMI_CTRL2), 0, - ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK); + /* enable LMI MC and UMC channels */ + WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_LMI_CTRL2), 0, + ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK); - tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET); - tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK; - tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK; - WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp); + tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET); + tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK; + tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK; + WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp); - /* setup regUVD_LMI_CTRL */ - tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL); - WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL, - tmp | UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK | - UVD_LMI_CTRL__MASK_MC_URGENT_MASK | - UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK | - UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK); + /* setup regUVD_LMI_CTRL */ + tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL); + WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL, + tmp | UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK | + UVD_LMI_CTRL__MASK_MC_URGENT_MASK | + UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK | + UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK); - /* setup regUVD_MPC_CNTL */ - tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_MPC_CNTL); - tmp &= ~UVD_MPC_CNTL__REPLACEMENT_MODE_MASK; - tmp |= 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT; - WREG32_SOC15(VCN, vcn_inst, regUVD_MPC_CNTL, tmp); + /* setup regUVD_MPC_CNTL */ + tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_MPC_CNTL); + tmp &= ~UVD_MPC_CNTL__REPLACEMENT_MODE_MASK; + tmp |= 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT; + WREG32_SOC15(VCN, vcn_inst, regUVD_MPC_CNTL, tmp); - /* setup UVD_MPC_SET_MUXA0 */ - WREG32_SOC15(VCN, vcn_inst, regUVD_MPC_SET_MUXA0, - ((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) | - (0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) | - (0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) | - (0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT))); + /* setup UVD_MPC_SET_MUXA0 */ + WREG32_SOC15(VCN, vcn_inst, regUVD_MPC_SET_MUXA0, + ((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) | + (0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) | + (0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) | + (0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT))); - /* setup UVD_MPC_SET_MUXB0 */ - WREG32_SOC15(VCN, vcn_inst, regUVD_MPC_SET_MUXB0, - ((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) | - (0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) | - (0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) | - (0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT))); + /* setup UVD_MPC_SET_MUXB0 */ + WREG32_SOC15(VCN, vcn_inst, regUVD_MPC_SET_MUXB0, + ((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) | + (0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) | + (0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) | + (0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT))); - /* setup UVD_MPC_SET_MUX */ - WREG32_SOC15(VCN, vcn_inst, regUVD_MPC_SET_MUX, - ((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) | - (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) | - (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT))); + /* setup UVD_MPC_SET_MUX */ + WREG32_SOC15(VCN, vcn_inst, regUVD_MPC_SET_MUX, + ((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) | + (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) | + (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT))); - vcn_v4_0_3_mc_resume(adev, i); + vcn_v4_0_3_mc_resume(adev, i); - /* VCN global tiling registers */ - WREG32_SOC15(VCN, vcn_inst, regUVD_GFX8_ADDR_CONFIG, - adev->gfx.config.gb_addr_config); - WREG32_SOC15(VCN, vcn_inst, regUVD_GFX10_ADDR_CONFIG, - adev->gfx.config.gb_addr_config); + /* VCN global tiling registers */ + WREG32_SOC15(VCN, vcn_inst, regUVD_GFX8_ADDR_CONFIG, + adev->gfx.config.gb_addr_config); + WREG32_SOC15(VCN, vcn_inst, regUVD_GFX10_ADDR_CONFIG, + adev->gfx.config.gb_addr_config); - /* unblock VCPU register access */ - WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_RB_ARB_CTRL), 0, - ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK); + /* unblock VCPU register access */ + WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_RB_ARB_CTRL), 0, + ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK); - /* release VCPU reset to boot */ - WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0, - ~UVD_VCPU_CNTL__BLK_RST_MASK); + /* release VCPU reset to boot */ + WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0, + ~UVD_VCPU_CNTL__BLK_RST_MASK); - for (j = 0; j < 10; ++j) { - uint32_t status; + for (j = 0; j < 10; ++j) { + uint32_t status; - for (k = 0; k < 100; ++k) { - status = RREG32_SOC15(VCN, vcn_inst, - regUVD_STATUS); - if (status & 2) - break; - mdelay(10); - } - r = 0; + for (k = 0; k < 100; ++k) { + status = RREG32_SOC15(VCN, vcn_inst, + regUVD_STATUS); if (status & 2) break; - - DRM_DEV_ERROR(adev->dev, - "VCN decode not responding, trying to reset the VCPU!!!\n"); - WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, - regUVD_VCPU_CNTL), - UVD_VCPU_CNTL__BLK_RST_MASK, - ~UVD_VCPU_CNTL__BLK_RST_MASK); mdelay(10); - WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, - regUVD_VCPU_CNTL), - 0, ~UVD_VCPU_CNTL__BLK_RST_MASK); - - mdelay(10); - r = -1; } + r = 0; + if (status & 2) + break; - if (r) { - DRM_DEV_ERROR(adev->dev, "VCN decode not responding, giving up!!!\n"); - return r; - } - - /* enable master interrupt */ - WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_MASTINT_EN), - UVD_MASTINT_EN__VCPU_EN_MASK, - ~UVD_MASTINT_EN__VCPU_EN_MASK); - - /* clear the busy bit of VCN_STATUS */ - WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_STATUS), 0, - ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT)); - - ring = &adev->vcn.inst[i].ring_enc[0]; - fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; - - /* program the RB_BASE for ring buffer */ - WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_LO, - lower_32_bits(ring->gpu_addr)); - WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_HI, - upper_32_bits(ring->gpu_addr)); - - WREG32_SOC15(VCN, vcn_inst, regUVD_RB_SIZE, - ring->ring_size / sizeof(uint32_t)); - - /* resetting ring, fw should not check RB ring */ - tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE); - tmp &= ~(VCN_RB_ENABLE__RB_EN_MASK); - WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp); - - /* Initialize the ring buffer's read and write pointers */ - WREG32_SOC15(VCN, vcn_inst, regUVD_RB_RPTR, 0); - WREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR, 0); - - tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE); - tmp |= VCN_RB_ENABLE__RB_EN_MASK; - WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp); - - ring->wptr = RREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR); - fw_shared->sq.queue_mode &= - cpu_to_le32(~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF)); + DRM_DEV_ERROR(adev->dev, + "VCN decode not responding, trying to reset the VCPU!!!\n"); + WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, + regUVD_VCPU_CNTL), + UVD_VCPU_CNTL__BLK_RST_MASK, + ~UVD_VCPU_CNTL__BLK_RST_MASK); + mdelay(10); + WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, + regUVD_VCPU_CNTL), + 0, ~UVD_VCPU_CNTL__BLK_RST_MASK); + mdelay(10); + r = -1; } + + if (r) { + DRM_DEV_ERROR(adev->dev, "VCN decode not responding, giving up!!!\n"); + return r; + } + + /* enable master interrupt */ + WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_MASTINT_EN), + UVD_MASTINT_EN__VCPU_EN_MASK, + ~UVD_MASTINT_EN__VCPU_EN_MASK); + + /* clear the busy bit of VCN_STATUS */ + WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_STATUS), 0, + ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT)); + + ring = &adev->vcn.inst[i].ring_enc[0]; + fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; + + /* program the RB_BASE for ring buffer */ + WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_LO, + lower_32_bits(ring->gpu_addr)); + WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_HI, + upper_32_bits(ring->gpu_addr)); + + WREG32_SOC15(VCN, vcn_inst, regUVD_RB_SIZE, + ring->ring_size / sizeof(uint32_t)); + + /* resetting ring, fw should not check RB ring */ + tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE); + tmp &= ~(VCN_RB_ENABLE__RB_EN_MASK); + WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp); + + /* Initialize the ring buffer's read and write pointers */ + WREG32_SOC15(VCN, vcn_inst, regUVD_RB_RPTR, 0); + WREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR, 0); + + tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE); + tmp |= VCN_RB_ENABLE__RB_EN_MASK; + WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp); + + ring->wptr = RREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR); + fw_shared->sq.queue_mode &= + cpu_to_le32(~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF)); + return 0; } @@ -1322,81 +1319,81 @@ static int vcn_v4_0_3_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx) * vcn_v4_0_3_stop - VCN stop * * @adev: amdgpu_device pointer + * @i: instance to stop * * Stop VCN block */ -static int vcn_v4_0_3_stop(struct amdgpu_device *adev) +static int vcn_v4_0_3_stop(struct amdgpu_device *adev, int i) { volatile struct amdgpu_vcn4_fw_shared *fw_shared; - int i, r = 0, vcn_inst; + int r = 0, vcn_inst; uint32_t tmp; - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { - vcn_inst = GET_INST(VCN, i); + vcn_inst = GET_INST(VCN, i); - fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; - fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF; + fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; + fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF; - if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) { - vcn_v4_0_3_stop_dpg_mode(adev, i); - continue; - } - - /* wait for vcn idle */ - r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_STATUS, - UVD_STATUS__IDLE, 0x7); - if (r) - goto Done; - - tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK | - UVD_LMI_STATUS__READ_CLEAN_MASK | - UVD_LMI_STATUS__WRITE_CLEAN_MASK | - UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK; - r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_LMI_STATUS, tmp, - tmp); - if (r) - goto Done; - - /* stall UMC channel */ - tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL2); - tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK; - WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL2, tmp); - tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK | - UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK; - r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_LMI_STATUS, tmp, - tmp); - if (r) - goto Done; - - /* Unblock VCPU Register access */ - WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_RB_ARB_CTRL), - UVD_RB_ARB_CTRL__VCPU_DIS_MASK, - ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK); - - /* release VCPU reset to boot */ - WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), - UVD_VCPU_CNTL__BLK_RST_MASK, - ~UVD_VCPU_CNTL__BLK_RST_MASK); - - /* disable VCPU clock */ - WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0, - ~(UVD_VCPU_CNTL__CLK_EN_MASK)); - - /* reset LMI UMC/LMI/VCPU */ - tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET); - tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK; - WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp); - - tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET); - tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK; - WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp); - - /* clear VCN status */ - WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, 0); - - /* apply HW clock gating */ - vcn_v4_0_3_enable_clock_gating(adev, i); + if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) { + vcn_v4_0_3_stop_dpg_mode(adev, i); + goto Done; } + + /* wait for vcn idle */ + r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_STATUS, + UVD_STATUS__IDLE, 0x7); + if (r) + goto Done; + + tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK | + UVD_LMI_STATUS__READ_CLEAN_MASK | + UVD_LMI_STATUS__WRITE_CLEAN_MASK | + UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK; + r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_LMI_STATUS, tmp, + tmp); + if (r) + goto Done; + + /* stall UMC channel */ + tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL2); + tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK; + WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL2, tmp); + tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK | + UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK; + r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_LMI_STATUS, tmp, + tmp); + if (r) + goto Done; + + /* Unblock VCPU Register access */ + WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_RB_ARB_CTRL), + UVD_RB_ARB_CTRL__VCPU_DIS_MASK, + ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK); + + /* release VCPU reset to boot */ + WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), + UVD_VCPU_CNTL__BLK_RST_MASK, + ~UVD_VCPU_CNTL__BLK_RST_MASK); + + /* disable VCPU clock */ + WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0, + ~(UVD_VCPU_CNTL__CLK_EN_MASK)); + + /* reset LMI UMC/LMI/VCPU */ + tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET); + tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK; + WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp); + + tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET); + tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK; + WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp); + + /* clear VCN status */ + WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, 0); + + /* apply HW clock gating */ + vcn_v4_0_3_enable_clock_gating(adev, i); + Done: return 0; } @@ -1653,7 +1650,7 @@ static int vcn_v4_0_3_set_powergating_state(struct amdgpu_ip_block *ip_block, enum amd_powergating_state state) { struct amdgpu_device *adev = ip_block->adev; - int ret; + int ret = 0, i; /* for SRIOV, guest should not control VCN Power-gating * MMSCH FW should control Power-gating and clock-gating @@ -1667,10 +1664,12 @@ static int vcn_v4_0_3_set_powergating_state(struct amdgpu_ip_block *ip_block, if (state == adev->vcn.cur_state) return 0; - if (state == AMD_PG_STATE_GATE) - ret = vcn_v4_0_3_stop(adev); - else - ret = vcn_v4_0_3_start(adev); + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { + if (state == AMD_PG_STATE_GATE) + ret |= vcn_v4_0_3_stop(adev, i); + else + ret |= vcn_v4_0_3_start(adev, i); + } if (!ret) adev->vcn.cur_state = state; From ecc9ab4e924b7eb9e2c4a668162aaa1d9d60d08c Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 13 Nov 2024 12:21:18 -0500 Subject: [PATCH 079/235] drm/amdgpu/vcn4.0.5: split code along instances Split the code on a per instance basis. This will allow us to use the per instance functions in the future to handle more things per instance. v2: squash in fix for stop() from Boyuan Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c | 466 ++++++++++++------------ 1 file changed, 231 insertions(+), 235 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c index 5e6ad825cc47..c2bbacb176c1 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c @@ -990,184 +990,179 @@ static int vcn_v4_0_5_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, b * vcn_v4_0_5_start - VCN start * * @adev: amdgpu_device pointer + * @i: instance to start * * Start VCN block */ -static int vcn_v4_0_5_start(struct amdgpu_device *adev) +static int vcn_v4_0_5_start(struct amdgpu_device *adev, int i) { volatile struct amdgpu_vcn4_fw_shared *fw_shared; struct amdgpu_ring *ring; uint32_t tmp; - int i, j, k, r; + int j, k, r; - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { - if (adev->pm.dpm_enabled) - amdgpu_dpm_enable_vcn(adev, true, i); - } + if (adev->vcn.harvest_config & (1 << i)) + return 0; - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { - if (adev->vcn.harvest_config & (1 << i)) - continue; + if (adev->pm.dpm_enabled) + amdgpu_dpm_enable_vcn(adev, true, i); - fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; + fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; - if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) { - r = vcn_v4_0_5_start_dpg_mode(adev, i, adev->vcn.indirect_sram); - continue; + if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) + return vcn_v4_0_5_start_dpg_mode(adev, i, adev->vcn.indirect_sram); + + /* disable VCN power gating */ + vcn_v4_0_5_disable_static_power_gating(adev, i); + + /* set VCN status busy */ + tmp = RREG32_SOC15(VCN, i, regUVD_STATUS) | UVD_STATUS__UVD_BUSY; + WREG32_SOC15(VCN, i, regUVD_STATUS, tmp); + + /* SW clock gating */ + vcn_v4_0_5_disable_clock_gating(adev, i); + + /* enable VCPU clock */ + WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), + UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK); + + /* disable master interrupt */ + WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN), 0, + ~UVD_MASTINT_EN__VCPU_EN_MASK); + + /* enable LMI MC and UMC channels */ + WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_LMI_CTRL2), 0, + ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK); + + tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET); + tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK; + tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK; + WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp); + + /* setup regUVD_LMI_CTRL */ + tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL); + WREG32_SOC15(VCN, i, regUVD_LMI_CTRL, tmp | + UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK | + UVD_LMI_CTRL__MASK_MC_URGENT_MASK | + UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK | + UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK); + + /* setup regUVD_MPC_CNTL */ + tmp = RREG32_SOC15(VCN, i, regUVD_MPC_CNTL); + tmp &= ~UVD_MPC_CNTL__REPLACEMENT_MODE_MASK; + tmp |= 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT; + WREG32_SOC15(VCN, i, regUVD_MPC_CNTL, tmp); + + /* setup UVD_MPC_SET_MUXA0 */ + WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUXA0, + ((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) | + (0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) | + (0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) | + (0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT))); + + /* setup UVD_MPC_SET_MUXB0 */ + WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUXB0, + ((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) | + (0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) | + (0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) | + (0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT))); + + /* setup UVD_MPC_SET_MUX */ + WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUX, + ((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) | + (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) | + (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT))); + + vcn_v4_0_5_mc_resume(adev, i); + + /* VCN global tiling registers */ + WREG32_SOC15(VCN, i, regUVD_GFX10_ADDR_CONFIG, + adev->gfx.config.gb_addr_config); + + /* unblock VCPU register access */ + WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL), 0, + ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK); + + /* release VCPU reset to boot */ + WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0, + ~UVD_VCPU_CNTL__BLK_RST_MASK); + + for (j = 0; j < 10; ++j) { + uint32_t status; + + for (k = 0; k < 100; ++k) { + status = RREG32_SOC15(VCN, i, regUVD_STATUS); + if (status & 2) + break; + mdelay(10); + if (amdgpu_emu_mode == 1) + msleep(1); } - /* disable VCN power gating */ - vcn_v4_0_5_disable_static_power_gating(adev, i); - - /* set VCN status busy */ - tmp = RREG32_SOC15(VCN, i, regUVD_STATUS) | UVD_STATUS__UVD_BUSY; - WREG32_SOC15(VCN, i, regUVD_STATUS, tmp); - - /*SW clock gating */ - vcn_v4_0_5_disable_clock_gating(adev, i); - - /* enable VCPU clock */ - WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), - UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK); - - /* disable master interrupt */ - WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN), 0, - ~UVD_MASTINT_EN__VCPU_EN_MASK); - - /* enable LMI MC and UMC channels */ - WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_LMI_CTRL2), 0, - ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK); - - tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET); - tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK; - tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK; - WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp); - - /* setup regUVD_LMI_CTRL */ - tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL); - WREG32_SOC15(VCN, i, regUVD_LMI_CTRL, tmp | - UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK | - UVD_LMI_CTRL__MASK_MC_URGENT_MASK | - UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK | - UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK); - - /* setup regUVD_MPC_CNTL */ - tmp = RREG32_SOC15(VCN, i, regUVD_MPC_CNTL); - tmp &= ~UVD_MPC_CNTL__REPLACEMENT_MODE_MASK; - tmp |= 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT; - WREG32_SOC15(VCN, i, regUVD_MPC_CNTL, tmp); - - /* setup UVD_MPC_SET_MUXA0 */ - WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUXA0, - ((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) | - (0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) | - (0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) | - (0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT))); - - /* setup UVD_MPC_SET_MUXB0 */ - WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUXB0, - ((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) | - (0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) | - (0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) | - (0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT))); - - /* setup UVD_MPC_SET_MUX */ - WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUX, - ((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) | - (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) | - (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT))); - - vcn_v4_0_5_mc_resume(adev, i); - - /* VCN global tiling registers */ - WREG32_SOC15(VCN, i, regUVD_GFX10_ADDR_CONFIG, - adev->gfx.config.gb_addr_config); - - /* unblock VCPU register access */ - WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL), 0, - ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK); - - /* release VCPU reset to boot */ - WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0, - ~UVD_VCPU_CNTL__BLK_RST_MASK); - - for (j = 0; j < 10; ++j) { - uint32_t status; - - for (k = 0; k < 100; ++k) { - status = RREG32_SOC15(VCN, i, regUVD_STATUS); - if (status & 2) - break; - mdelay(10); - if (amdgpu_emu_mode == 1) - msleep(1); - } - - if (amdgpu_emu_mode == 1) { - r = -1; - if (status & 2) { - r = 0; - break; - } - } else { + if (amdgpu_emu_mode == 1) { + r = -1; + if (status & 2) { r = 0; - if (status & 2) - break; - - dev_err(adev->dev, - "VCN[%d] is not responding, trying to reset VCPU!!!\n", i); - WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), - UVD_VCPU_CNTL__BLK_RST_MASK, - ~UVD_VCPU_CNTL__BLK_RST_MASK); - mdelay(10); - WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0, - ~UVD_VCPU_CNTL__BLK_RST_MASK); - - mdelay(10); - r = -1; + break; } + } else { + r = 0; + if (status & 2) + break; + + dev_err(adev->dev, + "VCN[%d] is not responding, trying to reset VCPU!!!\n", i); + WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), + UVD_VCPU_CNTL__BLK_RST_MASK, + ~UVD_VCPU_CNTL__BLK_RST_MASK); + mdelay(10); + WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0, + ~UVD_VCPU_CNTL__BLK_RST_MASK); + + mdelay(10); + r = -1; } - - if (r) { - dev_err(adev->dev, "VCN[%d] is not responding, giving up!!!\n", i); - return r; - } - - /* enable master interrupt */ - WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN), - UVD_MASTINT_EN__VCPU_EN_MASK, - ~UVD_MASTINT_EN__VCPU_EN_MASK); - - /* clear the busy bit of VCN_STATUS */ - WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_STATUS), 0, - ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT)); - - ring = &adev->vcn.inst[i].ring_enc[0]; - WREG32_SOC15(VCN, i, regVCN_RB1_DB_CTRL, - ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT | - VCN_RB1_DB_CTRL__EN_MASK); - - WREG32_SOC15(VCN, i, regUVD_RB_BASE_LO, ring->gpu_addr); - WREG32_SOC15(VCN, i, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr)); - WREG32_SOC15(VCN, i, regUVD_RB_SIZE, ring->ring_size / 4); - - tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE); - tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK); - WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp); - fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET; - WREG32_SOC15(VCN, i, regUVD_RB_RPTR, 0); - WREG32_SOC15(VCN, i, regUVD_RB_WPTR, 0); - - tmp = RREG32_SOC15(VCN, i, regUVD_RB_RPTR); - WREG32_SOC15(VCN, i, regUVD_RB_WPTR, tmp); - ring->wptr = RREG32_SOC15(VCN, i, regUVD_RB_WPTR); - - tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE); - tmp |= VCN_RB_ENABLE__RB1_EN_MASK; - WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp); - fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF); } + if (r) { + dev_err(adev->dev, "VCN[%d] is not responding, giving up!!!\n", i); + return r; + } + + /* enable master interrupt */ + WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN), + UVD_MASTINT_EN__VCPU_EN_MASK, + ~UVD_MASTINT_EN__VCPU_EN_MASK); + + /* clear the busy bit of VCN_STATUS */ + WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_STATUS), 0, + ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT)); + + ring = &adev->vcn.inst[i].ring_enc[0]; + WREG32_SOC15(VCN, i, regVCN_RB1_DB_CTRL, + ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT | + VCN_RB1_DB_CTRL__EN_MASK); + + WREG32_SOC15(VCN, i, regUVD_RB_BASE_LO, ring->gpu_addr); + WREG32_SOC15(VCN, i, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr)); + WREG32_SOC15(VCN, i, regUVD_RB_SIZE, ring->ring_size / 4); + + tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE); + tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK); + WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp); + fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET; + WREG32_SOC15(VCN, i, regUVD_RB_RPTR, 0); + WREG32_SOC15(VCN, i, regUVD_RB_WPTR, 0); + + tmp = RREG32_SOC15(VCN, i, regUVD_RB_RPTR); + WREG32_SOC15(VCN, i, regUVD_RB_WPTR, tmp); + ring->wptr = RREG32_SOC15(VCN, i, regUVD_RB_WPTR); + + tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE); + tmp |= VCN_RB_ENABLE__RB1_EN_MASK; + WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp); + fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF); + return 0; } @@ -1203,88 +1198,87 @@ static void vcn_v4_0_5_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx) * vcn_v4_0_5_stop - VCN stop * * @adev: amdgpu_device pointer + * @i: instance to stop * * Stop VCN block */ -static int vcn_v4_0_5_stop(struct amdgpu_device *adev) +static int vcn_v4_0_5_stop(struct amdgpu_device *adev, int i) { volatile struct amdgpu_vcn4_fw_shared *fw_shared; uint32_t tmp; - int i, r = 0; + int r = 0; - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { - if (adev->vcn.harvest_config & (1 << i)) - continue; + if (adev->vcn.harvest_config & (1 << i)) + return 0; - fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; - fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF; + fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; + fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF; - if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) { - vcn_v4_0_5_stop_dpg_mode(adev, i); - continue; - } - - /* wait for vcn idle */ - r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_STATUS, UVD_STATUS__IDLE, 0x7); - if (r) - return r; - - tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK | - UVD_LMI_STATUS__READ_CLEAN_MASK | - UVD_LMI_STATUS__WRITE_CLEAN_MASK | - UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK; - r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp); - if (r) - return r; - - /* disable LMI UMC channel */ - tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL2); - tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK; - WREG32_SOC15(VCN, i, regUVD_LMI_CTRL2, tmp); - tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK | - UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK; - r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp); - if (r) - return r; - - /* block VCPU register access */ - WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL), - UVD_RB_ARB_CTRL__VCPU_DIS_MASK, - ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK); - - /* reset VCPU */ - WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), - UVD_VCPU_CNTL__BLK_RST_MASK, - ~UVD_VCPU_CNTL__BLK_RST_MASK); - - /* disable VCPU clock */ - WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0, - ~(UVD_VCPU_CNTL__CLK_EN_MASK)); - - /* apply soft reset */ - tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET); - tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK; - WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp); - tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET); - tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK; - WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp); - - /* clear status */ - WREG32_SOC15(VCN, i, regUVD_STATUS, 0); - - /* apply HW clock gating */ - vcn_v4_0_5_enable_clock_gating(adev, i); - - /* enable VCN power gating */ - vcn_v4_0_5_enable_static_power_gating(adev, i); + if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) { + vcn_v4_0_5_stop_dpg_mode(adev, i); + r = 0; + goto done; } - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { - if (adev->pm.dpm_enabled) - amdgpu_dpm_enable_vcn(adev, false, i); - } + /* wait for vcn idle */ + r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_STATUS, UVD_STATUS__IDLE, 0x7); + if (r) + goto done; - return 0; + tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK | + UVD_LMI_STATUS__READ_CLEAN_MASK | + UVD_LMI_STATUS__WRITE_CLEAN_MASK | + UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK; + r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp); + if (r) + goto done; + + /* disable LMI UMC channel */ + tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL2); + tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK; + WREG32_SOC15(VCN, i, regUVD_LMI_CTRL2, tmp); + tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK | + UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK; + r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp); + if (r) + goto done; + + /* block VCPU register access */ + WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL), + UVD_RB_ARB_CTRL__VCPU_DIS_MASK, + ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK); + + /* reset VCPU */ + WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), + UVD_VCPU_CNTL__BLK_RST_MASK, + ~UVD_VCPU_CNTL__BLK_RST_MASK); + + /* disable VCPU clock */ + WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0, + ~(UVD_VCPU_CNTL__CLK_EN_MASK)); + + /* apply soft reset */ + tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET); + tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK; + WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp); + tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET); + tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK; + WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp); + + /* clear status */ + WREG32_SOC15(VCN, i, regUVD_STATUS, 0); + + /* apply HW clock gating */ + vcn_v4_0_5_enable_clock_gating(adev, i); + + /* enable VCN power gating */ + vcn_v4_0_5_enable_static_power_gating(adev, i); + +done: + if (adev->pm.dpm_enabled) + amdgpu_dpm_enable_vcn(adev, false, i); + + return r; } /** @@ -1539,15 +1533,17 @@ static int vcn_v4_0_5_set_powergating_state(struct amdgpu_ip_block *ip_block, enum amd_powergating_state state) { struct amdgpu_device *adev = ip_block->adev; - int ret; + int ret = 0, i; if (state == adev->vcn.cur_state) return 0; - if (state == AMD_PG_STATE_GATE) - ret = vcn_v4_0_5_stop(adev); - else - ret = vcn_v4_0_5_start(adev); + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { + if (state == AMD_PG_STATE_GATE) + ret |= vcn_v4_0_5_stop(adev, i); + else + ret |= vcn_v4_0_5_start(adev, i); + } if (!ret) adev->vcn.cur_state = state; From 0797c54502d6cdb806aaf8d482b3ed445d6e298f Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 13 Nov 2024 12:27:45 -0500 Subject: [PATCH 080/235] drm/amdgpu/vcn5.0.0: split code along instances Split the code on a per instance basis. This will allow us to use the per instance functions in the future to handle more things per instance. v2: squash in fix for stop() from Boyuan Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c | 402 ++++++++++++------------ 1 file changed, 199 insertions(+), 203 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c index e937ed682abd..188cd6f1dda2 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c @@ -767,155 +767,150 @@ static int vcn_v5_0_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, b * vcn_v5_0_0_start - VCN start * * @adev: amdgpu_device pointer + * @i: instance to start * * Start VCN block */ -static int vcn_v5_0_0_start(struct amdgpu_device *adev) +static int vcn_v5_0_0_start(struct amdgpu_device *adev, int i) { volatile struct amdgpu_vcn5_fw_shared *fw_shared; struct amdgpu_ring *ring; uint32_t tmp; - int i, j, k, r; + int j, k, r; - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { - if (adev->pm.dpm_enabled) - amdgpu_dpm_enable_vcn(adev, true, i); - } + if (adev->vcn.harvest_config & (1 << i)) + return 0; - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { - if (adev->vcn.harvest_config & (1 << i)) - continue; + if (adev->pm.dpm_enabled) + amdgpu_dpm_enable_vcn(adev, true, i); - fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; + fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; - if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) { - r = vcn_v5_0_0_start_dpg_mode(adev, i, adev->vcn.indirect_sram); - continue; + if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) + return vcn_v5_0_0_start_dpg_mode(adev, i, adev->vcn.indirect_sram); + + /* disable VCN power gating */ + vcn_v5_0_0_disable_static_power_gating(adev, i); + + /* set VCN status busy */ + tmp = RREG32_SOC15(VCN, i, regUVD_STATUS) | UVD_STATUS__UVD_BUSY; + WREG32_SOC15(VCN, i, regUVD_STATUS, tmp); + + /* enable VCPU clock */ + WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), + UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK); + + /* disable master interrupt */ + WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN), 0, + ~UVD_MASTINT_EN__VCPU_EN_MASK); + + /* enable LMI MC and UMC channels */ + WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_LMI_CTRL2), 0, + ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK); + + tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET); + tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK; + tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK; + WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp); + + /* setup regUVD_LMI_CTRL */ + tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL); + WREG32_SOC15(VCN, i, regUVD_LMI_CTRL, tmp | + UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK | + UVD_LMI_CTRL__MASK_MC_URGENT_MASK | + UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK | + UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK); + + vcn_v5_0_0_mc_resume(adev, i); + + /* VCN global tiling registers */ + WREG32_SOC15(VCN, i, regUVD_GFX10_ADDR_CONFIG, + adev->gfx.config.gb_addr_config); + + /* unblock VCPU register access */ + WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL), 0, + ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK); + + /* release VCPU reset to boot */ + WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0, + ~UVD_VCPU_CNTL__BLK_RST_MASK); + + for (j = 0; j < 10; ++j) { + uint32_t status; + + for (k = 0; k < 100; ++k) { + status = RREG32_SOC15(VCN, i, regUVD_STATUS); + if (status & 2) + break; + mdelay(10); + if (amdgpu_emu_mode == 1) + msleep(1); } - /* disable VCN power gating */ - vcn_v5_0_0_disable_static_power_gating(adev, i); - - /* set VCN status busy */ - tmp = RREG32_SOC15(VCN, i, regUVD_STATUS) | UVD_STATUS__UVD_BUSY; - WREG32_SOC15(VCN, i, regUVD_STATUS, tmp); - - /* enable VCPU clock */ - WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), - UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK); - - /* disable master interrupt */ - WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN), 0, - ~UVD_MASTINT_EN__VCPU_EN_MASK); - - /* enable LMI MC and UMC channels */ - WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_LMI_CTRL2), 0, - ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK); - - tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET); - tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK; - tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK; - WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp); - - /* setup regUVD_LMI_CTRL */ - tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL); - WREG32_SOC15(VCN, i, regUVD_LMI_CTRL, tmp | - UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK | - UVD_LMI_CTRL__MASK_MC_URGENT_MASK | - UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK | - UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK); - - vcn_v5_0_0_mc_resume(adev, i); - - /* VCN global tiling registers */ - WREG32_SOC15(VCN, i, regUVD_GFX10_ADDR_CONFIG, - adev->gfx.config.gb_addr_config); - - /* unblock VCPU register access */ - WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL), 0, - ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK); - - /* release VCPU reset to boot */ - WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0, - ~UVD_VCPU_CNTL__BLK_RST_MASK); - - for (j = 0; j < 10; ++j) { - uint32_t status; - - for (k = 0; k < 100; ++k) { - status = RREG32_SOC15(VCN, i, regUVD_STATUS); - if (status & 2) - break; - mdelay(10); - if (amdgpu_emu_mode == 1) - msleep(1); - } - - if (amdgpu_emu_mode == 1) { - r = -1; - if (status & 2) { - r = 0; - break; - } - } else { + if (amdgpu_emu_mode == 1) { + r = -1; + if (status & 2) { r = 0; - if (status & 2) - break; - - dev_err(adev->dev, - "VCN[%d] is not responding, trying to reset the VCPU!!!\n", i); - WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), - UVD_VCPU_CNTL__BLK_RST_MASK, - ~UVD_VCPU_CNTL__BLK_RST_MASK); - mdelay(10); - WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0, - ~UVD_VCPU_CNTL__BLK_RST_MASK); - - mdelay(10); - r = -1; + break; } + } else { + r = 0; + if (status & 2) + break; + + dev_err(adev->dev, + "VCN[%d] is not responding, trying to reset the VCPU!!!\n", i); + WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), + UVD_VCPU_CNTL__BLK_RST_MASK, + ~UVD_VCPU_CNTL__BLK_RST_MASK); + mdelay(10); + WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0, + ~UVD_VCPU_CNTL__BLK_RST_MASK); + + mdelay(10); + r = -1; } - - if (r) { - dev_err(adev->dev, "VCN[%d] is not responding, giving up!!!\n", i); - return r; - } - - /* enable master interrupt */ - WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN), - UVD_MASTINT_EN__VCPU_EN_MASK, - ~UVD_MASTINT_EN__VCPU_EN_MASK); - - /* clear the busy bit of VCN_STATUS */ - WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_STATUS), 0, - ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT)); - - ring = &adev->vcn.inst[i].ring_enc[0]; - WREG32_SOC15(VCN, i, regVCN_RB1_DB_CTRL, - ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT | - VCN_RB1_DB_CTRL__EN_MASK); - - WREG32_SOC15(VCN, i, regUVD_RB_BASE_LO, ring->gpu_addr); - WREG32_SOC15(VCN, i, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr)); - WREG32_SOC15(VCN, i, regUVD_RB_SIZE, ring->ring_size / 4); - - tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE); - tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK); - WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp); - fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET; - WREG32_SOC15(VCN, i, regUVD_RB_RPTR, 0); - WREG32_SOC15(VCN, i, regUVD_RB_WPTR, 0); - - tmp = RREG32_SOC15(VCN, i, regUVD_RB_RPTR); - WREG32_SOC15(VCN, i, regUVD_RB_WPTR, tmp); - ring->wptr = RREG32_SOC15(VCN, i, regUVD_RB_WPTR); - - tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE); - tmp |= VCN_RB_ENABLE__RB1_EN_MASK; - WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp); - fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF); } + if (r) { + dev_err(adev->dev, "VCN[%d] is not responding, giving up!!!\n", i); + return r; + } + + /* enable master interrupt */ + WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN), + UVD_MASTINT_EN__VCPU_EN_MASK, + ~UVD_MASTINT_EN__VCPU_EN_MASK); + + /* clear the busy bit of VCN_STATUS */ + WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_STATUS), 0, + ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT)); + + ring = &adev->vcn.inst[i].ring_enc[0]; + WREG32_SOC15(VCN, i, regVCN_RB1_DB_CTRL, + ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT | + VCN_RB1_DB_CTRL__EN_MASK); + + WREG32_SOC15(VCN, i, regUVD_RB_BASE_LO, ring->gpu_addr); + WREG32_SOC15(VCN, i, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr)); + WREG32_SOC15(VCN, i, regUVD_RB_SIZE, ring->ring_size / 4); + + tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE); + tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK); + WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp); + fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET; + WREG32_SOC15(VCN, i, regUVD_RB_RPTR, 0); + WREG32_SOC15(VCN, i, regUVD_RB_WPTR, 0); + + tmp = RREG32_SOC15(VCN, i, regUVD_RB_RPTR); + WREG32_SOC15(VCN, i, regUVD_RB_WPTR, tmp); + ring->wptr = RREG32_SOC15(VCN, i, regUVD_RB_WPTR); + + tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE); + tmp |= VCN_RB_ENABLE__RB1_EN_MASK; + WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp); + fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF); + return 0; } @@ -953,85 +948,84 @@ static void vcn_v5_0_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx) * vcn_v5_0_0_stop - VCN stop * * @adev: amdgpu_device pointer + * @i: instance to stop * * Stop VCN block */ -static int vcn_v5_0_0_stop(struct amdgpu_device *adev) +static int vcn_v5_0_0_stop(struct amdgpu_device *adev, int i) { volatile struct amdgpu_vcn5_fw_shared *fw_shared; uint32_t tmp; - int i, r = 0; + int r = 0; - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { - if (adev->vcn.harvest_config & (1 << i)) - continue; + if (adev->vcn.harvest_config & (1 << i)) + return 0; - fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; - fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF; + fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; + fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF; - if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) { - vcn_v5_0_0_stop_dpg_mode(adev, i); - continue; - } - - /* wait for vcn idle */ - r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_STATUS, UVD_STATUS__IDLE, 0x7); - if (r) - return r; - - tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK | - UVD_LMI_STATUS__READ_CLEAN_MASK | - UVD_LMI_STATUS__WRITE_CLEAN_MASK | - UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK; - r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp); - if (r) - return r; - - /* disable LMI UMC channel */ - tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL2); - tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK; - WREG32_SOC15(VCN, i, regUVD_LMI_CTRL2, tmp); - tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK | - UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK; - r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp); - if (r) - return r; - - /* block VCPU register access */ - WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL), - UVD_RB_ARB_CTRL__VCPU_DIS_MASK, - ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK); - - /* reset VCPU */ - WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), - UVD_VCPU_CNTL__BLK_RST_MASK, - ~UVD_VCPU_CNTL__BLK_RST_MASK); - - /* disable VCPU clock */ - WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0, - ~(UVD_VCPU_CNTL__CLK_EN_MASK)); - - /* apply soft reset */ - tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET); - tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK; - WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp); - tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET); - tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK; - WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp); - - /* clear status */ - WREG32_SOC15(VCN, i, regUVD_STATUS, 0); - - /* enable VCN power gating */ - vcn_v5_0_0_enable_static_power_gating(adev, i); + if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) { + vcn_v5_0_0_stop_dpg_mode(adev, i); + r = 0; + goto done; } - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { - if (adev->pm.dpm_enabled) - amdgpu_dpm_enable_vcn(adev, false, i); - } + /* wait for vcn idle */ + r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_STATUS, UVD_STATUS__IDLE, 0x7); + if (r) + goto done; - return 0; + tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK | + UVD_LMI_STATUS__READ_CLEAN_MASK | + UVD_LMI_STATUS__WRITE_CLEAN_MASK | + UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK; + r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp); + if (r) + goto done; + + /* disable LMI UMC channel */ + tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL2); + tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK; + WREG32_SOC15(VCN, i, regUVD_LMI_CTRL2, tmp); + tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK | + UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK; + r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp); + if (r) + goto done; + + /* block VCPU register access */ + WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL), + UVD_RB_ARB_CTRL__VCPU_DIS_MASK, + ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK); + + /* reset VCPU */ + WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), + UVD_VCPU_CNTL__BLK_RST_MASK, + ~UVD_VCPU_CNTL__BLK_RST_MASK); + + /* disable VCPU clock */ + WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0, + ~(UVD_VCPU_CNTL__CLK_EN_MASK)); + + /* apply soft reset */ + tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET); + tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK; + WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp); + tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET); + tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK; + WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp); + + /* clear status */ + WREG32_SOC15(VCN, i, regUVD_STATUS, 0); + + /* enable VCN power gating */ + vcn_v5_0_0_enable_static_power_gating(adev, i); + +done: + if (adev->pm.dpm_enabled) + amdgpu_dpm_enable_vcn(adev, false, i); + + return r; } /** @@ -1279,15 +1273,17 @@ static int vcn_v5_0_0_set_powergating_state(struct amdgpu_ip_block *ip_block, enum amd_powergating_state state) { struct amdgpu_device *adev = ip_block->adev; - int ret; + int ret = 0, i; if (state == adev->vcn.cur_state) return 0; - if (state == AMD_PG_STATE_GATE) - ret = vcn_v5_0_0_stop(adev); - else - ret = vcn_v5_0_0_start(adev); + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { + if (state == AMD_PG_STATE_GATE) + ret |= vcn_v5_0_0_stop(adev, i); + else + ret |= vcn_v5_0_0_start(adev, i); + } if (!ret) adev->vcn.cur_state = state; From 94629182f3096fb8beafabc7e7cba097630185b7 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 10 Dec 2024 12:34:54 -0500 Subject: [PATCH 081/235] drm/amdgpu/vcn5.0.1: split code along instances Split the code on a per instance basis. This will allow us to use the per instance functions in the future to handle more things per instance. Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c | 378 ++++++++++++------------ 1 file changed, 187 insertions(+), 191 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c index 40f36c9a4132..bfe48e4a4859 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c @@ -568,147 +568,143 @@ static int vcn_v5_0_1_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, b * * Start VCN block */ -static int vcn_v5_0_1_start(struct amdgpu_device *adev) +static int vcn_v5_0_1_start(struct amdgpu_device *adev, int i) { volatile struct amdgpu_vcn4_fw_shared *fw_shared; struct amdgpu_ring *ring; uint32_t tmp; - int i, j, k, r, vcn_inst; + int j, k, r, vcn_inst; - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { - fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; + fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; - if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) { - r = vcn_v5_0_1_start_dpg_mode(adev, i, adev->vcn.indirect_sram); - continue; + if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) + return vcn_v5_0_1_start_dpg_mode(adev, i, adev->vcn.indirect_sram); + + vcn_inst = GET_INST(VCN, i); + + /* set VCN status busy */ + tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_STATUS) | UVD_STATUS__UVD_BUSY; + WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, tmp); + + /* enable VCPU clock */ + WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), + UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK); + + /* disable master interrupt */ + WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_MASTINT_EN), 0, + ~UVD_MASTINT_EN__VCPU_EN_MASK); + + /* enable LMI MC and UMC channels */ + WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_LMI_CTRL2), 0, + ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK); + + tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET); + tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK; + tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK; + WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp); + + /* setup regUVD_LMI_CTRL */ + tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL); + WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL, tmp | + UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK | + UVD_LMI_CTRL__MASK_MC_URGENT_MASK | + UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK | + UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK); + + vcn_v5_0_1_mc_resume(adev, i); + + /* VCN global tiling registers */ + WREG32_SOC15(VCN, vcn_inst, regUVD_GFX10_ADDR_CONFIG, + adev->gfx.config.gb_addr_config); + + /* unblock VCPU register access */ + WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_RB_ARB_CTRL), 0, + ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK); + + /* release VCPU reset to boot */ + WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0, + ~UVD_VCPU_CNTL__BLK_RST_MASK); + + for (j = 0; j < 10; ++j) { + uint32_t status; + + for (k = 0; k < 100; ++k) { + status = RREG32_SOC15(VCN, vcn_inst, regUVD_STATUS); + if (status & 2) + break; + mdelay(100); + if (amdgpu_emu_mode == 1) + msleep(20); } - vcn_inst = GET_INST(VCN, i); - - /* set VCN status busy */ - tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_STATUS) | UVD_STATUS__UVD_BUSY; - WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, tmp); - - /* enable VCPU clock */ - WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), - UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK); - - /* disable master interrupt */ - WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_MASTINT_EN), 0, - ~UVD_MASTINT_EN__VCPU_EN_MASK); - - /* enable LMI MC and UMC channels */ - WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_LMI_CTRL2), 0, - ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK); - - tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET); - tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK; - tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK; - WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp); - - /* setup regUVD_LMI_CTRL */ - tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL); - WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL, tmp | - UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK | - UVD_LMI_CTRL__MASK_MC_URGENT_MASK | - UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK | - UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK); - - vcn_v5_0_1_mc_resume(adev, i); - - /* VCN global tiling registers */ - WREG32_SOC15(VCN, vcn_inst, regUVD_GFX10_ADDR_CONFIG, - adev->gfx.config.gb_addr_config); - - /* unblock VCPU register access */ - WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_RB_ARB_CTRL), 0, - ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK); - - /* release VCPU reset to boot */ - WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0, - ~UVD_VCPU_CNTL__BLK_RST_MASK); - - for (j = 0; j < 10; ++j) { - uint32_t status; - - for (k = 0; k < 100; ++k) { - status = RREG32_SOC15(VCN, vcn_inst, regUVD_STATUS); - if (status & 2) - break; - mdelay(100); - if (amdgpu_emu_mode == 1) - msleep(20); - } - - if (amdgpu_emu_mode == 1) { - r = -1; - if (status & 2) { - r = 0; - break; - } - } else { + if (amdgpu_emu_mode == 1) { + r = -1; + if (status & 2) { r = 0; - if (status & 2) - break; - - dev_err(adev->dev, - "VCN[%d] is not responding, trying to reset the VCPU!!!\n", i); - WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), - UVD_VCPU_CNTL__BLK_RST_MASK, - ~UVD_VCPU_CNTL__BLK_RST_MASK); - mdelay(10); - WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0, - ~UVD_VCPU_CNTL__BLK_RST_MASK); - - mdelay(10); - r = -1; + break; } + } else { + r = 0; + if (status & 2) + break; + + dev_err(adev->dev, + "VCN[%d] is not responding, trying to reset the VCPU!!!\n", i); + WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), + UVD_VCPU_CNTL__BLK_RST_MASK, + ~UVD_VCPU_CNTL__BLK_RST_MASK); + mdelay(10); + WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0, + ~UVD_VCPU_CNTL__BLK_RST_MASK); + + mdelay(10); + r = -1; } - - if (r) { - dev_err(adev->dev, "VCN[%d] is not responding, giving up!!!\n", i); - return r; - } - - /* enable master interrupt */ - WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_MASTINT_EN), - UVD_MASTINT_EN__VCPU_EN_MASK, - ~UVD_MASTINT_EN__VCPU_EN_MASK); - - /* clear the busy bit of VCN_STATUS */ - WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_STATUS), 0, - ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT)); - - ring = &adev->vcn.inst[i].ring_enc[0]; - - WREG32_SOC15(VCN, vcn_inst, regVCN_RB1_DB_CTRL, - ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT | - VCN_RB1_DB_CTRL__EN_MASK); - - /* Read DB_CTRL to flush the write DB_CTRL command. */ - RREG32_SOC15(VCN, vcn_inst, regVCN_RB1_DB_CTRL); - - WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_LO, ring->gpu_addr); - WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr)); - WREG32_SOC15(VCN, vcn_inst, regUVD_RB_SIZE, ring->ring_size / 4); - - tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE); - tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK); - WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp); - fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET; - WREG32_SOC15(VCN, vcn_inst, regUVD_RB_RPTR, 0); - WREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR, 0); - - tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_RB_RPTR); - WREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR, tmp); - ring->wptr = RREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR); - - tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE); - tmp |= VCN_RB_ENABLE__RB1_EN_MASK; - WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp); - fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF); } + if (r) { + dev_err(adev->dev, "VCN[%d] is not responding, giving up!!!\n", i); + return r; + } + + /* enable master interrupt */ + WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_MASTINT_EN), + UVD_MASTINT_EN__VCPU_EN_MASK, + ~UVD_MASTINT_EN__VCPU_EN_MASK); + + /* clear the busy bit of VCN_STATUS */ + WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_STATUS), 0, + ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT)); + + ring = &adev->vcn.inst[i].ring_enc[0]; + + WREG32_SOC15(VCN, vcn_inst, regVCN_RB1_DB_CTRL, + ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT | + VCN_RB1_DB_CTRL__EN_MASK); + + /* Read DB_CTRL to flush the write DB_CTRL command. */ + RREG32_SOC15(VCN, vcn_inst, regVCN_RB1_DB_CTRL); + + WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_LO, ring->gpu_addr); + WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr)); + WREG32_SOC15(VCN, vcn_inst, regUVD_RB_SIZE, ring->ring_size / 4); + + tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE); + tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK); + WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp); + fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET; + WREG32_SOC15(VCN, vcn_inst, regUVD_RB_RPTR, 0); + WREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR, 0); + + tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_RB_RPTR); + WREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR, tmp); + ring->wptr = RREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR); + + tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE); + tmp |= VCN_RB_ENABLE__RB1_EN_MASK; + WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp); + fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF); + return 0; } @@ -747,72 +743,70 @@ static void vcn_v5_0_1_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx) * * Stop VCN block */ -static int vcn_v5_0_1_stop(struct amdgpu_device *adev) +static int vcn_v5_0_1_stop(struct amdgpu_device *adev, int i) { volatile struct amdgpu_vcn4_fw_shared *fw_shared; uint32_t tmp; - int i, r = 0, vcn_inst; + int r = 0, vcn_inst; - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { - vcn_inst = GET_INST(VCN, i); + vcn_inst = GET_INST(VCN, i); - fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; - fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF; + fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; + fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF; - if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) { - vcn_v5_0_1_stop_dpg_mode(adev, i); - continue; - } - - /* wait for vcn idle */ - r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_STATUS, UVD_STATUS__IDLE, 0x7); - if (r) - return r; - - tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK | - UVD_LMI_STATUS__READ_CLEAN_MASK | - UVD_LMI_STATUS__WRITE_CLEAN_MASK | - UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK; - r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_LMI_STATUS, tmp, tmp); - if (r) - return r; - - /* disable LMI UMC channel */ - tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL2); - tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK; - WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL2, tmp); - tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK | - UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK; - r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_LMI_STATUS, tmp, tmp); - if (r) - return r; - - /* block VCPU register access */ - WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_RB_ARB_CTRL), - UVD_RB_ARB_CTRL__VCPU_DIS_MASK, - ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK); - - /* reset VCPU */ - WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), - UVD_VCPU_CNTL__BLK_RST_MASK, - ~UVD_VCPU_CNTL__BLK_RST_MASK); - - /* disable VCPU clock */ - WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0, - ~(UVD_VCPU_CNTL__CLK_EN_MASK)); - - /* apply soft reset */ - tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET); - tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK; - WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp); - tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET); - tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK; - WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp); - - /* clear status */ - WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, 0); + if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) { + vcn_v5_0_1_stop_dpg_mode(adev, i); + return 0; } + /* wait for vcn idle */ + r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_STATUS, UVD_STATUS__IDLE, 0x7); + if (r) + return r; + + tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK | + UVD_LMI_STATUS__READ_CLEAN_MASK | + UVD_LMI_STATUS__WRITE_CLEAN_MASK | + UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK; + r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_LMI_STATUS, tmp, tmp); + if (r) + return r; + + /* disable LMI UMC channel */ + tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL2); + tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK; + WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL2, tmp); + tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK | + UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK; + r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_LMI_STATUS, tmp, tmp); + if (r) + return r; + + /* block VCPU register access */ + WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_RB_ARB_CTRL), + UVD_RB_ARB_CTRL__VCPU_DIS_MASK, + ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK); + + /* reset VCPU */ + WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), + UVD_VCPU_CNTL__BLK_RST_MASK, + ~UVD_VCPU_CNTL__BLK_RST_MASK); + + /* disable VCPU clock */ + WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0, + ~(UVD_VCPU_CNTL__CLK_EN_MASK)); + + /* apply soft reset */ + tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET); + tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK; + WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp); + tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET); + tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK; + WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp); + + /* clear status */ + WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, 0); + return 0; } @@ -1004,15 +998,17 @@ static int vcn_v5_0_1_set_powergating_state(struct amdgpu_ip_block *ip_block, enum amd_powergating_state state) { struct amdgpu_device *adev = ip_block->adev; - int ret; + int ret = 0, i; if (state == adev->vcn.cur_state) return 0; - if (state == AMD_PG_STATE_GATE) - ret = vcn_v5_0_1_stop(adev); - else - ret = vcn_v5_0_1_start(adev); + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { + if (state == AMD_PG_STATE_GATE) + ret = vcn_v5_0_1_stop(adev, i); + else + ret = vcn_v5_0_1_start(adev, i); + } if (!ret) adev->vcn.cur_state = state; From bee48570cf8e312faec9b8f465762052555158d0 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 13 Nov 2024 14:43:15 -0500 Subject: [PATCH 082/235] drm/amdgpu/vcn: switch work handler to be per instance Have a separate work handler for each VCN instance. This paves the way for per instance VCN power gating at runtime. v2: index instances directly on vcn1.0 and 2.0 to make it clear that they only support a single instance (Lijo) Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 84 +++++++++++++------------ drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h | 8 ++- drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c | 17 ++--- drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c | 4 +- drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 4 +- drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c | 5 +- drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c | 4 +- drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c | 5 +- drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c | 5 +- drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c | 4 +- 12 files changed, 80 insertions(+), 64 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c index 83faf6e6788a..0c3081a198d9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c @@ -100,6 +100,9 @@ int amdgpu_vcn_early_init(struct amdgpu_device *adev) amdgpu_ucode_ip_version_decode(adev, UVD_HWIP, ucode_prefix, sizeof(ucode_prefix)); for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + adev->vcn.inst[i].adev = adev; + adev->vcn.inst[i].inst = i; + if (i == 1 && amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(4, 0, 6)) r = amdgpu_ucode_request(adev, &adev->vcn.inst[i].fw, AMDGPU_UCODE_REQUIRED, @@ -124,12 +127,13 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev) unsigned int fw_shared_size, log_offset; int i, r; - INIT_DELAYED_WORK(&adev->vcn.idle_work, amdgpu_vcn_idle_work_handler); - mutex_init(&adev->vcn.vcn_pg_lock); mutex_init(&adev->vcn.vcn1_jpeg1_workaround); - atomic_set(&adev->vcn.total_submission_cnt, 0); - for (i = 0; i < adev->vcn.num_vcn_inst; i++) + for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + mutex_init(&adev->vcn.inst[i].vcn_pg_lock); + atomic_set(&adev->vcn.inst[i].total_submission_cnt, 0); + INIT_DELAYED_WORK(&adev->vcn.inst[i].idle_work, amdgpu_vcn_idle_work_handler); atomic_set(&adev->vcn.inst[i].dpg_enc_submission_cnt, 0); + } if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) && (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)) @@ -277,10 +281,10 @@ int amdgpu_vcn_sw_fini(struct amdgpu_device *adev) amdgpu_ring_fini(&adev->vcn.inst[j].ring_enc[i]); amdgpu_ucode_release(&adev->vcn.inst[j].fw); + mutex_destroy(&adev->vcn.inst[j].vcn_pg_lock); } mutex_destroy(&adev->vcn.vcn1_jpeg1_workaround); - mutex_destroy(&adev->vcn.vcn_pg_lock); return 0; } @@ -331,8 +335,10 @@ int amdgpu_vcn_save_vcpu_bo(struct amdgpu_device *adev) int amdgpu_vcn_suspend(struct amdgpu_device *adev) { bool in_ras_intr = amdgpu_ras_intr_triggered(); + int i; - cancel_delayed_work_sync(&adev->vcn.idle_work); + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) + cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work); /* err_event_athub will corrupt VCPU buffer, so we need to * restore fw data and clear buffer in amdgpu_vcn_resume() */ @@ -388,46 +394,45 @@ int amdgpu_vcn_resume(struct amdgpu_device *adev) static void amdgpu_vcn_idle_work_handler(struct work_struct *work) { - struct amdgpu_device *adev = - container_of(work, struct amdgpu_device, vcn.idle_work.work); + struct amdgpu_vcn_inst *vcn_inst = + container_of(work, struct amdgpu_vcn_inst, idle_work.work); + struct amdgpu_device *adev = vcn_inst->adev; unsigned int fences = 0, fence[AMDGPU_MAX_VCN_INSTANCES] = {0}; - unsigned int i, j; + unsigned int i = vcn_inst->inst, j; int r = 0; - for (j = 0; j < adev->vcn.num_vcn_inst; ++j) { - if (adev->vcn.harvest_config & (1 << j)) - continue; + if (adev->vcn.harvest_config & (1 << i)) + return; - for (i = 0; i < adev->vcn.num_enc_rings; ++i) - fence[j] += amdgpu_fence_count_emitted(&adev->vcn.inst[j].ring_enc[i]); + for (j = 0; j < adev->vcn.num_enc_rings; ++j) + fence[i] += amdgpu_fence_count_emitted(&vcn_inst->ring_enc[j]); - /* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */ - if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG && - !adev->vcn.using_unified_queue) { - struct dpg_pause_state new_state; + /* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */ + if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG && + !adev->vcn.using_unified_queue) { + struct dpg_pause_state new_state; - if (fence[j] || - unlikely(atomic_read(&adev->vcn.inst[j].dpg_enc_submission_cnt))) - new_state.fw_based = VCN_DPG_STATE__PAUSE; - else - new_state.fw_based = VCN_DPG_STATE__UNPAUSE; + if (fence[i] || + unlikely(atomic_read(&vcn_inst->dpg_enc_submission_cnt))) + new_state.fw_based = VCN_DPG_STATE__PAUSE; + else + new_state.fw_based = VCN_DPG_STATE__UNPAUSE; - adev->vcn.pause_dpg_mode(adev, j, &new_state); - } - - fence[j] += amdgpu_fence_count_emitted(&adev->vcn.inst[j].ring_dec); - fences += fence[j]; + adev->vcn.pause_dpg_mode(adev, i, &new_state); } - if (!fences && !atomic_read(&adev->vcn.total_submission_cnt)) { + fence[i] += amdgpu_fence_count_emitted(&vcn_inst->ring_dec); + fences += fence[i]; + + if (!fences && !atomic_read(&vcn_inst->total_submission_cnt)) { amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN, - AMD_PG_STATE_GATE); + AMD_PG_STATE_GATE); r = amdgpu_dpm_switch_power_profile(adev, PP_SMC_POWER_PROFILE_VIDEO, - false); + false); if (r) dev_warn(adev->dev, "(%d) failed to disable video power profile mode\n", r); } else { - schedule_delayed_work(&adev->vcn.idle_work, VCN_IDLE_TIMEOUT); + schedule_delayed_work(&vcn_inst->idle_work, VCN_IDLE_TIMEOUT); } } @@ -436,18 +441,18 @@ void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring) struct amdgpu_device *adev = ring->adev; int r = 0; - atomic_inc(&adev->vcn.total_submission_cnt); + atomic_inc(&adev->vcn.inst[ring->me].total_submission_cnt); - if (!cancel_delayed_work_sync(&adev->vcn.idle_work)) { + if (!cancel_delayed_work_sync(&adev->vcn.inst[ring->me].idle_work)) { r = amdgpu_dpm_switch_power_profile(adev, PP_SMC_POWER_PROFILE_VIDEO, true); if (r) dev_warn(adev->dev, "(%d) failed to switch to video power profile mode\n", r); } - mutex_lock(&adev->vcn.vcn_pg_lock); + mutex_lock(&adev->vcn.inst[ring->me].vcn_pg_lock); amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN, - AMD_PG_STATE_UNGATE); + AMD_PG_STATE_UNGATE); /* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */ if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG && @@ -472,7 +477,7 @@ void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring) adev->vcn.pause_dpg_mode(adev, ring->me, &new_state); } - mutex_unlock(&adev->vcn.vcn_pg_lock); + mutex_unlock(&adev->vcn.inst[ring->me].vcn_pg_lock); } void amdgpu_vcn_ring_end_use(struct amdgpu_ring *ring) @@ -485,9 +490,10 @@ void amdgpu_vcn_ring_end_use(struct amdgpu_ring *ring) !adev->vcn.using_unified_queue) atomic_dec(&ring->adev->vcn.inst[ring->me].dpg_enc_submission_cnt); - atomic_dec(&ring->adev->vcn.total_submission_cnt); + atomic_dec(&ring->adev->vcn.inst[ring->me].total_submission_cnt); - schedule_delayed_work(&ring->adev->vcn.idle_work, VCN_IDLE_TIMEOUT); + schedule_delayed_work(&ring->adev->vcn.inst[ring->me].idle_work, + VCN_IDLE_TIMEOUT); } int amdgpu_vcn_dec_ring_test_ring(struct amdgpu_ring *ring) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h index c92f683ee595..f1685283c2f1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h @@ -295,6 +295,8 @@ struct amdgpu_vcn_fw_shared { }; struct amdgpu_vcn_inst { + struct amdgpu_device *adev; + int inst; struct amdgpu_bo *vcpu_bo; void *cpu_addr; uint64_t gpu_addr; @@ -316,6 +318,9 @@ struct amdgpu_vcn_inst { const struct firmware *fw; /* VCN firmware */ uint8_t vcn_config; uint32_t vcn_codec_disable_mask; + atomic_t total_submission_cnt; + struct mutex vcn_pg_lock; + struct delayed_work idle_work; }; struct amdgpu_vcn_ras { @@ -324,7 +329,6 @@ struct amdgpu_vcn_ras { struct amdgpu_vcn { unsigned fw_version; - struct delayed_work idle_work; unsigned num_enc_rings; enum amd_powergating_state cur_state; bool indirect_sram; @@ -332,9 +336,7 @@ struct amdgpu_vcn { uint8_t num_vcn_inst; struct amdgpu_vcn_inst inst[AMDGPU_MAX_VCN_INSTANCES]; struct amdgpu_vcn_reg internal; - struct mutex vcn_pg_lock; struct mutex vcn1_jpeg1_workaround; - atomic_t total_submission_cnt; unsigned harvest_config; int (*pause_dpg_mode)(struct amdgpu_device *adev, diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c index 03b8b7cd5229..8031406e20ff 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c @@ -604,7 +604,7 @@ static void jpeg_v1_0_set_irq_funcs(struct amdgpu_device *adev) static void jpeg_v1_0_ring_begin_use(struct amdgpu_ring *ring) { struct amdgpu_device *adev = ring->adev; - bool set_clocks = !cancel_delayed_work_sync(&adev->vcn.idle_work); + bool set_clocks = !cancel_delayed_work_sync(&adev->vcn.inst[0].idle_work); int cnt = 0; mutex_lock(&adev->vcn.vcn1_jpeg1_workaround); diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c index 06e1bbcf1a52..cccf8e5b0037 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c @@ -150,7 +150,7 @@ static int vcn_v1_0_sw_init(struct amdgpu_ip_block *ip_block) return r; /* Override the work func */ - adev->vcn.idle_work.work.func = vcn_v1_0_idle_work_handler; + adev->vcn.inst[0].idle_work.work.func = vcn_v1_0_idle_work_handler; amdgpu_vcn_setup_ucode(adev); @@ -277,7 +277,7 @@ static int vcn_v1_0_hw_fini(struct amdgpu_ip_block *ip_block) { struct amdgpu_device *adev = ip_block->adev; - cancel_delayed_work_sync(&adev->vcn.idle_work); + cancel_delayed_work_sync(&adev->vcn.inst[0].idle_work); if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) || (adev->vcn.cur_state != AMD_PG_STATE_GATE && @@ -301,7 +301,7 @@ static int vcn_v1_0_suspend(struct amdgpu_ip_block *ip_block) struct amdgpu_device *adev = ip_block->adev; bool idle_work_unexecuted; - idle_work_unexecuted = cancel_delayed_work_sync(&adev->vcn.idle_work); + idle_work_unexecuted = cancel_delayed_work_sync(&adev->vcn.inst[0].idle_work); if (idle_work_unexecuted) { if (adev->pm.dpm_enabled) amdgpu_dpm_enable_vcn(adev, false, 0); @@ -1828,8 +1828,9 @@ static int vcn_v1_0_set_powergating_state(struct amdgpu_ip_block *ip_block, static void vcn_v1_0_idle_work_handler(struct work_struct *work) { - struct amdgpu_device *adev = - container_of(work, struct amdgpu_device, vcn.idle_work.work); + struct amdgpu_vcn_inst *vcn_inst = + container_of(work, struct amdgpu_vcn_inst, idle_work.work); + struct amdgpu_device *adev = vcn_inst->adev; unsigned int fences = 0, i; for (i = 0; i < adev->vcn.num_enc_rings; ++i) @@ -1862,14 +1863,14 @@ static void vcn_v1_0_idle_work_handler(struct work_struct *work) amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN, AMD_PG_STATE_GATE); } else { - schedule_delayed_work(&adev->vcn.idle_work, VCN_IDLE_TIMEOUT); + schedule_delayed_work(&adev->vcn.inst[0].idle_work, VCN_IDLE_TIMEOUT); } } static void vcn_v1_0_ring_begin_use(struct amdgpu_ring *ring) { struct amdgpu_device *adev = ring->adev; - bool set_clocks = !cancel_delayed_work_sync(&adev->vcn.idle_work); + bool set_clocks = !cancel_delayed_work_sync(&adev->vcn.inst[0].idle_work); mutex_lock(&adev->vcn.vcn1_jpeg1_workaround); @@ -1921,7 +1922,7 @@ void vcn_v1_0_set_pg_for_begin_use(struct amdgpu_ring *ring, bool set_clocks) void vcn_v1_0_ring_end_use(struct amdgpu_ring *ring) { - schedule_delayed_work(&ring->adev->vcn.idle_work, VCN_IDLE_TIMEOUT); + schedule_delayed_work(&ring->adev->vcn.inst[0].idle_work, VCN_IDLE_TIMEOUT); mutex_unlock(&ring->adev->vcn.vcn1_jpeg1_workaround); } diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c index 1e1c8f57d4cd..86d20141f39c 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c @@ -313,7 +313,7 @@ static int vcn_v2_0_hw_fini(struct amdgpu_ip_block *ip_block) { struct amdgpu_device *adev = ip_block->adev; - cancel_delayed_work_sync(&adev->vcn.idle_work); + cancel_delayed_work_sync(&adev->vcn.inst[0].idle_work); if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) || (adev->vcn.cur_state != AMD_PG_STATE_GATE && diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c index e36e2a5676df..aee236aaa7d0 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c @@ -390,12 +390,12 @@ static int vcn_v2_5_hw_fini(struct amdgpu_ip_block *ip_block) struct amdgpu_device *adev = ip_block->adev; int i; - cancel_delayed_work_sync(&adev->vcn.idle_work); - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { if (adev->vcn.harvest_config & (1 << i)) continue; + cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work); + if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) || (adev->vcn.cur_state != AMD_PG_STATE_GATE && RREG32_SOC15(VCN, i, mmUVD_STATUS))) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c index ec42a456c541..dd3f3c409105 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c @@ -422,12 +422,12 @@ static int vcn_v3_0_hw_fini(struct amdgpu_ip_block *ip_block) struct amdgpu_device *adev = ip_block->adev; int i; - cancel_delayed_work_sync(&adev->vcn.idle_work); - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { if (adev->vcn.harvest_config & (1 << i)) continue; + cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work); + if (!amdgpu_sriov_vf(adev)) { if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) || (adev->vcn.cur_state != AMD_PG_STATE_GATE && diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c index c99c121faac0..4d20d58802f6 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c @@ -359,11 +359,12 @@ static int vcn_v4_0_hw_fini(struct amdgpu_ip_block *ip_block) struct amdgpu_device *adev = ip_block->adev; int i; - cancel_delayed_work_sync(&adev->vcn.idle_work); - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { if (adev->vcn.harvest_config & (1 << i)) continue; + + cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work); + if (!amdgpu_sriov_vf(adev)) { if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) || (adev->vcn.cur_state != AMD_PG_STATE_GATE && diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c index 00b94d01cd4c..932b65072dbc 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c @@ -349,8 +349,10 @@ static int vcn_v4_0_3_hw_init(struct amdgpu_ip_block *ip_block) static int vcn_v4_0_3_hw_fini(struct amdgpu_ip_block *ip_block) { struct amdgpu_device *adev = ip_block->adev; + int i; - cancel_delayed_work_sync(&adev->vcn.idle_work); + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) + cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work); if (adev->vcn.cur_state != AMD_PG_STATE_GATE) vcn_v4_0_3_set_powergating_state(ip_block, AMD_PG_STATE_GATE); diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c index c2bbacb176c1..83093e5c5cca 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c @@ -300,11 +300,12 @@ static int vcn_v4_0_5_hw_fini(struct amdgpu_ip_block *ip_block) struct amdgpu_device *adev = ip_block->adev; int i; - cancel_delayed_work_sync(&adev->vcn.idle_work); - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { if (adev->vcn.harvest_config & (1 << i)) continue; + + cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work); + if (!amdgpu_sriov_vf(adev)) { if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) || (adev->vcn.cur_state != AMD_PG_STATE_GATE && diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c index 188cd6f1dda2..26f788ceeb11 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c @@ -280,11 +280,12 @@ static int vcn_v5_0_0_hw_fini(struct amdgpu_ip_block *ip_block) struct amdgpu_device *adev = ip_block->adev; int i; - cancel_delayed_work_sync(&adev->vcn.idle_work); - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { if (adev->vcn.harvest_config & (1 << i)) continue; + + cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work); + if (!amdgpu_sriov_vf(adev)) { if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) || (adev->vcn.cur_state != AMD_PG_STATE_GATE && diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c index bfe48e4a4859..512e5f6ae7b3 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c @@ -206,8 +206,10 @@ static int vcn_v5_0_1_hw_init(struct amdgpu_ip_block *ip_block) static int vcn_v5_0_1_hw_fini(struct amdgpu_ip_block *ip_block) { struct amdgpu_device *adev = ip_block->adev; + int i; - cancel_delayed_work_sync(&adev->vcn.idle_work); + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) + cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work); return 0; } From 9bf9442051c0af835b683411d9ebc6a5036d4cbb Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 13 Nov 2024 15:28:41 -0500 Subject: [PATCH 083/235] drm/amdgpu/vcn: make powergating status per instance Store it per instance so we can track it per instance. v2: index instances directly on vcn1.0 and 2.0 to make it clear that they only support a single instance (Lijo) Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h | 2 +- drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c | 6 +- drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c | 11 ++-- drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c | 51 +++++++++++------ drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 49 +++++++++++------ drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c | 62 +++++++++++++-------- drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c | 67 ++++++++++++++--------- drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c | 48 ++++++++++------ drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c | 48 ++++++++++------ drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c | 40 +++++++++----- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 8 +-- 11 files changed, 248 insertions(+), 144 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h index f1685283c2f1..0bcf4d1c7175 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h @@ -320,6 +320,7 @@ struct amdgpu_vcn_inst { uint32_t vcn_codec_disable_mask; atomic_t total_submission_cnt; struct mutex vcn_pg_lock; + enum amd_powergating_state cur_state; struct delayed_work idle_work; }; @@ -330,7 +331,6 @@ struct amdgpu_vcn_ras { struct amdgpu_vcn { unsigned fw_version; unsigned num_enc_rings; - enum amd_powergating_state cur_state; bool indirect_sram; uint8_t num_vcn_inst; diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c index cccf8e5b0037..291a5866c148 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c @@ -280,7 +280,7 @@ static int vcn_v1_0_hw_fini(struct amdgpu_ip_block *ip_block) cancel_delayed_work_sync(&adev->vcn.inst[0].idle_work); if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) || - (adev->vcn.cur_state != AMD_PG_STATE_GATE && + (adev->vcn.inst[0].cur_state != AMD_PG_STATE_GATE && RREG32_SOC15(VCN, 0, mmUVD_STATUS))) { vcn_v1_0_set_powergating_state(ip_block, AMD_PG_STATE_GATE); } @@ -1813,7 +1813,7 @@ static int vcn_v1_0_set_powergating_state(struct amdgpu_ip_block *ip_block, int ret; struct amdgpu_device *adev = ip_block->adev; - if (state == adev->vcn.cur_state) + if (state == adev->vcn.inst[0].cur_state) return 0; if (state == AMD_PG_STATE_GATE) @@ -1822,7 +1822,7 @@ static int vcn_v1_0_set_powergating_state(struct amdgpu_ip_block *ip_block, ret = vcn_v1_0_start(adev); if (!ret) - adev->vcn.cur_state = state; + adev->vcn.inst[0].cur_state = state; return ret; } diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c index 86d20141f39c..cc2b9dcc8868 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c @@ -316,8 +316,8 @@ static int vcn_v2_0_hw_fini(struct amdgpu_ip_block *ip_block) cancel_delayed_work_sync(&adev->vcn.inst[0].idle_work); if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) || - (adev->vcn.cur_state != AMD_PG_STATE_GATE && - RREG32_SOC15(VCN, 0, mmUVD_STATUS))) + (adev->vcn.inst[0].cur_state != AMD_PG_STATE_GATE && + RREG32_SOC15(VCN, 0, mmUVD_STATUS))) vcn_v2_0_set_powergating_state(ip_block, AMD_PG_STATE_GATE); return 0; @@ -1810,11 +1810,11 @@ static int vcn_v2_0_set_powergating_state(struct amdgpu_ip_block *ip_block, struct amdgpu_device *adev = ip_block->adev; if (amdgpu_sriov_vf(adev)) { - adev->vcn.cur_state = AMD_PG_STATE_UNGATE; + adev->vcn.inst[0].cur_state = AMD_PG_STATE_UNGATE; return 0; } - if (state == adev->vcn.cur_state) + if (state == adev->vcn.inst[0].cur_state) return 0; if (state == AMD_PG_STATE_GATE) @@ -1823,7 +1823,8 @@ static int vcn_v2_0_set_powergating_state(struct amdgpu_ip_block *ip_block, ret = vcn_v2_0_start(adev); if (!ret) - adev->vcn.cur_state = state; + adev->vcn.inst[0].cur_state = state; + return ret; } diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c index aee236aaa7d0..0d78377f8ffe 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c @@ -95,8 +95,11 @@ static const struct amdgpu_hwip_reg_entry vcn_reg_list_2_5[] = { static void vcn_v2_5_set_dec_ring_funcs(struct amdgpu_device *adev); static void vcn_v2_5_set_enc_ring_funcs(struct amdgpu_device *adev); static void vcn_v2_5_set_irq_funcs(struct amdgpu_device *adev); +static int vcn_v2_5_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, + enum amd_powergating_state state, + int i); static int vcn_v2_5_set_powergating_state(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state); + enum amd_powergating_state state); static int vcn_v2_5_pause_dpg_mode(struct amdgpu_device *adev, int inst_idx, struct dpg_pause_state *new_state); static int vcn_v2_5_sriov_start(struct amdgpu_device *adev); @@ -397,9 +400,9 @@ static int vcn_v2_5_hw_fini(struct amdgpu_ip_block *ip_block) cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work); if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) || - (adev->vcn.cur_state != AMD_PG_STATE_GATE && + (adev->vcn.inst[i].cur_state != AMD_PG_STATE_GATE && RREG32_SOC15(VCN, i, mmUVD_STATUS))) - vcn_v2_5_set_powergating_state(ip_block, AMD_PG_STATE_GATE); + vcn_v2_5_set_powergating_state_inst(ip_block, AMD_PG_STATE_GATE, i); if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__VCN)) amdgpu_irq_put(adev, &adev->vcn.inst[i].ras_poison_irq, 0); @@ -1808,27 +1811,39 @@ static int vcn_v2_5_set_clockgating_state(struct amdgpu_ip_block *ip_block, return 0; } +static int vcn_v2_5_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, + enum amd_powergating_state state, + int i) +{ + struct amdgpu_device *adev = ip_block->adev; + int ret; + + if (amdgpu_sriov_vf(adev)) + return 0; + + if (state == adev->vcn.inst[i].cur_state) + return 0; + + if (state == AMD_PG_STATE_GATE) + ret = vcn_v2_5_stop(adev, i); + else + ret = vcn_v2_5_start(adev, i); + + if (!ret) + adev->vcn.inst[i].cur_state = state; + + return ret; +} + static int vcn_v2_5_set_powergating_state(struct amdgpu_ip_block *ip_block, enum amd_powergating_state state) { struct amdgpu_device *adev = ip_block->adev; int ret = 0, i; - if (amdgpu_sriov_vf(adev)) - return 0; - - if (state == adev->vcn.cur_state) - return 0; - - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { - if (state == AMD_PG_STATE_GATE) - ret |= vcn_v2_5_stop(adev, i); - else - ret |= vcn_v2_5_start(adev, i); - } - - if (!ret) - adev->vcn.cur_state = state; + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) + ret |= vcn_v2_5_set_powergating_state_inst(ip_block, + state, i); return ret; } diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c index dd3f3c409105..acfe85b0c062 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c @@ -105,8 +105,11 @@ static int vcn_v3_0_start_sriov(struct amdgpu_device *adev); static void vcn_v3_0_set_dec_ring_funcs(struct amdgpu_device *adev); static void vcn_v3_0_set_enc_ring_funcs(struct amdgpu_device *adev); static void vcn_v3_0_set_irq_funcs(struct amdgpu_device *adev); +static int vcn_v3_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, + enum amd_powergating_state state, + int i); static int vcn_v3_0_set_powergating_state(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state); + enum amd_powergating_state state); static int vcn_v3_0_pause_dpg_mode(struct amdgpu_device *adev, int inst_idx, struct dpg_pause_state *new_state); @@ -430,9 +433,11 @@ static int vcn_v3_0_hw_fini(struct amdgpu_ip_block *ip_block) if (!amdgpu_sriov_vf(adev)) { if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) || - (adev->vcn.cur_state != AMD_PG_STATE_GATE && - RREG32_SOC15(VCN, i, mmUVD_STATUS))) { - vcn_v3_0_set_powergating_state(ip_block, AMD_PG_STATE_GATE); + (adev->vcn.inst[i].cur_state != AMD_PG_STATE_GATE && + RREG32_SOC15(VCN, i, mmUVD_STATUS))) { + vcn_v3_0_set_powergating_state_inst(ip_block, + AMD_PG_STATE_GATE, + i); } } } @@ -2150,33 +2155,45 @@ static int vcn_v3_0_set_clockgating_state(struct amdgpu_ip_block *ip_block, return 0; } -static int vcn_v3_0_set_powergating_state(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state) +static int vcn_v3_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, + enum amd_powergating_state state, + int i) { struct amdgpu_device *adev = ip_block->adev; - int ret = 0, i; + int ret = 0; /* for SRIOV, guest should not control VCN Power-gating * MMSCH FW should control Power-gating and clock-gating * guest should avoid touching CGC and PG */ if (amdgpu_sriov_vf(adev)) { - adev->vcn.cur_state = AMD_PG_STATE_UNGATE; + adev->vcn.inst[i].cur_state = AMD_PG_STATE_UNGATE; return 0; } - if (state == adev->vcn.cur_state) + if (state == adev->vcn.inst[i].cur_state) return 0; - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { - if (state == AMD_PG_STATE_GATE) - ret |= vcn_v3_0_stop(adev, i); - else - ret |= vcn_v3_0_start(adev, i); - } + if (state == AMD_PG_STATE_GATE) + ret = vcn_v3_0_stop(adev, i); + else + ret = vcn_v3_0_start(adev, i); if (!ret) - adev->vcn.cur_state = state; + adev->vcn.inst[i].cur_state = state; + + return ret; +} + +static int vcn_v3_0_set_powergating_state(struct amdgpu_ip_block *ip_block, + enum amd_powergating_state state) +{ + struct amdgpu_device *adev = ip_block->adev; + int ret = 0, i; + + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) + ret |= vcn_v3_0_set_powergating_state_inst(ip_block, + state, i); return ret; } diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c index 4d20d58802f6..1f67e5973cf8 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c @@ -96,8 +96,11 @@ static int amdgpu_ih_clientid_vcns[] = { static int vcn_v4_0_start_sriov(struct amdgpu_device *adev); static void vcn_v4_0_set_unified_ring_funcs(struct amdgpu_device *adev); static void vcn_v4_0_set_irq_funcs(struct amdgpu_device *adev); +static int vcn_v4_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, + enum amd_powergating_state state, + int i); static int vcn_v4_0_set_powergating_state(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state); + enum amd_powergating_state state); static int vcn_v4_0_pause_dpg_mode(struct amdgpu_device *adev, int inst_idx, struct dpg_pause_state *new_state); static void vcn_v4_0_unified_ring_set_wptr(struct amdgpu_ring *ring); @@ -367,9 +370,9 @@ static int vcn_v4_0_hw_fini(struct amdgpu_ip_block *ip_block) if (!amdgpu_sriov_vf(adev)) { if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) || - (adev->vcn.cur_state != AMD_PG_STATE_GATE && + (adev->vcn.inst[i].cur_state != AMD_PG_STATE_GATE && RREG32_SOC15(VCN, i, regUVD_STATUS))) { - vcn_v4_0_set_powergating_state(ip_block, AMD_PG_STATE_GATE); + vcn_v4_0_set_powergating_state_inst(ip_block, AMD_PG_STATE_GATE, i); } } if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__VCN)) @@ -2034,6 +2037,36 @@ static int vcn_v4_0_set_clockgating_state(struct amdgpu_ip_block *ip_block, return 0; } +static int vcn_v4_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, + enum amd_powergating_state state, + int i) +{ + struct amdgpu_device *adev = ip_block->adev; + int ret = 0; + + /* for SRIOV, guest should not control VCN Power-gating + * MMSCH FW should control Power-gating and clock-gating + * guest should avoid touching CGC and PG + */ + if (amdgpu_sriov_vf(adev)) { + adev->vcn.inst[i].cur_state = AMD_PG_STATE_UNGATE; + return 0; + } + + if (state == adev->vcn.inst[i].cur_state) + return 0; + + if (state == AMD_PG_STATE_GATE) + ret = vcn_v4_0_stop(adev, i); + else + ret = vcn_v4_0_start(adev, i); + + if (!ret) + adev->vcn.inst[i].cur_state = state; + + return ret; +} + /** * vcn_v4_0_set_powergating_state - set VCN block powergating state * @@ -2048,27 +2081,8 @@ static int vcn_v4_0_set_powergating_state(struct amdgpu_ip_block *ip_block, struct amdgpu_device *adev = ip_block->adev; int ret = 0, i; - /* for SRIOV, guest should not control VCN Power-gating - * MMSCH FW should control Power-gating and clock-gating - * guest should avoid touching CGC and PG - */ - if (amdgpu_sriov_vf(adev)) { - adev->vcn.cur_state = AMD_PG_STATE_UNGATE; - return 0; - } - - if (state == adev->vcn.cur_state) - return 0; - - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { - if (state == AMD_PG_STATE_GATE) - ret |= vcn_v4_0_stop(adev, i); - else - ret |= vcn_v4_0_start(adev, i); - } - - if (!ret) - adev->vcn.cur_state = state; + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) + ret |= vcn_v4_0_set_powergating_state_inst(ip_block, state, i); return ret; } diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c index 932b65072dbc..73b10813d9b8 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c @@ -87,8 +87,11 @@ static const struct amdgpu_hwip_reg_entry vcn_reg_list_4_0_3[] = { static int vcn_v4_0_3_start_sriov(struct amdgpu_device *adev); static void vcn_v4_0_3_set_unified_ring_funcs(struct amdgpu_device *adev); static void vcn_v4_0_3_set_irq_funcs(struct amdgpu_device *adev); +static int vcn_v4_0_3_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, + enum amd_powergating_state state, + int i); static int vcn_v4_0_3_set_powergating_state(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state); + enum amd_powergating_state state); static int vcn_v4_0_3_pause_dpg_mode(struct amdgpu_device *adev, int inst_idx, struct dpg_pause_state *new_state); static void vcn_v4_0_3_unified_ring_set_wptr(struct amdgpu_ring *ring); @@ -351,11 +354,12 @@ static int vcn_v4_0_3_hw_fini(struct amdgpu_ip_block *ip_block) struct amdgpu_device *adev = ip_block->adev; int i; - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work); - if (adev->vcn.cur_state != AMD_PG_STATE_GATE) - vcn_v4_0_3_set_powergating_state(ip_block, AMD_PG_STATE_GATE); + if (adev->vcn.inst[i].cur_state != AMD_PG_STATE_GATE) + vcn_v4_0_3_set_powergating_state_inst(ip_block, AMD_PG_STATE_GATE, i); + } return 0; } @@ -1640,6 +1644,36 @@ static int vcn_v4_0_3_set_clockgating_state(struct amdgpu_ip_block *ip_block, return 0; } +static int vcn_v4_0_3_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, + enum amd_powergating_state state, + int i) +{ + struct amdgpu_device *adev = ip_block->adev; + int ret = 0; + + /* for SRIOV, guest should not control VCN Power-gating + * MMSCH FW should control Power-gating and clock-gating + * guest should avoid touching CGC and PG + */ + if (amdgpu_sriov_vf(adev)) { + adev->vcn.inst[i].cur_state = AMD_PG_STATE_UNGATE; + return 0; + } + + if (state == adev->vcn.inst[i].cur_state) + return 0; + + if (state == AMD_PG_STATE_GATE) + ret = vcn_v4_0_3_stop(adev, i); + else + ret = vcn_v4_0_3_start(adev, i); + + if (!ret) + adev->vcn.inst[i].cur_state = state; + + return ret; +} + /** * vcn_v4_0_3_set_powergating_state - set VCN block powergating state * @@ -1649,32 +1683,13 @@ static int vcn_v4_0_3_set_clockgating_state(struct amdgpu_ip_block *ip_block, * Set VCN block powergating state */ static int vcn_v4_0_3_set_powergating_state(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state) + enum amd_powergating_state state) { struct amdgpu_device *adev = ip_block->adev; int ret = 0, i; - /* for SRIOV, guest should not control VCN Power-gating - * MMSCH FW should control Power-gating and clock-gating - * guest should avoid touching CGC and PG - */ - if (amdgpu_sriov_vf(adev)) { - adev->vcn.cur_state = AMD_PG_STATE_UNGATE; - return 0; - } - - if (state == adev->vcn.cur_state) - return 0; - - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { - if (state == AMD_PG_STATE_GATE) - ret |= vcn_v4_0_3_stop(adev, i); - else - ret |= vcn_v4_0_3_start(adev, i); - } - - if (!ret) - adev->vcn.cur_state = state; + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) + vcn_v4_0_3_set_powergating_state_inst(ip_block, state, i); return ret; } diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c index 83093e5c5cca..06b5ef4b3e84 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c @@ -95,8 +95,11 @@ static int amdgpu_ih_clientid_vcns[] = { static void vcn_v4_0_5_set_unified_ring_funcs(struct amdgpu_device *adev); static void vcn_v4_0_5_set_irq_funcs(struct amdgpu_device *adev); +static int vcn_v4_0_5_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, + enum amd_powergating_state state, + int i); static int vcn_v4_0_5_set_powergating_state(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state); + enum amd_powergating_state state); static int vcn_v4_0_5_pause_dpg_mode(struct amdgpu_device *adev, int inst_idx, struct dpg_pause_state *new_state); static void vcn_v4_0_5_unified_ring_set_wptr(struct amdgpu_ring *ring); @@ -308,9 +311,9 @@ static int vcn_v4_0_5_hw_fini(struct amdgpu_ip_block *ip_block) if (!amdgpu_sriov_vf(adev)) { if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) || - (adev->vcn.cur_state != AMD_PG_STATE_GATE && - RREG32_SOC15(VCN, i, regUVD_STATUS))) { - vcn_v4_0_5_set_powergating_state(ip_block, AMD_PG_STATE_GATE); + (adev->vcn.inst[i].cur_state != AMD_PG_STATE_GATE && + RREG32_SOC15(VCN, i, regUVD_STATUS))) { + vcn_v4_0_5_set_powergating_state_inst(ip_block, AMD_PG_STATE_GATE, i); } } } @@ -1522,6 +1525,27 @@ static int vcn_v4_0_5_set_clockgating_state(struct amdgpu_ip_block *ip_block, return 0; } +static int vcn_v4_0_5_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, + enum amd_powergating_state state, + int i) +{ + struct amdgpu_device *adev = ip_block->adev; + int ret = 0; + + if (state == adev->vcn.inst[i].cur_state) + return 0; + + if (state == AMD_PG_STATE_GATE) + ret = vcn_v4_0_5_stop(adev, i); + else + ret = vcn_v4_0_5_start(adev, i); + + if (!ret) + adev->vcn.inst[i].cur_state = state; + + return ret; +} + /** * vcn_v4_0_5_set_powergating_state - set VCN block powergating state * @@ -1531,23 +1555,13 @@ static int vcn_v4_0_5_set_clockgating_state(struct amdgpu_ip_block *ip_block, * Set VCN block powergating state */ static int vcn_v4_0_5_set_powergating_state(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state) + enum amd_powergating_state state) { struct amdgpu_device *adev = ip_block->adev; int ret = 0, i; - if (state == adev->vcn.cur_state) - return 0; - - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { - if (state == AMD_PG_STATE_GATE) - ret |= vcn_v4_0_5_stop(adev, i); - else - ret |= vcn_v4_0_5_start(adev, i); - } - - if (!ret) - adev->vcn.cur_state = state; + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) + vcn_v4_0_5_set_powergating_state_inst(ip_block, state, i); return ret; } diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c index 26f788ceeb11..8e0bd2cc1002 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c @@ -78,8 +78,11 @@ static int amdgpu_ih_clientid_vcns[] = { static void vcn_v5_0_0_set_unified_ring_funcs(struct amdgpu_device *adev); static void vcn_v5_0_0_set_irq_funcs(struct amdgpu_device *adev); +static int vcn_v5_0_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, + enum amd_powergating_state state, + int i); static int vcn_v5_0_0_set_powergating_state(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state); + enum amd_powergating_state state); static int vcn_v5_0_0_pause_dpg_mode(struct amdgpu_device *adev, int inst_idx, struct dpg_pause_state *new_state); static void vcn_v5_0_0_unified_ring_set_wptr(struct amdgpu_ring *ring); @@ -288,9 +291,9 @@ static int vcn_v5_0_0_hw_fini(struct amdgpu_ip_block *ip_block) if (!amdgpu_sriov_vf(adev)) { if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) || - (adev->vcn.cur_state != AMD_PG_STATE_GATE && - RREG32_SOC15(VCN, i, regUVD_STATUS))) { - vcn_v5_0_0_set_powergating_state(ip_block, AMD_PG_STATE_GATE); + (adev->vcn.inst[i].cur_state != AMD_PG_STATE_GATE && + RREG32_SOC15(VCN, i, regUVD_STATUS))) { + vcn_v5_0_0_set_powergating_state_inst(ip_block, AMD_PG_STATE_GATE, i); } } } @@ -1262,6 +1265,27 @@ static int vcn_v5_0_0_set_clockgating_state(struct amdgpu_ip_block *ip_block, return 0; } +static int vcn_v5_0_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, + enum amd_powergating_state state, + int i) +{ + struct amdgpu_device *adev = ip_block->adev; + int ret = 0; + + if (state == adev->vcn.inst[i].cur_state) + return 0; + + if (state == AMD_PG_STATE_GATE) + ret = vcn_v5_0_0_stop(adev, i); + else + ret = vcn_v5_0_0_start(adev, i); + + if (!ret) + adev->vcn.inst[i].cur_state = state; + + return ret; +} + /** * vcn_v5_0_0_set_powergating_state - set VCN block powergating state * @@ -1271,23 +1295,13 @@ static int vcn_v5_0_0_set_clockgating_state(struct amdgpu_ip_block *ip_block, * Set VCN block powergating state */ static int vcn_v5_0_0_set_powergating_state(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state) + enum amd_powergating_state state) { struct amdgpu_device *adev = ip_block->adev; int ret = 0, i; - if (state == adev->vcn.cur_state) - return 0; - - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { - if (state == AMD_PG_STATE_GATE) - ret |= vcn_v5_0_0_stop(adev, i); - else - ret |= vcn_v5_0_0_start(adev, i); - } - - if (!ret) - adev->vcn.cur_state = state; + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) + vcn_v5_0_0_set_powergating_state_inst(ip_block, state, i); return ret; } diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c index 512e5f6ae7b3..83e873767a86 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c @@ -40,8 +40,11 @@ static void vcn_v5_0_1_set_unified_ring_funcs(struct amdgpu_device *adev); static void vcn_v5_0_1_set_irq_funcs(struct amdgpu_device *adev); +static int vcn_v5_0_1_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, + enum amd_powergating_state state, + int i); static int vcn_v5_0_1_set_powergating_state(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state); + enum amd_powergating_state state); static void vcn_v5_0_1_unified_ring_set_wptr(struct amdgpu_ring *ring); /** @@ -988,6 +991,27 @@ static int vcn_v5_0_1_set_clockgating_state(struct amdgpu_ip_block *ip_block, return 0; } +static int vcn_v5_0_1_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, + enum amd_powergating_state state, + int i) +{ + struct amdgpu_device *adev = ip_block->adev; + int ret = 0; + + if (state == adev->vcn.inst[i].cur_state) + return 0; + + if (state == AMD_PG_STATE_GATE) + ret = vcn_v5_0_1_stop(adev, i); + else + ret = vcn_v5_0_1_start(adev, i); + + if (!ret) + adev->vcn.inst[i].cur_state = state; + + return ret; +} + /** * vcn_v5_0_1_set_powergating_state - set VCN block powergating state * @@ -1002,18 +1026,8 @@ static int vcn_v5_0_1_set_powergating_state(struct amdgpu_ip_block *ip_block, struct amdgpu_device *adev = ip_block->adev; int ret = 0, i; - if (state == adev->vcn.cur_state) - return 0; - - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { - if (state == AMD_PG_STATE_GATE) - ret = vcn_v5_0_1_stop(adev, i); - else - ret = vcn_v5_0_1_start(adev, i); - } - - if (!ret) - adev->vcn.cur_state = state; + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) + vcn_v5_0_1_set_powergating_state_inst(ip_block, state, i); return ret; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 37ba84898bd5..8cfb07549f54 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -2041,15 +2041,15 @@ static int smu_hw_fini(struct amdgpu_ip_block *ip_block) if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev)) return 0; - for (i = 0; i < adev->vcn.num_vcn_inst; i++) + for (i = 0; i < adev->vcn.num_vcn_inst; i++) { smu_dpm_set_vcn_enable(smu, false, i); + adev->vcn.inst[i].cur_state = AMD_PG_STATE_GATE; + } smu_dpm_set_jpeg_enable(smu, false); + adev->jpeg.cur_state = AMD_PG_STATE_GATE; smu_dpm_set_vpe_enable(smu, false); smu_dpm_set_umsch_mm_enable(smu, false); - adev->vcn.cur_state = AMD_PG_STATE_GATE; - adev->jpeg.cur_state = AMD_PG_STATE_GATE; - if (!smu->pm_enabled) return 0; From cb107271687d569c3b706b974bcae6b9fdcfe9d0 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 15 Nov 2024 16:19:23 -0500 Subject: [PATCH 084/235] drm/amdgpu/vcn: move more instanced data to vcn_instance Move more per instance data into the per instance structure. v2: index instances directly on vcn1.0 and 2.0 to make it clear that they only support a single instance (Lijo) v3: fix typo on vcn 2.5 Reviewed-by: Boyuan Zhang (v2) Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 186 ++++++++++++------------ drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h | 17 ++- drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c | 4 +- drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c | 42 +++--- drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c | 92 ++++++------ drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c | 49 ++++--- drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 67 +++++---- drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c | 19 ++- drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c | 14 +- drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c | 18 ++- drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c | 16 +- drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c | 8 +- 13 files changed, 273 insertions(+), 261 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 05c73bf7541c..27bfe9c8af06 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -459,7 +459,7 @@ static int amdgpu_hw_ip_info(struct amdgpu_device *adev, if (adev->vcn.harvest_config & (1 << i)) continue; - for (j = 0; j < adev->vcn.num_enc_rings; j++) + for (j = 0; j < adev->vcn.inst[i].num_enc_rings; j++) if (adev->vcn.inst[i].ring_enc[j].sched.ready) ++num_rings; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c index 0c3081a198d9..9901b8e17f30 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c @@ -127,93 +127,88 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev) unsigned int fw_shared_size, log_offset; int i, r; - mutex_init(&adev->vcn.vcn1_jpeg1_workaround); for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + mutex_init(&adev->vcn.inst[i].vcn1_jpeg1_workaround); mutex_init(&adev->vcn.inst[i].vcn_pg_lock); atomic_set(&adev->vcn.inst[i].total_submission_cnt, 0); INIT_DELAYED_WORK(&adev->vcn.inst[i].idle_work, amdgpu_vcn_idle_work_handler); atomic_set(&adev->vcn.inst[i].dpg_enc_submission_cnt, 0); - } + if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) && + (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)) + adev->vcn.inst[i].indirect_sram = true; - if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) && - (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)) - adev->vcn.indirect_sram = true; + /* + * Some Steam Deck's BIOS versions are incompatible with the + * indirect SRAM mode, leading to amdgpu being unable to get + * properly probed (and even potentially crashing the kernel). + * Hence, check for these versions here - notice this is + * restricted to Vangogh (Deck's APU). + */ + if (amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(3, 0, 2)) { + const char *bios_ver = dmi_get_system_info(DMI_BIOS_VERSION); - /* - * Some Steam Deck's BIOS versions are incompatible with the - * indirect SRAM mode, leading to amdgpu being unable to get - * properly probed (and even potentially crashing the kernel). - * Hence, check for these versions here - notice this is - * restricted to Vangogh (Deck's APU). - */ - if (amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(3, 0, 2)) { - const char *bios_ver = dmi_get_system_info(DMI_BIOS_VERSION); - - if (bios_ver && (!strncmp("F7A0113", bios_ver, 7) || - !strncmp("F7A0114", bios_ver, 7))) { - adev->vcn.indirect_sram = false; - dev_info(adev->dev, - "Steam Deck quirk: indirect SRAM disabled on BIOS %s\n", bios_ver); + if (bios_ver && (!strncmp("F7A0113", bios_ver, 7) || + !strncmp("F7A0114", bios_ver, 7))) { + adev->vcn.inst[i].indirect_sram = false; + dev_info(adev->dev, + "Steam Deck quirk: indirect SRAM disabled on BIOS %s\n", bios_ver); + } } - } - /* from vcn4 and above, only unified queue is used */ - adev->vcn.using_unified_queue = - amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0); + /* from vcn4 and above, only unified queue is used */ + adev->vcn.inst[i].using_unified_queue = + amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0); - hdr = (const struct common_firmware_header *)adev->vcn.inst[0].fw->data; - adev->vcn.fw_version = le32_to_cpu(hdr->ucode_version); + hdr = (const struct common_firmware_header *)adev->vcn.inst[i].fw->data; + adev->vcn.inst[i].fw_version = le32_to_cpu(hdr->ucode_version); + adev->vcn.fw_version = le32_to_cpu(hdr->ucode_version); - /* Bit 20-23, it is encode major and non-zero for new naming convention. - * This field is part of version minor and DRM_DISABLED_FLAG in old naming - * convention. Since the l:wq!atest version minor is 0x5B and DRM_DISABLED_FLAG - * is zero in old naming convention, this field is always zero so far. - * These four bits are used to tell which naming convention is present. - */ - fw_check = (le32_to_cpu(hdr->ucode_version) >> 20) & 0xf; - if (fw_check) { - unsigned int dec_ver, enc_major, enc_minor, vep, fw_rev; + /* Bit 20-23, it is encode major and non-zero for new naming convention. + * This field is part of version minor and DRM_DISABLED_FLAG in old naming + * convention. Since the l:wq!atest version minor is 0x5B and DRM_DISABLED_FLAG + * is zero in old naming convention, this field is always zero so far. + * These four bits are used to tell which naming convention is present. + */ + fw_check = (le32_to_cpu(hdr->ucode_version) >> 20) & 0xf; + if (fw_check) { + unsigned int dec_ver, enc_major, enc_minor, vep, fw_rev; - fw_rev = le32_to_cpu(hdr->ucode_version) & 0xfff; - enc_minor = (le32_to_cpu(hdr->ucode_version) >> 12) & 0xff; - enc_major = fw_check; - dec_ver = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xf; - vep = (le32_to_cpu(hdr->ucode_version) >> 28) & 0xf; - DRM_INFO("Found VCN firmware Version ENC: %u.%u DEC: %u VEP: %u Revision: %u\n", - enc_major, enc_minor, dec_ver, vep, fw_rev); - } else { - unsigned int version_major, version_minor, family_id; + fw_rev = le32_to_cpu(hdr->ucode_version) & 0xfff; + enc_minor = (le32_to_cpu(hdr->ucode_version) >> 12) & 0xff; + enc_major = fw_check; + dec_ver = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xf; + vep = (le32_to_cpu(hdr->ucode_version) >> 28) & 0xf; + DRM_INFO("Found VCN firmware Version ENC: %u.%u DEC: %u VEP: %u Revision: %u\n", + enc_major, enc_minor, dec_ver, vep, fw_rev); + } else { + unsigned int version_major, version_minor, family_id; - family_id = le32_to_cpu(hdr->ucode_version) & 0xff; - version_major = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xff; - version_minor = (le32_to_cpu(hdr->ucode_version) >> 8) & 0xff; - DRM_INFO("Found VCN firmware Version: %u.%u Family ID: %u\n", - version_major, version_minor, family_id); - } + family_id = le32_to_cpu(hdr->ucode_version) & 0xff; + version_major = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xff; + version_minor = (le32_to_cpu(hdr->ucode_version) >> 8) & 0xff; + DRM_INFO("Found VCN firmware Version: %u.%u Family ID: %u\n", + version_major, version_minor, family_id); + } - bo_size = AMDGPU_VCN_STACK_SIZE + AMDGPU_VCN_CONTEXT_SIZE; - if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) - bo_size += AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8); + bo_size = AMDGPU_VCN_STACK_SIZE + AMDGPU_VCN_CONTEXT_SIZE; + if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) + bo_size += AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8); - if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(5, 0, 0)) { - fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn5_fw_shared)); - log_offset = offsetof(struct amdgpu_vcn5_fw_shared, fw_log); - } else if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0)) { - fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn4_fw_shared)); - log_offset = offsetof(struct amdgpu_vcn4_fw_shared, fw_log); - } else { - fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_fw_shared)); - log_offset = offsetof(struct amdgpu_fw_shared, fw_log); - } + if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(5, 0, 0)) { + fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn5_fw_shared)); + log_offset = offsetof(struct amdgpu_vcn5_fw_shared, fw_log); + } else if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0)) { + fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn4_fw_shared)); + log_offset = offsetof(struct amdgpu_vcn4_fw_shared, fw_log); + } else { + fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_fw_shared)); + log_offset = offsetof(struct amdgpu_fw_shared, fw_log); + } - bo_size += fw_shared_size; + bo_size += fw_shared_size; - if (amdgpu_vcnfw_log) - bo_size += AMDGPU_VCNFW_LOG_SIZE; - - for (i = 0; i < adev->vcn.num_vcn_inst; i++) { - if (adev->vcn.harvest_config & (1 << i)) - continue; + if (amdgpu_vcnfw_log) + bo_size += AMDGPU_VCNFW_LOG_SIZE; r = amdgpu_bo_create_kernel(adev, bo_size, PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM | @@ -239,7 +234,7 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev) adev->vcn.inst[i].fw_shared.log_offset = log_offset; } - if (adev->vcn.indirect_sram) { + if (adev->vcn.inst[i].indirect_sram) { r = amdgpu_bo_create_kernel(adev, 64 * 2 * 4, PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM | AMDGPU_GEM_DOMAIN_GTT, @@ -277,15 +272,14 @@ int amdgpu_vcn_sw_fini(struct amdgpu_device *adev) amdgpu_ring_fini(&adev->vcn.inst[j].ring_dec); - for (i = 0; i < adev->vcn.num_enc_rings; ++i) + for (i = 0; i < adev->vcn.inst[j].num_enc_rings; ++i) amdgpu_ring_fini(&adev->vcn.inst[j].ring_enc[i]); amdgpu_ucode_release(&adev->vcn.inst[j].fw); mutex_destroy(&adev->vcn.inst[j].vcn_pg_lock); + mutex_destroy(&adev->vcn.inst[j].vcn1_jpeg1_workaround); } - mutex_destroy(&adev->vcn.vcn1_jpeg1_workaround); - return 0; } @@ -404,12 +398,12 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work) if (adev->vcn.harvest_config & (1 << i)) return; - for (j = 0; j < adev->vcn.num_enc_rings; ++j) + for (j = 0; j < adev->vcn.inst[i].num_enc_rings; ++j) fence[i] += amdgpu_fence_count_emitted(&vcn_inst->ring_enc[j]); /* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */ if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG && - !adev->vcn.using_unified_queue) { + !adev->vcn.inst[i].using_unified_queue) { struct dpg_pause_state new_state; if (fence[i] || @@ -418,7 +412,7 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work) else new_state.fw_based = VCN_DPG_STATE__UNPAUSE; - adev->vcn.pause_dpg_mode(adev, i, &new_state); + adev->vcn.inst[i].pause_dpg_mode(adev, i, &new_state); } fence[i] += amdgpu_fence_count_emitted(&vcn_inst->ring_dec); @@ -456,7 +450,7 @@ void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring) /* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */ if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG && - !adev->vcn.using_unified_queue) { + !adev->vcn.inst[ring->me].using_unified_queue) { struct dpg_pause_state new_state; if (ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC) { @@ -466,7 +460,7 @@ void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring) unsigned int fences = 0; unsigned int i; - for (i = 0; i < adev->vcn.num_enc_rings; ++i) + for (i = 0; i < adev->vcn.inst[ring->me].num_enc_rings; ++i) fences += amdgpu_fence_count_emitted(&adev->vcn.inst[ring->me].ring_enc[i]); if (fences || atomic_read(&adev->vcn.inst[ring->me].dpg_enc_submission_cnt)) @@ -475,7 +469,7 @@ void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring) new_state.fw_based = VCN_DPG_STATE__UNPAUSE; } - adev->vcn.pause_dpg_mode(adev, ring->me, &new_state); + adev->vcn.inst[ring->me].pause_dpg_mode(adev, ring->me, &new_state); } mutex_unlock(&adev->vcn.inst[ring->me].vcn_pg_lock); } @@ -487,7 +481,7 @@ void amdgpu_vcn_ring_end_use(struct amdgpu_ring *ring) /* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */ if (ring->adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG && ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC && - !adev->vcn.using_unified_queue) + !adev->vcn.inst[ring->me].using_unified_queue) atomic_dec(&ring->adev->vcn.inst[ring->me].dpg_enc_submission_cnt); atomic_dec(&ring->adev->vcn.inst[ring->me].total_submission_cnt); @@ -511,7 +505,7 @@ int amdgpu_vcn_dec_ring_test_ring(struct amdgpu_ring *ring) r = amdgpu_ring_alloc(ring, 3); if (r) return r; - amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.scratch9, 0)); + amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.scratch9, 0)); amdgpu_ring_write(ring, 0xDEADBEEF); amdgpu_ring_commit(ring); for (i = 0; i < adev->usec_timeout; i++) { @@ -576,14 +570,14 @@ static int amdgpu_vcn_dec_send_msg(struct amdgpu_ring *ring, goto err; ib = &job->ibs[0]; - ib->ptr[0] = PACKET0(adev->vcn.internal.data0, 0); + ib->ptr[0] = PACKET0(adev->vcn.inst[ring->me].internal.data0, 0); ib->ptr[1] = addr; - ib->ptr[2] = PACKET0(adev->vcn.internal.data1, 0); + ib->ptr[2] = PACKET0(adev->vcn.inst[ring->me].internal.data1, 0); ib->ptr[3] = addr >> 32; - ib->ptr[4] = PACKET0(adev->vcn.internal.cmd, 0); + ib->ptr[4] = PACKET0(adev->vcn.inst[ring->me].internal.cmd, 0); ib->ptr[5] = 0; for (i = 6; i < 16; i += 2) { - ib->ptr[i] = PACKET0(adev->vcn.internal.nop, 0); + ib->ptr[i] = PACKET0(adev->vcn.inst[ring->me].internal.nop, 0); ib->ptr[i+1] = 0; } ib->length_dw = 16; @@ -746,7 +740,7 @@ static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring, uint32_t ib_pack_in_dw; int i, r; - if (adev->vcn.using_unified_queue) + if (adev->vcn.inst[ring->me].using_unified_queue) ib_size_dw += 8; r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL, @@ -759,7 +753,7 @@ static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring, ib->length_dw = 0; /* single queue headers */ - if (adev->vcn.using_unified_queue) { + if (adev->vcn.inst[ring->me].using_unified_queue) { ib_pack_in_dw = sizeof(struct amdgpu_vcn_decode_buffer) / sizeof(uint32_t) + 4 + 2; /* engine info + decoding ib in dw */ ib_checksum = amdgpu_vcn_unified_ring_ib_header(ib, ib_pack_in_dw, false); @@ -778,7 +772,7 @@ static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring, for (i = ib->length_dw; i < ib_size_dw; ++i) ib->ptr[i] = 0x0; - if (adev->vcn.using_unified_queue) + if (adev->vcn.inst[ring->me].using_unified_queue) amdgpu_vcn_unified_ring_ib_checksum(&ib_checksum, ib_pack_in_dw); r = amdgpu_job_submit_direct(job, ring, &f); @@ -876,7 +870,7 @@ static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t hand uint64_t addr; int i, r; - if (adev->vcn.using_unified_queue) + if (adev->vcn.inst[ring->me].using_unified_queue) ib_size_dw += 8; r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL, @@ -890,7 +884,7 @@ static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t hand ib->length_dw = 0; - if (adev->vcn.using_unified_queue) + if (adev->vcn.inst[ring->me].using_unified_queue) ib_checksum = amdgpu_vcn_unified_ring_ib_header(ib, 0x11, true); ib->ptr[ib->length_dw++] = 0x00000018; @@ -912,7 +906,7 @@ static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t hand for (i = ib->length_dw; i < ib_size_dw; ++i) ib->ptr[i] = 0x0; - if (adev->vcn.using_unified_queue) + if (adev->vcn.inst[ring->me].using_unified_queue) amdgpu_vcn_unified_ring_ib_checksum(&ib_checksum, 0x11); r = amdgpu_job_submit_direct(job, ring, &f); @@ -943,7 +937,7 @@ static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han uint64_t addr; int i, r; - if (adev->vcn.using_unified_queue) + if (adev->vcn.inst[ring->me].using_unified_queue) ib_size_dw += 8; r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL, @@ -957,7 +951,7 @@ static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han ib->length_dw = 0; - if (adev->vcn.using_unified_queue) + if (adev->vcn.inst[ring->me].using_unified_queue) ib_checksum = amdgpu_vcn_unified_ring_ib_header(ib, 0x11, true); ib->ptr[ib->length_dw++] = 0x00000018; @@ -979,7 +973,7 @@ static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han for (i = ib->length_dw; i < ib_size_dw; ++i) ib->ptr[i] = 0x0; - if (adev->vcn.using_unified_queue) + if (adev->vcn.inst[ring->me].using_unified_queue) amdgpu_vcn_unified_ring_ib_checksum(&ib_checksum, 0x11); r = amdgpu_job_submit_direct(job, ring, &f); @@ -1396,7 +1390,7 @@ void amdgpu_debugfs_vcn_sched_mask_init(struct amdgpu_device *adev) struct dentry *root = minor->debugfs_root; char name[32]; - if (adev->vcn.num_vcn_inst <= 1 || !adev->vcn.using_unified_queue) + if (adev->vcn.num_vcn_inst <= 1 || !adev->vcn.inst[0].using_unified_queue) return; sprintf(name, "amdgpu_vcn_sched_mask"); debugfs_create_file(name, 0600, root, adev, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h index 0bcf4d1c7175..3b059f51894b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h @@ -322,6 +322,15 @@ struct amdgpu_vcn_inst { struct mutex vcn_pg_lock; enum amd_powergating_state cur_state; struct delayed_work idle_work; + unsigned fw_version; + unsigned num_enc_rings; + bool indirect_sram; + struct amdgpu_vcn_reg internal; + struct mutex vcn1_jpeg1_workaround; + int (*pause_dpg_mode)(struct amdgpu_device *adev, + int inst_idx, + struct dpg_pause_state *new_state); + bool using_unified_queue; }; struct amdgpu_vcn_ras { @@ -330,24 +339,16 @@ struct amdgpu_vcn_ras { struct amdgpu_vcn { unsigned fw_version; - unsigned num_enc_rings; - bool indirect_sram; - uint8_t num_vcn_inst; struct amdgpu_vcn_inst inst[AMDGPU_MAX_VCN_INSTANCES]; - struct amdgpu_vcn_reg internal; - struct mutex vcn1_jpeg1_workaround; unsigned harvest_config; - int (*pause_dpg_mode)(struct amdgpu_device *adev, - int inst_idx, struct dpg_pause_state *new_state); struct ras_common_if *ras_if; struct amdgpu_vcn_ras *ras; uint16_t inst_mask; uint8_t num_inst_per_aid; - bool using_unified_queue; /* IP reg dump */ uint32_t *ip_dump; diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c index 8031406e20ff..9e428e669ada 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c @@ -607,12 +607,12 @@ static void jpeg_v1_0_ring_begin_use(struct amdgpu_ring *ring) bool set_clocks = !cancel_delayed_work_sync(&adev->vcn.inst[0].idle_work); int cnt = 0; - mutex_lock(&adev->vcn.vcn1_jpeg1_workaround); + mutex_lock(&adev->vcn.inst[0].vcn1_jpeg1_workaround); if (amdgpu_fence_wait_empty(&adev->vcn.inst->ring_dec)) DRM_ERROR("JPEG dec: vcn dec ring may not be empty\n"); - for (cnt = 0; cnt < adev->vcn.num_enc_rings; cnt++) { + for (cnt = 0; cnt < adev->vcn.inst[0].num_enc_rings; cnt++) { if (amdgpu_fence_wait_empty(&adev->vcn.inst->ring_enc[cnt])) DRM_ERROR("JPEG dec: vcn enc ring[%d] may not be empty\n", cnt); } diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c index 291a5866c148..edbcd0819d17 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c @@ -105,7 +105,7 @@ static int vcn_v1_0_early_init(struct amdgpu_ip_block *ip_block) { struct amdgpu_device *adev = ip_block->adev; - adev->vcn.num_enc_rings = 2; + adev->vcn.inst[0].num_enc_rings = 2; vcn_v1_0_set_dec_ring_funcs(adev); vcn_v1_0_set_enc_ring_funcs(adev); @@ -138,7 +138,7 @@ static int vcn_v1_0_sw_init(struct amdgpu_ip_block *ip_block) return r; /* VCN ENC TRAP */ - for (i = 0; i < adev->vcn.num_enc_rings; ++i) { + for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i) { r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN, i + VCN_1_0__SRCID__UVD_ENC_GENERAL_PURPOSE, &adev->vcn.inst->irq); if (r) @@ -166,18 +166,18 @@ static int vcn_v1_0_sw_init(struct amdgpu_ip_block *ip_block) if (r) return r; - adev->vcn.internal.scratch9 = adev->vcn.inst->external.scratch9 = + adev->vcn.inst[0].internal.scratch9 = adev->vcn.inst->external.scratch9 = SOC15_REG_OFFSET(UVD, 0, mmUVD_SCRATCH9); - adev->vcn.internal.data0 = adev->vcn.inst->external.data0 = + adev->vcn.inst[0].internal.data0 = adev->vcn.inst->external.data0 = SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_DATA0); - adev->vcn.internal.data1 = adev->vcn.inst->external.data1 = + adev->vcn.inst[0].internal.data1 = adev->vcn.inst->external.data1 = SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_DATA1); - adev->vcn.internal.cmd = adev->vcn.inst->external.cmd = + adev->vcn.inst[0].internal.cmd = adev->vcn.inst->external.cmd = SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_CMD); - adev->vcn.internal.nop = adev->vcn.inst->external.nop = + adev->vcn.inst[0].internal.nop = adev->vcn.inst->external.nop = SOC15_REG_OFFSET(UVD, 0, mmUVD_NO_OP); - for (i = 0; i < adev->vcn.num_enc_rings; ++i) { + for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i) { enum amdgpu_ring_priority_level hw_prio = amdgpu_vcn_get_enc_ring_prio(i); ring = &adev->vcn.inst->ring_enc[i]; @@ -189,7 +189,7 @@ static int vcn_v1_0_sw_init(struct amdgpu_ip_block *ip_block) return r; } - adev->vcn.pause_dpg_mode = vcn_v1_0_pause_dpg_mode; + adev->vcn.inst[0].pause_dpg_mode = vcn_v1_0_pause_dpg_mode; if (amdgpu_vcnfw_log) { volatile struct amdgpu_fw_shared *fw_shared = adev->vcn.inst->fw_shared.cpu_addr; @@ -253,7 +253,7 @@ static int vcn_v1_0_hw_init(struct amdgpu_ip_block *ip_block) if (r) return r; - for (i = 0; i < adev->vcn.num_enc_rings; ++i) { + for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i) { ring = &adev->vcn.inst->ring_enc[i]; r = amdgpu_ring_test_helper(ring); if (r) @@ -1833,7 +1833,7 @@ static void vcn_v1_0_idle_work_handler(struct work_struct *work) struct amdgpu_device *adev = vcn_inst->adev; unsigned int fences = 0, i; - for (i = 0; i < adev->vcn.num_enc_rings; ++i) + for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i) fences += amdgpu_fence_count_emitted(&adev->vcn.inst->ring_enc[i]); if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) { @@ -1849,7 +1849,7 @@ static void vcn_v1_0_idle_work_handler(struct work_struct *work) else new_state.jpeg = VCN_DPG_STATE__UNPAUSE; - adev->vcn.pause_dpg_mode(adev, 0, &new_state); + adev->vcn.inst[0].pause_dpg_mode(adev, 0, &new_state); } fences += amdgpu_fence_count_emitted(adev->jpeg.inst->ring_dec); @@ -1872,7 +1872,7 @@ static void vcn_v1_0_ring_begin_use(struct amdgpu_ring *ring) struct amdgpu_device *adev = ring->adev; bool set_clocks = !cancel_delayed_work_sync(&adev->vcn.inst[0].idle_work); - mutex_lock(&adev->vcn.vcn1_jpeg1_workaround); + mutex_lock(&adev->vcn.inst[0].vcn1_jpeg1_workaround); if (amdgpu_fence_wait_empty(ring->adev->jpeg.inst->ring_dec)) DRM_ERROR("VCN dec: jpeg dec ring may not be empty\n"); @@ -1898,7 +1898,7 @@ void vcn_v1_0_set_pg_for_begin_use(struct amdgpu_ring *ring, bool set_clocks) struct dpg_pause_state new_state; unsigned int fences = 0, i; - for (i = 0; i < adev->vcn.num_enc_rings; ++i) + for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i) fences += amdgpu_fence_count_emitted(&adev->vcn.inst->ring_enc[i]); if (fences) @@ -1916,14 +1916,14 @@ void vcn_v1_0_set_pg_for_begin_use(struct amdgpu_ring *ring, bool set_clocks) else if (ring->funcs->type == AMDGPU_RING_TYPE_VCN_JPEG) new_state.jpeg = VCN_DPG_STATE__PAUSE; - adev->vcn.pause_dpg_mode(adev, 0, &new_state); + adev->vcn.inst[0].pause_dpg_mode(adev, 0, &new_state); } } void vcn_v1_0_ring_end_use(struct amdgpu_ring *ring) { schedule_delayed_work(&ring->adev->vcn.inst[0].idle_work, VCN_IDLE_TIMEOUT); - mutex_unlock(&ring->adev->vcn.vcn1_jpeg1_workaround); + mutex_unlock(&ring->adev->vcn.inst[0].vcn1_jpeg1_workaround); } static void vcn_v1_0_print_ip_state(struct amdgpu_ip_block *ip_block, struct drm_printer *p) @@ -2057,11 +2057,11 @@ static int vcn_v1_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p, uint32_t reg = amdgpu_ib_get_value(ib, i); uint32_t val = amdgpu_ib_get_value(ib, i + 1); - if (reg == PACKET0(p->adev->vcn.internal.data0, 0)) { + if (reg == PACKET0(p->adev->vcn.inst[0].internal.data0, 0)) { msg_lo = val; - } else if (reg == PACKET0(p->adev->vcn.internal.data1, 0)) { + } else if (reg == PACKET0(p->adev->vcn.inst[0].internal.data1, 0)) { msg_hi = val; - } else if (reg == PACKET0(p->adev->vcn.internal.cmd, 0)) { + } else if (reg == PACKET0(p->adev->vcn.inst[0].internal.cmd, 0)) { r = vcn_v1_0_validate_bo(p, job, ((u64)msg_hi) << 32 | msg_lo); if (r) @@ -2146,7 +2146,7 @@ static void vcn_v1_0_set_enc_ring_funcs(struct amdgpu_device *adev) { int i; - for (i = 0; i < adev->vcn.num_enc_rings; ++i) + for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i) adev->vcn.inst->ring_enc[i].funcs = &vcn_v1_0_enc_ring_vm_funcs; } @@ -2157,7 +2157,7 @@ static const struct amdgpu_irq_src_funcs vcn_v1_0_irq_funcs = { static void vcn_v1_0_set_irq_funcs(struct amdgpu_device *adev) { - adev->vcn.inst->irq.num_types = adev->vcn.num_enc_rings + 2; + adev->vcn.inst->irq.num_types = adev->vcn.inst[0].num_enc_rings + 2; adev->vcn.inst->irq.funcs = &vcn_v1_0_irq_funcs; } diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c index cc2b9dcc8868..d94fd075a910 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c @@ -110,9 +110,9 @@ static int vcn_v2_0_early_init(struct amdgpu_ip_block *ip_block) struct amdgpu_device *adev = ip_block->adev; if (amdgpu_sriov_vf(adev)) - adev->vcn.num_enc_rings = 1; + adev->vcn.inst[0].num_enc_rings = 1; else - adev->vcn.num_enc_rings = 2; + adev->vcn.inst[0].num_enc_rings = 2; vcn_v2_0_set_dec_ring_funcs(adev); vcn_v2_0_set_enc_ring_funcs(adev); @@ -145,7 +145,7 @@ static int vcn_v2_0_sw_init(struct amdgpu_ip_block *ip_block) return r; /* VCN ENC TRAP */ - for (i = 0; i < adev->vcn.num_enc_rings; ++i) { + for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i) { r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN, i + VCN_2_0__SRCID__UVD_ENC_GENERAL_PURPOSE, &adev->vcn.inst->irq); @@ -175,25 +175,25 @@ static int vcn_v2_0_sw_init(struct amdgpu_ip_block *ip_block) if (r) return r; - adev->vcn.internal.context_id = mmUVD_CONTEXT_ID_INTERNAL_OFFSET; - adev->vcn.internal.ib_vmid = mmUVD_LMI_RBC_IB_VMID_INTERNAL_OFFSET; - adev->vcn.internal.ib_bar_low = mmUVD_LMI_RBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET; - adev->vcn.internal.ib_bar_high = mmUVD_LMI_RBC_IB_64BIT_BAR_HIGH_INTERNAL_OFFSET; - adev->vcn.internal.ib_size = mmUVD_RBC_IB_SIZE_INTERNAL_OFFSET; - adev->vcn.internal.gp_scratch8 = mmUVD_GP_SCRATCH8_INTERNAL_OFFSET; + adev->vcn.inst[0].internal.context_id = mmUVD_CONTEXT_ID_INTERNAL_OFFSET; + adev->vcn.inst[0].internal.ib_vmid = mmUVD_LMI_RBC_IB_VMID_INTERNAL_OFFSET; + adev->vcn.inst[0].internal.ib_bar_low = mmUVD_LMI_RBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET; + adev->vcn.inst[0].internal.ib_bar_high = mmUVD_LMI_RBC_IB_64BIT_BAR_HIGH_INTERNAL_OFFSET; + adev->vcn.inst[0].internal.ib_size = mmUVD_RBC_IB_SIZE_INTERNAL_OFFSET; + adev->vcn.inst[0].internal.gp_scratch8 = mmUVD_GP_SCRATCH8_INTERNAL_OFFSET; - adev->vcn.internal.scratch9 = mmUVD_SCRATCH9_INTERNAL_OFFSET; + adev->vcn.inst[0].internal.scratch9 = mmUVD_SCRATCH9_INTERNAL_OFFSET; adev->vcn.inst->external.scratch9 = SOC15_REG_OFFSET(UVD, 0, mmUVD_SCRATCH9); - adev->vcn.internal.data0 = mmUVD_GPCOM_VCPU_DATA0_INTERNAL_OFFSET; + adev->vcn.inst[0].internal.data0 = mmUVD_GPCOM_VCPU_DATA0_INTERNAL_OFFSET; adev->vcn.inst->external.data0 = SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_DATA0); - adev->vcn.internal.data1 = mmUVD_GPCOM_VCPU_DATA1_INTERNAL_OFFSET; + adev->vcn.inst[0].internal.data1 = mmUVD_GPCOM_VCPU_DATA1_INTERNAL_OFFSET; adev->vcn.inst->external.data1 = SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_DATA1); - adev->vcn.internal.cmd = mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET; + adev->vcn.inst[0].internal.cmd = mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET; adev->vcn.inst->external.cmd = SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_CMD); - adev->vcn.internal.nop = mmUVD_NO_OP_INTERNAL_OFFSET; + adev->vcn.inst[0].internal.nop = mmUVD_NO_OP_INTERNAL_OFFSET; adev->vcn.inst->external.nop = SOC15_REG_OFFSET(UVD, 0, mmUVD_NO_OP); - for (i = 0; i < adev->vcn.num_enc_rings; ++i) { + for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i) { enum amdgpu_ring_priority_level hw_prio = amdgpu_vcn_get_enc_ring_prio(i); ring = &adev->vcn.inst->ring_enc[i]; @@ -210,7 +210,7 @@ static int vcn_v2_0_sw_init(struct amdgpu_ip_block *ip_block) return r; } - adev->vcn.pause_dpg_mode = vcn_v2_0_pause_dpg_mode; + adev->vcn.inst[0].pause_dpg_mode = vcn_v2_0_pause_dpg_mode; r = amdgpu_virt_alloc_mm_table(adev); if (r) @@ -292,7 +292,7 @@ static int vcn_v2_0_hw_init(struct amdgpu_ip_block *ip_block) if (amdgpu_sriov_vf(adev)) ring->sched.ready = false; - for (i = 0; i < adev->vcn.num_enc_rings; ++i) { + for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i) { ring = &adev->vcn.inst->ring_enc[i]; r = amdgpu_ring_test_helper(ring); if (r) @@ -981,7 +981,7 @@ static int vcn_v2_0_start(struct amdgpu_device *adev) amdgpu_dpm_enable_vcn(adev, true, 0); if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) - return vcn_v2_0_start_dpg_mode(adev, adev->vcn.indirect_sram); + return vcn_v2_0_start_dpg_mode(adev, adev->vcn.inst->indirect_sram); vcn_v2_0_disable_static_power_gating(adev); @@ -1421,9 +1421,9 @@ void vcn_v2_0_dec_ring_insert_start(struct amdgpu_ring *ring) { struct amdgpu_device *adev = ring->adev; - amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data0, 0)); + amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data0, 0)); amdgpu_ring_write(ring, 0); - amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.cmd, 0)); + amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.cmd, 0)); amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_PACKET_START << 1)); } @@ -1438,7 +1438,7 @@ void vcn_v2_0_dec_ring_insert_end(struct amdgpu_ring *ring) { struct amdgpu_device *adev = ring->adev; - amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.cmd, 0)); + amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[0].internal.cmd, 0)); amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_PACKET_END << 1)); } @@ -1458,7 +1458,7 @@ void vcn_v2_0_dec_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count) WARN_ON(ring->wptr % 2 || count % 2); for (i = 0; i < count / 2; i++) { - amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.nop, 0)); + amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.nop, 0)); amdgpu_ring_write(ring, 0); } } @@ -1479,25 +1479,25 @@ void vcn_v2_0_dec_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq, struct amdgpu_device *adev = ring->adev; WARN_ON(flags & AMDGPU_FENCE_FLAG_64BIT); - amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.context_id, 0)); + amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.context_id, 0)); amdgpu_ring_write(ring, seq); - amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data0, 0)); + amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data0, 0)); amdgpu_ring_write(ring, addr & 0xffffffff); - amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data1, 0)); + amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data1, 0)); amdgpu_ring_write(ring, upper_32_bits(addr) & 0xff); - amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.cmd, 0)); + amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.cmd, 0)); amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_FENCE << 1)); - amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data0, 0)); + amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data0, 0)); amdgpu_ring_write(ring, 0); - amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data1, 0)); + amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data1, 0)); amdgpu_ring_write(ring, 0); - amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.cmd, 0)); + amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.cmd, 0)); amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_TRAP << 1)); } @@ -1520,14 +1520,14 @@ void vcn_v2_0_dec_ring_emit_ib(struct amdgpu_ring *ring, struct amdgpu_device *adev = ring->adev; unsigned vmid = AMDGPU_JOB_GET_VMID(job); - amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.ib_vmid, 0)); + amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.ib_vmid, 0)); amdgpu_ring_write(ring, vmid); - amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.ib_bar_low, 0)); + amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.ib_bar_low, 0)); amdgpu_ring_write(ring, lower_32_bits(ib->gpu_addr)); - amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.ib_bar_high, 0)); + amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.ib_bar_high, 0)); amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr)); - amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.ib_size, 0)); + amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.ib_size, 0)); amdgpu_ring_write(ring, ib->length_dw); } @@ -1536,16 +1536,16 @@ void vcn_v2_0_dec_ring_emit_reg_wait(struct amdgpu_ring *ring, uint32_t reg, { struct amdgpu_device *adev = ring->adev; - amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data0, 0)); + amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data0, 0)); amdgpu_ring_write(ring, reg << 2); - amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data1, 0)); + amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data1, 0)); amdgpu_ring_write(ring, val); - amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.gp_scratch8, 0)); + amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.gp_scratch8, 0)); amdgpu_ring_write(ring, mask); - amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.cmd, 0)); + amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.cmd, 0)); amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_REG_READ_COND_WAIT << 1)); } @@ -1570,13 +1570,13 @@ void vcn_v2_0_dec_ring_emit_wreg(struct amdgpu_ring *ring, { struct amdgpu_device *adev = ring->adev; - amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data0, 0)); + amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data0, 0)); amdgpu_ring_write(ring, reg << 2); - amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data1, 0)); + amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data1, 0)); amdgpu_ring_write(ring, val); - amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.cmd, 0)); + amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.cmd, 0)); amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_WRITE_REG << 1)); } @@ -1777,9 +1777,9 @@ int vcn_v2_0_dec_ring_test_ring(struct amdgpu_ring *ring) r = amdgpu_ring_alloc(ring, 4); if (r) return r; - amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.cmd, 0)); + amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.cmd, 0)); amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_PACKET_START << 1)); - amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.scratch9, 0)); + amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.scratch9, 0)); amdgpu_ring_write(ring, 0xDEADBEEF); amdgpu_ring_commit(ring); for (i = 0; i < adev->usec_timeout; i++) { @@ -1863,7 +1863,7 @@ static int vcn_v2_0_start_mmsch(struct amdgpu_device *adev, adev->vcn.inst->ring_dec.wptr_old = 0; vcn_v2_0_dec_ring_set_wptr(&adev->vcn.inst->ring_dec); - for (i = 0; i < adev->vcn.num_enc_rings; ++i) { + for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i) { adev->vcn.inst->ring_enc[i].wptr = 0; adev->vcn.inst->ring_enc[i].wptr_old = 0; vcn_v2_0_enc_ring_set_wptr(&adev->vcn.inst->ring_enc[i]); @@ -1989,7 +1989,7 @@ static int vcn_v2_0_start_sriov(struct amdgpu_device *adev) SOC15_REG_OFFSET(UVD, i, mmUVD_VCPU_CACHE_SIZE2), AMDGPU_VCN_CONTEXT_SIZE); - for (r = 0; r < adev->vcn.num_enc_rings; ++r) { + for (r = 0; r < adev->vcn.inst[0].num_enc_rings; ++r) { ring = &adev->vcn.inst->ring_enc[r]; ring->wptr = 0; MMSCH_V2_0_INSERT_DIRECT_WT( @@ -2178,7 +2178,7 @@ static void vcn_v2_0_set_enc_ring_funcs(struct amdgpu_device *adev) { int i; - for (i = 0; i < adev->vcn.num_enc_rings; ++i) + for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i) adev->vcn.inst->ring_enc[i].funcs = &vcn_v2_0_enc_ring_vm_funcs; } @@ -2189,7 +2189,7 @@ static const struct amdgpu_irq_src_funcs vcn_v2_0_irq_funcs = { static void vcn_v2_0_set_irq_funcs(struct amdgpu_device *adev) { - adev->vcn.inst->irq.num_types = adev->vcn.num_enc_rings + 1; + adev->vcn.inst->irq.num_types = adev->vcn.inst[0].num_enc_rings + 1; adev->vcn.inst->irq.funcs = &vcn_v2_0_irq_funcs; } diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c index 0d78377f8ffe..c20619c027e7 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c @@ -121,11 +121,13 @@ static int amdgpu_ih_clientid_vcns[] = { static int vcn_v2_5_early_init(struct amdgpu_ip_block *ip_block) { struct amdgpu_device *adev = ip_block->adev; + int i; if (amdgpu_sriov_vf(adev)) { adev->vcn.num_vcn_inst = 2; adev->vcn.harvest_config = 0; - adev->vcn.num_enc_rings = 1; + for (i = 0; i < adev->vcn.num_vcn_inst; i++) + adev->vcn.inst[i].num_enc_rings = 1; } else { u32 harvest; int i; @@ -134,13 +136,12 @@ static int vcn_v2_5_early_init(struct amdgpu_ip_block *ip_block) harvest = RREG32_SOC15(VCN, i, mmCC_UVD_HARVESTING); if (harvest & CC_UVD_HARVESTING__UVD_DISABLE_MASK) adev->vcn.harvest_config |= 1 << i; + adev->vcn.inst[i].num_enc_rings = 2; } if (adev->vcn.harvest_config == (AMDGPU_VCN_HARVEST_VCN0 | AMDGPU_VCN_HARVEST_VCN1)) /* both instances are harvested, disable the block */ return -ENOENT; - - adev->vcn.num_enc_rings = 2; } vcn_v2_5_set_dec_ring_funcs(adev); @@ -176,7 +177,7 @@ static int vcn_v2_5_sw_init(struct amdgpu_ip_block *ip_block) return r; /* VCN ENC TRAP */ - for (i = 0; i < adev->vcn.num_enc_rings; ++i) { + for (i = 0; i < adev->vcn.inst[j].num_enc_rings; ++i) { r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_vcns[j], i + VCN_2_0__SRCID__UVD_ENC_GENERAL_PURPOSE, &adev->vcn.inst[j].irq); if (r) @@ -205,22 +206,22 @@ static int vcn_v2_5_sw_init(struct amdgpu_ip_block *ip_block) if (adev->vcn.harvest_config & (1 << j)) continue; - adev->vcn.internal.context_id = mmUVD_CONTEXT_ID_INTERNAL_OFFSET; - adev->vcn.internal.ib_vmid = mmUVD_LMI_RBC_IB_VMID_INTERNAL_OFFSET; - adev->vcn.internal.ib_bar_low = mmUVD_LMI_RBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET; - adev->vcn.internal.ib_bar_high = mmUVD_LMI_RBC_IB_64BIT_BAR_HIGH_INTERNAL_OFFSET; - adev->vcn.internal.ib_size = mmUVD_RBC_IB_SIZE_INTERNAL_OFFSET; - adev->vcn.internal.gp_scratch8 = mmUVD_GP_SCRATCH8_INTERNAL_OFFSET; + adev->vcn.inst[j].internal.context_id = mmUVD_CONTEXT_ID_INTERNAL_OFFSET; + adev->vcn.inst[j].internal.ib_vmid = mmUVD_LMI_RBC_IB_VMID_INTERNAL_OFFSET; + adev->vcn.inst[j].internal.ib_bar_low = mmUVD_LMI_RBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET; + adev->vcn.inst[j].internal.ib_bar_high = mmUVD_LMI_RBC_IB_64BIT_BAR_HIGH_INTERNAL_OFFSET; + adev->vcn.inst[j].internal.ib_size = mmUVD_RBC_IB_SIZE_INTERNAL_OFFSET; + adev->vcn.inst[j].internal.gp_scratch8 = mmUVD_GP_SCRATCH8_INTERNAL_OFFSET; - adev->vcn.internal.scratch9 = mmUVD_SCRATCH9_INTERNAL_OFFSET; + adev->vcn.inst[j].internal.scratch9 = mmUVD_SCRATCH9_INTERNAL_OFFSET; adev->vcn.inst[j].external.scratch9 = SOC15_REG_OFFSET(VCN, j, mmUVD_SCRATCH9); - adev->vcn.internal.data0 = mmUVD_GPCOM_VCPU_DATA0_INTERNAL_OFFSET; + adev->vcn.inst[j].internal.data0 = mmUVD_GPCOM_VCPU_DATA0_INTERNAL_OFFSET; adev->vcn.inst[j].external.data0 = SOC15_REG_OFFSET(VCN, j, mmUVD_GPCOM_VCPU_DATA0); - adev->vcn.internal.data1 = mmUVD_GPCOM_VCPU_DATA1_INTERNAL_OFFSET; + adev->vcn.inst[j].internal.data1 = mmUVD_GPCOM_VCPU_DATA1_INTERNAL_OFFSET; adev->vcn.inst[j].external.data1 = SOC15_REG_OFFSET(VCN, j, mmUVD_GPCOM_VCPU_DATA1); - adev->vcn.internal.cmd = mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET; + adev->vcn.inst[j].internal.cmd = mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET; adev->vcn.inst[j].external.cmd = SOC15_REG_OFFSET(VCN, j, mmUVD_GPCOM_VCPU_CMD); - adev->vcn.internal.nop = mmUVD_NO_OP_INTERNAL_OFFSET; + adev->vcn.inst[j].internal.nop = mmUVD_NO_OP_INTERNAL_OFFSET; adev->vcn.inst[j].external.nop = SOC15_REG_OFFSET(VCN, j, mmUVD_NO_OP); ring = &adev->vcn.inst[j].ring_dec; @@ -240,7 +241,7 @@ static int vcn_v2_5_sw_init(struct amdgpu_ip_block *ip_block) if (r) return r; - for (i = 0; i < adev->vcn.num_enc_rings; ++i) { + for (i = 0; i < adev->vcn.inst[j].num_enc_rings; ++i) { enum amdgpu_ring_priority_level hw_prio = amdgpu_vcn_get_enc_ring_prio(i); ring = &adev->vcn.inst[j].ring_enc[i]; @@ -268,6 +269,9 @@ static int vcn_v2_5_sw_init(struct amdgpu_ip_block *ip_block) if (amdgpu_vcnfw_log) amdgpu_vcn_fwlog_init(&adev->vcn.inst[i]); + + if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) + adev->vcn.inst[j].pause_dpg_mode = vcn_v2_5_pause_dpg_mode; } if (amdgpu_sriov_vf(adev)) { @@ -276,9 +280,6 @@ static int vcn_v2_5_sw_init(struct amdgpu_ip_block *ip_block) return r; } - if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) - adev->vcn.pause_dpg_mode = vcn_v2_5_pause_dpg_mode; - r = amdgpu_vcn_ras_sw_init(adev); if (r) return r; @@ -369,7 +370,7 @@ static int vcn_v2_5_hw_init(struct amdgpu_ip_block *ip_block) if (r) return r; - for (i = 0; i < adev->vcn.num_enc_rings; ++i) { + for (i = 0; i < adev->vcn.inst[j].num_enc_rings; ++i) { ring = &adev->vcn.inst[j].ring_enc[i]; r = amdgpu_ring_test_helper(ring); if (r) @@ -1018,7 +1019,7 @@ static int vcn_v2_5_start(struct amdgpu_device *adev, int i) amdgpu_dpm_enable_vcn(adev, true, i); if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) - return vcn_v2_5_start_dpg_mode(adev, i, adev->vcn.indirect_sram); + return vcn_v2_5_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram); /* disable register anti-hang mechanism */ WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_POWER_STATUS), 0, @@ -1749,7 +1750,7 @@ static void vcn_v2_5_set_enc_ring_funcs(struct amdgpu_device *adev) for (j = 0; j < adev->vcn.num_vcn_inst; ++j) { if (adev->vcn.harvest_config & (1 << j)) continue; - for (i = 0; i < adev->vcn.num_enc_rings; ++i) { + for (i = 0; i < adev->vcn.inst[j].num_enc_rings; ++i) { adev->vcn.inst[j].ring_enc[i].funcs = &vcn_v2_5_enc_ring_vm_funcs; adev->vcn.inst[j].ring_enc[i].me = j; } @@ -1920,10 +1921,10 @@ static void vcn_v2_5_set_irq_funcs(struct amdgpu_device *adev) for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { if (adev->vcn.harvest_config & (1 << i)) continue; - adev->vcn.inst[i].irq.num_types = adev->vcn.num_enc_rings + 1; + adev->vcn.inst[i].irq.num_types = adev->vcn.inst[i].num_enc_rings + 1; adev->vcn.inst[i].irq.funcs = &vcn_v2_5_irq_funcs; - adev->vcn.inst[i].ras_poison_irq.num_types = adev->vcn.num_enc_rings + 1; + adev->vcn.inst[i].ras_poison_irq.num_types = adev->vcn.inst[i].num_enc_rings + 1; adev->vcn.inst[i].ras_poison_irq.funcs = &vcn_v2_6_ras_irq_funcs; } } diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c index acfe85b0c062..282a186cb0c5 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c @@ -127,11 +127,13 @@ static void vcn_v3_0_enc_ring_set_wptr(struct amdgpu_ring *ring); static int vcn_v3_0_early_init(struct amdgpu_ip_block *ip_block) { struct amdgpu_device *adev = ip_block->adev; + int i; if (amdgpu_sriov_vf(adev)) { adev->vcn.num_vcn_inst = VCN_INSTANCES_SIENNA_CICHLID; adev->vcn.harvest_config = 0; - adev->vcn.num_enc_rings = 1; + for (i = 0; i < adev->vcn.num_vcn_inst; i++) + adev->vcn.inst[i].num_enc_rings = 1; } else { if (adev->vcn.harvest_config == (AMDGPU_VCN_HARVEST_VCN0 | @@ -139,11 +141,13 @@ static int vcn_v3_0_early_init(struct amdgpu_ip_block *ip_block) /* both instances are harvested, disable the block */ return -ENOENT; - if (amdgpu_ip_version(adev, UVD_HWIP, 0) == - IP_VERSION(3, 0, 33)) - adev->vcn.num_enc_rings = 0; - else - adev->vcn.num_enc_rings = 2; + for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + if (amdgpu_ip_version(adev, UVD_HWIP, 0) == + IP_VERSION(3, 0, 33)) + adev->vcn.inst[i].num_enc_rings = 0; + else + adev->vcn.inst[i].num_enc_rings = 2; + } } vcn_v3_0_set_dec_ring_funcs(adev); @@ -198,22 +202,22 @@ static int vcn_v3_0_sw_init(struct amdgpu_ip_block *ip_block) if (adev->vcn.harvest_config & (1 << i)) continue; - adev->vcn.internal.context_id = mmUVD_CONTEXT_ID_INTERNAL_OFFSET; - adev->vcn.internal.ib_vmid = mmUVD_LMI_RBC_IB_VMID_INTERNAL_OFFSET; - adev->vcn.internal.ib_bar_low = mmUVD_LMI_RBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET; - adev->vcn.internal.ib_bar_high = mmUVD_LMI_RBC_IB_64BIT_BAR_HIGH_INTERNAL_OFFSET; - adev->vcn.internal.ib_size = mmUVD_RBC_IB_SIZE_INTERNAL_OFFSET; - adev->vcn.internal.gp_scratch8 = mmUVD_GP_SCRATCH8_INTERNAL_OFFSET; + adev->vcn.inst[i].internal.context_id = mmUVD_CONTEXT_ID_INTERNAL_OFFSET; + adev->vcn.inst[i].internal.ib_vmid = mmUVD_LMI_RBC_IB_VMID_INTERNAL_OFFSET; + adev->vcn.inst[i].internal.ib_bar_low = mmUVD_LMI_RBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET; + adev->vcn.inst[i].internal.ib_bar_high = mmUVD_LMI_RBC_IB_64BIT_BAR_HIGH_INTERNAL_OFFSET; + adev->vcn.inst[i].internal.ib_size = mmUVD_RBC_IB_SIZE_INTERNAL_OFFSET; + adev->vcn.inst[i].internal.gp_scratch8 = mmUVD_GP_SCRATCH8_INTERNAL_OFFSET; - adev->vcn.internal.scratch9 = mmUVD_SCRATCH9_INTERNAL_OFFSET; + adev->vcn.inst[i].internal.scratch9 = mmUVD_SCRATCH9_INTERNAL_OFFSET; adev->vcn.inst[i].external.scratch9 = SOC15_REG_OFFSET(VCN, i, mmUVD_SCRATCH9); - adev->vcn.internal.data0 = mmUVD_GPCOM_VCPU_DATA0_INTERNAL_OFFSET; + adev->vcn.inst[i].internal.data0 = mmUVD_GPCOM_VCPU_DATA0_INTERNAL_OFFSET; adev->vcn.inst[i].external.data0 = SOC15_REG_OFFSET(VCN, i, mmUVD_GPCOM_VCPU_DATA0); - adev->vcn.internal.data1 = mmUVD_GPCOM_VCPU_DATA1_INTERNAL_OFFSET; + adev->vcn.inst[i].internal.data1 = mmUVD_GPCOM_VCPU_DATA1_INTERNAL_OFFSET; adev->vcn.inst[i].external.data1 = SOC15_REG_OFFSET(VCN, i, mmUVD_GPCOM_VCPU_DATA1); - adev->vcn.internal.cmd = mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET; + adev->vcn.inst[i].internal.cmd = mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET; adev->vcn.inst[i].external.cmd = SOC15_REG_OFFSET(VCN, i, mmUVD_GPCOM_VCPU_CMD); - adev->vcn.internal.nop = mmUVD_NO_OP_INTERNAL_OFFSET; + adev->vcn.inst[i].internal.nop = mmUVD_NO_OP_INTERNAL_OFFSET; adev->vcn.inst[i].external.nop = SOC15_REG_OFFSET(VCN, i, mmUVD_NO_OP); /* VCN DEC TRAP */ @@ -227,7 +231,7 @@ static int vcn_v3_0_sw_init(struct amdgpu_ip_block *ip_block) ring = &adev->vcn.inst[i].ring_dec; ring->use_doorbell = true; if (amdgpu_sriov_vf(adev)) { - ring->doorbell_index = vcn_doorbell_index + i * (adev->vcn.num_enc_rings + 1); + ring->doorbell_index = vcn_doorbell_index + i * (adev->vcn.inst[i].num_enc_rings + 1); } else { ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 8 * i; } @@ -239,7 +243,7 @@ static int vcn_v3_0_sw_init(struct amdgpu_ip_block *ip_block) if (r) return r; - for (j = 0; j < adev->vcn.num_enc_rings; ++j) { + for (j = 0; j < adev->vcn.inst[i].num_enc_rings; ++j) { enum amdgpu_ring_priority_level hw_prio = amdgpu_vcn_get_enc_ring_prio(j); /* VCN ENC TRAP */ @@ -251,7 +255,7 @@ static int vcn_v3_0_sw_init(struct amdgpu_ip_block *ip_block) ring = &adev->vcn.inst[i].ring_enc[j]; ring->use_doorbell = true; if (amdgpu_sriov_vf(adev)) { - ring->doorbell_index = vcn_doorbell_index + i * (adev->vcn.num_enc_rings + 1) + 1 + j; + ring->doorbell_index = vcn_doorbell_index + i * (adev->vcn.inst[i].num_enc_rings + 1) + 1 + j; } else { ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 2 + j + 8 * i; } @@ -277,6 +281,9 @@ static int vcn_v3_0_sw_init(struct amdgpu_ip_block *ip_block) if (amdgpu_vcnfw_log) amdgpu_vcn_fwlog_init(&adev->vcn.inst[i]); + + if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) + adev->vcn.inst[i].pause_dpg_mode = vcn_v3_0_pause_dpg_mode; } if (amdgpu_sriov_vf(adev)) { @@ -284,8 +291,6 @@ static int vcn_v3_0_sw_init(struct amdgpu_ip_block *ip_block) if (r) return r; } - if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) - adev->vcn.pause_dpg_mode = vcn_v3_0_pause_dpg_mode; /* Allocate memory for VCN IP Dump buffer */ ptr = kcalloc(adev->vcn.num_vcn_inst * reg_count, sizeof(uint32_t), GFP_KERNEL); @@ -373,7 +378,7 @@ static int vcn_v3_0_hw_init(struct amdgpu_ip_block *ip_block) ring->sched.ready = true; } - for (j = 0; j < adev->vcn.num_enc_rings; ++j) { + for (j = 0; j < adev->vcn.inst[i].num_enc_rings; ++j) { ring = &adev->vcn.inst[i].ring_enc[j]; if (amdgpu_vcn_is_disabled_vcn(adev, VCN_ENCODE_RING, i)) { ring->sched.ready = false; @@ -401,7 +406,7 @@ static int vcn_v3_0_hw_init(struct amdgpu_ip_block *ip_block) if (r) return r; - for (j = 0; j < adev->vcn.num_enc_rings; ++j) { + for (j = 0; j < adev->vcn.inst[i].num_enc_rings; ++j) { ring = &adev->vcn.inst[i].ring_enc[j]; r = amdgpu_ring_test_helper(ring); if (r) @@ -1153,7 +1158,7 @@ static int vcn_v3_0_start(struct amdgpu_device *adev, int i) amdgpu_dpm_enable_vcn(adev, true, i); if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) - return vcn_v3_0_start_dpg_mode(adev, i, adev->vcn.indirect_sram); + return vcn_v3_0_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram); /* disable VCN power gating */ vcn_v3_0_disable_static_power_gating(adev, i); @@ -1433,7 +1438,7 @@ static int vcn_v3_0_start_sriov(struct amdgpu_device *adev) mmUVD_VCPU_CACHE_SIZE2), AMDGPU_VCN_CONTEXT_SIZE); - for (j = 0; j < adev->vcn.num_enc_rings; ++j) { + for (j = 0; j < adev->vcn.inst[i].num_enc_rings; ++j) { ring = &adev->vcn.inst[i].ring_enc[j]; ring->wptr = 0; rb_addr = ring->gpu_addr; @@ -1924,11 +1929,11 @@ static int vcn_v3_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p, uint32_t reg = amdgpu_ib_get_value(ib, i); uint32_t val = amdgpu_ib_get_value(ib, i + 1); - if (reg == PACKET0(p->adev->vcn.internal.data0, 0)) { + if (reg == PACKET0(p->adev->vcn.inst[ring->me].internal.data0, 0)) { msg_lo = val; - } else if (reg == PACKET0(p->adev->vcn.internal.data1, 0)) { + } else if (reg == PACKET0(p->adev->vcn.inst[ring->me].internal.data1, 0)) { msg_hi = val; - } else if (reg == PACKET0(p->adev->vcn.internal.cmd, 0) && + } else if (reg == PACKET0(p->adev->vcn.inst[ring->me].internal.cmd, 0) && val == 0) { r = vcn_v3_0_dec_msg(p, job, ((u64)msg_hi) << 32 | msg_lo); @@ -2092,7 +2097,7 @@ static void vcn_v3_0_set_enc_ring_funcs(struct amdgpu_device *adev) if (adev->vcn.harvest_config & (1 << i)) continue; - for (j = 0; j < adev->vcn.num_enc_rings; ++j) { + for (j = 0; j < adev->vcn.inst[i].num_enc_rings; ++j) { adev->vcn.inst[i].ring_enc[j].funcs = &vcn_v3_0_enc_ring_vm_funcs; adev->vcn.inst[i].ring_enc[j].me = i; } @@ -2258,7 +2263,7 @@ static void vcn_v3_0_set_irq_funcs(struct amdgpu_device *adev) if (adev->vcn.harvest_config & (1 << i)) continue; - adev->vcn.inst[i].irq.num_types = adev->vcn.num_enc_rings + 1; + adev->vcn.inst[i].irq.num_types = adev->vcn.inst[i].num_enc_rings + 1; adev->vcn.inst[i].irq.funcs = &vcn_v3_0_irq_funcs; } } diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c index 1f67e5973cf8..f5bb241c1af1 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c @@ -129,8 +129,9 @@ static int vcn_v4_0_early_init(struct amdgpu_ip_block *ip_block) } } - /* re-use enc ring as unified ring */ - adev->vcn.num_enc_rings = 1; + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) + /* re-use enc ring as unified ring */ + adev->vcn.inst[i].num_enc_rings = 1; vcn_v4_0_set_unified_ring_funcs(adev); vcn_v4_0_set_irq_funcs(adev); @@ -214,7 +215,8 @@ static int vcn_v4_0_sw_init(struct amdgpu_ip_block *ip_block) ring = &adev->vcn.inst[i].ring_enc[0]; ring->use_doorbell = true; if (amdgpu_sriov_vf(adev)) - ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + i * (adev->vcn.num_enc_rings + 1) + 1; + ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + i * + (adev->vcn.inst[i].num_enc_rings + 1) + 1; else ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 2 + 8 * i; ring->vm_hub = AMDGPU_MMHUB0(0); @@ -226,6 +228,9 @@ static int vcn_v4_0_sw_init(struct amdgpu_ip_block *ip_block) return r; vcn_v4_0_fw_shared_init(adev, i); + + if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) + adev->vcn.inst[i].pause_dpg_mode = vcn_v4_0_pause_dpg_mode; } /* TODO: Add queue reset mask when FW fully supports it */ @@ -238,8 +243,6 @@ static int vcn_v4_0_sw_init(struct amdgpu_ip_block *ip_block) return r; } - if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) - adev->vcn.pause_dpg_mode = vcn_v4_0_pause_dpg_mode; r = amdgpu_vcn_ras_sw_init(adev); if (r) @@ -1111,7 +1114,7 @@ static int vcn_v4_0_start(struct amdgpu_device *adev, int i) fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) - return vcn_v4_0_start_dpg_mode(adev, i, adev->vcn.indirect_sram); + return vcn_v4_0_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram); /* disable VCN power gating */ vcn_v4_0_disable_static_power_gating(adev, i); @@ -2174,10 +2177,10 @@ static void vcn_v4_0_set_irq_funcs(struct amdgpu_device *adev) if (adev->vcn.harvest_config & (1 << i)) continue; - adev->vcn.inst[i].irq.num_types = adev->vcn.num_enc_rings + 1; + adev->vcn.inst[i].irq.num_types = adev->vcn.inst[i].num_enc_rings + 1; adev->vcn.inst[i].irq.funcs = &vcn_v4_0_irq_funcs; - adev->vcn.inst[i].ras_poison_irq.num_types = adev->vcn.num_enc_rings + 1; + adev->vcn.inst[i].ras_poison_irq.num_types = adev->vcn.inst[i].num_enc_rings + 1; adev->vcn.inst[i].ras_poison_irq.funcs = &vcn_v4_0_ras_irq_funcs; } } diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c index 73b10813d9b8..fbe599c539c8 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c @@ -114,9 +114,11 @@ static inline bool vcn_v4_0_3_normalizn_reqd(struct amdgpu_device *adev) static int vcn_v4_0_3_early_init(struct amdgpu_ip_block *ip_block) { struct amdgpu_device *adev = ip_block->adev; + int i; - /* re-use enc ring as unified ring */ - adev->vcn.num_enc_rings = 1; + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) + /* re-use enc ring as unified ring */ + adev->vcn.inst[i].num_enc_rings = 1; vcn_v4_0_3_set_unified_ring_funcs(adev); vcn_v4_0_3_set_irq_funcs(adev); @@ -194,6 +196,9 @@ static int vcn_v4_0_3_sw_init(struct amdgpu_ip_block *ip_block) return r; vcn_v4_0_3_fw_shared_init(adev, i); + + if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) + adev->vcn.inst[i].pause_dpg_mode = vcn_v4_0_3_pause_dpg_mode; } /* TODO: Add queue reset mask when FW fully supports it */ @@ -206,9 +211,6 @@ static int vcn_v4_0_3_sw_init(struct amdgpu_ip_block *ip_block) return r; } - if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) - adev->vcn.pause_dpg_mode = vcn_v4_0_3_pause_dpg_mode; - if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__VCN)) { r = amdgpu_vcn_ras_sw_init(adev); if (r) { @@ -1135,7 +1137,7 @@ static int vcn_v4_0_3_start(struct amdgpu_device *adev, int i) uint32_t tmp; if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) - return vcn_v4_0_3_start_dpg_mode(adev, i, adev->vcn.indirect_sram); + return vcn_v4_0_3_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram); vcn_inst = GET_INST(VCN, i); /* set VCN status busy */ diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c index 06b5ef4b3e84..2513929b2d43 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c @@ -115,9 +115,11 @@ static void vcn_v4_0_5_unified_ring_set_wptr(struct amdgpu_ring *ring); static int vcn_v4_0_5_early_init(struct amdgpu_ip_block *ip_block) { struct amdgpu_device *adev = ip_block->adev; + int i; - /* re-use enc ring as unified ring */ - adev->vcn.num_enc_rings = 1; + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) + /* re-use enc ring as unified ring */ + adev->vcn.inst[i].num_enc_rings = 1; vcn_v4_0_5_set_unified_ring_funcs(adev); vcn_v4_0_5_set_irq_funcs(adev); @@ -173,7 +175,7 @@ static int vcn_v4_0_5_sw_init(struct amdgpu_ip_block *ip_block) ring->use_doorbell = true; if (amdgpu_sriov_vf(adev)) ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + - i * (adev->vcn.num_enc_rings + 1) + 1; + i * (adev->vcn.inst[i].num_enc_rings + 1) + 1; else ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 2 + 8 * i; @@ -198,6 +200,9 @@ static int vcn_v4_0_5_sw_init(struct amdgpu_ip_block *ip_block) if (amdgpu_vcnfw_log) amdgpu_vcn_fwlog_init(&adev->vcn.inst[i]); + + if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) + adev->vcn.inst[i].pause_dpg_mode = vcn_v4_0_5_pause_dpg_mode; } if (amdgpu_sriov_vf(adev)) { @@ -206,9 +211,6 @@ static int vcn_v4_0_5_sw_init(struct amdgpu_ip_block *ip_block) return r; } - if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) - adev->vcn.pause_dpg_mode = vcn_v4_0_5_pause_dpg_mode; - /* Allocate memory for VCN IP Dump buffer */ ptr = kcalloc(adev->vcn.num_vcn_inst * reg_count, sizeof(uint32_t), GFP_KERNEL); if (!ptr) { @@ -1014,7 +1016,7 @@ static int vcn_v4_0_5_start(struct amdgpu_device *adev, int i) fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) - return vcn_v4_0_5_start_dpg_mode(adev, i, adev->vcn.indirect_sram); + return vcn_v4_0_5_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram); /* disable VCN power gating */ vcn_v4_0_5_disable_static_power_gating(adev, i); @@ -1629,7 +1631,7 @@ static void vcn_v4_0_5_set_irq_funcs(struct amdgpu_device *adev) if (adev->vcn.harvest_config & (1 << i)) continue; - adev->vcn.inst[i].irq.num_types = adev->vcn.num_enc_rings + 1; + adev->vcn.inst[i].irq.num_types = adev->vcn.inst[i].num_enc_rings + 1; adev->vcn.inst[i].irq.funcs = &vcn_v4_0_5_irq_funcs; } } diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c index 8e0bd2cc1002..50e0928c3a20 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c @@ -98,9 +98,11 @@ static void vcn_v5_0_0_unified_ring_set_wptr(struct amdgpu_ring *ring); static int vcn_v5_0_0_early_init(struct amdgpu_ip_block *ip_block) { struct amdgpu_device *adev = ip_block->adev; + int i; - /* re-use enc ring as unified ring */ - adev->vcn.num_enc_rings = 1; + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) + /* re-use enc ring as unified ring */ + adev->vcn.inst[i].num_enc_rings = 1; vcn_v5_0_0_set_unified_ring_funcs(adev); vcn_v5_0_0_set_irq_funcs(adev); @@ -184,15 +186,15 @@ static int vcn_v5_0_0_sw_init(struct amdgpu_ip_block *ip_block) if (amdgpu_vcnfw_log) amdgpu_vcn_fwlog_init(&adev->vcn.inst[i]); + + if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) + adev->vcn.inst[i].pause_dpg_mode = vcn_v5_0_0_pause_dpg_mode; } /* TODO: Add queue reset mask when FW fully supports it */ adev->vcn.supported_reset = amdgpu_get_soft_full_reset_mask(&adev->vcn.inst[0].ring_enc[0]); - if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) - adev->vcn.pause_dpg_mode = vcn_v5_0_0_pause_dpg_mode; - vcn_v5_0_0_alloc_ip_dump(adev); r = amdgpu_vcn_sysfs_reset_mask_init(adev); @@ -791,7 +793,7 @@ static int vcn_v5_0_0_start(struct amdgpu_device *adev, int i) fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) - return vcn_v5_0_0_start_dpg_mode(adev, i, adev->vcn.indirect_sram); + return vcn_v5_0_0_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram); /* disable VCN power gating */ vcn_v5_0_0_disable_static_power_gating(adev, i); @@ -1369,7 +1371,7 @@ static void vcn_v5_0_0_set_irq_funcs(struct amdgpu_device *adev) if (adev->vcn.harvest_config & (1 << i)) continue; - adev->vcn.inst[i].irq.num_types = adev->vcn.num_enc_rings + 1; + adev->vcn.inst[i].irq.num_types = adev->vcn.inst[i].num_enc_rings + 1; adev->vcn.inst[i].irq.funcs = &vcn_v5_0_0_irq_funcs; } } diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c index 83e873767a86..ebe977507bc3 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c @@ -58,9 +58,11 @@ static void vcn_v5_0_1_unified_ring_set_wptr(struct amdgpu_ring *ring); static int vcn_v5_0_1_early_init(struct amdgpu_ip_block *ip_block) { struct amdgpu_device *adev = ip_block->adev; + int i; - /* re-use enc ring as unified ring */ - adev->vcn.num_enc_rings = 1; + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) + /* re-use enc ring as unified ring */ + adev->vcn.inst[i].num_enc_rings = 1; vcn_v5_0_1_set_unified_ring_funcs(adev); vcn_v5_0_1_set_irq_funcs(adev); @@ -583,7 +585,7 @@ static int vcn_v5_0_1_start(struct amdgpu_device *adev, int i) fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) - return vcn_v5_0_1_start_dpg_mode(adev, i, adev->vcn.indirect_sram); + return vcn_v5_0_1_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram); vcn_inst = GET_INST(VCN, i); From f98675638f0a818a2eb802103b1e140b091358c4 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 15 Nov 2024 17:44:01 -0500 Subject: [PATCH 085/235] drm/amdgpu/vcn: switch vcn helpers to be instance based Pass the instance to the helpers. Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 425 ++++++++++++------------ drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h | 12 +- drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c | 16 +- drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c | 16 +- drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c | 71 ++-- drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 65 ++-- drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c | 69 ++-- drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c | 70 ++-- drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c | 63 ++-- drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c | 67 ++-- drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c | 64 ++-- 11 files changed, 535 insertions(+), 403 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c index 9901b8e17f30..010cc64a950a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c @@ -93,192 +93,186 @@ MODULE_FIRMWARE(FIRMWARE_VCN5_0_1); static void amdgpu_vcn_idle_work_handler(struct work_struct *work); -int amdgpu_vcn_early_init(struct amdgpu_device *adev) +int amdgpu_vcn_early_init(struct amdgpu_device *adev, int i) { char ucode_prefix[25]; - int r, i; + int r; + adev->vcn.inst[i].adev = adev; + adev->vcn.inst[i].inst = i; amdgpu_ucode_ip_version_decode(adev, UVD_HWIP, ucode_prefix, sizeof(ucode_prefix)); - for (i = 0; i < adev->vcn.num_vcn_inst; i++) { - adev->vcn.inst[i].adev = adev; - adev->vcn.inst[i].inst = i; - if (i == 1 && amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(4, 0, 6)) - r = amdgpu_ucode_request(adev, &adev->vcn.inst[i].fw, - AMDGPU_UCODE_REQUIRED, - "amdgpu/%s_%d.bin", ucode_prefix, i); - else - r = amdgpu_ucode_request(adev, &adev->vcn.inst[i].fw, - AMDGPU_UCODE_REQUIRED, - "amdgpu/%s.bin", ucode_prefix); - if (r) { - amdgpu_ucode_release(&adev->vcn.inst[i].fw); - return r; - } + if (i == 1 && amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(4, 0, 6)) + r = amdgpu_ucode_request(adev, &adev->vcn.inst[i].fw, + AMDGPU_UCODE_REQUIRED, + "amdgpu/%s_%d.bin", ucode_prefix, i); + else + r = amdgpu_ucode_request(adev, &adev->vcn.inst[i].fw, + AMDGPU_UCODE_REQUIRED, + "amdgpu/%s.bin", ucode_prefix); + if (r) { + amdgpu_ucode_release(&adev->vcn.inst[i].fw); + return r; } return r; } -int amdgpu_vcn_sw_init(struct amdgpu_device *adev) +int amdgpu_vcn_sw_init(struct amdgpu_device *adev, int i) { unsigned long bo_size; const struct common_firmware_header *hdr; unsigned char fw_check; unsigned int fw_shared_size, log_offset; - int i, r; + int r; - for (i = 0; i < adev->vcn.num_vcn_inst; i++) { - mutex_init(&adev->vcn.inst[i].vcn1_jpeg1_workaround); - mutex_init(&adev->vcn.inst[i].vcn_pg_lock); - atomic_set(&adev->vcn.inst[i].total_submission_cnt, 0); - INIT_DELAYED_WORK(&adev->vcn.inst[i].idle_work, amdgpu_vcn_idle_work_handler); - atomic_set(&adev->vcn.inst[i].dpg_enc_submission_cnt, 0); - if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) && - (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)) - adev->vcn.inst[i].indirect_sram = true; + mutex_init(&adev->vcn.inst[i].vcn1_jpeg1_workaround); + mutex_init(&adev->vcn.inst[i].vcn_pg_lock); + atomic_set(&adev->vcn.inst[i].total_submission_cnt, 0); + INIT_DELAYED_WORK(&adev->vcn.inst[i].idle_work, amdgpu_vcn_idle_work_handler); + atomic_set(&adev->vcn.inst[i].dpg_enc_submission_cnt, 0); + if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) && + (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)) + adev->vcn.inst[i].indirect_sram = true; - /* - * Some Steam Deck's BIOS versions are incompatible with the - * indirect SRAM mode, leading to amdgpu being unable to get - * properly probed (and even potentially crashing the kernel). - * Hence, check for these versions here - notice this is - * restricted to Vangogh (Deck's APU). - */ - if (amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(3, 0, 2)) { - const char *bios_ver = dmi_get_system_info(DMI_BIOS_VERSION); + /* + * Some Steam Deck's BIOS versions are incompatible with the + * indirect SRAM mode, leading to amdgpu being unable to get + * properly probed (and even potentially crashing the kernel). + * Hence, check for these versions here - notice this is + * restricted to Vangogh (Deck's APU). + */ + if (amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(3, 0, 2)) { + const char *bios_ver = dmi_get_system_info(DMI_BIOS_VERSION); - if (bios_ver && (!strncmp("F7A0113", bios_ver, 7) || - !strncmp("F7A0114", bios_ver, 7))) { - adev->vcn.inst[i].indirect_sram = false; - dev_info(adev->dev, - "Steam Deck quirk: indirect SRAM disabled on BIOS %s\n", bios_ver); - } + if (bios_ver && (!strncmp("F7A0113", bios_ver, 7) || + !strncmp("F7A0114", bios_ver, 7))) { + adev->vcn.inst[i].indirect_sram = false; + dev_info(adev->dev, + "Steam Deck quirk: indirect SRAM disabled on BIOS %s\n", bios_ver); } + } - /* from vcn4 and above, only unified queue is used */ - adev->vcn.inst[i].using_unified_queue = - amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0); + /* from vcn4 and above, only unified queue is used */ + adev->vcn.inst[i].using_unified_queue = + amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0); - hdr = (const struct common_firmware_header *)adev->vcn.inst[i].fw->data; - adev->vcn.inst[i].fw_version = le32_to_cpu(hdr->ucode_version); - adev->vcn.fw_version = le32_to_cpu(hdr->ucode_version); + hdr = (const struct common_firmware_header *)adev->vcn.inst[i].fw->data; + adev->vcn.inst[i].fw_version = le32_to_cpu(hdr->ucode_version); + adev->vcn.fw_version = le32_to_cpu(hdr->ucode_version); - /* Bit 20-23, it is encode major and non-zero for new naming convention. - * This field is part of version minor and DRM_DISABLED_FLAG in old naming - * convention. Since the l:wq!atest version minor is 0x5B and DRM_DISABLED_FLAG - * is zero in old naming convention, this field is always zero so far. - * These four bits are used to tell which naming convention is present. - */ - fw_check = (le32_to_cpu(hdr->ucode_version) >> 20) & 0xf; - if (fw_check) { - unsigned int dec_ver, enc_major, enc_minor, vep, fw_rev; + /* Bit 20-23, it is encode major and non-zero for new naming convention. + * This field is part of version minor and DRM_DISABLED_FLAG in old naming + * convention. Since the l:wq!atest version minor is 0x5B and DRM_DISABLED_FLAG + * is zero in old naming convention, this field is always zero so far. + * These four bits are used to tell which naming convention is present. + */ + fw_check = (le32_to_cpu(hdr->ucode_version) >> 20) & 0xf; + if (fw_check) { + unsigned int dec_ver, enc_major, enc_minor, vep, fw_rev; - fw_rev = le32_to_cpu(hdr->ucode_version) & 0xfff; - enc_minor = (le32_to_cpu(hdr->ucode_version) >> 12) & 0xff; - enc_major = fw_check; - dec_ver = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xf; - vep = (le32_to_cpu(hdr->ucode_version) >> 28) & 0xf; - DRM_INFO("Found VCN firmware Version ENC: %u.%u DEC: %u VEP: %u Revision: %u\n", - enc_major, enc_minor, dec_ver, vep, fw_rev); - } else { - unsigned int version_major, version_minor, family_id; + fw_rev = le32_to_cpu(hdr->ucode_version) & 0xfff; + enc_minor = (le32_to_cpu(hdr->ucode_version) >> 12) & 0xff; + enc_major = fw_check; + dec_ver = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xf; + vep = (le32_to_cpu(hdr->ucode_version) >> 28) & 0xf; + DRM_INFO("Found VCN firmware Version ENC: %u.%u DEC: %u VEP: %u Revision: %u\n", + enc_major, enc_minor, dec_ver, vep, fw_rev); + } else { + unsigned int version_major, version_minor, family_id; - family_id = le32_to_cpu(hdr->ucode_version) & 0xff; - version_major = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xff; - version_minor = (le32_to_cpu(hdr->ucode_version) >> 8) & 0xff; - DRM_INFO("Found VCN firmware Version: %u.%u Family ID: %u\n", - version_major, version_minor, family_id); - } + family_id = le32_to_cpu(hdr->ucode_version) & 0xff; + version_major = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xff; + version_minor = (le32_to_cpu(hdr->ucode_version) >> 8) & 0xff; + DRM_INFO("Found VCN firmware Version: %u.%u Family ID: %u\n", + version_major, version_minor, family_id); + } - bo_size = AMDGPU_VCN_STACK_SIZE + AMDGPU_VCN_CONTEXT_SIZE; - if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) - bo_size += AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8); + bo_size = AMDGPU_VCN_STACK_SIZE + AMDGPU_VCN_CONTEXT_SIZE; + if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) + bo_size += AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8); - if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(5, 0, 0)) { - fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn5_fw_shared)); - log_offset = offsetof(struct amdgpu_vcn5_fw_shared, fw_log); - } else if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0)) { - fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn4_fw_shared)); - log_offset = offsetof(struct amdgpu_vcn4_fw_shared, fw_log); - } else { - fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_fw_shared)); - log_offset = offsetof(struct amdgpu_fw_shared, fw_log); - } + if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(5, 0, 0)) { + fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn5_fw_shared)); + log_offset = offsetof(struct amdgpu_vcn5_fw_shared, fw_log); + } else if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0)) { + fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn4_fw_shared)); + log_offset = offsetof(struct amdgpu_vcn4_fw_shared, fw_log); + } else { + fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_fw_shared)); + log_offset = offsetof(struct amdgpu_fw_shared, fw_log); + } - bo_size += fw_shared_size; + bo_size += fw_shared_size; - if (amdgpu_vcnfw_log) - bo_size += AMDGPU_VCNFW_LOG_SIZE; + if (amdgpu_vcnfw_log) + bo_size += AMDGPU_VCNFW_LOG_SIZE; - r = amdgpu_bo_create_kernel(adev, bo_size, PAGE_SIZE, + r = amdgpu_bo_create_kernel(adev, bo_size, PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM | + AMDGPU_GEM_DOMAIN_GTT, + &adev->vcn.inst[i].vcpu_bo, + &adev->vcn.inst[i].gpu_addr, + &adev->vcn.inst[i].cpu_addr); + if (r) { + dev_err(adev->dev, "(%d) failed to allocate vcn bo\n", r); + return r; + } + + adev->vcn.inst[i].fw_shared.cpu_addr = adev->vcn.inst[i].cpu_addr + + bo_size - fw_shared_size; + adev->vcn.inst[i].fw_shared.gpu_addr = adev->vcn.inst[i].gpu_addr + + bo_size - fw_shared_size; + + adev->vcn.inst[i].fw_shared.mem_size = fw_shared_size; + + if (amdgpu_vcnfw_log) { + adev->vcn.inst[i].fw_shared.cpu_addr -= AMDGPU_VCNFW_LOG_SIZE; + adev->vcn.inst[i].fw_shared.gpu_addr -= AMDGPU_VCNFW_LOG_SIZE; + adev->vcn.inst[i].fw_shared.log_offset = log_offset; + } + + if (adev->vcn.inst[i].indirect_sram) { + r = amdgpu_bo_create_kernel(adev, 64 * 2 * 4, PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM | AMDGPU_GEM_DOMAIN_GTT, - &adev->vcn.inst[i].vcpu_bo, - &adev->vcn.inst[i].gpu_addr, - &adev->vcn.inst[i].cpu_addr); + &adev->vcn.inst[i].dpg_sram_bo, + &adev->vcn.inst[i].dpg_sram_gpu_addr, + &adev->vcn.inst[i].dpg_sram_cpu_addr); if (r) { - dev_err(adev->dev, "(%d) failed to allocate vcn bo\n", r); + dev_err(adev->dev, "VCN %d (%d) failed to allocate DPG bo\n", i, r); return r; } - - adev->vcn.inst[i].fw_shared.cpu_addr = adev->vcn.inst[i].cpu_addr + - bo_size - fw_shared_size; - adev->vcn.inst[i].fw_shared.gpu_addr = adev->vcn.inst[i].gpu_addr + - bo_size - fw_shared_size; - - adev->vcn.inst[i].fw_shared.mem_size = fw_shared_size; - - if (amdgpu_vcnfw_log) { - adev->vcn.inst[i].fw_shared.cpu_addr -= AMDGPU_VCNFW_LOG_SIZE; - adev->vcn.inst[i].fw_shared.gpu_addr -= AMDGPU_VCNFW_LOG_SIZE; - adev->vcn.inst[i].fw_shared.log_offset = log_offset; - } - - if (adev->vcn.inst[i].indirect_sram) { - r = amdgpu_bo_create_kernel(adev, 64 * 2 * 4, PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM | - AMDGPU_GEM_DOMAIN_GTT, - &adev->vcn.inst[i].dpg_sram_bo, - &adev->vcn.inst[i].dpg_sram_gpu_addr, - &adev->vcn.inst[i].dpg_sram_cpu_addr); - if (r) { - dev_err(adev->dev, "VCN %d (%d) failed to allocate DPG bo\n", i, r); - return r; - } - } } return 0; } -int amdgpu_vcn_sw_fini(struct amdgpu_device *adev) +int amdgpu_vcn_sw_fini(struct amdgpu_device *adev, int i) { - int i, j; + int j; - for (j = 0; j < adev->vcn.num_vcn_inst; ++j) { - if (adev->vcn.harvest_config & (1 << j)) - continue; + if (adev->vcn.harvest_config & (1 << i)) + return 0; - amdgpu_bo_free_kernel( - &adev->vcn.inst[j].dpg_sram_bo, - &adev->vcn.inst[j].dpg_sram_gpu_addr, - (void **)&adev->vcn.inst[j].dpg_sram_cpu_addr); + amdgpu_bo_free_kernel( + &adev->vcn.inst[i].dpg_sram_bo, + &adev->vcn.inst[i].dpg_sram_gpu_addr, + (void **)&adev->vcn.inst[i].dpg_sram_cpu_addr); - kvfree(adev->vcn.inst[j].saved_bo); + kvfree(adev->vcn.inst[i].saved_bo); - amdgpu_bo_free_kernel(&adev->vcn.inst[j].vcpu_bo, - &adev->vcn.inst[j].gpu_addr, - (void **)&adev->vcn.inst[j].cpu_addr); + amdgpu_bo_free_kernel(&adev->vcn.inst[i].vcpu_bo, + &adev->vcn.inst[i].gpu_addr, + (void **)&adev->vcn.inst[i].cpu_addr); - amdgpu_ring_fini(&adev->vcn.inst[j].ring_dec); + amdgpu_ring_fini(&adev->vcn.inst[i].ring_dec); - for (i = 0; i < adev->vcn.inst[j].num_enc_rings; ++i) - amdgpu_ring_fini(&adev->vcn.inst[j].ring_enc[i]); + for (j = 0; j < adev->vcn.inst[i].num_enc_rings; ++j) + amdgpu_ring_fini(&adev->vcn.inst[i].ring_enc[j]); - amdgpu_ucode_release(&adev->vcn.inst[j].fw); - mutex_destroy(&adev->vcn.inst[j].vcn_pg_lock); - mutex_destroy(&adev->vcn.inst[j].vcn1_jpeg1_workaround); - } + amdgpu_ucode_release(&adev->vcn.inst[i].fw); + mutex_destroy(&adev->vcn.inst[i].vcn_pg_lock); + mutex_destroy(&adev->vcn.inst[i].vcn1_jpeg1_workaround); return 0; } @@ -298,91 +292,102 @@ bool amdgpu_vcn_is_disabled_vcn(struct amdgpu_device *adev, enum vcn_ring_type t return ret; } -int amdgpu_vcn_save_vcpu_bo(struct amdgpu_device *adev) +static int amdgpu_vcn_save_vcpu_bo_inst(struct amdgpu_device *adev, int i) { unsigned int size; void *ptr; - int i, idx; + int idx; - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { - if (adev->vcn.harvest_config & (1 << i)) - continue; - if (adev->vcn.inst[i].vcpu_bo == NULL) - return 0; + if (adev->vcn.harvest_config & (1 << i)) + return 0; + if (adev->vcn.inst[i].vcpu_bo == NULL) + return 0; - size = amdgpu_bo_size(adev->vcn.inst[i].vcpu_bo); - ptr = adev->vcn.inst[i].cpu_addr; + size = amdgpu_bo_size(adev->vcn.inst[i].vcpu_bo); + ptr = adev->vcn.inst[i].cpu_addr; - adev->vcn.inst[i].saved_bo = kvmalloc(size, GFP_KERNEL); - if (!adev->vcn.inst[i].saved_bo) - return -ENOMEM; + adev->vcn.inst[i].saved_bo = kvmalloc(size, GFP_KERNEL); + if (!adev->vcn.inst[i].saved_bo) + return -ENOMEM; - if (drm_dev_enter(adev_to_drm(adev), &idx)) { - memcpy_fromio(adev->vcn.inst[i].saved_bo, ptr, size); - drm_dev_exit(idx); - } + if (drm_dev_enter(adev_to_drm(adev), &idx)) { + memcpy_fromio(adev->vcn.inst[i].saved_bo, ptr, size); + drm_dev_exit(idx); } return 0; } -int amdgpu_vcn_suspend(struct amdgpu_device *adev) +int amdgpu_vcn_save_vcpu_bo(struct amdgpu_device *adev) +{ + int ret, i; + + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { + ret = amdgpu_vcn_save_vcpu_bo_inst(adev, i); + if (ret) + return ret; + } + + return 0; +} + +int amdgpu_vcn_suspend(struct amdgpu_device *adev, int i) { bool in_ras_intr = amdgpu_ras_intr_triggered(); - int i; - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) - cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work); + if (adev->vcn.harvest_config & (1 << i)) + return 0; + + cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work); /* err_event_athub will corrupt VCPU buffer, so we need to * restore fw data and clear buffer in amdgpu_vcn_resume() */ if (in_ras_intr) return 0; - return amdgpu_vcn_save_vcpu_bo(adev); + return amdgpu_vcn_save_vcpu_bo_inst(adev, i); } -int amdgpu_vcn_resume(struct amdgpu_device *adev) +int amdgpu_vcn_resume(struct amdgpu_device *adev, int i) { unsigned int size; void *ptr; - int i, idx; + int idx; - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { - if (adev->vcn.harvest_config & (1 << i)) - continue; - if (adev->vcn.inst[i].vcpu_bo == NULL) - return -EINVAL; + if (adev->vcn.harvest_config & (1 << i)) + return 0; + if (adev->vcn.inst[i].vcpu_bo == NULL) + return -EINVAL; - size = amdgpu_bo_size(adev->vcn.inst[i].vcpu_bo); - ptr = adev->vcn.inst[i].cpu_addr; + size = amdgpu_bo_size(adev->vcn.inst[i].vcpu_bo); + ptr = adev->vcn.inst[i].cpu_addr; - if (adev->vcn.inst[i].saved_bo != NULL) { + if (adev->vcn.inst[i].saved_bo != NULL) { + if (drm_dev_enter(adev_to_drm(adev), &idx)) { + memcpy_toio(ptr, adev->vcn.inst[i].saved_bo, size); + drm_dev_exit(idx); + } + kvfree(adev->vcn.inst[i].saved_bo); + adev->vcn.inst[i].saved_bo = NULL; + } else { + const struct common_firmware_header *hdr; + unsigned int offset; + + hdr = (const struct common_firmware_header *)adev->vcn.inst[i].fw->data; + if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) { + offset = le32_to_cpu(hdr->ucode_array_offset_bytes); if (drm_dev_enter(adev_to_drm(adev), &idx)) { - memcpy_toio(ptr, adev->vcn.inst[i].saved_bo, size); + memcpy_toio(adev->vcn.inst[i].cpu_addr, + adev->vcn.inst[i].fw->data + offset, + le32_to_cpu(hdr->ucode_size_bytes)); drm_dev_exit(idx); } - kvfree(adev->vcn.inst[i].saved_bo); - adev->vcn.inst[i].saved_bo = NULL; - } else { - const struct common_firmware_header *hdr; - unsigned int offset; - - hdr = (const struct common_firmware_header *)adev->vcn.inst[i].fw->data; - if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) { - offset = le32_to_cpu(hdr->ucode_array_offset_bytes); - if (drm_dev_enter(adev_to_drm(adev), &idx)) { - memcpy_toio(adev->vcn.inst[i].cpu_addr, - adev->vcn.inst[i].fw->data + offset, - le32_to_cpu(hdr->ucode_size_bytes)); - drm_dev_exit(idx); - } - size -= le32_to_cpu(hdr->ucode_size_bytes); - ptr += le32_to_cpu(hdr->ucode_size_bytes); - } - memset_io(ptr, 0, size); + size -= le32_to_cpu(hdr->ucode_size_bytes); + ptr += le32_to_cpu(hdr->ucode_size_bytes); } + memset_io(ptr, 0, size); } + return 0; } @@ -1058,36 +1063,32 @@ enum amdgpu_ring_priority_level amdgpu_vcn_get_enc_ring_prio(int ring) } } -void amdgpu_vcn_setup_ucode(struct amdgpu_device *adev) +void amdgpu_vcn_setup_ucode(struct amdgpu_device *adev, int i) { - int i; unsigned int idx; if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) { const struct common_firmware_header *hdr; - for (i = 0; i < adev->vcn.num_vcn_inst; i++) { - if (adev->vcn.harvest_config & (1 << i)) - continue; + if (adev->vcn.harvest_config & (1 << i)) + return; - hdr = (const struct common_firmware_header *)adev->vcn.inst[i].fw->data; - /* currently only support 2 FW instances */ - if (i >= 2) { - dev_info(adev->dev, "More then 2 VCN FW instances!\n"); - break; - } - idx = AMDGPU_UCODE_ID_VCN + i; - adev->firmware.ucode[idx].ucode_id = idx; - adev->firmware.ucode[idx].fw = adev->vcn.inst[i].fw; - adev->firmware.fw_size += - ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE); + if ((amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(4, 0, 3) || + amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(5, 0, 1)) + && (i > 0)) + return; - if (amdgpu_ip_version(adev, UVD_HWIP, 0) == - IP_VERSION(4, 0, 3) || - amdgpu_ip_version(adev, UVD_HWIP, 0) == - IP_VERSION(5, 0, 1)) - break; + hdr = (const struct common_firmware_header *)adev->vcn.inst[i].fw->data; + /* currently only support 2 FW instances */ + if (i >= 2) { + dev_info(adev->dev, "More then 2 VCN FW instances!\n"); + return; } + idx = AMDGPU_UCODE_ID_VCN + i; + adev->firmware.ucode[idx].ucode_id = idx; + adev->firmware.ucode[idx].fw = adev->vcn.inst[i].fw; + adev->firmware.fw_size += + ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE); } } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h index 3b059f51894b..5f92cf28cc75 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h @@ -503,11 +503,11 @@ enum vcn_ring_type { VCN_UNIFIED_RING, }; -int amdgpu_vcn_early_init(struct amdgpu_device *adev); -int amdgpu_vcn_sw_init(struct amdgpu_device *adev); -int amdgpu_vcn_sw_fini(struct amdgpu_device *adev); -int amdgpu_vcn_suspend(struct amdgpu_device *adev); -int amdgpu_vcn_resume(struct amdgpu_device *adev); +int amdgpu_vcn_early_init(struct amdgpu_device *adev, int i); +int amdgpu_vcn_sw_init(struct amdgpu_device *adev, int i); +int amdgpu_vcn_sw_fini(struct amdgpu_device *adev, int i); +int amdgpu_vcn_suspend(struct amdgpu_device *adev, int i); +int amdgpu_vcn_resume(struct amdgpu_device *adev, int i); void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring); void amdgpu_vcn_ring_end_use(struct amdgpu_ring *ring); @@ -525,7 +525,7 @@ int amdgpu_vcn_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout); enum amdgpu_ring_priority_level amdgpu_vcn_get_enc_ring_prio(int ring); -void amdgpu_vcn_setup_ucode(struct amdgpu_device *adev); +void amdgpu_vcn_setup_ucode(struct amdgpu_device *adev, int i); void amdgpu_vcn_fwlog_init(struct amdgpu_vcn_inst *vcn); void amdgpu_debugfs_vcn_fwlog_init(struct amdgpu_device *adev, diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c index edbcd0819d17..49542d947727 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c @@ -113,7 +113,7 @@ static int vcn_v1_0_early_init(struct amdgpu_ip_block *ip_block) jpeg_v1_0_early_init(ip_block); - return amdgpu_vcn_early_init(adev); + return amdgpu_vcn_early_init(adev, 0); } /** @@ -145,16 +145,16 @@ static int vcn_v1_0_sw_init(struct amdgpu_ip_block *ip_block) return r; } - r = amdgpu_vcn_sw_init(adev); + r = amdgpu_vcn_sw_init(adev, 0); if (r) return r; /* Override the work func */ adev->vcn.inst[0].idle_work.work.func = vcn_v1_0_idle_work_handler; - amdgpu_vcn_setup_ucode(adev); + amdgpu_vcn_setup_ucode(adev, 0); - r = amdgpu_vcn_resume(adev); + r = amdgpu_vcn_resume(adev, 0); if (r) return r; @@ -223,13 +223,13 @@ static int vcn_v1_0_sw_fini(struct amdgpu_ip_block *ip_block) int r; struct amdgpu_device *adev = ip_block->adev; - r = amdgpu_vcn_suspend(adev); + r = amdgpu_vcn_suspend(adev, 0); if (r) return r; jpeg_v1_0_sw_fini(ip_block); - r = amdgpu_vcn_sw_fini(adev); + r = amdgpu_vcn_sw_fini(adev, 0); kfree(adev->vcn.ip_dump); @@ -311,7 +311,7 @@ static int vcn_v1_0_suspend(struct amdgpu_ip_block *ip_block) if (r) return r; - r = amdgpu_vcn_suspend(adev); + r = amdgpu_vcn_suspend(adev, 0); return r; } @@ -327,7 +327,7 @@ static int vcn_v1_0_resume(struct amdgpu_ip_block *ip_block) { int r; - r = amdgpu_vcn_resume(ip_block->adev); + r = amdgpu_vcn_resume(ip_block->adev, 0); if (r) return r; diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c index d94fd075a910..5f537d2a5618 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c @@ -118,7 +118,7 @@ static int vcn_v2_0_early_init(struct amdgpu_ip_block *ip_block) vcn_v2_0_set_enc_ring_funcs(adev); vcn_v2_0_set_irq_funcs(adev); - return amdgpu_vcn_early_init(adev); + return amdgpu_vcn_early_init(adev, 0); } /** @@ -153,13 +153,13 @@ static int vcn_v2_0_sw_init(struct amdgpu_ip_block *ip_block) return r; } - r = amdgpu_vcn_sw_init(adev); + r = amdgpu_vcn_sw_init(adev, 0); if (r) return r; - amdgpu_vcn_setup_ucode(adev); + amdgpu_vcn_setup_ucode(adev, 0); - r = amdgpu_vcn_resume(adev); + r = amdgpu_vcn_resume(adev, 0); if (r) return r; @@ -254,11 +254,11 @@ static int vcn_v2_0_sw_fini(struct amdgpu_ip_block *ip_block) amdgpu_virt_free_mm_table(adev); - r = amdgpu_vcn_suspend(adev); + r = amdgpu_vcn_suspend(adev, 0); if (r) return r; - r = amdgpu_vcn_sw_fini(adev); + r = amdgpu_vcn_sw_fini(adev, 0); kfree(adev->vcn.ip_dump); @@ -338,7 +338,7 @@ static int vcn_v2_0_suspend(struct amdgpu_ip_block *ip_block) if (r) return r; - r = amdgpu_vcn_suspend(ip_block->adev); + r = amdgpu_vcn_suspend(ip_block->adev, 0); return r; } @@ -354,7 +354,7 @@ static int vcn_v2_0_resume(struct amdgpu_ip_block *ip_block) { int r; - r = amdgpu_vcn_resume(ip_block->adev); + r = amdgpu_vcn_resume(ip_block->adev, 0); if (r) return r; diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c index c20619c027e7..3ee00dc6d533 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c @@ -121,7 +121,7 @@ static int amdgpu_ih_clientid_vcns[] = { static int vcn_v2_5_early_init(struct amdgpu_ip_block *ip_block) { struct amdgpu_device *adev = ip_block->adev; - int i; + int i, r; if (amdgpu_sriov_vf(adev)) { adev->vcn.num_vcn_inst = 2; @@ -139,7 +139,7 @@ static int vcn_v2_5_early_init(struct amdgpu_ip_block *ip_block) adev->vcn.inst[i].num_enc_rings = 2; } if (adev->vcn.harvest_config == (AMDGPU_VCN_HARVEST_VCN0 | - AMDGPU_VCN_HARVEST_VCN1)) + AMDGPU_VCN_HARVEST_VCN1)) /* both instances are harvested, disable the block */ return -ENOENT; } @@ -149,7 +149,13 @@ static int vcn_v2_5_early_init(struct amdgpu_ip_block *ip_block) vcn_v2_5_set_irq_funcs(adev); vcn_v2_5_set_ras_funcs(adev); - return amdgpu_vcn_early_init(adev); + for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + r = amdgpu_vcn_early_init(adev, i); + if (r) + return r; + } + + return 0; } /** @@ -168,6 +174,8 @@ static int vcn_v2_5_sw_init(struct amdgpu_ip_block *ip_block) struct amdgpu_device *adev = ip_block->adev; for (j = 0; j < adev->vcn.num_vcn_inst; j++) { + volatile struct amdgpu_fw_shared *fw_shared; + if (adev->vcn.harvest_config & (1 << j)) continue; /* VCN DEC TRAP */ @@ -189,23 +197,17 @@ static int vcn_v2_5_sw_init(struct amdgpu_ip_block *ip_block) VCN_2_6__SRCID_UVD_POISON, &adev->vcn.inst[j].ras_poison_irq); if (r) return r; - } - r = amdgpu_vcn_sw_init(adev); - if (r) - return r; + r = amdgpu_vcn_sw_init(adev, j); + if (r) + return r; - amdgpu_vcn_setup_ucode(adev); + amdgpu_vcn_setup_ucode(adev, j); - r = amdgpu_vcn_resume(adev); - if (r) - return r; + r = amdgpu_vcn_resume(adev, j); + if (r) + return r; - for (j = 0; j < adev->vcn.num_vcn_inst; j++) { - volatile struct amdgpu_fw_shared *fw_shared; - - if (adev->vcn.harvest_config & (1 << j)) - continue; adev->vcn.inst[j].internal.context_id = mmUVD_CONTEXT_ID_INTERNAL_OFFSET; adev->vcn.inst[j].internal.ib_vmid = mmUVD_LMI_RBC_IB_VMID_INTERNAL_OFFSET; adev->vcn.inst[j].internal.ib_bar_low = mmUVD_LMI_RBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET; @@ -323,15 +325,18 @@ static int vcn_v2_5_sw_fini(struct amdgpu_ip_block *ip_block) if (amdgpu_sriov_vf(adev)) amdgpu_virt_free_mm_table(adev); - r = amdgpu_vcn_suspend(adev); - if (r) - return r; - - r = amdgpu_vcn_sw_fini(adev); + for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + r = amdgpu_vcn_suspend(adev, i); + if (r) + return r; + r = amdgpu_vcn_sw_fini(adev, i); + if (r) + return r; + } kfree(adev->vcn.ip_dump); - return r; + return 0; } /** @@ -421,15 +426,20 @@ static int vcn_v2_5_hw_fini(struct amdgpu_ip_block *ip_block) */ static int vcn_v2_5_suspend(struct amdgpu_ip_block *ip_block) { - int r; + struct amdgpu_device *adev = ip_block->adev; + int r, i; r = vcn_v2_5_hw_fini(ip_block); if (r) return r; - r = amdgpu_vcn_suspend(ip_block->adev); + for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + r = amdgpu_vcn_suspend(ip_block->adev, i); + if (r) + return r; + } - return r; + return 0; } /** @@ -441,11 +451,14 @@ static int vcn_v2_5_suspend(struct amdgpu_ip_block *ip_block) */ static int vcn_v2_5_resume(struct amdgpu_ip_block *ip_block) { - int r; + struct amdgpu_device *adev = ip_block->adev; + int r, i; - r = amdgpu_vcn_resume(ip_block->adev); - if (r) - return r; + for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + r = amdgpu_vcn_resume(ip_block->adev, i); + if (r) + return r; + } r = vcn_v2_5_hw_init(ip_block); diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c index 282a186cb0c5..6052e963fcab 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c @@ -127,7 +127,7 @@ static void vcn_v3_0_enc_ring_set_wptr(struct amdgpu_ring *ring); static int vcn_v3_0_early_init(struct amdgpu_ip_block *ip_block) { struct amdgpu_device *adev = ip_block->adev; - int i; + int i, r; if (amdgpu_sriov_vf(adev)) { adev->vcn.num_vcn_inst = VCN_INSTANCES_SIENNA_CICHLID; @@ -154,7 +154,12 @@ static int vcn_v3_0_early_init(struct amdgpu_ip_block *ip_block) vcn_v3_0_set_enc_ring_funcs(adev); vcn_v3_0_set_irq_funcs(adev); - return amdgpu_vcn_early_init(adev); + for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + r = amdgpu_vcn_early_init(adev, i); + if (r) + return r; + } + return 0; } /** @@ -173,16 +178,6 @@ static int vcn_v3_0_sw_init(struct amdgpu_ip_block *ip_block) uint32_t *ptr; struct amdgpu_device *adev = ip_block->adev; - r = amdgpu_vcn_sw_init(adev); - if (r) - return r; - - amdgpu_vcn_setup_ucode(adev); - - r = amdgpu_vcn_resume(adev); - if (r) - return r; - /* * Note: doorbell assignment is fixed for SRIOV multiple VCN engines * Formula: @@ -202,6 +197,16 @@ static int vcn_v3_0_sw_init(struct amdgpu_ip_block *ip_block) if (adev->vcn.harvest_config & (1 << i)) continue; + r = amdgpu_vcn_sw_init(adev, i); + if (r) + return r; + + amdgpu_vcn_setup_ucode(adev, i); + + r = amdgpu_vcn_resume(adev, i); + if (r) + return r; + adev->vcn.inst[i].internal.context_id = mmUVD_CONTEXT_ID_INTERNAL_OFFSET; adev->vcn.inst[i].internal.ib_vmid = mmUVD_LMI_RBC_IB_VMID_INTERNAL_OFFSET; adev->vcn.inst[i].internal.ib_bar_low = mmUVD_LMI_RBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET; @@ -333,14 +338,18 @@ static int vcn_v3_0_sw_fini(struct amdgpu_ip_block *ip_block) if (amdgpu_sriov_vf(adev)) amdgpu_virt_free_mm_table(adev); - r = amdgpu_vcn_suspend(adev); - if (r) - return r; + for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + r = amdgpu_vcn_suspend(adev, i); + if (r) + return r; - r = amdgpu_vcn_sw_fini(adev); + r = amdgpu_vcn_sw_fini(adev, i); + if (r) + return r; + } kfree(adev->vcn.ip_dump); - return r; + return 0; } /** @@ -459,15 +468,20 @@ static int vcn_v3_0_hw_fini(struct amdgpu_ip_block *ip_block) */ static int vcn_v3_0_suspend(struct amdgpu_ip_block *ip_block) { - int r; + struct amdgpu_device *adev = ip_block->adev; + int r, i; r = vcn_v3_0_hw_fini(ip_block); if (r) return r; - r = amdgpu_vcn_suspend(ip_block->adev); + for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + r = amdgpu_vcn_suspend(ip_block->adev, i); + if (r) + return r; + } - return r; + return 0; } /** @@ -479,11 +493,14 @@ static int vcn_v3_0_suspend(struct amdgpu_ip_block *ip_block) */ static int vcn_v3_0_resume(struct amdgpu_ip_block *ip_block) { - int r; + struct amdgpu_device *adev = ip_block->adev; + int r, i; - r = amdgpu_vcn_resume(ip_block->adev); - if (r) - return r; + for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + r = amdgpu_vcn_resume(ip_block->adev, i); + if (r) + return r; + } r = vcn_v3_0_hw_init(ip_block); diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c index f5bb241c1af1..8c7566960a3b 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c @@ -117,7 +117,7 @@ static void vcn_v4_0_set_ras_funcs(struct amdgpu_device *adev); static int vcn_v4_0_early_init(struct amdgpu_ip_block *ip_block) { struct amdgpu_device *adev = ip_block->adev; - int i; + int i, r; if (amdgpu_sriov_vf(adev)) { adev->vcn.harvest_config = VCN_HARVEST_MMSCH; @@ -137,7 +137,13 @@ static int vcn_v4_0_early_init(struct amdgpu_ip_block *ip_block) vcn_v4_0_set_irq_funcs(adev); vcn_v4_0_set_ras_funcs(adev); - return amdgpu_vcn_early_init(adev); + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { + r = amdgpu_vcn_early_init(adev, i); + if (r) + return r; + } + + return 0; } static int vcn_v4_0_fw_shared_init(struct amdgpu_device *adev, int inst_idx) @@ -180,20 +186,20 @@ static int vcn_v4_0_sw_init(struct amdgpu_ip_block *ip_block) uint32_t reg_count = ARRAY_SIZE(vcn_reg_list_4_0); uint32_t *ptr; - r = amdgpu_vcn_sw_init(adev); - if (r) - return r; - - amdgpu_vcn_setup_ucode(adev); - - r = amdgpu_vcn_resume(adev); - if (r) - return r; - for (i = 0; i < adev->vcn.num_vcn_inst; i++) { if (adev->vcn.harvest_config & (1 << i)) continue; + r = amdgpu_vcn_sw_init(adev, i); + if (r) + return r; + + amdgpu_vcn_setup_ucode(adev, i); + + r = amdgpu_vcn_resume(adev, i); + if (r) + return r; + /* Init instance 0 sched_score to 1, so it's scheduled after other instances */ if (i == 0) atomic_set(&adev->vcn.inst[i].sched_score, 1); @@ -294,16 +300,23 @@ static int vcn_v4_0_sw_fini(struct amdgpu_ip_block *ip_block) if (amdgpu_sriov_vf(adev)) amdgpu_virt_free_mm_table(adev); - r = amdgpu_vcn_suspend(adev); - if (r) - return r; + for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + r = amdgpu_vcn_suspend(adev, i); + if (r) + return r; + } amdgpu_vcn_sysfs_reset_mask_fini(adev); - r = amdgpu_vcn_sw_fini(adev); + + for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + r = amdgpu_vcn_sw_fini(adev, i); + if (r) + return r; + } kfree(adev->vcn.ip_dump); - return r; + return 0; } /** @@ -394,15 +407,20 @@ static int vcn_v4_0_hw_fini(struct amdgpu_ip_block *ip_block) */ static int vcn_v4_0_suspend(struct amdgpu_ip_block *ip_block) { - int r; + struct amdgpu_device *adev = ip_block->adev; + int r, i; r = vcn_v4_0_hw_fini(ip_block); if (r) return r; - r = amdgpu_vcn_suspend(ip_block->adev); + for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + r = amdgpu_vcn_suspend(ip_block->adev, i); + if (r) + return r; + } - return r; + return 0; } /** @@ -414,11 +432,14 @@ static int vcn_v4_0_suspend(struct amdgpu_ip_block *ip_block) */ static int vcn_v4_0_resume(struct amdgpu_ip_block *ip_block) { - int r; + struct amdgpu_device *adev = ip_block->adev; + int r, i; - r = amdgpu_vcn_resume(ip_block->adev); - if (r) - return r; + for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + r = amdgpu_vcn_resume(ip_block->adev, i); + if (r) + return r; + } r = vcn_v4_0_hw_init(ip_block); diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c index fbe599c539c8..a0b848ad097b 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c @@ -114,7 +114,7 @@ static inline bool vcn_v4_0_3_normalizn_reqd(struct amdgpu_device *adev) static int vcn_v4_0_3_early_init(struct amdgpu_ip_block *ip_block) { struct amdgpu_device *adev = ip_block->adev; - int i; + int i, r; for (i = 0; i < adev->vcn.num_vcn_inst; ++i) /* re-use enc ring as unified ring */ @@ -124,7 +124,13 @@ static int vcn_v4_0_3_early_init(struct amdgpu_ip_block *ip_block) vcn_v4_0_3_set_irq_funcs(adev); vcn_v4_0_3_set_ras_funcs(adev); - return amdgpu_vcn_early_init(adev); + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { + r = amdgpu_vcn_early_init(adev, i); + if (r) + return r; + } + + return 0; } static int vcn_v4_0_3_fw_shared_init(struct amdgpu_device *adev, int inst_idx) @@ -156,16 +162,6 @@ static int vcn_v4_0_3_sw_init(struct amdgpu_ip_block *ip_block) uint32_t reg_count = ARRAY_SIZE(vcn_reg_list_4_0_3); uint32_t *ptr; - r = amdgpu_vcn_sw_init(adev); - if (r) - return r; - - amdgpu_vcn_setup_ucode(adev); - - r = amdgpu_vcn_resume(adev); - if (r) - return r; - /* VCN DEC TRAP */ r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN, VCN_4_0__SRCID__UVD_ENC_GENERAL_PURPOSE, &adev->vcn.inst->irq); @@ -173,6 +169,17 @@ static int vcn_v4_0_3_sw_init(struct amdgpu_ip_block *ip_block) return r; for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + + r = amdgpu_vcn_sw_init(adev, i); + if (r) + return r; + + amdgpu_vcn_setup_ucode(adev, i); + + r = amdgpu_vcn_resume(adev, i); + if (r) + return r; + vcn_inst = GET_INST(VCN, i); ring = &adev->vcn.inst[i].ring_enc[0]; @@ -261,16 +268,23 @@ static int vcn_v4_0_3_sw_fini(struct amdgpu_ip_block *ip_block) if (amdgpu_sriov_vf(adev)) amdgpu_virt_free_mm_table(adev); - r = amdgpu_vcn_suspend(adev); - if (r) - return r; + for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + r = amdgpu_vcn_suspend(adev, i); + if (r) + return r; + } amdgpu_vcn_sysfs_reset_mask_fini(adev); - r = amdgpu_vcn_sw_fini(adev); + + for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + r = amdgpu_vcn_sw_fini(adev, i); + if (r) + return r; + } kfree(adev->vcn.ip_dump); - return r; + return 0; } /** @@ -375,15 +389,20 @@ static int vcn_v4_0_3_hw_fini(struct amdgpu_ip_block *ip_block) */ static int vcn_v4_0_3_suspend(struct amdgpu_ip_block *ip_block) { - int r; + struct amdgpu_device *adev = ip_block->adev; + int r, i; r = vcn_v4_0_3_hw_fini(ip_block); if (r) return r; - r = amdgpu_vcn_suspend(ip_block->adev); + for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + r = amdgpu_vcn_suspend(adev, i); + if (r) + return r; + } - return r; + return 0; } /** @@ -395,11 +414,14 @@ static int vcn_v4_0_3_suspend(struct amdgpu_ip_block *ip_block) */ static int vcn_v4_0_3_resume(struct amdgpu_ip_block *ip_block) { - int r; + struct amdgpu_device *adev = ip_block->adev; + int r, i; - r = amdgpu_vcn_resume(ip_block->adev); - if (r) - return r; + for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + r = amdgpu_vcn_resume(ip_block->adev, i); + if (r) + return r; + } r = vcn_v4_0_3_hw_init(ip_block); diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c index 2513929b2d43..68ed7950e3d5 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c @@ -115,7 +115,7 @@ static void vcn_v4_0_5_unified_ring_set_wptr(struct amdgpu_ring *ring); static int vcn_v4_0_5_early_init(struct amdgpu_ip_block *ip_block) { struct amdgpu_device *adev = ip_block->adev; - int i; + int i, r; for (i = 0; i < adev->vcn.num_vcn_inst; ++i) /* re-use enc ring as unified ring */ @@ -123,7 +123,13 @@ static int vcn_v4_0_5_early_init(struct amdgpu_ip_block *ip_block) vcn_v4_0_5_set_unified_ring_funcs(adev); vcn_v4_0_5_set_irq_funcs(adev); - return amdgpu_vcn_early_init(adev); + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { + r = amdgpu_vcn_early_init(adev, i); + if (r) + return r; + } + + return 0; } /** @@ -141,15 +147,6 @@ static int vcn_v4_0_5_sw_init(struct amdgpu_ip_block *ip_block) uint32_t reg_count = ARRAY_SIZE(vcn_reg_list_4_0_5); uint32_t *ptr; - r = amdgpu_vcn_sw_init(adev); - if (r) - return r; - - amdgpu_vcn_setup_ucode(adev); - - r = amdgpu_vcn_resume(adev); - if (r) - return r; for (i = 0; i < adev->vcn.num_vcn_inst; i++) { volatile struct amdgpu_vcn4_fw_shared *fw_shared; @@ -157,6 +154,16 @@ static int vcn_v4_0_5_sw_init(struct amdgpu_ip_block *ip_block) if (adev->vcn.harvest_config & (1 << i)) continue; + r = amdgpu_vcn_sw_init(adev, i); + if (r) + return r; + + amdgpu_vcn_setup_ucode(adev, i); + + r = amdgpu_vcn_resume(adev, i); + if (r) + return r; + atomic_set(&adev->vcn.inst[i].sched_score, 0); /* VCN UNIFIED TRAP */ @@ -252,15 +259,19 @@ static int vcn_v4_0_5_sw_fini(struct amdgpu_ip_block *ip_block) if (amdgpu_sriov_vf(adev)) amdgpu_virt_free_mm_table(adev); - r = amdgpu_vcn_suspend(adev); - if (r) - return r; + for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + r = amdgpu_vcn_suspend(adev, i); + if (r) + return r; - r = amdgpu_vcn_sw_fini(adev); + r = amdgpu_vcn_sw_fini(adev, i); + if (r) + return r; + } kfree(adev->vcn.ip_dump); - return r; + return 0; } /** @@ -332,13 +343,18 @@ static int vcn_v4_0_5_hw_fini(struct amdgpu_ip_block *ip_block) */ static int vcn_v4_0_5_suspend(struct amdgpu_ip_block *ip_block) { - int r; + struct amdgpu_device *adev = ip_block->adev; + int r, i; r = vcn_v4_0_5_hw_fini(ip_block); if (r) return r; - r = amdgpu_vcn_suspend(ip_block->adev); + for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + r = amdgpu_vcn_suspend(ip_block->adev, i); + if (r) + return r; + } return r; } @@ -352,11 +368,14 @@ static int vcn_v4_0_5_suspend(struct amdgpu_ip_block *ip_block) */ static int vcn_v4_0_5_resume(struct amdgpu_ip_block *ip_block) { - int r; + struct amdgpu_device *adev = ip_block->adev; + int r, i; - r = amdgpu_vcn_resume(ip_block->adev); - if (r) - return r; + for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + r = amdgpu_vcn_resume(ip_block->adev, i); + if (r) + return r; + } r = vcn_v4_0_5_hw_init(ip_block); diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c index 50e0928c3a20..d773766ebbe2 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c @@ -98,7 +98,7 @@ static void vcn_v5_0_0_unified_ring_set_wptr(struct amdgpu_ring *ring); static int vcn_v5_0_0_early_init(struct amdgpu_ip_block *ip_block) { struct amdgpu_device *adev = ip_block->adev; - int i; + int i, r; for (i = 0; i < adev->vcn.num_vcn_inst; ++i) /* re-use enc ring as unified ring */ @@ -107,7 +107,13 @@ static int vcn_v5_0_0_early_init(struct amdgpu_ip_block *ip_block) vcn_v5_0_0_set_unified_ring_funcs(adev); vcn_v5_0_0_set_irq_funcs(adev); - return amdgpu_vcn_early_init(adev); + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { + r = amdgpu_vcn_early_init(adev, i); + if (r) + return r; + } + + return 0; } void vcn_v5_0_0_alloc_ip_dump(struct amdgpu_device *adev) @@ -138,22 +144,22 @@ static int vcn_v5_0_0_sw_init(struct amdgpu_ip_block *ip_block) struct amdgpu_device *adev = ip_block->adev; int i, r; - r = amdgpu_vcn_sw_init(adev); - if (r) - return r; - - amdgpu_vcn_setup_ucode(adev); - - r = amdgpu_vcn_resume(adev); - if (r) - return r; - for (i = 0; i < adev->vcn.num_vcn_inst; i++) { volatile struct amdgpu_vcn5_fw_shared *fw_shared; if (adev->vcn.harvest_config & (1 << i)) continue; + r = amdgpu_vcn_sw_init(adev, i); + if (r) + return r; + + amdgpu_vcn_setup_ucode(adev, i); + + r = amdgpu_vcn_resume(adev, i); + if (r) + return r; + atomic_set(&adev->vcn.inst[i].sched_score, 0); /* VCN UNIFIED TRAP */ @@ -231,16 +237,23 @@ static int vcn_v5_0_0_sw_fini(struct amdgpu_ip_block *ip_block) drm_dev_exit(idx); } - r = amdgpu_vcn_suspend(adev); - if (r) - return r; + for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + r = amdgpu_vcn_suspend(adev, i); + if (r) + return r; + } amdgpu_vcn_sysfs_reset_mask_fini(adev); - r = amdgpu_vcn_sw_fini(adev); + + for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + r = amdgpu_vcn_sw_fini(adev, i); + if (r) + return r; + } kfree(adev->vcn.ip_dump); - return r; + return 0; } /** @@ -312,13 +325,18 @@ static int vcn_v5_0_0_hw_fini(struct amdgpu_ip_block *ip_block) */ static int vcn_v5_0_0_suspend(struct amdgpu_ip_block *ip_block) { - int r; + struct amdgpu_device *adev = ip_block->adev; + int r, i; r = vcn_v5_0_0_hw_fini(ip_block); if (r) return r; - r = amdgpu_vcn_suspend(ip_block->adev); + for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + r = amdgpu_vcn_suspend(ip_block->adev, i); + if (r) + return r; + } return r; } @@ -332,11 +350,14 @@ static int vcn_v5_0_0_suspend(struct amdgpu_ip_block *ip_block) */ static int vcn_v5_0_0_resume(struct amdgpu_ip_block *ip_block) { - int r; + struct amdgpu_device *adev = ip_block->adev; + int r, i; - r = amdgpu_vcn_resume(ip_block->adev); - if (r) - return r; + for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + r = amdgpu_vcn_resume(ip_block->adev, i); + if (r) + return r; + } r = vcn_v5_0_0_hw_init(ip_block); diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c index ebe977507bc3..afa8f1f0b572 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c @@ -58,7 +58,7 @@ static void vcn_v5_0_1_unified_ring_set_wptr(struct amdgpu_ring *ring); static int vcn_v5_0_1_early_init(struct amdgpu_ip_block *ip_block) { struct amdgpu_device *adev = ip_block->adev; - int i; + int i, r; for (i = 0; i < adev->vcn.num_vcn_inst; ++i) /* re-use enc ring as unified ring */ @@ -67,7 +67,13 @@ static int vcn_v5_0_1_early_init(struct amdgpu_ip_block *ip_block) vcn_v5_0_1_set_unified_ring_funcs(adev); vcn_v5_0_1_set_irq_funcs(adev); - return amdgpu_vcn_early_init(adev); + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { + r = amdgpu_vcn_early_init(adev, i); + if (r) + return r; + } + + return 0; } /** @@ -83,16 +89,6 @@ static int vcn_v5_0_1_sw_init(struct amdgpu_ip_block *ip_block) struct amdgpu_ring *ring; int i, r, vcn_inst; - r = amdgpu_vcn_sw_init(adev); - if (r) - return r; - - amdgpu_vcn_setup_ucode(adev); - - r = amdgpu_vcn_resume(adev); - if (r) - return r; - /* VCN UNIFIED TRAP */ r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN, VCN_5_0__SRCID__UVD_ENC_GENERAL_PURPOSE, &adev->vcn.inst->irq); @@ -104,6 +100,16 @@ static int vcn_v5_0_1_sw_init(struct amdgpu_ip_block *ip_block) vcn_inst = GET_INST(VCN, i); + r = amdgpu_vcn_sw_init(adev, i); + if (r) + return r; + + amdgpu_vcn_setup_ucode(adev, i); + + r = amdgpu_vcn_resume(adev, i); + if (r) + return r; + ring = &adev->vcn.inst[i].ring_enc[0]; ring->use_doorbell = true; ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 9 * vcn_inst; @@ -157,17 +163,23 @@ static int vcn_v5_0_1_sw_fini(struct amdgpu_ip_block *ip_block) drm_dev_exit(idx); } - r = amdgpu_vcn_suspend(adev); - if (r) - return r; + for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + r = amdgpu_vcn_suspend(adev, i); + if (r) + return r; + } - r = amdgpu_vcn_sw_fini(adev); + for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + r = amdgpu_vcn_sw_fini(adev, i); + if (r) + return r; + } amdgpu_vcn_sysfs_reset_mask_fini(adev); kfree(adev->vcn.ip_dump); - return r; + return 0; } /** @@ -229,13 +241,17 @@ static int vcn_v5_0_1_hw_fini(struct amdgpu_ip_block *ip_block) static int vcn_v5_0_1_suspend(struct amdgpu_ip_block *ip_block) { struct amdgpu_device *adev = ip_block->adev; - int r; + int r, i; r = vcn_v5_0_1_hw_fini(ip_block); if (r) return r; - r = amdgpu_vcn_suspend(adev); + for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + r = amdgpu_vcn_suspend(ip_block->adev, i); + if (r) + return r; + } return r; } @@ -250,11 +266,13 @@ static int vcn_v5_0_1_suspend(struct amdgpu_ip_block *ip_block) static int vcn_v5_0_1_resume(struct amdgpu_ip_block *ip_block) { struct amdgpu_device *adev = ip_block->adev; - int r; + int r, i; - r = amdgpu_vcn_resume(adev); - if (r) - return r; + for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + r = amdgpu_vcn_resume(ip_block->adev, i); + if (r) + return r; + } r = vcn_v5_0_1_hw_init(ip_block); From 710151263ca5f2ac3d120e3d727d2c75be905d7f Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 19 Nov 2024 16:10:46 -0500 Subject: [PATCH 086/235] drm/amdgpu/vcn3.0: convert internal functions to use vcn_inst Pass the vcn instance structure to these functions rather than adev and the instance number. TODO: clean up the function internals to use the vinst state directly rather than accessing it indirectly via adev->vcn.inst[]. Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 79 ++++++++++++++++++--------- 1 file changed, 52 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c index 6052e963fcab..2fd58d548b19 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c @@ -510,13 +510,14 @@ static int vcn_v3_0_resume(struct amdgpu_ip_block *ip_block) /** * vcn_v3_0_mc_resume - memory controller programming * - * @adev: amdgpu_device pointer - * @inst: instance number + * @vinst: VCN instance * * Let the VCN memory controller know it's offsets */ -static void vcn_v3_0_mc_resume(struct amdgpu_device *adev, int inst) +static void vcn_v3_0_mc_resume(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int inst = vinst->inst; uint32_t size = AMDGPU_GPU_PAGE_ALIGN(adev->vcn.inst[inst].fw->size + 4); uint32_t offset; @@ -565,8 +566,11 @@ static void vcn_v3_0_mc_resume(struct amdgpu_device *adev, int inst) AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_fw_shared))); } -static void vcn_v3_0_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect) +static void vcn_v3_0_mc_resume_dpg_mode(struct amdgpu_vcn_inst *vinst, + bool indirect) { + struct amdgpu_device *adev = vinst->adev; + int inst_idx = vinst->inst; uint32_t size = AMDGPU_GPU_PAGE_ALIGN(adev->vcn.inst[inst_idx].fw->size + 4); uint32_t offset; @@ -661,8 +665,10 @@ static void vcn_v3_0_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx UVD, inst_idx, mmUVD_GFX10_ADDR_CONFIG), adev->gfx.config.gb_addr_config, 0, indirect); } -static void vcn_v3_0_disable_static_power_gating(struct amdgpu_device *adev, int inst) +static void vcn_v3_0_disable_static_power_gating(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int inst = vinst->inst; uint32_t data = 0; if (adev->pg_flags & AMD_PG_SUPPORT_VCN) { @@ -712,8 +718,10 @@ static void vcn_v3_0_disable_static_power_gating(struct amdgpu_device *adev, int WREG32_SOC15(VCN, inst, mmUVD_POWER_STATUS, data); } -static void vcn_v3_0_enable_static_power_gating(struct amdgpu_device *adev, int inst) +static void vcn_v3_0_enable_static_power_gating(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int inst = vinst->inst; uint32_t data; if (adev->pg_flags & AMD_PG_SUPPORT_VCN) { @@ -765,8 +773,10 @@ static void vcn_v3_0_enable_static_power_gating(struct amdgpu_device *adev, int * * Disable clock gating for VCN block */ -static void vcn_v3_0_disable_clock_gating(struct amdgpu_device *adev, int inst) +static void vcn_v3_0_disable_clock_gating(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int inst = vinst->inst; uint32_t data; /* VCN disable CGC */ @@ -893,9 +903,12 @@ static void vcn_v3_0_disable_clock_gating(struct amdgpu_device *adev, int inst) WREG32_SOC15(VCN, inst, mmUVD_SUVD_CGC_CTRL, data); } -static void vcn_v3_0_clock_gating_dpg_mode(struct amdgpu_device *adev, - uint8_t sram_sel, int inst_idx, uint8_t indirect) +static void vcn_v3_0_clock_gating_dpg_mode(struct amdgpu_vcn_inst *vinst, + uint8_t sram_sel, + uint8_t indirect) { + struct amdgpu_device *adev = vinst->adev; + int inst_idx = vinst->inst; uint32_t reg_data = 0; /* enable sw clock gating control */ @@ -949,8 +962,10 @@ static void vcn_v3_0_clock_gating_dpg_mode(struct amdgpu_device *adev, * * Enable clock gating for VCN block */ -static void vcn_v3_0_enable_clock_gating(struct amdgpu_device *adev, int inst) +static void vcn_v3_0_enable_clock_gating(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int inst = vinst->inst; uint32_t data; /* enable VCN CGC */ @@ -1009,8 +1024,10 @@ static void vcn_v3_0_enable_clock_gating(struct amdgpu_device *adev, int inst) WREG32_SOC15(VCN, inst, mmUVD_SUVD_CGC_CTRL, data); } -static int vcn_v3_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect) +static int vcn_v3_0_start_dpg_mode(struct amdgpu_vcn_inst *vinst, bool indirect) { + struct amdgpu_device *adev = vinst->adev; + int inst_idx = vinst->inst; volatile struct amdgpu_fw_shared *fw_shared = adev->vcn.inst[inst_idx].fw_shared.cpu_addr; struct amdgpu_ring *ring; uint32_t rb_bufsz, tmp; @@ -1028,7 +1045,7 @@ static int vcn_v3_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo adev->vcn.inst[inst_idx].dpg_sram_curr_addr = (uint32_t *)adev->vcn.inst[inst_idx].dpg_sram_cpu_addr; /* enable clock gating */ - vcn_v3_0_clock_gating_dpg_mode(adev, 0, inst_idx, indirect); + vcn_v3_0_clock_gating_dpg_mode(vinst, 0, indirect); /* enable VCPU clock */ tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT); @@ -1077,7 +1094,7 @@ static int vcn_v3_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) | (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)), 0, indirect); - vcn_v3_0_mc_resume_dpg_mode(adev, inst_idx, indirect); + vcn_v3_0_mc_resume_dpg_mode(vinst, indirect); WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( VCN, inst_idx, mmUVD_REG_XX_MASK), 0x10, 0, indirect); @@ -1161,8 +1178,10 @@ static int vcn_v3_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo return 0; } -static int vcn_v3_0_start(struct amdgpu_device *adev, int i) +static int vcn_v3_0_start(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int i = vinst->inst; volatile struct amdgpu_fw_shared *fw_shared; struct amdgpu_ring *ring; uint32_t rb_bufsz, tmp; @@ -1175,17 +1194,17 @@ static int vcn_v3_0_start(struct amdgpu_device *adev, int i) amdgpu_dpm_enable_vcn(adev, true, i); if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) - return vcn_v3_0_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram); + return vcn_v3_0_start_dpg_mode(vinst, vinst->indirect_sram); /* disable VCN power gating */ - vcn_v3_0_disable_static_power_gating(adev, i); + vcn_v3_0_disable_static_power_gating(vinst); /* set VCN status busy */ tmp = RREG32_SOC15(VCN, i, mmUVD_STATUS) | UVD_STATUS__UVD_BUSY; WREG32_SOC15(VCN, i, mmUVD_STATUS, tmp); /* SW clock gating */ - vcn_v3_0_disable_clock_gating(adev, i); + vcn_v3_0_disable_clock_gating(vinst); /* enable VCPU clock */ WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL), @@ -1238,7 +1257,7 @@ static int vcn_v3_0_start(struct amdgpu_device *adev, int i) (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) | (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT))); - vcn_v3_0_mc_resume(adev, i); + vcn_v3_0_mc_resume(vinst); /* VCN global tiling registers */ WREG32_SOC15(VCN, i, mmUVD_GFX10_ADDR_CONFIG, @@ -1555,8 +1574,10 @@ static int vcn_v3_0_start_sriov(struct amdgpu_device *adev) return 0; } -static int vcn_v3_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx) +static int vcn_v3_0_stop_dpg_mode(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int inst_idx = vinst->inst; struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE}; uint32_t tmp; @@ -1586,8 +1607,10 @@ static int vcn_v3_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx) return 0; } -static int vcn_v3_0_stop(struct amdgpu_device *adev, int i) +static int vcn_v3_0_stop(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int i = vinst->inst; uint32_t tmp; int r = 0; @@ -1595,7 +1618,7 @@ static int vcn_v3_0_stop(struct amdgpu_device *adev, int i) return 0; if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) { - r = vcn_v3_0_stop_dpg_mode(adev, i); + r = vcn_v3_0_stop_dpg_mode(vinst); goto done; } @@ -1648,10 +1671,10 @@ static int vcn_v3_0_stop(struct amdgpu_device *adev, int i) WREG32_SOC15(VCN, i, mmUVD_STATUS, 0); /* apply HW clock gating */ - vcn_v3_0_enable_clock_gating(adev, i); + vcn_v3_0_enable_clock_gating(vinst); /* enable VCN power gating */ - vcn_v3_0_enable_static_power_gating(adev, i); + vcn_v3_0_enable_static_power_gating(vinst); done: if (adev->pm.dpm_enabled) @@ -2162,15 +2185,16 @@ static int vcn_v3_0_set_clockgating_state(struct amdgpu_ip_block *ip_block, int i; for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { + struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; if (adev->vcn.harvest_config & (1 << i)) continue; if (enable) { if (RREG32_SOC15(VCN, i, mmUVD_STATUS) != UVD_STATUS__IDLE) return -EBUSY; - vcn_v3_0_enable_clock_gating(adev, i); + vcn_v3_0_enable_clock_gating(vinst); } else { - vcn_v3_0_disable_clock_gating(adev, i); + vcn_v3_0_disable_clock_gating(vinst); } } @@ -2182,6 +2206,7 @@ static int vcn_v3_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, int i) { struct amdgpu_device *adev = ip_block->adev; + struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; int ret = 0; /* for SRIOV, guest should not control VCN Power-gating @@ -2197,9 +2222,9 @@ static int vcn_v3_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, return 0; if (state == AMD_PG_STATE_GATE) - ret = vcn_v3_0_stop(adev, i); + ret = vcn_v3_0_stop(vinst); else - ret = vcn_v3_0_start(adev, i); + ret = vcn_v3_0_start(vinst); if (!ret) adev->vcn.inst[i].cur_state = state; From 201fee333d4ca8cc9cdfc3ee27fadf35ca512a14 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 19 Nov 2024 16:51:36 -0500 Subject: [PATCH 087/235] drm/amdgpu/vcn1.0: convert internal functions to use vcn_inst Pass the vcn instance structure to these functions rather than adev and the instance number. TODO: clean up the function internals to use the vinst state directly rather than accessing it indirectly via adev->vcn.inst[]. Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c | 85 ++++++++++++++++----------- 1 file changed, 51 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c index 49542d947727..267bfc32284c 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c @@ -81,7 +81,7 @@ static const struct amdgpu_hwip_reg_entry vcn_reg_list_1_0[] = { SOC15_REG_ENTRY_STR(VCN, 0, mmUVD_DPG_PAUSE) }; -static int vcn_v1_0_stop(struct amdgpu_device *adev); +static int vcn_v1_0_stop(struct amdgpu_vcn_inst *vinst); static void vcn_v1_0_set_dec_ring_funcs(struct amdgpu_device *adev); static void vcn_v1_0_set_enc_ring_funcs(struct amdgpu_device *adev); static void vcn_v1_0_set_irq_funcs(struct amdgpu_device *adev); @@ -339,12 +339,13 @@ static int vcn_v1_0_resume(struct amdgpu_ip_block *ip_block) /** * vcn_v1_0_mc_resume_spg_mode - memory controller programming * - * @adev: amdgpu_device pointer + * @vinst: VCN instance * * Let the VCN memory controller know it's offsets */ -static void vcn_v1_0_mc_resume_spg_mode(struct amdgpu_device *adev) +static void vcn_v1_0_mc_resume_spg_mode(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; uint32_t size = AMDGPU_GPU_PAGE_ALIGN(adev->vcn.inst[0].fw->size + 4); uint32_t offset; @@ -410,8 +411,9 @@ static void vcn_v1_0_mc_resume_spg_mode(struct amdgpu_device *adev) adev->gfx.config.gb_addr_config); } -static void vcn_v1_0_mc_resume_dpg_mode(struct amdgpu_device *adev) +static void vcn_v1_0_mc_resume_dpg_mode(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; uint32_t size = AMDGPU_GPU_PAGE_ALIGN(adev->vcn.inst[0].fw->size + 4); uint32_t offset; @@ -485,12 +487,13 @@ static void vcn_v1_0_mc_resume_dpg_mode(struct amdgpu_device *adev) /** * vcn_v1_0_disable_clock_gating - disable VCN clock gating * - * @adev: amdgpu_device pointer + * @vinst: VCN instance * * Disable clock gating for VCN block */ -static void vcn_v1_0_disable_clock_gating(struct amdgpu_device *adev) +static void vcn_v1_0_disable_clock_gating(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; uint32_t data; /* JPEG disable CGC */ @@ -615,8 +618,9 @@ static void vcn_v1_0_disable_clock_gating(struct amdgpu_device *adev) * * Enable clock gating for VCN block */ -static void vcn_v1_0_enable_clock_gating(struct amdgpu_device *adev) +static void vcn_v1_0_enable_clock_gating(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; uint32_t data = 0; /* enable JPEG CGC */ @@ -680,8 +684,10 @@ static void vcn_v1_0_enable_clock_gating(struct amdgpu_device *adev) WREG32_SOC15(VCN, 0, mmUVD_SUVD_CGC_CTRL, data); } -static void vcn_v1_0_clock_gating_dpg_mode(struct amdgpu_device *adev, uint8_t sram_sel) +static void vcn_v1_0_clock_gating_dpg_mode(struct amdgpu_vcn_inst *vinst, + uint8_t sram_sel) { + struct amdgpu_device *adev = vinst->adev; uint32_t reg_data = 0; /* disable JPEG CGC */ @@ -734,8 +740,9 @@ static void vcn_v1_0_clock_gating_dpg_mode(struct amdgpu_device *adev, uint8_t s WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_SUVD_CGC_CTRL, 0, 0xFFFFFFFF, sram_sel); } -static void vcn_1_0_disable_static_power_gating(struct amdgpu_device *adev) +static void vcn_1_0_disable_static_power_gating(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; uint32_t data = 0; if (adev->pg_flags & AMD_PG_SUPPORT_VCN) { @@ -779,8 +786,9 @@ static void vcn_1_0_disable_static_power_gating(struct amdgpu_device *adev) WREG32_SOC15(VCN, 0, mmUVD_POWER_STATUS, data); } -static void vcn_1_0_enable_static_power_gating(struct amdgpu_device *adev) +static void vcn_1_0_enable_static_power_gating(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; uint32_t data = 0; if (adev->pg_flags & AMD_PG_SUPPORT_VCN) { @@ -823,12 +831,13 @@ static void vcn_1_0_enable_static_power_gating(struct amdgpu_device *adev) /** * vcn_v1_0_start_spg_mode - start VCN block * - * @adev: amdgpu_device pointer + * @vinst: VCN instance * * Setup and start the VCN block */ -static int vcn_v1_0_start_spg_mode(struct amdgpu_device *adev) +static int vcn_v1_0_start_spg_mode(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; struct amdgpu_ring *ring = &adev->vcn.inst->ring_dec; uint32_t rb_bufsz, tmp; uint32_t lmi_swap_cntl; @@ -837,13 +846,13 @@ static int vcn_v1_0_start_spg_mode(struct amdgpu_device *adev) /* disable byte swapping */ lmi_swap_cntl = 0; - vcn_1_0_disable_static_power_gating(adev); + vcn_1_0_disable_static_power_gating(vinst); tmp = RREG32_SOC15(UVD, 0, mmUVD_STATUS) | UVD_STATUS__UVD_BUSY; WREG32_SOC15(UVD, 0, mmUVD_STATUS, tmp); /* disable clock gating */ - vcn_v1_0_disable_clock_gating(adev); + vcn_v1_0_disable_clock_gating(vinst); /* disable interupt */ WREG32_P(SOC15_REG_OFFSET(UVD, 0, mmUVD_MASTINT_EN), 0, @@ -885,7 +894,7 @@ static int vcn_v1_0_start_spg_mode(struct amdgpu_device *adev) (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) | (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT))); - vcn_v1_0_mc_resume_spg_mode(adev); + vcn_v1_0_mc_resume_spg_mode(vinst); WREG32_SOC15(UVD, 0, mmUVD_REG_XX_MASK_1_0, 0x10); WREG32_SOC15(UVD, 0, mmUVD_RBC_XX_IB_REG_CHECK_1_0, @@ -1001,8 +1010,9 @@ static int vcn_v1_0_start_spg_mode(struct amdgpu_device *adev) return 0; } -static int vcn_v1_0_start_dpg_mode(struct amdgpu_device *adev) +static int vcn_v1_0_start_dpg_mode(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; struct amdgpu_ring *ring = &adev->vcn.inst->ring_dec; uint32_t rb_bufsz, tmp; uint32_t lmi_swap_cntl; @@ -1010,7 +1020,7 @@ static int vcn_v1_0_start_dpg_mode(struct amdgpu_device *adev) /* disable byte swapping */ lmi_swap_cntl = 0; - vcn_1_0_enable_static_power_gating(adev); + vcn_1_0_enable_static_power_gating(vinst); /* enable dynamic power gating mode */ tmp = RREG32_SOC15(UVD, 0, mmUVD_POWER_STATUS); @@ -1019,7 +1029,7 @@ static int vcn_v1_0_start_dpg_mode(struct amdgpu_device *adev) WREG32_SOC15(UVD, 0, mmUVD_POWER_STATUS, tmp); /* enable clock gating */ - vcn_v1_0_clock_gating_dpg_mode(adev, 0); + vcn_v1_0_clock_gating_dpg_mode(vinst, 0); /* enable VCPU clock */ tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT); @@ -1068,7 +1078,7 @@ static int vcn_v1_0_start_dpg_mode(struct amdgpu_device *adev) (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) | (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)), 0xFFFFFFFF, 0); - vcn_v1_0_mc_resume_dpg_mode(adev); + vcn_v1_0_mc_resume_dpg_mode(vinst); WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_REG_XX_MASK, 0x10, 0xFFFFFFFF, 0); WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_RBC_XX_IB_REG_CHECK, 0x3, 0xFFFFFFFF, 0); @@ -1085,7 +1095,7 @@ static int vcn_v1_0_start_dpg_mode(struct amdgpu_device *adev) WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_MASTINT_EN, UVD_MASTINT_EN__VCPU_EN_MASK, UVD_MASTINT_EN__VCPU_EN_MASK, 0); - vcn_v1_0_clock_gating_dpg_mode(adev, 1); + vcn_v1_0_clock_gating_dpg_mode(vinst, 1); /* setup mmUVD_LMI_CTRL */ WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_LMI_CTRL, (8 << UVD_LMI_CTRL__WRITE_CLEAN_TIMER__SHIFT) | @@ -1145,21 +1155,24 @@ static int vcn_v1_0_start_dpg_mode(struct amdgpu_device *adev) return 0; } -static int vcn_v1_0_start(struct amdgpu_device *adev) +static int vcn_v1_0_start(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + return (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ? - vcn_v1_0_start_dpg_mode(adev) : vcn_v1_0_start_spg_mode(adev); + vcn_v1_0_start_dpg_mode(vinst) : vcn_v1_0_start_spg_mode(vinst); } /** * vcn_v1_0_stop_spg_mode - stop VCN block * - * @adev: amdgpu_device pointer + * @vinst: VCN instance * * stop the VCN block */ -static int vcn_v1_0_stop_spg_mode(struct amdgpu_device *adev) +static int vcn_v1_0_stop_spg_mode(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; int tmp; SOC15_WAIT_ON_RREG(UVD, 0, mmUVD_STATUS, UVD_STATUS__IDLE, 0x7); @@ -1199,13 +1212,14 @@ static int vcn_v1_0_stop_spg_mode(struct amdgpu_device *adev) WREG32_SOC15(UVD, 0, mmUVD_STATUS, 0); - vcn_v1_0_enable_clock_gating(adev); - vcn_1_0_enable_static_power_gating(adev); + vcn_v1_0_enable_clock_gating(vinst); + vcn_1_0_enable_static_power_gating(vinst); return 0; } -static int vcn_v1_0_stop_dpg_mode(struct amdgpu_device *adev) +static int vcn_v1_0_stop_dpg_mode(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; uint32_t tmp; /* Wait for power status to be UVD_POWER_STATUS__UVD_POWER_STATUS_TILES_OFF */ @@ -1237,14 +1251,15 @@ static int vcn_v1_0_stop_dpg_mode(struct amdgpu_device *adev) return 0; } -static int vcn_v1_0_stop(struct amdgpu_device *adev) +static int vcn_v1_0_stop(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; int r; if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) - r = vcn_v1_0_stop_dpg_mode(adev); + r = vcn_v1_0_stop_dpg_mode(vinst); else - r = vcn_v1_0_stop_spg_mode(adev); + r = vcn_v1_0_stop_spg_mode(vinst); return r; } @@ -1399,16 +1414,17 @@ static int vcn_v1_0_set_clockgating_state(struct amdgpu_ip_block *ip_block, enum amd_clockgating_state state) { struct amdgpu_device *adev = ip_block->adev; + struct amdgpu_vcn_inst *vinst = adev->vcn.inst; bool enable = (state == AMD_CG_STATE_GATE); if (enable) { /* wait for STATUS to clear */ if (!vcn_v1_0_is_idle(ip_block)) return -EBUSY; - vcn_v1_0_enable_clock_gating(adev); + vcn_v1_0_enable_clock_gating(vinst); } else { /* disable HW gating and enable Sw gating */ - vcn_v1_0_disable_clock_gating(adev); + vcn_v1_0_disable_clock_gating(vinst); } return 0; } @@ -1812,14 +1828,15 @@ static int vcn_v1_0_set_powergating_state(struct amdgpu_ip_block *ip_block, */ int ret; struct amdgpu_device *adev = ip_block->adev; + struct amdgpu_vcn_inst *vinst = adev->vcn.inst; if (state == adev->vcn.inst[0].cur_state) return 0; if (state == AMD_PG_STATE_GATE) - ret = vcn_v1_0_stop(adev); + ret = vcn_v1_0_stop(vinst); else - ret = vcn_v1_0_start(adev); + ret = vcn_v1_0_start(vinst); if (!ret) adev->vcn.inst[0].cur_state = state; From 38a404f8afa93c57ecb7868089fdc2c4371eb084 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 22 Nov 2024 13:30:16 -0500 Subject: [PATCH 088/235] drm/amdgpu/vcn2.0: convert internal functions to use vcn_inst Pass the vcn instance structure to these functions rather than adev and the instance number. TODO: clean up the function internals to use the vinst state directly rather than accessing it indirectly via adev->vcn.inst[]. v2: index instances directly on vcn1.0 and 2.0 to make it clear that they only support a single instance (Lijo) Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c | 66 ++++++++++++++++----------- 1 file changed, 39 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c index 5f537d2a5618..43672ba236e3 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c @@ -370,8 +370,9 @@ static int vcn_v2_0_resume(struct amdgpu_ip_block *ip_block) * * Let the VCN memory controller know it's offsets */ -static void vcn_v2_0_mc_resume(struct amdgpu_device *adev) +static void vcn_v2_0_mc_resume(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; uint32_t size = AMDGPU_GPU_PAGE_ALIGN(adev->vcn.inst[0].fw->size + 4); uint32_t offset; @@ -426,8 +427,10 @@ static void vcn_v2_0_mc_resume(struct amdgpu_device *adev) WREG32_SOC15(UVD, 0, mmUVD_GFX10_ADDR_CONFIG, adev->gfx.config.gb_addr_config); } -static void vcn_v2_0_mc_resume_dpg_mode(struct amdgpu_device *adev, bool indirect) +static void vcn_v2_0_mc_resume_dpg_mode(struct amdgpu_vcn_inst *vinst, + bool indirect) { + struct amdgpu_device *adev = vinst->adev; uint32_t size = AMDGPU_GPU_PAGE_ALIGN(adev->vcn.inst[0].fw->size + 4); uint32_t offset; @@ -525,12 +528,13 @@ static void vcn_v2_0_mc_resume_dpg_mode(struct amdgpu_device *adev, bool indirec /** * vcn_v2_0_disable_clock_gating - disable VCN clock gating * - * @adev: amdgpu_device pointer + * @vinst: VCN instance * * Disable clock gating for VCN block */ -static void vcn_v2_0_disable_clock_gating(struct amdgpu_device *adev) +static void vcn_v2_0_disable_clock_gating(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; uint32_t data; if (amdgpu_sriov_vf(adev)) @@ -634,9 +638,10 @@ static void vcn_v2_0_disable_clock_gating(struct amdgpu_device *adev) WREG32_SOC15(VCN, 0, mmUVD_SUVD_CGC_CTRL, data); } -static void vcn_v2_0_clock_gating_dpg_mode(struct amdgpu_device *adev, +static void vcn_v2_0_clock_gating_dpg_mode(struct amdgpu_vcn_inst *vinst, uint8_t sram_sel, uint8_t indirect) { + struct amdgpu_device *adev = vinst->adev; uint32_t reg_data = 0; /* enable sw clock gating control */ @@ -685,12 +690,13 @@ static void vcn_v2_0_clock_gating_dpg_mode(struct amdgpu_device *adev, /** * vcn_v2_0_enable_clock_gating - enable VCN clock gating * - * @adev: amdgpu_device pointer + * @vinst: VCN instance * * Enable clock gating for VCN block */ -static void vcn_v2_0_enable_clock_gating(struct amdgpu_device *adev) +static void vcn_v2_0_enable_clock_gating(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; uint32_t data = 0; if (amdgpu_sriov_vf(adev)) @@ -743,8 +749,9 @@ static void vcn_v2_0_enable_clock_gating(struct amdgpu_device *adev) WREG32_SOC15(VCN, 0, mmUVD_SUVD_CGC_CTRL, data); } -static void vcn_v2_0_disable_static_power_gating(struct amdgpu_device *adev) +static void vcn_v2_0_disable_static_power_gating(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; uint32_t data = 0; if (amdgpu_sriov_vf(adev)) @@ -792,8 +799,9 @@ static void vcn_v2_0_disable_static_power_gating(struct amdgpu_device *adev) WREG32_SOC15(VCN, 0, mmUVD_POWER_STATUS, data); } -static void vcn_v2_0_enable_static_power_gating(struct amdgpu_device *adev) +static void vcn_v2_0_enable_static_power_gating(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; uint32_t data = 0; if (amdgpu_sriov_vf(adev)) @@ -834,13 +842,14 @@ static void vcn_v2_0_enable_static_power_gating(struct amdgpu_device *adev) } } -static int vcn_v2_0_start_dpg_mode(struct amdgpu_device *adev, bool indirect) +static int vcn_v2_0_start_dpg_mode(struct amdgpu_vcn_inst *vinst, bool indirect) { + struct amdgpu_device *adev = vinst->adev; volatile struct amdgpu_fw_shared *fw_shared = adev->vcn.inst->fw_shared.cpu_addr; struct amdgpu_ring *ring = &adev->vcn.inst->ring_dec; uint32_t rb_bufsz, tmp; - vcn_v2_0_enable_static_power_gating(adev); + vcn_v2_0_enable_static_power_gating(vinst); /* enable dynamic power gating mode */ tmp = RREG32_SOC15(UVD, 0, mmUVD_POWER_STATUS); @@ -852,7 +861,7 @@ static int vcn_v2_0_start_dpg_mode(struct amdgpu_device *adev, bool indirect) adev->vcn.inst->dpg_sram_curr_addr = (uint32_t *)adev->vcn.inst->dpg_sram_cpu_addr; /* enable clock gating */ - vcn_v2_0_clock_gating_dpg_mode(adev, 0, indirect); + vcn_v2_0_clock_gating_dpg_mode(vinst, 0, indirect); /* enable VCPU clock */ tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT); @@ -901,7 +910,7 @@ static int vcn_v2_0_start_dpg_mode(struct amdgpu_device *adev, bool indirect) (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) | (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)), 0, indirect); - vcn_v2_0_mc_resume_dpg_mode(adev, indirect); + vcn_v2_0_mc_resume_dpg_mode(vinst, indirect); WREG32_SOC15_DPG_MODE(0, SOC15_DPG_MODE_OFFSET( UVD, 0, mmUVD_REG_XX_MASK), 0x10, 0, indirect); @@ -969,8 +978,9 @@ static int vcn_v2_0_start_dpg_mode(struct amdgpu_device *adev, bool indirect) return 0; } -static int vcn_v2_0_start(struct amdgpu_device *adev) +static int vcn_v2_0_start(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; volatile struct amdgpu_fw_shared *fw_shared = adev->vcn.inst->fw_shared.cpu_addr; struct amdgpu_ring *ring = &adev->vcn.inst->ring_dec; uint32_t rb_bufsz, tmp; @@ -981,16 +991,16 @@ static int vcn_v2_0_start(struct amdgpu_device *adev) amdgpu_dpm_enable_vcn(adev, true, 0); if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) - return vcn_v2_0_start_dpg_mode(adev, adev->vcn.inst->indirect_sram); + return vcn_v2_0_start_dpg_mode(vinst, adev->vcn.inst->indirect_sram); - vcn_v2_0_disable_static_power_gating(adev); + vcn_v2_0_disable_static_power_gating(vinst); /* set uvd status busy */ tmp = RREG32_SOC15(UVD, 0, mmUVD_STATUS) | UVD_STATUS__UVD_BUSY; WREG32_SOC15(UVD, 0, mmUVD_STATUS, tmp); /*SW clock gating */ - vcn_v2_0_disable_clock_gating(adev); + vcn_v2_0_disable_clock_gating(vinst); /* enable VCPU clock */ WREG32_P(SOC15_REG_OFFSET(UVD, 0, mmUVD_VCPU_CNTL), @@ -1034,7 +1044,7 @@ static int vcn_v2_0_start(struct amdgpu_device *adev) (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) | (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT))); - vcn_v2_0_mc_resume(adev); + vcn_v2_0_mc_resume(vinst); /* release VCPU reset to boot */ WREG32_P(SOC15_REG_OFFSET(UVD, 0, mmUVD_SOFT_RESET), 0, @@ -1142,8 +1152,9 @@ static int vcn_v2_0_start(struct amdgpu_device *adev) return 0; } -static int vcn_v2_0_stop_dpg_mode(struct amdgpu_device *adev) +static int vcn_v2_0_stop_dpg_mode(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE}; uint32_t tmp; @@ -1172,13 +1183,14 @@ static int vcn_v2_0_stop_dpg_mode(struct amdgpu_device *adev) return 0; } -static int vcn_v2_0_stop(struct amdgpu_device *adev) +static int vcn_v2_0_stop(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; uint32_t tmp; int r; if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) { - r = vcn_v2_0_stop_dpg_mode(adev); + r = vcn_v2_0_stop_dpg_mode(vinst); if (r) return r; goto power_off; @@ -1230,8 +1242,8 @@ static int vcn_v2_0_stop(struct amdgpu_device *adev) /* clear status */ WREG32_SOC15(VCN, 0, mmUVD_STATUS, 0); - vcn_v2_0_enable_clock_gating(adev); - vcn_v2_0_enable_static_power_gating(adev); + vcn_v2_0_enable_clock_gating(vinst); + vcn_v2_0_enable_static_power_gating(vinst); power_off: if (adev->pm.dpm_enabled) @@ -1348,10 +1360,10 @@ static int vcn_v2_0_set_clockgating_state(struct amdgpu_ip_block *ip_block, /* wait for STATUS to clear */ if (!vcn_v2_0_is_idle(ip_block)) return -EBUSY; - vcn_v2_0_enable_clock_gating(adev); + vcn_v2_0_enable_clock_gating(&adev->vcn.inst[0]); } else { /* disable HW gating and enable Sw gating */ - vcn_v2_0_disable_clock_gating(adev); + vcn_v2_0_disable_clock_gating(&adev->vcn.inst[0]); } return 0; } @@ -1818,9 +1830,9 @@ static int vcn_v2_0_set_powergating_state(struct amdgpu_ip_block *ip_block, return 0; if (state == AMD_PG_STATE_GATE) - ret = vcn_v2_0_stop(adev); + ret = vcn_v2_0_stop(adev->vcn.inst); else - ret = vcn_v2_0_start(adev); + ret = vcn_v2_0_start(adev->vcn.inst); if (!ret) adev->vcn.inst[0].cur_state = state; From f1ab6870402f128a61ad2da47bbed1cc67d7b644 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 22 Nov 2024 13:53:40 -0500 Subject: [PATCH 089/235] drm/amdgpu/vcn2.5: convert internal functions to use vcn_inst Pass the vcn instance structure to these functions rather than adev and the instance number. TODO: clean up the function internals to use the vinst state directly rather than accessing it indirectly via adev->vcn.inst[]. Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c | 80 +++++++++++++++++---------- 1 file changed, 51 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c index 3ee00dc6d533..5df2decd9d79 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c @@ -468,13 +468,14 @@ static int vcn_v2_5_resume(struct amdgpu_ip_block *ip_block) /** * vcn_v2_5_mc_resume - memory controller programming * - * @adev: amdgpu_device pointer - * @i: instance to resume + * @vinst: VCN instance * * Let the VCN memory controller know it's offsets */ -static void vcn_v2_5_mc_resume(struct amdgpu_device *adev, int i) +static void vcn_v2_5_mc_resume(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int i = vinst->inst; uint32_t size; uint32_t offset; @@ -527,8 +528,11 @@ static void vcn_v2_5_mc_resume(struct amdgpu_device *adev, int i) AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_fw_shared))); } -static void vcn_v2_5_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect) +static void vcn_v2_5_mc_resume_dpg_mode(struct amdgpu_vcn_inst *vinst, + bool indirect) { + struct amdgpu_device *adev = vinst->adev; + int inst_idx = vinst->inst; uint32_t size = AMDGPU_GPU_PAGE_ALIGN(adev->vcn.inst[inst_idx].fw->size + 4); uint32_t offset; @@ -626,13 +630,14 @@ static void vcn_v2_5_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx /** * vcn_v2_5_disable_clock_gating - disable VCN clock gating * - * @adev: amdgpu_device pointer - * @i: instance to disable clockgating on + * @vinst: VCN instance * * Disable clock gating for VCN block */ -static void vcn_v2_5_disable_clock_gating(struct amdgpu_device *adev, int i) +static void vcn_v2_5_disable_clock_gating(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int i = vinst->inst; uint32_t data; if (adev->vcn.harvest_config & (1 << i)) @@ -738,9 +743,11 @@ static void vcn_v2_5_disable_clock_gating(struct amdgpu_device *adev, int i) WREG32_SOC15(VCN, i, mmUVD_SUVD_CGC_CTRL, data); } -static void vcn_v2_5_clock_gating_dpg_mode(struct amdgpu_device *adev, - uint8_t sram_sel, int inst_idx, uint8_t indirect) +static void vcn_v2_5_clock_gating_dpg_mode(struct amdgpu_vcn_inst *vinst, + uint8_t sram_sel, uint8_t indirect) { + struct amdgpu_device *adev = vinst->adev; + int inst_idx = vinst->inst; uint32_t reg_data = 0; /* enable sw clock gating control */ @@ -789,13 +796,14 @@ static void vcn_v2_5_clock_gating_dpg_mode(struct amdgpu_device *adev, /** * vcn_v2_5_enable_clock_gating - enable VCN clock gating * - * @adev: amdgpu_device pointer - * @i: instance to enable clockgating on + * @vinst: VCN instance * * Enable clock gating for VCN block */ -static void vcn_v2_5_enable_clock_gating(struct amdgpu_device *adev, int i) +static void vcn_v2_5_enable_clock_gating(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int i = vinst->inst; uint32_t data = 0; if (adev->vcn.harvest_config & (1 << i)) @@ -846,9 +854,11 @@ static void vcn_v2_5_enable_clock_gating(struct amdgpu_device *adev, int i) WREG32_SOC15(VCN, i, mmUVD_SUVD_CGC_CTRL, data); } -static void vcn_v2_6_enable_ras(struct amdgpu_device *adev, int inst_idx, +static void vcn_v2_6_enable_ras(struct amdgpu_vcn_inst *vinst, bool indirect) { + struct amdgpu_device *adev = vinst->adev; + int inst_idx = vinst->inst; uint32_t tmp; if (amdgpu_ip_version(adev, UVD_HWIP, 0) != IP_VERSION(2, 6, 0)) @@ -873,8 +883,10 @@ static void vcn_v2_6_enable_ras(struct amdgpu_device *adev, int inst_idx, tmp, 0, indirect); } -static int vcn_v2_5_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect) +static int vcn_v2_5_start_dpg_mode(struct amdgpu_vcn_inst *vinst, bool indirect) { + struct amdgpu_device *adev = vinst->adev; + int inst_idx = vinst->inst; volatile struct amdgpu_fw_shared *fw_shared = adev->vcn.inst[inst_idx].fw_shared.cpu_addr; struct amdgpu_ring *ring; uint32_t rb_bufsz, tmp; @@ -892,7 +904,7 @@ static int vcn_v2_5_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo adev->vcn.inst[inst_idx].dpg_sram_curr_addr = (uint32_t *)adev->vcn.inst[inst_idx].dpg_sram_cpu_addr; /* enable clock gating */ - vcn_v2_5_clock_gating_dpg_mode(adev, 0, inst_idx, indirect); + vcn_v2_5_clock_gating_dpg_mode(vinst, 0, indirect); /* enable VCPU clock */ tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT); @@ -941,7 +953,7 @@ static int vcn_v2_5_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) | (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)), 0, indirect); - vcn_v2_5_mc_resume_dpg_mode(adev, inst_idx, indirect); + vcn_v2_5_mc_resume_dpg_mode(vinst, indirect); WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( VCN, 0, mmUVD_REG_XX_MASK), 0x10, 0, indirect); @@ -952,7 +964,7 @@ static int vcn_v2_5_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( VCN, 0, mmUVD_LMI_CTRL2), 0, 0, indirect); - vcn_v2_6_enable_ras(adev, inst_idx, indirect); + vcn_v2_6_enable_ras(vinst, indirect); /* unblock VCPU register access */ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( @@ -1017,8 +1029,10 @@ static int vcn_v2_5_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo return 0; } -static int vcn_v2_5_start(struct amdgpu_device *adev, int i) +static int vcn_v2_5_start(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int i = vinst->inst; volatile struct amdgpu_fw_shared *fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; struct amdgpu_ring *ring; @@ -1032,7 +1046,7 @@ static int vcn_v2_5_start(struct amdgpu_device *adev, int i) amdgpu_dpm_enable_vcn(adev, true, i); if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) - return vcn_v2_5_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram); + return vcn_v2_5_start_dpg_mode(vinst, adev->vcn.inst[i].indirect_sram); /* disable register anti-hang mechanism */ WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_POWER_STATUS), 0, @@ -1046,7 +1060,7 @@ static int vcn_v2_5_start(struct amdgpu_device *adev, int i) return 0; /* SW clock gating */ - vcn_v2_5_disable_clock_gating(adev, i); + vcn_v2_5_disable_clock_gating(vinst); /* enable VCPU clock */ WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL), @@ -1091,7 +1105,7 @@ static int vcn_v2_5_start(struct amdgpu_device *adev, int i) (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) | (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT))); - vcn_v2_5_mc_resume(adev, i); + vcn_v2_5_mc_resume(vinst); /* VCN global tiling registers */ WREG32_SOC15(VCN, i, mmUVD_GFX8_ADDR_CONFIG, @@ -1396,8 +1410,10 @@ static int vcn_v2_5_sriov_start(struct amdgpu_device *adev) return vcn_v2_5_mmsch_start(adev, &adev->virt.mm_table); } -static int vcn_v2_5_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx) +static int vcn_v2_5_stop_dpg_mode(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int inst_idx = vinst->inst; uint32_t tmp; /* Wait for power status to be 1 */ @@ -1424,15 +1440,18 @@ static int vcn_v2_5_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx) return 0; } -static int vcn_v2_5_stop(struct amdgpu_device *adev, int i) +static int vcn_v2_5_stop(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int i = vinst->inst; uint32_t tmp; int r; if (adev->vcn.harvest_config & (1 << i)) return 0; + if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) { - r = vcn_v2_5_stop_dpg_mode(adev, i); + r = vcn_v2_5_stop_dpg_mode(vinst); goto done; } @@ -1477,7 +1496,7 @@ static int vcn_v2_5_stop(struct amdgpu_device *adev, int i) /* clear status */ WREG32_SOC15(VCN, i, mmUVD_STATUS, 0); - vcn_v2_5_enable_clock_gating(adev, i); + vcn_v2_5_enable_clock_gating(vinst); /* enable register anti-hang mechanism */ WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_POWER_STATUS), @@ -1813,12 +1832,14 @@ static int vcn_v2_5_set_clockgating_state(struct amdgpu_ip_block *ip_block, return 0; for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { + struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; + if (enable) { if (!vcn_v2_5_is_idle(ip_block)) return -EBUSY; - vcn_v2_5_enable_clock_gating(adev, i); + vcn_v2_5_enable_clock_gating(vinst); } else { - vcn_v2_5_disable_clock_gating(adev, i); + vcn_v2_5_disable_clock_gating(vinst); } } @@ -1830,6 +1851,7 @@ static int vcn_v2_5_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, int i) { struct amdgpu_device *adev = ip_block->adev; + struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; int ret; if (amdgpu_sriov_vf(adev)) @@ -1839,9 +1861,9 @@ static int vcn_v2_5_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, return 0; if (state == AMD_PG_STATE_GATE) - ret = vcn_v2_5_stop(adev, i); + ret = vcn_v2_5_stop(vinst); else - ret = vcn_v2_5_start(adev, i); + ret = vcn_v2_5_start(vinst); if (!ret) adev->vcn.inst[i].cur_state = state; From 259873561f3be91f5dcf1839ba1c3962642ca626 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 22 Nov 2024 15:38:37 -0500 Subject: [PATCH 090/235] drm/amdgpu/vcn4.0: convert internal functions to use vcn_inst Pass the vcn instance structure to these functions rather than adev and the instance number. TODO: clean up the function internals to use the vinst state directly rather than accessing it indirectly via adev->vcn.inst[]. Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c | 116 +++++++++++++++----------- 1 file changed, 67 insertions(+), 49 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c index 8c7566960a3b..0e6af9be0d3c 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c @@ -449,13 +449,14 @@ static int vcn_v4_0_resume(struct amdgpu_ip_block *ip_block) /** * vcn_v4_0_mc_resume - memory controller programming * - * @adev: amdgpu_device pointer - * @inst: instance number + * @vinst: VCN instance * * Let the VCN memory controller know it's offsets */ -static void vcn_v4_0_mc_resume(struct amdgpu_device *adev, int inst) +static void vcn_v4_0_mc_resume(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int inst = vinst->inst; uint32_t offset, size; const struct common_firmware_header *hdr; @@ -509,14 +510,16 @@ static void vcn_v4_0_mc_resume(struct amdgpu_device *adev, int inst) /** * vcn_v4_0_mc_resume_dpg_mode - memory controller programming for dpg mode * - * @adev: amdgpu_device pointer - * @inst_idx: instance number index + * @vinst: VCN instance * @indirect: indirectly write sram * * Let the VCN memory controller know it's offsets with dpg mode */ -static void vcn_v4_0_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect) +static void vcn_v4_0_mc_resume_dpg_mode(struct amdgpu_vcn_inst *vinst, + bool indirect) { + struct amdgpu_device *adev = vinst->adev; + int inst_idx = vinst->inst; uint32_t offset, size; const struct common_firmware_header *hdr; hdr = (const struct common_firmware_header *)adev->vcn.inst[inst_idx].fw->data; @@ -616,13 +619,14 @@ static void vcn_v4_0_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx /** * vcn_v4_0_disable_static_power_gating - disable VCN static power gating * - * @adev: amdgpu_device pointer - * @inst: instance number + * @vinst: VCN instance * * Disable static power gating for VCN block */ -static void vcn_v4_0_disable_static_power_gating(struct amdgpu_device *adev, int inst) +static void vcn_v4_0_disable_static_power_gating(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int inst = vinst->inst; uint32_t data = 0; if (adev->pg_flags & AMD_PG_SUPPORT_VCN) { @@ -681,13 +685,14 @@ static void vcn_v4_0_disable_static_power_gating(struct amdgpu_device *adev, int /** * vcn_v4_0_enable_static_power_gating - enable VCN static power gating * - * @adev: amdgpu_device pointer - * @inst: instance number + * @vinst: VCN instance * * Enable static power gating for VCN block */ -static void vcn_v4_0_enable_static_power_gating(struct amdgpu_device *adev, int inst) +static void vcn_v4_0_enable_static_power_gating(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int inst = vinst->inst; uint32_t data; if (adev->pg_flags & AMD_PG_SUPPORT_VCN) { @@ -736,13 +741,14 @@ static void vcn_v4_0_enable_static_power_gating(struct amdgpu_device *adev, int /** * vcn_v4_0_disable_clock_gating - disable VCN clock gating * - * @adev: amdgpu_device pointer - * @inst: instance number + * @vinst: VCN instance * * Disable clock gating for VCN block */ -static void vcn_v4_0_disable_clock_gating(struct amdgpu_device *adev, int inst) +static void vcn_v4_0_disable_clock_gating(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int inst = vinst->inst; uint32_t data; if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG) @@ -847,16 +853,18 @@ static void vcn_v4_0_disable_clock_gating(struct amdgpu_device *adev, int inst) /** * vcn_v4_0_disable_clock_gating_dpg_mode - disable VCN clock gating dpg mode * - * @adev: amdgpu_device pointer + * @vinst: VCN instance * @sram_sel: sram select - * @inst_idx: instance number index * @indirect: indirectly write sram * * Disable clock gating for VCN block with dpg mode */ -static void vcn_v4_0_disable_clock_gating_dpg_mode(struct amdgpu_device *adev, uint8_t sram_sel, - int inst_idx, uint8_t indirect) +static void vcn_v4_0_disable_clock_gating_dpg_mode(struct amdgpu_vcn_inst *vinst, + uint8_t sram_sel, + uint8_t indirect) { + struct amdgpu_device *adev = vinst->adev; + int inst_idx = vinst->inst; uint32_t reg_data = 0; if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG) @@ -904,13 +912,14 @@ static void vcn_v4_0_disable_clock_gating_dpg_mode(struct amdgpu_device *adev, u /** * vcn_v4_0_enable_clock_gating - enable VCN clock gating * - * @adev: amdgpu_device pointer - * @inst: instance number + * @vinst: VCN instance * * Enable clock gating for VCN block */ -static void vcn_v4_0_enable_clock_gating(struct amdgpu_device *adev, int inst) +static void vcn_v4_0_enable_clock_gating(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int inst = vinst->inst; uint32_t data; if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG) @@ -960,9 +969,11 @@ static void vcn_v4_0_enable_clock_gating(struct amdgpu_device *adev, int inst) WREG32_SOC15(VCN, inst, regUVD_SUVD_CGC_CTRL, data); } -static void vcn_v4_0_enable_ras(struct amdgpu_device *adev, int inst_idx, +static void vcn_v4_0_enable_ras(struct amdgpu_vcn_inst *vinst, bool indirect) { + struct amdgpu_device *adev = vinst->adev; + int inst_idx = vinst->inst; uint32_t tmp; if (!amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__VCN)) @@ -985,14 +996,15 @@ static void vcn_v4_0_enable_ras(struct amdgpu_device *adev, int inst_idx, /** * vcn_v4_0_start_dpg_mode - VCN start with dpg mode * - * @adev: amdgpu_device pointer - * @inst_idx: instance number index + * @vinst: VCN instance * @indirect: indirectly write sram * * Start VCN block with dpg mode */ -static int vcn_v4_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect) +static int vcn_v4_0_start_dpg_mode(struct amdgpu_vcn_inst *vinst, bool indirect) { + struct amdgpu_device *adev = vinst->adev; + int inst_idx = vinst->inst; volatile struct amdgpu_vcn4_fw_shared *fw_shared = adev->vcn.inst[inst_idx].fw_shared.cpu_addr; struct amdgpu_ring *ring; uint32_t tmp; @@ -1010,7 +1022,7 @@ static int vcn_v4_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo adev->vcn.inst[inst_idx].dpg_sram_curr_addr = (uint32_t *)adev->vcn.inst[inst_idx].dpg_sram_cpu_addr; /* enable clock gating */ - vcn_v4_0_disable_clock_gating_dpg_mode(adev, 0, inst_idx, indirect); + vcn_v4_0_disable_clock_gating_dpg_mode(vinst, 0, indirect); /* enable VCPU clock */ tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT); @@ -1058,7 +1070,7 @@ static int vcn_v4_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) | (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)), 0, indirect); - vcn_v4_0_mc_resume_dpg_mode(adev, inst_idx, indirect); + vcn_v4_0_mc_resume_dpg_mode(vinst, indirect); tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT); tmp |= UVD_VCPU_CNTL__CLK_EN_MASK; @@ -1070,7 +1082,7 @@ static int vcn_v4_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( VCN, inst_idx, regUVD_LMI_CTRL2), tmp, 0, indirect); - vcn_v4_0_enable_ras(adev, inst_idx, indirect); + vcn_v4_0_enable_ras(vinst, indirect); /* enable master interrupt */ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( @@ -1114,13 +1126,14 @@ static int vcn_v4_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo /** * vcn_v4_0_start - VCN start * - * @adev: amdgpu_device pointer - * @i: instance to start + * @vinst: VCN instance * * Start VCN block */ -static int vcn_v4_0_start(struct amdgpu_device *adev, int i) +static int vcn_v4_0_start(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int i = vinst->inst; volatile struct amdgpu_vcn4_fw_shared *fw_shared; struct amdgpu_ring *ring; uint32_t tmp; @@ -1135,17 +1148,17 @@ static int vcn_v4_0_start(struct amdgpu_device *adev, int i) fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) - return vcn_v4_0_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram); + return vcn_v4_0_start_dpg_mode(vinst, adev->vcn.inst[i].indirect_sram); /* disable VCN power gating */ - vcn_v4_0_disable_static_power_gating(adev, i); + vcn_v4_0_disable_static_power_gating(vinst); /* set VCN status busy */ tmp = RREG32_SOC15(VCN, i, regUVD_STATUS) | UVD_STATUS__UVD_BUSY; WREG32_SOC15(VCN, i, regUVD_STATUS, tmp); /*SW clock gating */ - vcn_v4_0_disable_clock_gating(adev, i); + vcn_v4_0_disable_clock_gating(vinst); /* enable VCPU clock */ WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), @@ -1198,7 +1211,7 @@ static int vcn_v4_0_start(struct amdgpu_device *adev, int i) (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) | (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT))); - vcn_v4_0_mc_resume(adev, i); + vcn_v4_0_mc_resume(vinst); /* VCN global tiling registers */ WREG32_SOC15(VCN, i, regUVD_GFX10_ADDR_CONFIG, @@ -1541,13 +1554,14 @@ static int vcn_v4_0_start_sriov(struct amdgpu_device *adev) /** * vcn_v4_0_stop_dpg_mode - VCN stop with dpg mode * - * @adev: amdgpu_device pointer - * @inst_idx: instance number index + * @vinst: VCN instance * * Stop VCN block with dpg mode */ -static void vcn_v4_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx) +static void vcn_v4_0_stop_dpg_mode(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int inst_idx = vinst->inst; struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE}; uint32_t tmp; @@ -1571,13 +1585,14 @@ static void vcn_v4_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx) /** * vcn_v4_0_stop - VCN stop * - * @adev: amdgpu_device pointer - * @i: instance to stop + * @vinst: VCN instance * * Stop VCN block */ -static int vcn_v4_0_stop(struct amdgpu_device *adev, int i) +static int vcn_v4_0_stop(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int i = vinst->inst; volatile struct amdgpu_vcn4_fw_shared *fw_shared; uint32_t tmp; int r = 0; @@ -1589,7 +1604,7 @@ static int vcn_v4_0_stop(struct amdgpu_device *adev, int i) fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF; if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) { - vcn_v4_0_stop_dpg_mode(adev, i); + vcn_v4_0_stop_dpg_mode(vinst); r = 0; goto done; } @@ -1643,10 +1658,10 @@ static int vcn_v4_0_stop(struct amdgpu_device *adev, int i) WREG32_SOC15(VCN, i, regUVD_STATUS, 0); /* apply HW clock gating */ - vcn_v4_0_enable_clock_gating(adev, i); + vcn_v4_0_enable_clock_gating(vinst); /* enable VCN power gating */ - vcn_v4_0_enable_static_power_gating(adev, i); + vcn_v4_0_enable_static_power_gating(vinst); done: if (adev->pm.dpm_enabled) @@ -2046,15 +2061,17 @@ static int vcn_v4_0_set_clockgating_state(struct amdgpu_ip_block *ip_block, int i; for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { + struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; + if (adev->vcn.harvest_config & (1 << i)) continue; if (enable) { if (RREG32_SOC15(VCN, i, regUVD_STATUS) != UVD_STATUS__IDLE) return -EBUSY; - vcn_v4_0_enable_clock_gating(adev, i); + vcn_v4_0_enable_clock_gating(vinst); } else { - vcn_v4_0_disable_clock_gating(adev, i); + vcn_v4_0_disable_clock_gating(vinst); } } @@ -2066,6 +2083,7 @@ static int vcn_v4_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, int i) { struct amdgpu_device *adev = ip_block->adev; + struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; int ret = 0; /* for SRIOV, guest should not control VCN Power-gating @@ -2081,9 +2099,9 @@ static int vcn_v4_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, return 0; if (state == AMD_PG_STATE_GATE) - ret = vcn_v4_0_stop(adev, i); + ret = vcn_v4_0_stop(vinst); else - ret = vcn_v4_0_start(adev, i); + ret = vcn_v4_0_start(vinst); if (!ret) adev->vcn.inst[i].cur_state = state; From 4a23b9c67021c421a1cf9161e355b2b16e02252b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 22 Nov 2024 17:01:49 -0500 Subject: [PATCH 091/235] drm/amdgpu/vcn4.0.3: convert internal functions to use vcn_inst Pass the vcn instance structure to these functions rather than adev and the instance number. TODO: clean up the function internals to use the vinst state directly rather than accessing it indirectly via adev->vcn.inst[]. Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c | 93 ++++++++++++++----------- 1 file changed, 54 insertions(+), 39 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c index a0b848ad097b..9e1c25210f88 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c @@ -431,13 +431,14 @@ static int vcn_v4_0_3_resume(struct amdgpu_ip_block *ip_block) /** * vcn_v4_0_3_mc_resume - memory controller programming * - * @adev: amdgpu_device pointer - * @inst_idx: instance number + * @vinst: VCN instance * * Let the VCN memory controller know it's offsets */ -static void vcn_v4_0_3_mc_resume(struct amdgpu_device *adev, int inst_idx) +static void vcn_v4_0_3_mc_resume(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int inst_idx = vinst->inst; uint32_t offset, size, vcn_inst; const struct common_firmware_header *hdr; @@ -505,14 +506,16 @@ static void vcn_v4_0_3_mc_resume(struct amdgpu_device *adev, int inst_idx) /** * vcn_v4_0_3_mc_resume_dpg_mode - memory controller programming for dpg mode * - * @adev: amdgpu_device pointer - * @inst_idx: instance number index + * @vinst: VCN instance * @indirect: indirectly write sram * * Let the VCN memory controller know it's offsets with dpg mode */ -static void vcn_v4_0_3_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect) +static void vcn_v4_0_3_mc_resume_dpg_mode(struct amdgpu_vcn_inst *vinst, + bool indirect) { + struct amdgpu_device *adev = vinst->adev; + int inst_idx = vinst->inst; uint32_t offset, size; const struct common_firmware_header *hdr; @@ -619,13 +622,14 @@ static void vcn_v4_0_3_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_i /** * vcn_v4_0_3_disable_clock_gating - disable VCN clock gating * - * @adev: amdgpu_device pointer - * @inst_idx: instance number + * @vinst: VCN instance * * Disable clock gating for VCN block */ -static void vcn_v4_0_3_disable_clock_gating(struct amdgpu_device *adev, int inst_idx) +static void vcn_v4_0_3_disable_clock_gating(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int inst_idx = vinst->inst; uint32_t data; int vcn_inst; @@ -712,16 +716,18 @@ static void vcn_v4_0_3_disable_clock_gating(struct amdgpu_device *adev, int inst /** * vcn_v4_0_3_disable_clock_gating_dpg_mode - disable VCN clock gating dpg mode * - * @adev: amdgpu_device pointer + * @vinst: VCN instance * @sram_sel: sram select - * @inst_idx: instance number index * @indirect: indirectly write sram * * Disable clock gating for VCN block with dpg mode */ -static void vcn_v4_0_3_disable_clock_gating_dpg_mode(struct amdgpu_device *adev, uint8_t sram_sel, - int inst_idx, uint8_t indirect) +static void vcn_v4_0_3_disable_clock_gating_dpg_mode(struct amdgpu_vcn_inst *vinst, + uint8_t sram_sel, + uint8_t indirect) { + struct amdgpu_device *adev = vinst->adev; + int inst_idx = vinst->inst; uint32_t reg_data = 0; if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG) @@ -763,13 +769,14 @@ static void vcn_v4_0_3_disable_clock_gating_dpg_mode(struct amdgpu_device *adev, /** * vcn_v4_0_3_enable_clock_gating - enable VCN clock gating * - * @adev: amdgpu_device pointer - * @inst_idx: instance number + * @vinst: VCN instance * * Enable clock gating for VCN block */ -static void vcn_v4_0_3_enable_clock_gating(struct amdgpu_device *adev, int inst_idx) +static void vcn_v4_0_3_enable_clock_gating(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int inst_idx = vinst->inst; uint32_t data; int vcn_inst; @@ -814,14 +821,16 @@ static void vcn_v4_0_3_enable_clock_gating(struct amdgpu_device *adev, int inst_ /** * vcn_v4_0_3_start_dpg_mode - VCN start with dpg mode * - * @adev: amdgpu_device pointer - * @inst_idx: instance number index + * @vinst: VCN instance * @indirect: indirectly write sram * * Start VCN block with dpg mode */ -static int vcn_v4_0_3_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect) +static int vcn_v4_0_3_start_dpg_mode(struct amdgpu_vcn_inst *vinst, + bool indirect) { + struct amdgpu_device *adev = vinst->adev; + int inst_idx = vinst->inst; volatile struct amdgpu_vcn4_fw_shared *fw_shared = adev->vcn.inst[inst_idx].fw_shared.cpu_addr; struct amdgpu_ring *ring; @@ -849,7 +858,7 @@ static int vcn_v4_0_3_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, b } /* enable clock gating */ - vcn_v4_0_3_disable_clock_gating_dpg_mode(adev, 0, inst_idx, indirect); + vcn_v4_0_3_disable_clock_gating_dpg_mode(vinst, 0, indirect); /* enable VCPU clock */ tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT); @@ -899,7 +908,7 @@ static int vcn_v4_0_3_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, b (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) | (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)), 0, indirect); - vcn_v4_0_3_mc_resume_dpg_mode(adev, inst_idx, indirect); + vcn_v4_0_3_mc_resume_dpg_mode(vinst, indirect); tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT); tmp |= UVD_VCPU_CNTL__CLK_EN_MASK; @@ -1146,20 +1155,21 @@ static int vcn_v4_0_3_start_sriov(struct amdgpu_device *adev) /** * vcn_v4_0_3_start - VCN start * - * @adev: amdgpu_device pointer - * @i: instance to start + * @vinst: VCN instance * * Start VCN block */ -static int vcn_v4_0_3_start(struct amdgpu_device *adev, int i) +static int vcn_v4_0_3_start(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int i = vinst->inst; volatile struct amdgpu_vcn4_fw_shared *fw_shared; struct amdgpu_ring *ring; int j, k, r, vcn_inst; uint32_t tmp; if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) - return vcn_v4_0_3_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram); + return vcn_v4_0_3_start_dpg_mode(vinst, adev->vcn.inst[i].indirect_sram); vcn_inst = GET_INST(VCN, i); /* set VCN status busy */ @@ -1168,7 +1178,7 @@ static int vcn_v4_0_3_start(struct amdgpu_device *adev, int i) WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, tmp); /* SW clock gating */ - vcn_v4_0_3_disable_clock_gating(adev, i); + vcn_v4_0_3_disable_clock_gating(vinst); /* enable VCPU clock */ WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), @@ -1222,7 +1232,7 @@ static int vcn_v4_0_3_start(struct amdgpu_device *adev, int i) (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) | (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT))); - vcn_v4_0_3_mc_resume(adev, i); + vcn_v4_0_3_mc_resume(vinst); /* VCN global tiling registers */ WREG32_SOC15(VCN, vcn_inst, regUVD_GFX8_ADDR_CONFIG, @@ -1316,13 +1326,14 @@ static int vcn_v4_0_3_start(struct amdgpu_device *adev, int i) /** * vcn_v4_0_3_stop_dpg_mode - VCN stop with dpg mode * - * @adev: amdgpu_device pointer - * @inst_idx: instance number index + * @vinst: VCN instance * * Stop VCN block with dpg mode */ -static int vcn_v4_0_3_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx) +static int vcn_v4_0_3_stop_dpg_mode(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int inst_idx = vinst->inst; uint32_t tmp; int vcn_inst; @@ -1348,13 +1359,14 @@ static int vcn_v4_0_3_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx) /** * vcn_v4_0_3_stop - VCN stop * - * @adev: amdgpu_device pointer - * @i: instance to stop + * @vinst: VCN instance * * Stop VCN block */ -static int vcn_v4_0_3_stop(struct amdgpu_device *adev, int i) +static int vcn_v4_0_3_stop(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int i = vinst->inst; volatile struct amdgpu_vcn4_fw_shared *fw_shared; int r = 0, vcn_inst; uint32_t tmp; @@ -1365,7 +1377,7 @@ static int vcn_v4_0_3_stop(struct amdgpu_device *adev, int i) fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF; if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) { - vcn_v4_0_3_stop_dpg_mode(adev, i); + vcn_v4_0_3_stop_dpg_mode(vinst); goto Done; } @@ -1422,7 +1434,7 @@ static int vcn_v4_0_3_stop(struct amdgpu_device *adev, int i) WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, 0); /* apply HW clock gating */ - vcn_v4_0_3_enable_clock_gating(adev, i); + vcn_v4_0_3_enable_clock_gating(vinst); Done: return 0; @@ -1656,13 +1668,15 @@ static int vcn_v4_0_3_set_clockgating_state(struct amdgpu_ip_block *ip_block, int i; for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { + struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; + if (enable) { if (RREG32_SOC15(VCN, GET_INST(VCN, i), regUVD_STATUS) != UVD_STATUS__IDLE) return -EBUSY; - vcn_v4_0_3_enable_clock_gating(adev, i); + vcn_v4_0_3_enable_clock_gating(vinst); } else { - vcn_v4_0_3_disable_clock_gating(adev, i); + vcn_v4_0_3_disable_clock_gating(vinst); } } return 0; @@ -1673,6 +1687,7 @@ static int vcn_v4_0_3_set_powergating_state_inst(struct amdgpu_ip_block *ip_bloc int i) { struct amdgpu_device *adev = ip_block->adev; + struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; int ret = 0; /* for SRIOV, guest should not control VCN Power-gating @@ -1688,9 +1703,9 @@ static int vcn_v4_0_3_set_powergating_state_inst(struct amdgpu_ip_block *ip_bloc return 0; if (state == AMD_PG_STATE_GATE) - ret = vcn_v4_0_3_stop(adev, i); + ret = vcn_v4_0_3_stop(vinst); else - ret = vcn_v4_0_3_start(adev, i); + ret = vcn_v4_0_3_start(vinst); if (!ret) adev->vcn.inst[i].cur_state = state; From c07c0c0df92050f2f9a9a009213702e029bb04e0 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 22 Nov 2024 17:38:48 -0500 Subject: [PATCH 092/235] drm/amdgpu/vcn4.0.5: convert internal functions to use vcn_inst Pass the vcn instance structure to these functions rather than adev and the instance number. TODO: clean up the function internals to use the vinst state directly rather than accessing it indirectly via adev->vcn.inst[]. Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c | 111 ++++++++++++++---------- 1 file changed, 64 insertions(+), 47 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c index 68ed7950e3d5..9b5c6812a0b4 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c @@ -385,13 +385,14 @@ static int vcn_v4_0_5_resume(struct amdgpu_ip_block *ip_block) /** * vcn_v4_0_5_mc_resume - memory controller programming * - * @adev: amdgpu_device pointer - * @inst: instance number + * @vinst: VCN instance * * Let the VCN memory controller know it's offsets */ -static void vcn_v4_0_5_mc_resume(struct amdgpu_device *adev, int inst) +static void vcn_v4_0_5_mc_resume(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int inst = vinst->inst; uint32_t offset, size; const struct common_firmware_header *hdr; @@ -445,14 +446,16 @@ static void vcn_v4_0_5_mc_resume(struct amdgpu_device *adev, int inst) /** * vcn_v4_0_5_mc_resume_dpg_mode - memory controller programming for dpg mode * - * @adev: amdgpu_device pointer - * @inst_idx: instance number index + * @vinst: VCN instance * @indirect: indirectly write sram * * Let the VCN memory controller know it's offsets with dpg mode */ -static void vcn_v4_0_5_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect) +static void vcn_v4_0_5_mc_resume_dpg_mode(struct amdgpu_vcn_inst *vinst, + bool indirect) { + struct amdgpu_device *adev = vinst->adev; + int inst_idx = vinst->inst; uint32_t offset, size; const struct common_firmware_header *hdr; @@ -559,13 +562,14 @@ static void vcn_v4_0_5_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_i /** * vcn_v4_0_5_disable_static_power_gating - disable VCN static power gating * - * @adev: amdgpu_device pointer - * @inst: instance number + * @vinst: VCN instance * * Disable static power gating for VCN block */ -static void vcn_v4_0_5_disable_static_power_gating(struct amdgpu_device *adev, int inst) +static void vcn_v4_0_5_disable_static_power_gating(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int inst = vinst->inst; uint32_t data = 0; if (adev->pg_flags & AMD_PG_SUPPORT_VCN) { @@ -618,13 +622,14 @@ static void vcn_v4_0_5_disable_static_power_gating(struct amdgpu_device *adev, i /** * vcn_v4_0_5_enable_static_power_gating - enable VCN static power gating * - * @adev: amdgpu_device pointer - * @inst: instance number + * @vinst: VCN instance * * Enable static power gating for VCN block */ -static void vcn_v4_0_5_enable_static_power_gating(struct amdgpu_device *adev, int inst) +static void vcn_v4_0_5_enable_static_power_gating(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int inst = vinst->inst; uint32_t data; if (adev->pg_flags & AMD_PG_SUPPORT_VCN) { @@ -660,13 +665,14 @@ static void vcn_v4_0_5_enable_static_power_gating(struct amdgpu_device *adev, in /** * vcn_v4_0_5_disable_clock_gating - disable VCN clock gating * - * @adev: amdgpu_device pointer - * @inst: instance number + * @vinst: VCN instance * * Disable clock gating for VCN block */ -static void vcn_v4_0_5_disable_clock_gating(struct amdgpu_device *adev, int inst) +static void vcn_v4_0_5_disable_clock_gating(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int inst = vinst->inst; uint32_t data; if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG) @@ -771,16 +777,18 @@ static void vcn_v4_0_5_disable_clock_gating(struct amdgpu_device *adev, int inst /** * vcn_v4_0_5_disable_clock_gating_dpg_mode - disable VCN clock gating dpg mode * - * @adev: amdgpu_device pointer + * @vinst: VCN instance * @sram_sel: sram select - * @inst_idx: instance number index * @indirect: indirectly write sram * * Disable clock gating for VCN block with dpg mode */ -static void vcn_v4_0_5_disable_clock_gating_dpg_mode(struct amdgpu_device *adev, uint8_t sram_sel, - int inst_idx, uint8_t indirect) +static void vcn_v4_0_5_disable_clock_gating_dpg_mode(struct amdgpu_vcn_inst *vinst, + uint8_t sram_sel, + uint8_t indirect) { + struct amdgpu_device *adev = vinst->adev; + int inst_idx = vinst->inst; uint32_t reg_data = 0; if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG) @@ -828,13 +836,14 @@ static void vcn_v4_0_5_disable_clock_gating_dpg_mode(struct amdgpu_device *adev, /** * vcn_v4_0_5_enable_clock_gating - enable VCN clock gating * - * @adev: amdgpu_device pointer - * @inst: instance number + * @vinst: VCN instance * * Enable clock gating for VCN block */ -static void vcn_v4_0_5_enable_clock_gating(struct amdgpu_device *adev, int inst) +static void vcn_v4_0_5_enable_clock_gating(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int inst = vinst->inst; uint32_t data; if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG) @@ -887,14 +896,16 @@ static void vcn_v4_0_5_enable_clock_gating(struct amdgpu_device *adev, int inst) /** * vcn_v4_0_5_start_dpg_mode - VCN start with dpg mode * - * @adev: amdgpu_device pointer - * @inst_idx: instance number index + * @vinst: VCN instance * @indirect: indirectly write sram * * Start VCN block with dpg mode */ -static int vcn_v4_0_5_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect) +static int vcn_v4_0_5_start_dpg_mode(struct amdgpu_vcn_inst *vinst, + bool indirect) { + struct amdgpu_device *adev = vinst->adev; + int inst_idx = vinst->inst; volatile struct amdgpu_vcn4_fw_shared *fw_shared = adev->vcn.inst[inst_idx].fw_shared.cpu_addr; struct amdgpu_ring *ring; uint32_t tmp; @@ -913,7 +924,7 @@ static int vcn_v4_0_5_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, b (uint32_t *)adev->vcn.inst[inst_idx].dpg_sram_cpu_addr; /* enable clock gating */ - vcn_v4_0_5_disable_clock_gating_dpg_mode(adev, 0, inst_idx, indirect); + vcn_v4_0_5_disable_clock_gating_dpg_mode(vinst, 0, indirect); /* enable VCPU clock */ tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT); @@ -961,7 +972,7 @@ static int vcn_v4_0_5_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, b (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) | (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)), 0, indirect); - vcn_v4_0_5_mc_resume_dpg_mode(adev, inst_idx, indirect); + vcn_v4_0_5_mc_resume_dpg_mode(vinst, indirect); tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT); tmp |= UVD_VCPU_CNTL__CLK_EN_MASK; @@ -1014,13 +1025,14 @@ static int vcn_v4_0_5_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, b /** * vcn_v4_0_5_start - VCN start * - * @adev: amdgpu_device pointer - * @i: instance to start + * @vinst: VCN instance * * Start VCN block */ -static int vcn_v4_0_5_start(struct amdgpu_device *adev, int i) +static int vcn_v4_0_5_start(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int i = vinst->inst; volatile struct amdgpu_vcn4_fw_shared *fw_shared; struct amdgpu_ring *ring; uint32_t tmp; @@ -1035,17 +1047,17 @@ static int vcn_v4_0_5_start(struct amdgpu_device *adev, int i) fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) - return vcn_v4_0_5_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram); + return vcn_v4_0_5_start_dpg_mode(vinst, adev->vcn.inst[i].indirect_sram); /* disable VCN power gating */ - vcn_v4_0_5_disable_static_power_gating(adev, i); + vcn_v4_0_5_disable_static_power_gating(vinst); /* set VCN status busy */ tmp = RREG32_SOC15(VCN, i, regUVD_STATUS) | UVD_STATUS__UVD_BUSY; WREG32_SOC15(VCN, i, regUVD_STATUS, tmp); /* SW clock gating */ - vcn_v4_0_5_disable_clock_gating(adev, i); + vcn_v4_0_5_disable_clock_gating(vinst); /* enable VCPU clock */ WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), @@ -1098,7 +1110,7 @@ static int vcn_v4_0_5_start(struct amdgpu_device *adev, int i) (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) | (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT))); - vcn_v4_0_5_mc_resume(adev, i); + vcn_v4_0_5_mc_resume(vinst); /* VCN global tiling registers */ WREG32_SOC15(VCN, i, regUVD_GFX10_ADDR_CONFIG, @@ -1194,13 +1206,14 @@ static int vcn_v4_0_5_start(struct amdgpu_device *adev, int i) /** * vcn_v4_0_5_stop_dpg_mode - VCN stop with dpg mode * - * @adev: amdgpu_device pointer - * @inst_idx: instance number index + * @vinst: VCN instance * * Stop VCN block with dpg mode */ -static void vcn_v4_0_5_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx) +static void vcn_v4_0_5_stop_dpg_mode(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int inst_idx = vinst->inst; uint32_t tmp; /* Wait for power status to be 1 */ @@ -1222,13 +1235,14 @@ static void vcn_v4_0_5_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx) /** * vcn_v4_0_5_stop - VCN stop * - * @adev: amdgpu_device pointer - * @i: instance to stop + * @vinst: VCN instance * * Stop VCN block */ -static int vcn_v4_0_5_stop(struct amdgpu_device *adev, int i) +static int vcn_v4_0_5_stop(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int i = vinst->inst; volatile struct amdgpu_vcn4_fw_shared *fw_shared; uint32_t tmp; int r = 0; @@ -1240,7 +1254,7 @@ static int vcn_v4_0_5_stop(struct amdgpu_device *adev, int i) fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF; if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) { - vcn_v4_0_5_stop_dpg_mode(adev, i); + vcn_v4_0_5_stop_dpg_mode(vinst); r = 0; goto done; } @@ -1294,10 +1308,10 @@ static int vcn_v4_0_5_stop(struct amdgpu_device *adev, int i) WREG32_SOC15(VCN, i, regUVD_STATUS, 0); /* apply HW clock gating */ - vcn_v4_0_5_enable_clock_gating(adev, i); + vcn_v4_0_5_enable_clock_gating(vinst); /* enable VCN power gating */ - vcn_v4_0_5_enable_static_power_gating(adev, i); + vcn_v4_0_5_enable_static_power_gating(vinst); done: if (adev->pm.dpm_enabled) @@ -1531,15 +1545,17 @@ static int vcn_v4_0_5_set_clockgating_state(struct amdgpu_ip_block *ip_block, int i; for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { + struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; + if (adev->vcn.harvest_config & (1 << i)) continue; if (enable) { if (RREG32_SOC15(VCN, i, regUVD_STATUS) != UVD_STATUS__IDLE) return -EBUSY; - vcn_v4_0_5_enable_clock_gating(adev, i); + vcn_v4_0_5_enable_clock_gating(vinst); } else { - vcn_v4_0_5_disable_clock_gating(adev, i); + vcn_v4_0_5_disable_clock_gating(vinst); } } @@ -1551,15 +1567,16 @@ static int vcn_v4_0_5_set_powergating_state_inst(struct amdgpu_ip_block *ip_bloc int i) { struct amdgpu_device *adev = ip_block->adev; + struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; int ret = 0; if (state == adev->vcn.inst[i].cur_state) return 0; if (state == AMD_PG_STATE_GATE) - ret = vcn_v4_0_5_stop(adev, i); + ret = vcn_v4_0_5_stop(vinst); else - ret = vcn_v4_0_5_start(adev, i); + ret = vcn_v4_0_5_start(vinst); if (!ret) adev->vcn.inst[i].cur_state = state; From e3eb71cd699e718f12aea5d16d8d06dd93e35332 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 22 Nov 2024 18:07:03 -0500 Subject: [PATCH 093/235] drm/amdgpu/vcn5.0.0: convert internal functions to use vcn_inst Pass the vcn instance structure to these functions rather than adev and the instance number. TODO: clean up the function internals to use the vinst state directly rather than accessing it indirectly via adev->vcn.inst[]. Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c | 99 ++++++++++++++----------- 1 file changed, 55 insertions(+), 44 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c index d773766ebbe2..288be78280dd 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c @@ -367,13 +367,14 @@ static int vcn_v5_0_0_resume(struct amdgpu_ip_block *ip_block) /** * vcn_v5_0_0_mc_resume - memory controller programming * - * @adev: amdgpu_device pointer - * @inst: instance number + * @vinst: VCN instance * * Let the VCN memory controller know it's offsets */ -static void vcn_v5_0_0_mc_resume(struct amdgpu_device *adev, int inst) +static void vcn_v5_0_0_mc_resume(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int inst = vinst->inst; uint32_t offset, size; const struct common_firmware_header *hdr; @@ -427,14 +428,16 @@ static void vcn_v5_0_0_mc_resume(struct amdgpu_device *adev, int inst) /** * vcn_v5_0_0_mc_resume_dpg_mode - memory controller programming for dpg mode * - * @adev: amdgpu_device pointer - * @inst_idx: instance number index + * @vinst: VCN instance * @indirect: indirectly write sram * * Let the VCN memory controller know it's offsets with dpg mode */ -static void vcn_v5_0_0_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect) +static void vcn_v5_0_0_mc_resume_dpg_mode(struct amdgpu_vcn_inst *vinst, + bool indirect) { + struct amdgpu_device *adev = vinst->adev; + int inst_idx = vinst->inst; uint32_t offset, size; const struct common_firmware_header *hdr; @@ -537,13 +540,14 @@ static void vcn_v5_0_0_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_i /** * vcn_v5_0_0_disable_static_power_gating - disable VCN static power gating * - * @adev: amdgpu_device pointer - * @inst: instance number + * @vinst: VCN instance * * Disable static power gating for VCN block */ -static void vcn_v5_0_0_disable_static_power_gating(struct amdgpu_device *adev, int inst) +static void vcn_v5_0_0_disable_static_power_gating(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int inst = vinst->inst; uint32_t data = 0; if (adev->pg_flags & AMD_PG_SUPPORT_VCN) { @@ -604,13 +608,14 @@ static void vcn_v5_0_0_disable_static_power_gating(struct amdgpu_device *adev, i /** * vcn_v5_0_0_enable_static_power_gating - enable VCN static power gating * - * @adev: amdgpu_device pointer - * @inst: instance number + * @vinst: VCN instance * * Enable static power gating for VCN block */ -static void vcn_v5_0_0_enable_static_power_gating(struct amdgpu_device *adev, int inst) +static void vcn_v5_0_0_enable_static_power_gating(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int inst = vinst->inst; uint32_t data; if (adev->pg_flags & AMD_PG_SUPPORT_VCN) { @@ -650,12 +655,11 @@ static void vcn_v5_0_0_enable_static_power_gating(struct amdgpu_device *adev, in /** * vcn_v5_0_0_disable_clock_gating - disable VCN clock gating * - * @adev: amdgpu_device pointer - * @inst: instance number + * @vinst: VCN instance * * Disable clock gating for VCN block */ -static void vcn_v5_0_0_disable_clock_gating(struct amdgpu_device *adev, int inst) +static void vcn_v5_0_0_disable_clock_gating(struct amdgpu_vcn_inst *vinst) { return; } @@ -664,15 +668,15 @@ static void vcn_v5_0_0_disable_clock_gating(struct amdgpu_device *adev, int inst /** * vcn_v5_0_0_disable_clock_gating_dpg_mode - disable VCN clock gating dpg mode * - * @adev: amdgpu_device pointer + * @vinst: VCN instance * @sram_sel: sram select - * @inst_idx: instance number index * @indirect: indirectly write sram * * Disable clock gating for VCN block with dpg mode */ -static void vcn_v5_0_0_disable_clock_gating_dpg_mode(struct amdgpu_device *adev, uint8_t sram_sel, - int inst_idx, uint8_t indirect) +static void vcn_v5_0_0_disable_clock_gating_dpg_mode(struct amdgpu_vcn_inst *vinst, + uint8_t sram_sel, + uint8_t indirect) { return; } @@ -681,12 +685,11 @@ static void vcn_v5_0_0_disable_clock_gating_dpg_mode(struct amdgpu_device *adev, /** * vcn_v5_0_0_enable_clock_gating - enable VCN clock gating * - * @adev: amdgpu_device pointer - * @inst: instance number + * @vinst: VCN instance * * Enable clock gating for VCN block */ -static void vcn_v5_0_0_enable_clock_gating(struct amdgpu_device *adev, int inst) +static void vcn_v5_0_0_enable_clock_gating(struct amdgpu_vcn_inst *vinst) { return; } @@ -694,14 +697,16 @@ static void vcn_v5_0_0_enable_clock_gating(struct amdgpu_device *adev, int inst) /** * vcn_v5_0_0_start_dpg_mode - VCN start with dpg mode * - * @adev: amdgpu_device pointer - * @inst_idx: instance number index + * @vinst: VCN instance * @indirect: indirectly write sram * * Start VCN block with dpg mode */ -static int vcn_v5_0_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect) +static int vcn_v5_0_0_start_dpg_mode(struct amdgpu_vcn_inst *vinst, + bool indirect) { + struct amdgpu_device *adev = vinst->adev; + int inst_idx = vinst->inst; volatile struct amdgpu_vcn5_fw_shared *fw_shared = adev->vcn.inst[inst_idx].fw_shared.cpu_addr; struct amdgpu_ring *ring; uint32_t tmp; @@ -741,7 +746,7 @@ static int vcn_v5_0_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, b WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET( VCN, inst_idx, regUVD_LMI_CTRL), tmp, 0, indirect); - vcn_v5_0_0_mc_resume_dpg_mode(adev, inst_idx, indirect); + vcn_v5_0_0_mc_resume_dpg_mode(vinst, indirect); tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT); tmp |= UVD_VCPU_CNTL__CLK_EN_MASK; @@ -793,13 +798,14 @@ static int vcn_v5_0_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, b /** * vcn_v5_0_0_start - VCN start * - * @adev: amdgpu_device pointer - * @i: instance to start + * @vinst: VCN instance * * Start VCN block */ -static int vcn_v5_0_0_start(struct amdgpu_device *adev, int i) +static int vcn_v5_0_0_start(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int i = vinst->inst; volatile struct amdgpu_vcn5_fw_shared *fw_shared; struct amdgpu_ring *ring; uint32_t tmp; @@ -814,10 +820,10 @@ static int vcn_v5_0_0_start(struct amdgpu_device *adev, int i) fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) - return vcn_v5_0_0_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram); + return vcn_v5_0_0_start_dpg_mode(vinst, adev->vcn.inst[i].indirect_sram); /* disable VCN power gating */ - vcn_v5_0_0_disable_static_power_gating(adev, i); + vcn_v5_0_0_disable_static_power_gating(vinst); /* set VCN status busy */ tmp = RREG32_SOC15(VCN, i, regUVD_STATUS) | UVD_STATUS__UVD_BUSY; @@ -848,7 +854,7 @@ static int vcn_v5_0_0_start(struct amdgpu_device *adev, int i) UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK | UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK); - vcn_v5_0_0_mc_resume(adev, i); + vcn_v5_0_0_mc_resume(vinst); /* VCN global tiling registers */ WREG32_SOC15(VCN, i, regUVD_GFX10_ADDR_CONFIG, @@ -944,13 +950,14 @@ static int vcn_v5_0_0_start(struct amdgpu_device *adev, int i) /** * vcn_v5_0_0_stop_dpg_mode - VCN stop with dpg mode * - * @adev: amdgpu_device pointer - * @inst_idx: instance number index + * @vinst: VCN instance * * Stop VCN block with dpg mode */ -static void vcn_v5_0_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx) +static void vcn_v5_0_0_stop_dpg_mode(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int inst_idx = vinst->inst; struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE}; uint32_t tmp; @@ -974,13 +981,14 @@ static void vcn_v5_0_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx) /** * vcn_v5_0_0_stop - VCN stop * - * @adev: amdgpu_device pointer - * @i: instance to stop + * @vinst: VCN instance * * Stop VCN block */ -static int vcn_v5_0_0_stop(struct amdgpu_device *adev, int i) +static int vcn_v5_0_0_stop(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int i = vinst->inst; volatile struct amdgpu_vcn5_fw_shared *fw_shared; uint32_t tmp; int r = 0; @@ -992,7 +1000,7 @@ static int vcn_v5_0_0_stop(struct amdgpu_device *adev, int i) fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF; if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) { - vcn_v5_0_0_stop_dpg_mode(adev, i); + vcn_v5_0_0_stop_dpg_mode(vinst); r = 0; goto done; } @@ -1046,7 +1054,7 @@ static int vcn_v5_0_0_stop(struct amdgpu_device *adev, int i) WREG32_SOC15(VCN, i, regUVD_STATUS, 0); /* enable VCN power gating */ - vcn_v5_0_0_enable_static_power_gating(adev, i); + vcn_v5_0_0_enable_static_power_gating(vinst); done: if (adev->pm.dpm_enabled) @@ -1273,15 +1281,17 @@ static int vcn_v5_0_0_set_clockgating_state(struct amdgpu_ip_block *ip_block, int i; for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { + struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; + if (adev->vcn.harvest_config & (1 << i)) continue; if (enable) { if (RREG32_SOC15(VCN, i, regUVD_STATUS) != UVD_STATUS__IDLE) return -EBUSY; - vcn_v5_0_0_enable_clock_gating(adev, i); + vcn_v5_0_0_enable_clock_gating(vinst); } else { - vcn_v5_0_0_disable_clock_gating(adev, i); + vcn_v5_0_0_disable_clock_gating(vinst); } } @@ -1293,15 +1303,16 @@ static int vcn_v5_0_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_bloc int i) { struct amdgpu_device *adev = ip_block->adev; + struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; int ret = 0; if (state == adev->vcn.inst[i].cur_state) return 0; if (state == AMD_PG_STATE_GATE) - ret = vcn_v5_0_0_stop(adev, i); + ret = vcn_v5_0_0_stop(vinst); else - ret = vcn_v5_0_0_start(adev, i); + ret = vcn_v5_0_0_start(vinst); if (!ret) adev->vcn.inst[i].cur_state = state; From 0a3fb7338fb05285de76ce38fcf56cc3ab61d982 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 10 Dec 2024 14:00:57 -0500 Subject: [PATCH 094/235] drm/amdgpu/vcn5.0.1: convert internal functions to use vcn_inst Pass the vcn instance structure to these functions rather than adev and the instance number. TODO: clean up the function internals to use the vinst state directly rather than accessing it indirectly via adev->vcn.inst[]. Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c | 71 ++++++++++++++----------- 1 file changed, 41 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c index afa8f1f0b572..e3398eb39e5f 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c @@ -282,13 +282,14 @@ static int vcn_v5_0_1_resume(struct amdgpu_ip_block *ip_block) /** * vcn_v5_0_1_mc_resume - memory controller programming * - * @adev: amdgpu_device pointer - * @inst: instance number + * @vinst: VCN instance * * Let the VCN memory controller know it's offsets */ -static void vcn_v5_0_1_mc_resume(struct amdgpu_device *adev, int inst) +static void vcn_v5_0_1_mc_resume(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int inst = vinst->inst; uint32_t offset, size, vcn_inst; const struct common_firmware_header *hdr; @@ -344,14 +345,16 @@ static void vcn_v5_0_1_mc_resume(struct amdgpu_device *adev, int inst) /** * vcn_v5_0_1_mc_resume_dpg_mode - memory controller programming for dpg mode * - * @adev: amdgpu_device pointer - * @inst_idx: instance number index + * @vinst: VCN instance * @indirect: indirectly write sram * * Let the VCN memory controller know it's offsets with dpg mode */ -static void vcn_v5_0_1_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect) +static void vcn_v5_0_1_mc_resume_dpg_mode(struct amdgpu_vcn_inst *vinst, + bool indirect) { + struct amdgpu_device *adev = vinst->adev; + int inst_idx = vinst->inst; uint32_t offset, size; const struct common_firmware_header *hdr; @@ -456,38 +459,38 @@ static void vcn_v5_0_1_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_i /** * vcn_v5_0_1_disable_clock_gating - disable VCN clock gating * - * @adev: amdgpu_device pointer - * @inst: instance number + * @vinst: VCN instance * * Disable clock gating for VCN block */ -static void vcn_v5_0_1_disable_clock_gating(struct amdgpu_device *adev, int inst) +static void vcn_v5_0_1_disable_clock_gating(struct amdgpu_vcn_inst *vinst) { } /** * vcn_v5_0_1_enable_clock_gating - enable VCN clock gating * - * @adev: amdgpu_device pointer - * @inst: instance number + * @vinst: VCN instance * * Enable clock gating for VCN block */ -static void vcn_v5_0_1_enable_clock_gating(struct amdgpu_device *adev, int inst) +static void vcn_v5_0_1_enable_clock_gating(struct amdgpu_vcn_inst *vinst) { } /** * vcn_v5_0_1_start_dpg_mode - VCN start with dpg mode * - * @adev: amdgpu_device pointer - * @inst_idx: instance number index + * @vinst: VCN instance * @indirect: indirectly write sram * * Start VCN block with dpg mode */ -static int vcn_v5_0_1_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect) +static int vcn_v5_0_1_start_dpg_mode(struct amdgpu_vcn_inst *vinst, + bool indirect) { + struct amdgpu_device *adev = vinst->adev; + int inst_idx = vinst->inst; volatile struct amdgpu_vcn4_fw_shared *fw_shared = adev->vcn.inst[inst_idx].fw_shared.cpu_addr; struct amdgpu_ring *ring; @@ -535,7 +538,7 @@ static int vcn_v5_0_1_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, b WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET( VCN, 0, regUVD_LMI_CTRL), tmp, 0, indirect); - vcn_v5_0_1_mc_resume_dpg_mode(adev, inst_idx, indirect); + vcn_v5_0_1_mc_resume_dpg_mode(vinst, indirect); tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT); tmp |= UVD_VCPU_CNTL__CLK_EN_MASK; @@ -589,12 +592,14 @@ static int vcn_v5_0_1_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, b /** * vcn_v5_0_1_start - VCN start * - * @adev: amdgpu_device pointer + * @vinst: VCN instance * * Start VCN block */ -static int vcn_v5_0_1_start(struct amdgpu_device *adev, int i) +static int vcn_v5_0_1_start(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int i = vinst->inst; volatile struct amdgpu_vcn4_fw_shared *fw_shared; struct amdgpu_ring *ring; uint32_t tmp; @@ -603,7 +608,7 @@ static int vcn_v5_0_1_start(struct amdgpu_device *adev, int i) fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) - return vcn_v5_0_1_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram); + return vcn_v5_0_1_start_dpg_mode(vinst, adev->vcn.inst[i].indirect_sram); vcn_inst = GET_INST(VCN, i); @@ -636,7 +641,7 @@ static int vcn_v5_0_1_start(struct amdgpu_device *adev, int i) UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK | UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK); - vcn_v5_0_1_mc_resume(adev, i); + vcn_v5_0_1_mc_resume(vinst); /* VCN global tiling registers */ WREG32_SOC15(VCN, vcn_inst, regUVD_GFX10_ADDR_CONFIG, @@ -736,13 +741,14 @@ static int vcn_v5_0_1_start(struct amdgpu_device *adev, int i) /** * vcn_v5_0_1_stop_dpg_mode - VCN stop with dpg mode * - * @adev: amdgpu_device pointer - * @inst_idx: instance number index + * @vinst: VCN instance * * Stop VCN block with dpg mode */ -static void vcn_v5_0_1_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx) +static void vcn_v5_0_1_stop_dpg_mode(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int inst_idx = vinst->inst; uint32_t tmp; int vcn_inst; @@ -764,12 +770,14 @@ static void vcn_v5_0_1_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx) /** * vcn_v5_0_1_stop - VCN stop * - * @adev: amdgpu_device pointer + * @vinst: VCN instance * * Stop VCN block */ -static int vcn_v5_0_1_stop(struct amdgpu_device *adev, int i) +static int vcn_v5_0_1_stop(struct amdgpu_vcn_inst *vinst) { + struct amdgpu_device *adev = vinst->adev; + int i = vinst->inst; volatile struct amdgpu_vcn4_fw_shared *fw_shared; uint32_t tmp; int r = 0, vcn_inst; @@ -780,7 +788,7 @@ static int vcn_v5_0_1_stop(struct amdgpu_device *adev, int i) fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF; if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) { - vcn_v5_0_1_stop_dpg_mode(adev, i); + vcn_v5_0_1_stop_dpg_mode(vinst); return 0; } @@ -999,12 +1007,14 @@ static int vcn_v5_0_1_set_clockgating_state(struct amdgpu_ip_block *ip_block, int i; for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { + struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; + if (enable) { if (RREG32_SOC15(VCN, GET_INST(VCN, i), regUVD_STATUS) != UVD_STATUS__IDLE) return -EBUSY; - vcn_v5_0_1_enable_clock_gating(adev, i); + vcn_v5_0_1_enable_clock_gating(vinst); } else { - vcn_v5_0_1_disable_clock_gating(adev, i); + vcn_v5_0_1_disable_clock_gating(vinst); } } @@ -1016,15 +1026,16 @@ static int vcn_v5_0_1_set_powergating_state_inst(struct amdgpu_ip_block *ip_bloc int i) { struct amdgpu_device *adev = ip_block->adev; + struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; int ret = 0; if (state == adev->vcn.inst[i].cur_state) return 0; if (state == AMD_PG_STATE_GATE) - ret = vcn_v5_0_1_stop(adev, i); + ret = vcn_v5_0_1_stop(vinst); else - ret = vcn_v5_0_1_start(adev, i); + ret = vcn_v5_0_1_start(vinst); if (!ret) adev->vcn.inst[i].cur_state = state; From 64303b72de787b61a7d295d6973f5fbd955b85a5 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 26 Nov 2024 11:14:58 -0500 Subject: [PATCH 095/235] drm/amdgpu/vcn: adjust pause_dpg_mode function signature Change it to take a vcn instance rather than adev to align with the vcn instance changes. TODO: clean up the function internals to use the vinst state directly rather than accessing it indirectly via adev->vcn.inst[]. Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h | 3 +-- drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c | 14 ++++++++------ drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c | 12 +++++++----- drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c | 10 ++++++---- drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 12 +++++++----- drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c | 15 ++++++++------- drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c | 11 +++++------ drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c | 13 +++++++------ drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c | 15 ++++++++------- 10 files changed, 59 insertions(+), 50 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c index 010cc64a950a..a2250747a7c8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c @@ -417,7 +417,7 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work) else new_state.fw_based = VCN_DPG_STATE__UNPAUSE; - adev->vcn.inst[i].pause_dpg_mode(adev, i, &new_state); + adev->vcn.inst[i].pause_dpg_mode(vcn_inst, &new_state); } fence[i] += amdgpu_fence_count_emitted(&vcn_inst->ring_dec); @@ -474,7 +474,7 @@ void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring) new_state.fw_based = VCN_DPG_STATE__UNPAUSE; } - adev->vcn.inst[ring->me].pause_dpg_mode(adev, ring->me, &new_state); + adev->vcn.inst[ring->me].pause_dpg_mode(&adev->vcn.inst[ring->me], &new_state); } mutex_unlock(&adev->vcn.inst[ring->me].vcn_pg_lock); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h index 5f92cf28cc75..8d34e3814ab1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h @@ -327,8 +327,7 @@ struct amdgpu_vcn_inst { bool indirect_sram; struct amdgpu_vcn_reg internal; struct mutex vcn1_jpeg1_workaround; - int (*pause_dpg_mode)(struct amdgpu_device *adev, - int inst_idx, + int (*pause_dpg_mode)(struct amdgpu_vcn_inst *vinst, struct dpg_pause_state *new_state); bool using_unified_queue; }; diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c index 267bfc32284c..9c583ae0ff7e 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c @@ -87,8 +87,8 @@ static void vcn_v1_0_set_enc_ring_funcs(struct amdgpu_device *adev); static void vcn_v1_0_set_irq_funcs(struct amdgpu_device *adev); static int vcn_v1_0_set_powergating_state(struct amdgpu_ip_block *ip_block, enum amd_powergating_state state); -static int vcn_v1_0_pause_dpg_mode(struct amdgpu_device *adev, - int inst_idx, struct dpg_pause_state *new_state); +static int vcn_v1_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst, + struct dpg_pause_state *new_state); static void vcn_v1_0_idle_work_handler(struct work_struct *work); static void vcn_v1_0_ring_begin_use(struct amdgpu_ring *ring); @@ -1264,9 +1264,11 @@ static int vcn_v1_0_stop(struct amdgpu_vcn_inst *vinst) return r; } -static int vcn_v1_0_pause_dpg_mode(struct amdgpu_device *adev, - int inst_idx, struct dpg_pause_state *new_state) +static int vcn_v1_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst, + struct dpg_pause_state *new_state) { + struct amdgpu_device *adev = vinst->adev; + int inst_idx = vinst->inst; int ret_code; uint32_t reg_data = 0; uint32_t reg_data2 = 0; @@ -1866,7 +1868,7 @@ static void vcn_v1_0_idle_work_handler(struct work_struct *work) else new_state.jpeg = VCN_DPG_STATE__UNPAUSE; - adev->vcn.inst[0].pause_dpg_mode(adev, 0, &new_state); + adev->vcn.inst->pause_dpg_mode(vcn_inst, &new_state); } fences += amdgpu_fence_count_emitted(adev->jpeg.inst->ring_dec); @@ -1933,7 +1935,7 @@ void vcn_v1_0_set_pg_for_begin_use(struct amdgpu_ring *ring, bool set_clocks) else if (ring->funcs->type == AMDGPU_RING_TYPE_VCN_JPEG) new_state.jpeg = VCN_DPG_STATE__PAUSE; - adev->vcn.inst[0].pause_dpg_mode(adev, 0, &new_state); + adev->vcn.inst->pause_dpg_mode(adev->vcn.inst, &new_state); } } diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c index 43672ba236e3..506b070be3ec 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c @@ -94,8 +94,8 @@ static void vcn_v2_0_set_enc_ring_funcs(struct amdgpu_device *adev); static void vcn_v2_0_set_irq_funcs(struct amdgpu_device *adev); static int vcn_v2_0_set_powergating_state(struct amdgpu_ip_block *ip_block, enum amd_powergating_state state); -static int vcn_v2_0_pause_dpg_mode(struct amdgpu_device *adev, - int inst_idx, struct dpg_pause_state *new_state); +static int vcn_v2_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst, + struct dpg_pause_state *new_state); static int vcn_v2_0_start_sriov(struct amdgpu_device *adev); /** * vcn_v2_0_early_init - set function pointers and load microcode @@ -1158,7 +1158,7 @@ static int vcn_v2_0_stop_dpg_mode(struct amdgpu_vcn_inst *vinst) struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE}; uint32_t tmp; - vcn_v2_0_pause_dpg_mode(adev, 0, &state); + vcn_v2_0_pause_dpg_mode(vinst, &state); /* Wait for power status to be 1 */ SOC15_WAIT_ON_RREG(UVD, 0, mmUVD_POWER_STATUS, 1, UVD_POWER_STATUS__UVD_POWER_STATUS_MASK); @@ -1252,9 +1252,11 @@ static int vcn_v2_0_stop(struct amdgpu_vcn_inst *vinst) return 0; } -static int vcn_v2_0_pause_dpg_mode(struct amdgpu_device *adev, - int inst_idx, struct dpg_pause_state *new_state) +static int vcn_v2_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst, + struct dpg_pause_state *new_state) { + struct amdgpu_device *adev = vinst->adev; + int inst_idx = vinst->inst; struct amdgpu_ring *ring; uint32_t reg_data = 0; int ret_code; diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c index 5df2decd9d79..9752f99297df 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c @@ -100,8 +100,8 @@ static int vcn_v2_5_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, int i); static int vcn_v2_5_set_powergating_state(struct amdgpu_ip_block *ip_block, enum amd_powergating_state state); -static int vcn_v2_5_pause_dpg_mode(struct amdgpu_device *adev, - int inst_idx, struct dpg_pause_state *new_state); +static int vcn_v2_5_pause_dpg_mode(struct amdgpu_vcn_inst *vinst, + struct dpg_pause_state *new_state); static int vcn_v2_5_sriov_start(struct amdgpu_device *adev); static void vcn_v2_5_set_ras_funcs(struct amdgpu_device *adev); @@ -1510,9 +1510,11 @@ static int vcn_v2_5_stop(struct amdgpu_vcn_inst *vinst) return r; } -static int vcn_v2_5_pause_dpg_mode(struct amdgpu_device *adev, - int inst_idx, struct dpg_pause_state *new_state) +static int vcn_v2_5_pause_dpg_mode(struct amdgpu_vcn_inst *vinst, + struct dpg_pause_state *new_state) { + struct amdgpu_device *adev = vinst->adev; + int inst_idx = vinst->inst; struct amdgpu_ring *ring; uint32_t reg_data = 0; int ret_code = 0; diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c index 2fd58d548b19..7e98f251f23e 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c @@ -110,8 +110,8 @@ static int vcn_v3_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, int i); static int vcn_v3_0_set_powergating_state(struct amdgpu_ip_block *ip_block, enum amd_powergating_state state); -static int vcn_v3_0_pause_dpg_mode(struct amdgpu_device *adev, - int inst_idx, struct dpg_pause_state *new_state); +static int vcn_v3_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst, + struct dpg_pause_state *new_state); static void vcn_v3_0_dec_ring_set_wptr(struct amdgpu_ring *ring); static void vcn_v3_0_enc_ring_set_wptr(struct amdgpu_ring *ring); @@ -1581,7 +1581,7 @@ static int vcn_v3_0_stop_dpg_mode(struct amdgpu_vcn_inst *vinst) struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE}; uint32_t tmp; - vcn_v3_0_pause_dpg_mode(adev, inst_idx, &state); + vcn_v3_0_pause_dpg_mode(vinst, &state); /* Wait for power status to be 1 */ SOC15_WAIT_ON_RREG(VCN, inst_idx, mmUVD_POWER_STATUS, 1, @@ -1683,9 +1683,11 @@ static int vcn_v3_0_stop(struct amdgpu_vcn_inst *vinst) return r; } -static int vcn_v3_0_pause_dpg_mode(struct amdgpu_device *adev, - int inst_idx, struct dpg_pause_state *new_state) +static int vcn_v3_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst, + struct dpg_pause_state *new_state) { + struct amdgpu_device *adev = vinst->adev; + int inst_idx = vinst->inst; volatile struct amdgpu_fw_shared *fw_shared; struct amdgpu_ring *ring; uint32_t reg_data = 0; diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c index 0e6af9be0d3c..41ec696bd210 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c @@ -101,8 +101,8 @@ static int vcn_v4_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, int i); static int vcn_v4_0_set_powergating_state(struct amdgpu_ip_block *ip_block, enum amd_powergating_state state); -static int vcn_v4_0_pause_dpg_mode(struct amdgpu_device *adev, - int inst_idx, struct dpg_pause_state *new_state); +static int vcn_v4_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst, + struct dpg_pause_state *new_state); static void vcn_v4_0_unified_ring_set_wptr(struct amdgpu_ring *ring); static void vcn_v4_0_set_ras_funcs(struct amdgpu_device *adev); @@ -1565,7 +1565,7 @@ static void vcn_v4_0_stop_dpg_mode(struct amdgpu_vcn_inst *vinst) struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE}; uint32_t tmp; - vcn_v4_0_pause_dpg_mode(adev, inst_idx, &state); + vcn_v4_0_pause_dpg_mode(vinst, &state); /* Wait for power status to be 1 */ SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_POWER_STATUS, 1, UVD_POWER_STATUS__UVD_POWER_STATUS_MASK); @@ -1673,15 +1673,16 @@ static int vcn_v4_0_stop(struct amdgpu_vcn_inst *vinst) /** * vcn_v4_0_pause_dpg_mode - VCN pause with dpg mode * - * @adev: amdgpu_device pointer - * @inst_idx: instance number index + * @vinst: VCN instance * @new_state: pause state * * Pause dpg mode for VCN block */ -static int vcn_v4_0_pause_dpg_mode(struct amdgpu_device *adev, int inst_idx, - struct dpg_pause_state *new_state) +static int vcn_v4_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst, + struct dpg_pause_state *new_state) { + struct amdgpu_device *adev = vinst->adev; + int inst_idx = vinst->inst; uint32_t reg_data = 0; int ret_code; diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c index 9e1c25210f88..e681e0939eeb 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c @@ -92,8 +92,8 @@ static int vcn_v4_0_3_set_powergating_state_inst(struct amdgpu_ip_block *ip_bloc int i); static int vcn_v4_0_3_set_powergating_state(struct amdgpu_ip_block *ip_block, enum amd_powergating_state state); -static int vcn_v4_0_3_pause_dpg_mode(struct amdgpu_device *adev, - int inst_idx, struct dpg_pause_state *new_state); +static int vcn_v4_0_3_pause_dpg_mode(struct amdgpu_vcn_inst *vinst, + struct dpg_pause_state *new_state); static void vcn_v4_0_3_unified_ring_set_wptr(struct amdgpu_ring *ring); static void vcn_v4_0_3_set_ras_funcs(struct amdgpu_device *adev); static void vcn_v4_0_3_enable_ras(struct amdgpu_device *adev, @@ -1443,14 +1443,13 @@ static int vcn_v4_0_3_stop(struct amdgpu_vcn_inst *vinst) /** * vcn_v4_0_3_pause_dpg_mode - VCN pause with dpg mode * - * @adev: amdgpu_device pointer - * @inst_idx: instance number index + * @vinst: VCN instance * @new_state: pause state * * Pause dpg mode for VCN block */ -static int vcn_v4_0_3_pause_dpg_mode(struct amdgpu_device *adev, int inst_idx, - struct dpg_pause_state *new_state) +static int vcn_v4_0_3_pause_dpg_mode(struct amdgpu_vcn_inst *vinst, + struct dpg_pause_state *new_state) { return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c index 9b5c6812a0b4..3e2206e5e0e1 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c @@ -100,8 +100,8 @@ static int vcn_v4_0_5_set_powergating_state_inst(struct amdgpu_ip_block *ip_bloc int i); static int vcn_v4_0_5_set_powergating_state(struct amdgpu_ip_block *ip_block, enum amd_powergating_state state); -static int vcn_v4_0_5_pause_dpg_mode(struct amdgpu_device *adev, - int inst_idx, struct dpg_pause_state *new_state); +static int vcn_v4_0_5_pause_dpg_mode(struct amdgpu_vcn_inst *vinst, + struct dpg_pause_state *new_state); static void vcn_v4_0_5_unified_ring_set_wptr(struct amdgpu_ring *ring); /** @@ -1323,15 +1323,16 @@ static int vcn_v4_0_5_stop(struct amdgpu_vcn_inst *vinst) /** * vcn_v4_0_5_pause_dpg_mode - VCN pause with dpg mode * - * @adev: amdgpu_device pointer - * @inst_idx: instance number index + * @vinst: VCN instance * @new_state: pause state * * Pause dpg mode for VCN block */ -static int vcn_v4_0_5_pause_dpg_mode(struct amdgpu_device *adev, int inst_idx, - struct dpg_pause_state *new_state) +static int vcn_v4_0_5_pause_dpg_mode(struct amdgpu_vcn_inst *vinst, + struct dpg_pause_state *new_state) { + struct amdgpu_device *adev = vinst->adev; + int inst_idx = vinst->inst; uint32_t reg_data = 0; int ret_code; diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c index 288be78280dd..ec57c7dd78bf 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c @@ -83,8 +83,8 @@ static int vcn_v5_0_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_bloc int i); static int vcn_v5_0_0_set_powergating_state(struct amdgpu_ip_block *ip_block, enum amd_powergating_state state); -static int vcn_v5_0_0_pause_dpg_mode(struct amdgpu_device *adev, - int inst_idx, struct dpg_pause_state *new_state); +static int vcn_v5_0_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst, + struct dpg_pause_state *new_state); static void vcn_v5_0_0_unified_ring_set_wptr(struct amdgpu_ring *ring); /** @@ -961,7 +961,7 @@ static void vcn_v5_0_0_stop_dpg_mode(struct amdgpu_vcn_inst *vinst) struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE}; uint32_t tmp; - vcn_v5_0_0_pause_dpg_mode(adev, inst_idx, &state); + vcn_v5_0_0_pause_dpg_mode(vinst, &state); /* Wait for power status to be 1 */ SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_POWER_STATUS, 1, @@ -1066,15 +1066,16 @@ static int vcn_v5_0_0_stop(struct amdgpu_vcn_inst *vinst) /** * vcn_v5_0_0_pause_dpg_mode - VCN pause with dpg mode * - * @adev: amdgpu_device pointer - * @inst_idx: instance number index + * @vinst: VCN instance * @new_state: pause state * * Pause dpg mode for VCN block */ -static int vcn_v5_0_0_pause_dpg_mode(struct amdgpu_device *adev, int inst_idx, - struct dpg_pause_state *new_state) +static int vcn_v5_0_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst, + struct dpg_pause_state *new_state) { + struct amdgpu_device *adev = vinst->adev; + int inst_idx = vinst->inst; uint32_t reg_data = 0; int ret_code; From 55945f08d9b7a13f92a6fb7f681b95c031627a1a Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 26 Nov 2024 11:27:06 -0500 Subject: [PATCH 096/235] drm/amdgpu/vcn: add new per instance callback for powergating This is per instance so add a new function pointer for it. Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h index 8d34e3814ab1..508fa022df78 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h @@ -329,6 +329,8 @@ struct amdgpu_vcn_inst { struct mutex vcn1_jpeg1_workaround; int (*pause_dpg_mode)(struct amdgpu_vcn_inst *vinst, struct dpg_pause_state *new_state); + int (*set_pg_state)(struct amdgpu_vcn_inst *vinst, + enum amd_powergating_state state); bool using_unified_queue; }; From c5ed3655cde2db070e64b721029ec9fee94ecae5 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 26 Nov 2024 10:52:15 -0500 Subject: [PATCH 097/235] drm/amdgpu/vcn1.0: add set_pg_state callback Rework the code as a vcn instance callback. Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c | 32 ++++++++++++++++++--------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c index 9c583ae0ff7e..f017c33e663d 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c @@ -85,6 +85,8 @@ static int vcn_v1_0_stop(struct amdgpu_vcn_inst *vinst); static void vcn_v1_0_set_dec_ring_funcs(struct amdgpu_device *adev); static void vcn_v1_0_set_enc_ring_funcs(struct amdgpu_device *adev); static void vcn_v1_0_set_irq_funcs(struct amdgpu_device *adev); +static int vcn_v1_0_set_pg_state(struct amdgpu_vcn_inst *vinst, + enum amd_powergating_state state); static int vcn_v1_0_set_powergating_state(struct amdgpu_ip_block *ip_block, enum amd_powergating_state state); static int vcn_v1_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst, @@ -106,6 +108,7 @@ static int vcn_v1_0_early_init(struct amdgpu_ip_block *ip_block) struct amdgpu_device *adev = ip_block->adev; adev->vcn.inst[0].num_enc_rings = 2; + adev->vcn.inst[0].set_pg_state = vcn_v1_0_set_pg_state; vcn_v1_0_set_dec_ring_funcs(adev); vcn_v1_0_set_enc_ring_funcs(adev); @@ -276,13 +279,14 @@ static int vcn_v1_0_hw_init(struct amdgpu_ip_block *ip_block) static int vcn_v1_0_hw_fini(struct amdgpu_ip_block *ip_block) { struct amdgpu_device *adev = ip_block->adev; + struct amdgpu_vcn_inst *vinst = adev->vcn.inst; - cancel_delayed_work_sync(&adev->vcn.inst[0].idle_work); + cancel_delayed_work_sync(&vinst->idle_work); if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) || - (adev->vcn.inst[0].cur_state != AMD_PG_STATE_GATE && - RREG32_SOC15(VCN, 0, mmUVD_STATUS))) { - vcn_v1_0_set_powergating_state(ip_block, AMD_PG_STATE_GATE); + (vinst->cur_state != AMD_PG_STATE_GATE && + RREG32_SOC15(VCN, 0, mmUVD_STATUS))) { + vinst->set_pg_state(vinst, AMD_PG_STATE_GATE); } return 0; @@ -1818,8 +1822,8 @@ static void vcn_v1_0_dec_ring_insert_nop(struct amdgpu_ring *ring, uint32_t coun } } -static int vcn_v1_0_set_powergating_state(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state) +static int vcn_v1_0_set_pg_state(struct amdgpu_vcn_inst *vinst, + enum amd_powergating_state state) { /* This doesn't actually powergate the VCN block. * That's done in the dpm code via the SMC. This @@ -1829,10 +1833,8 @@ static int vcn_v1_0_set_powergating_state(struct amdgpu_ip_block *ip_block, * the smc and the hw blocks */ int ret; - struct amdgpu_device *adev = ip_block->adev; - struct amdgpu_vcn_inst *vinst = adev->vcn.inst; - if (state == adev->vcn.inst[0].cur_state) + if (state == vinst->cur_state) return 0; if (state == AMD_PG_STATE_GATE) @@ -1841,10 +1843,20 @@ static int vcn_v1_0_set_powergating_state(struct amdgpu_ip_block *ip_block, ret = vcn_v1_0_start(vinst); if (!ret) - adev->vcn.inst[0].cur_state = state; + vinst->cur_state = state; + return ret; } +static int vcn_v1_0_set_powergating_state(struct amdgpu_ip_block *ip_block, + enum amd_powergating_state state) +{ + struct amdgpu_device *adev = ip_block->adev; + struct amdgpu_vcn_inst *vinst = adev->vcn.inst; + + return vinst->set_pg_state(vinst, state); +} + static void vcn_v1_0_idle_work_handler(struct work_struct *work) { struct amdgpu_vcn_inst *vcn_inst = From 40c6d55806a7da7e269f43af1410a36f865c0956 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 26 Nov 2024 10:57:48 -0500 Subject: [PATCH 098/235] drm/amdgpu/vcn2.0: add set_pg_state callback Rework the code as a vcn instance callback. Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c | 35 ++++++++++++++++++--------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c index 506b070be3ec..3b41c9c625c6 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c @@ -92,6 +92,8 @@ static const struct amdgpu_hwip_reg_entry vcn_reg_list_2_0[] = { static void vcn_v2_0_set_dec_ring_funcs(struct amdgpu_device *adev); static void vcn_v2_0_set_enc_ring_funcs(struct amdgpu_device *adev); static void vcn_v2_0_set_irq_funcs(struct amdgpu_device *adev); +static int vcn_v2_0_set_pg_state(struct amdgpu_vcn_inst *vinst, + enum amd_powergating_state state); static int vcn_v2_0_set_powergating_state(struct amdgpu_ip_block *ip_block, enum amd_powergating_state state); static int vcn_v2_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst, @@ -114,6 +116,7 @@ static int vcn_v2_0_early_init(struct amdgpu_ip_block *ip_block) else adev->vcn.inst[0].num_enc_rings = 2; + adev->vcn.inst->set_pg_state = vcn_v2_0_set_pg_state; vcn_v2_0_set_dec_ring_funcs(adev); vcn_v2_0_set_enc_ring_funcs(adev); vcn_v2_0_set_irq_funcs(adev); @@ -312,13 +315,14 @@ static int vcn_v2_0_hw_init(struct amdgpu_ip_block *ip_block) static int vcn_v2_0_hw_fini(struct amdgpu_ip_block *ip_block) { struct amdgpu_device *adev = ip_block->adev; + struct amdgpu_vcn_inst *vinst = adev->vcn.inst; - cancel_delayed_work_sync(&adev->vcn.inst[0].idle_work); + cancel_delayed_work_sync(&vinst->idle_work); if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) || - (adev->vcn.inst[0].cur_state != AMD_PG_STATE_GATE && + (vinst->cur_state != AMD_PG_STATE_GATE && RREG32_SOC15(VCN, 0, mmUVD_STATUS))) - vcn_v2_0_set_powergating_state(ip_block, AMD_PG_STATE_GATE); + vinst->set_pg_state(vinst, AMD_PG_STATE_GATE); return 0; } @@ -1810,8 +1814,8 @@ int vcn_v2_0_dec_ring_test_ring(struct amdgpu_ring *ring) } -static int vcn_v2_0_set_powergating_state(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state) +static int vcn_v2_0_set_pg_state(struct amdgpu_vcn_inst *vinst, + enum amd_powergating_state state) { /* This doesn't actually powergate the VCN block. * That's done in the dpm code via the SMC. This @@ -1821,27 +1825,36 @@ static int vcn_v2_0_set_powergating_state(struct amdgpu_ip_block *ip_block, * the smc and the hw blocks */ int ret; - struct amdgpu_device *adev = ip_block->adev; + struct amdgpu_device *adev = vinst->adev; if (amdgpu_sriov_vf(adev)) { - adev->vcn.inst[0].cur_state = AMD_PG_STATE_UNGATE; + vinst->cur_state = AMD_PG_STATE_UNGATE; return 0; } - if (state == adev->vcn.inst[0].cur_state) + if (state == vinst->cur_state) return 0; if (state == AMD_PG_STATE_GATE) - ret = vcn_v2_0_stop(adev->vcn.inst); + ret = vcn_v2_0_stop(vinst); else - ret = vcn_v2_0_start(adev->vcn.inst); + ret = vcn_v2_0_start(vinst); if (!ret) - adev->vcn.inst[0].cur_state = state; + vinst->cur_state = state; return ret; } +static int vcn_v2_0_set_powergating_state(struct amdgpu_ip_block *ip_block, + enum amd_powergating_state state) +{ + struct amdgpu_device *adev = ip_block->adev; + struct amdgpu_vcn_inst *vinst = adev->vcn.inst; + + return vinst->set_pg_state(vinst, state); +} + static int vcn_v2_0_start_mmsch(struct amdgpu_device *adev, struct amdgpu_mm_table *table) { From 307ce8bdc64ec3be8ce712b48026917d2e32a71c Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 26 Nov 2024 12:19:15 -0500 Subject: [PATCH 099/235] drm/amdgpu/vcn2.5: add set_pg_state callback Rework the code as a vcn instance callback. Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c | 37 +++++++++++++++------------ 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c index 9752f99297df..435161d246b6 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c @@ -95,9 +95,8 @@ static const struct amdgpu_hwip_reg_entry vcn_reg_list_2_5[] = { static void vcn_v2_5_set_dec_ring_funcs(struct amdgpu_device *adev); static void vcn_v2_5_set_enc_ring_funcs(struct amdgpu_device *adev); static void vcn_v2_5_set_irq_funcs(struct amdgpu_device *adev); -static int vcn_v2_5_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state, - int i); +static int vcn_v2_5_set_pg_state(struct amdgpu_vcn_inst *vinst, + enum amd_powergating_state state); static int vcn_v2_5_set_powergating_state(struct amdgpu_ip_block *ip_block, enum amd_powergating_state state); static int vcn_v2_5_pause_dpg_mode(struct amdgpu_vcn_inst *vinst, @@ -150,6 +149,8 @@ static int vcn_v2_5_early_init(struct amdgpu_ip_block *ip_block) vcn_v2_5_set_ras_funcs(adev); for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + adev->vcn.inst[i].set_pg_state = vcn_v2_5_set_pg_state; + r = amdgpu_vcn_early_init(adev, i); if (r) return r; @@ -400,18 +401,20 @@ static int vcn_v2_5_hw_fini(struct amdgpu_ip_block *ip_block) int i; for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { + struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; + if (adev->vcn.harvest_config & (1 << i)) continue; - cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work); + cancel_delayed_work_sync(&vinst->idle_work); if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) || - (adev->vcn.inst[i].cur_state != AMD_PG_STATE_GATE && + (vinst->cur_state != AMD_PG_STATE_GATE && RREG32_SOC15(VCN, i, mmUVD_STATUS))) - vcn_v2_5_set_powergating_state_inst(ip_block, AMD_PG_STATE_GATE, i); + vinst->set_pg_state(vinst, AMD_PG_STATE_GATE); if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__VCN)) - amdgpu_irq_put(adev, &adev->vcn.inst[i].ras_poison_irq, 0); + amdgpu_irq_put(adev, &vinst->ras_poison_irq, 0); } return 0; @@ -1848,18 +1851,16 @@ static int vcn_v2_5_set_clockgating_state(struct amdgpu_ip_block *ip_block, return 0; } -static int vcn_v2_5_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state, - int i) +static int vcn_v2_5_set_pg_state(struct amdgpu_vcn_inst *vinst, + enum amd_powergating_state state) { - struct amdgpu_device *adev = ip_block->adev; - struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; + struct amdgpu_device *adev = vinst->adev; int ret; if (amdgpu_sriov_vf(adev)) return 0; - if (state == adev->vcn.inst[i].cur_state) + if (state == vinst->cur_state) return 0; if (state == AMD_PG_STATE_GATE) @@ -1868,7 +1869,7 @@ static int vcn_v2_5_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, ret = vcn_v2_5_start(vinst); if (!ret) - adev->vcn.inst[i].cur_state = state; + vinst->cur_state = state; return ret; } @@ -1879,9 +1880,11 @@ static int vcn_v2_5_set_powergating_state(struct amdgpu_ip_block *ip_block, struct amdgpu_device *adev = ip_block->adev; int ret = 0, i; - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) - ret |= vcn_v2_5_set_powergating_state_inst(ip_block, - state, i); + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { + struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; + + ret |= vinst->set_pg_state(vinst, state); + } return ret; } From bda37b68f6d387e3a481fcf24420ecbca5f524f7 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 26 Nov 2024 12:19:33 -0500 Subject: [PATCH 100/235] drm/amdgpu/vcn3.0: add set_pg_state callback Rework the code as a vcn instance callback. Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 39 ++++++++++++++------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c index 7e98f251f23e..78438541c29a 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c @@ -105,9 +105,8 @@ static int vcn_v3_0_start_sriov(struct amdgpu_device *adev); static void vcn_v3_0_set_dec_ring_funcs(struct amdgpu_device *adev); static void vcn_v3_0_set_enc_ring_funcs(struct amdgpu_device *adev); static void vcn_v3_0_set_irq_funcs(struct amdgpu_device *adev); -static int vcn_v3_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state, - int i); +static int vcn_v3_0_set_pg_state(struct amdgpu_vcn_inst *vinst, + enum amd_powergating_state state); static int vcn_v3_0_set_powergating_state(struct amdgpu_ip_block *ip_block, enum amd_powergating_state state); static int vcn_v3_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst, @@ -155,6 +154,8 @@ static int vcn_v3_0_early_init(struct amdgpu_ip_block *ip_block) vcn_v3_0_set_irq_funcs(adev); for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + adev->vcn.inst[i].set_pg_state = vcn_v3_0_set_pg_state; + r = amdgpu_vcn_early_init(adev, i); if (r) return r; @@ -440,18 +441,18 @@ static int vcn_v3_0_hw_fini(struct amdgpu_ip_block *ip_block) int i; for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { + struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; + if (adev->vcn.harvest_config & (1 << i)) continue; - cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work); + cancel_delayed_work_sync(&vinst->idle_work); if (!amdgpu_sriov_vf(adev)) { if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) || - (adev->vcn.inst[i].cur_state != AMD_PG_STATE_GATE && + (vinst->cur_state != AMD_PG_STATE_GATE && RREG32_SOC15(VCN, i, mmUVD_STATUS))) { - vcn_v3_0_set_powergating_state_inst(ip_block, - AMD_PG_STATE_GATE, - i); + vinst->set_pg_state(vinst, AMD_PG_STATE_GATE); } } } @@ -2203,12 +2204,10 @@ static int vcn_v3_0_set_clockgating_state(struct amdgpu_ip_block *ip_block, return 0; } -static int vcn_v3_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state, - int i) +static int vcn_v3_0_set_pg_state(struct amdgpu_vcn_inst *vinst, + enum amd_powergating_state state) { - struct amdgpu_device *adev = ip_block->adev; - struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; + struct amdgpu_device *adev = vinst->adev; int ret = 0; /* for SRIOV, guest should not control VCN Power-gating @@ -2216,11 +2215,11 @@ static int vcn_v3_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, * guest should avoid touching CGC and PG */ if (amdgpu_sriov_vf(adev)) { - adev->vcn.inst[i].cur_state = AMD_PG_STATE_UNGATE; + vinst->cur_state = AMD_PG_STATE_UNGATE; return 0; } - if (state == adev->vcn.inst[i].cur_state) + if (state == vinst->cur_state) return 0; if (state == AMD_PG_STATE_GATE) @@ -2229,7 +2228,7 @@ static int vcn_v3_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, ret = vcn_v3_0_start(vinst); if (!ret) - adev->vcn.inst[i].cur_state = state; + vinst->cur_state = state; return ret; } @@ -2240,9 +2239,11 @@ static int vcn_v3_0_set_powergating_state(struct amdgpu_ip_block *ip_block, struct amdgpu_device *adev = ip_block->adev; int ret = 0, i; - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) - ret |= vcn_v3_0_set_powergating_state_inst(ip_block, - state, i); + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { + struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; + + ret |= vinst->set_pg_state(vinst, state); + } return ret; } From 8b18f0314285f128c473c92233dfcb96901d0af7 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 26 Nov 2024 12:19:49 -0500 Subject: [PATCH 101/235] drm/amdgpu/vcn4.0: add set_pg_state callback Rework the code as a vcn instance callback. Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c | 38 +++++++++++++++------------ 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c index 41ec696bd210..35cb93ff070c 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c @@ -96,9 +96,8 @@ static int amdgpu_ih_clientid_vcns[] = { static int vcn_v4_0_start_sriov(struct amdgpu_device *adev); static void vcn_v4_0_set_unified_ring_funcs(struct amdgpu_device *adev); static void vcn_v4_0_set_irq_funcs(struct amdgpu_device *adev); -static int vcn_v4_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state, - int i); +static int vcn_v4_0_set_pg_state(struct amdgpu_vcn_inst *vinst, + enum amd_powergating_state state); static int vcn_v4_0_set_powergating_state(struct amdgpu_ip_block *ip_block, enum amd_powergating_state state); static int vcn_v4_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst, @@ -138,6 +137,8 @@ static int vcn_v4_0_early_init(struct amdgpu_ip_block *ip_block) vcn_v4_0_set_ras_funcs(adev); for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { + adev->vcn.inst[i].set_pg_state = vcn_v4_0_set_pg_state; + r = amdgpu_vcn_early_init(adev, i); if (r) return r; @@ -379,20 +380,22 @@ static int vcn_v4_0_hw_fini(struct amdgpu_ip_block *ip_block) int i; for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { + struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; + if (adev->vcn.harvest_config & (1 << i)) continue; - cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work); + cancel_delayed_work_sync(&vinst->idle_work); if (!amdgpu_sriov_vf(adev)) { if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) || - (adev->vcn.inst[i].cur_state != AMD_PG_STATE_GATE && + (vinst->cur_state != AMD_PG_STATE_GATE && RREG32_SOC15(VCN, i, regUVD_STATUS))) { - vcn_v4_0_set_powergating_state_inst(ip_block, AMD_PG_STATE_GATE, i); + vinst->set_pg_state(vinst, AMD_PG_STATE_GATE); } } if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__VCN)) - amdgpu_irq_put(adev, &adev->vcn.inst[i].ras_poison_irq, 0); + amdgpu_irq_put(adev, &vinst->ras_poison_irq, 0); } return 0; @@ -2079,12 +2082,10 @@ static int vcn_v4_0_set_clockgating_state(struct amdgpu_ip_block *ip_block, return 0; } -static int vcn_v4_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state, - int i) +static int vcn_v4_0_set_pg_state(struct amdgpu_vcn_inst *vinst, + enum amd_powergating_state state) { - struct amdgpu_device *adev = ip_block->adev; - struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; + struct amdgpu_device *adev = vinst->adev; int ret = 0; /* for SRIOV, guest should not control VCN Power-gating @@ -2092,11 +2093,11 @@ static int vcn_v4_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, * guest should avoid touching CGC and PG */ if (amdgpu_sriov_vf(adev)) { - adev->vcn.inst[i].cur_state = AMD_PG_STATE_UNGATE; + vinst->cur_state = AMD_PG_STATE_UNGATE; return 0; } - if (state == adev->vcn.inst[i].cur_state) + if (state == vinst->cur_state) return 0; if (state == AMD_PG_STATE_GATE) @@ -2105,7 +2106,7 @@ static int vcn_v4_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, ret = vcn_v4_0_start(vinst); if (!ret) - adev->vcn.inst[i].cur_state = state; + vinst->cur_state = state; return ret; } @@ -2124,8 +2125,11 @@ static int vcn_v4_0_set_powergating_state(struct amdgpu_ip_block *ip_block, struct amdgpu_device *adev = ip_block->adev; int ret = 0, i; - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) - ret |= vcn_v4_0_set_powergating_state_inst(ip_block, state, i); + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { + struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; + + ret |= vinst->set_pg_state(vinst, state); + } return ret; } From 39fb77a8d37eeaab8ed8127bd9b62b9d0af98534 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 26 Nov 2024 12:20:04 -0500 Subject: [PATCH 102/235] drm/amdgpu/vcn4.0.3: add set_pg_state callback Rework the code as a vcn instance callback. Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c | 36 ++++++++++++++----------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c index e681e0939eeb..58da0505b4d7 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c @@ -87,9 +87,8 @@ static const struct amdgpu_hwip_reg_entry vcn_reg_list_4_0_3[] = { static int vcn_v4_0_3_start_sriov(struct amdgpu_device *adev); static void vcn_v4_0_3_set_unified_ring_funcs(struct amdgpu_device *adev); static void vcn_v4_0_3_set_irq_funcs(struct amdgpu_device *adev); -static int vcn_v4_0_3_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state, - int i); +static int vcn_v4_0_3_set_pg_state(struct amdgpu_vcn_inst *vinst, + enum amd_powergating_state state); static int vcn_v4_0_3_set_powergating_state(struct amdgpu_ip_block *ip_block, enum amd_powergating_state state); static int vcn_v4_0_3_pause_dpg_mode(struct amdgpu_vcn_inst *vinst, @@ -125,6 +124,8 @@ static int vcn_v4_0_3_early_init(struct amdgpu_ip_block *ip_block) vcn_v4_0_3_set_ras_funcs(adev); for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { + adev->vcn.inst[i].set_pg_state = vcn_v4_0_3_set_pg_state; + r = amdgpu_vcn_early_init(adev, i); if (r) return r; @@ -371,10 +372,12 @@ static int vcn_v4_0_3_hw_fini(struct amdgpu_ip_block *ip_block) int i; for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { - cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work); + struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; - if (adev->vcn.inst[i].cur_state != AMD_PG_STATE_GATE) - vcn_v4_0_3_set_powergating_state_inst(ip_block, AMD_PG_STATE_GATE, i); + cancel_delayed_work_sync(&vinst->idle_work); + + if (vinst->cur_state != AMD_PG_STATE_GATE) + vinst->set_pg_state(vinst, AMD_PG_STATE_GATE); } return 0; @@ -1681,12 +1684,10 @@ static int vcn_v4_0_3_set_clockgating_state(struct amdgpu_ip_block *ip_block, return 0; } -static int vcn_v4_0_3_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state, - int i) +static int vcn_v4_0_3_set_pg_state(struct amdgpu_vcn_inst *vinst, + enum amd_powergating_state state) { - struct amdgpu_device *adev = ip_block->adev; - struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; + struct amdgpu_device *adev = vinst->adev; int ret = 0; /* for SRIOV, guest should not control VCN Power-gating @@ -1694,11 +1695,11 @@ static int vcn_v4_0_3_set_powergating_state_inst(struct amdgpu_ip_block *ip_bloc * guest should avoid touching CGC and PG */ if (amdgpu_sriov_vf(adev)) { - adev->vcn.inst[i].cur_state = AMD_PG_STATE_UNGATE; + vinst->cur_state = AMD_PG_STATE_UNGATE; return 0; } - if (state == adev->vcn.inst[i].cur_state) + if (state == vinst->cur_state) return 0; if (state == AMD_PG_STATE_GATE) @@ -1707,7 +1708,7 @@ static int vcn_v4_0_3_set_powergating_state_inst(struct amdgpu_ip_block *ip_bloc ret = vcn_v4_0_3_start(vinst); if (!ret) - adev->vcn.inst[i].cur_state = state; + vinst->cur_state = state; return ret; } @@ -1726,8 +1727,11 @@ static int vcn_v4_0_3_set_powergating_state(struct amdgpu_ip_block *ip_block, struct amdgpu_device *adev = ip_block->adev; int ret = 0, i; - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) - vcn_v4_0_3_set_powergating_state_inst(ip_block, state, i); + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { + struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; + + ret |= vinst->set_pg_state(vinst, state); + } return ret; } From f9993efed789ba52fda5ece8ca48ffd84b3cbe19 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 26 Nov 2024 12:20:19 -0500 Subject: [PATCH 103/235] drm/amdgpu/vcn4.0.5: add set_pg_state callback Rework the code as a vcn instance callback. Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c | 33 ++++++++++++++----------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c index 3e2206e5e0e1..3a988639fd51 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c @@ -95,9 +95,8 @@ static int amdgpu_ih_clientid_vcns[] = { static void vcn_v4_0_5_set_unified_ring_funcs(struct amdgpu_device *adev); static void vcn_v4_0_5_set_irq_funcs(struct amdgpu_device *adev); -static int vcn_v4_0_5_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state, - int i); +static int vcn_v4_0_5_set_pg_state(struct amdgpu_vcn_inst *vinst, + enum amd_powergating_state state); static int vcn_v4_0_5_set_powergating_state(struct amdgpu_ip_block *ip_block, enum amd_powergating_state state); static int vcn_v4_0_5_pause_dpg_mode(struct amdgpu_vcn_inst *vinst, @@ -124,6 +123,8 @@ static int vcn_v4_0_5_early_init(struct amdgpu_ip_block *ip_block) vcn_v4_0_5_set_irq_funcs(adev); for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { + adev->vcn.inst[i].set_pg_state = vcn_v4_0_5_set_pg_state; + r = amdgpu_vcn_early_init(adev, i); if (r) return r; @@ -317,16 +318,18 @@ static int vcn_v4_0_5_hw_fini(struct amdgpu_ip_block *ip_block) int i; for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { + struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; + if (adev->vcn.harvest_config & (1 << i)) continue; - cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work); + cancel_delayed_work_sync(&vinst->idle_work); if (!amdgpu_sriov_vf(adev)) { if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) || - (adev->vcn.inst[i].cur_state != AMD_PG_STATE_GATE && + (vinst->cur_state != AMD_PG_STATE_GATE && RREG32_SOC15(VCN, i, regUVD_STATUS))) { - vcn_v4_0_5_set_powergating_state_inst(ip_block, AMD_PG_STATE_GATE, i); + vinst->set_pg_state(vinst, AMD_PG_STATE_GATE); } } } @@ -1563,15 +1566,12 @@ static int vcn_v4_0_5_set_clockgating_state(struct amdgpu_ip_block *ip_block, return 0; } -static int vcn_v4_0_5_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state, - int i) +static int vcn_v4_0_5_set_pg_state(struct amdgpu_vcn_inst *vinst, + enum amd_powergating_state state) { - struct amdgpu_device *adev = ip_block->adev; - struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; int ret = 0; - if (state == adev->vcn.inst[i].cur_state) + if (state == vinst->cur_state) return 0; if (state == AMD_PG_STATE_GATE) @@ -1580,7 +1580,7 @@ static int vcn_v4_0_5_set_powergating_state_inst(struct amdgpu_ip_block *ip_bloc ret = vcn_v4_0_5_start(vinst); if (!ret) - adev->vcn.inst[i].cur_state = state; + vinst->cur_state = state; return ret; } @@ -1599,8 +1599,11 @@ static int vcn_v4_0_5_set_powergating_state(struct amdgpu_ip_block *ip_block, struct amdgpu_device *adev = ip_block->adev; int ret = 0, i; - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) - vcn_v4_0_5_set_powergating_state_inst(ip_block, state, i); + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { + struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; + + ret |= vinst->set_pg_state(vinst, state); + } return ret; } From f2eb0a66ca160998302d3acdc6f50dbb8c0db833 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 26 Nov 2024 12:20:38 -0500 Subject: [PATCH 104/235] drm/amdgpu/vcn5.0.0: add set_pg_state callback Rework the code as a vcn instance callback. Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c | 33 ++++++++++++++----------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c index ec57c7dd78bf..0ed6a49722ba 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c @@ -78,9 +78,8 @@ static int amdgpu_ih_clientid_vcns[] = { static void vcn_v5_0_0_set_unified_ring_funcs(struct amdgpu_device *adev); static void vcn_v5_0_0_set_irq_funcs(struct amdgpu_device *adev); -static int vcn_v5_0_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state, - int i); +static int vcn_v5_0_0_set_pg_state(struct amdgpu_vcn_inst *vinst, + enum amd_powergating_state state); static int vcn_v5_0_0_set_powergating_state(struct amdgpu_ip_block *ip_block, enum amd_powergating_state state); static int vcn_v5_0_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst, @@ -108,6 +107,8 @@ static int vcn_v5_0_0_early_init(struct amdgpu_ip_block *ip_block) vcn_v5_0_0_set_irq_funcs(adev); for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { + adev->vcn.inst[i].set_pg_state = vcn_v5_0_0_set_pg_state; + r = amdgpu_vcn_early_init(adev, i); if (r) return r; @@ -299,16 +300,18 @@ static int vcn_v5_0_0_hw_fini(struct amdgpu_ip_block *ip_block) int i; for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { + struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; + if (adev->vcn.harvest_config & (1 << i)) continue; - cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work); + cancel_delayed_work_sync(&vinst->idle_work); if (!amdgpu_sriov_vf(adev)) { if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) || - (adev->vcn.inst[i].cur_state != AMD_PG_STATE_GATE && + (vinst->cur_state != AMD_PG_STATE_GATE && RREG32_SOC15(VCN, i, regUVD_STATUS))) { - vcn_v5_0_0_set_powergating_state_inst(ip_block, AMD_PG_STATE_GATE, i); + vinst->set_pg_state(vinst, AMD_PG_STATE_GATE); } } } @@ -1299,15 +1302,12 @@ static int vcn_v5_0_0_set_clockgating_state(struct amdgpu_ip_block *ip_block, return 0; } -static int vcn_v5_0_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state, - int i) +static int vcn_v5_0_0_set_pg_state(struct amdgpu_vcn_inst *vinst, + enum amd_powergating_state state) { - struct amdgpu_device *adev = ip_block->adev; - struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; int ret = 0; - if (state == adev->vcn.inst[i].cur_state) + if (state == vinst->cur_state) return 0; if (state == AMD_PG_STATE_GATE) @@ -1316,7 +1316,7 @@ static int vcn_v5_0_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_bloc ret = vcn_v5_0_0_start(vinst); if (!ret) - adev->vcn.inst[i].cur_state = state; + vinst->cur_state = state; return ret; } @@ -1335,8 +1335,11 @@ static int vcn_v5_0_0_set_powergating_state(struct amdgpu_ip_block *ip_block, struct amdgpu_device *adev = ip_block->adev; int ret = 0, i; - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) - vcn_v5_0_0_set_powergating_state_inst(ip_block, state, i); + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { + struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; + + ret |= vinst->set_pg_state(vinst, state); + } return ret; } From 592846e3fe87cf120ef8b2c5e490762354e5ec2e Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 10 Dec 2024 14:15:34 -0500 Subject: [PATCH 105/235] drm/amdgpu/vcn5.0.1: add set_pg_state callback Rework the code as a vcn instance callback. Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c index e3398eb39e5f..da6cbb172f62 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c @@ -40,9 +40,8 @@ static void vcn_v5_0_1_set_unified_ring_funcs(struct amdgpu_device *adev); static void vcn_v5_0_1_set_irq_funcs(struct amdgpu_device *adev); -static int vcn_v5_0_1_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state, - int i); +static int vcn_v5_0_1_set_pg_state(struct amdgpu_vcn_inst *vinst, + enum amd_powergating_state state); static int vcn_v5_0_1_set_powergating_state(struct amdgpu_ip_block *ip_block, enum amd_powergating_state state); static void vcn_v5_0_1_unified_ring_set_wptr(struct amdgpu_ring *ring); @@ -68,6 +67,8 @@ static int vcn_v5_0_1_early_init(struct amdgpu_ip_block *ip_block) vcn_v5_0_1_set_irq_funcs(adev); for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { + adev->vcn.inst[i].set_pg_state = vcn_v5_0_1_set_pg_state; + r = amdgpu_vcn_early_init(adev, i); if (r) return r; @@ -1021,15 +1022,12 @@ static int vcn_v5_0_1_set_clockgating_state(struct amdgpu_ip_block *ip_block, return 0; } -static int vcn_v5_0_1_set_powergating_state_inst(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state, - int i) +static int vcn_v5_0_1_set_pg_state(struct amdgpu_vcn_inst *vinst, + enum amd_powergating_state state) { - struct amdgpu_device *adev = ip_block->adev; - struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; int ret = 0; - if (state == adev->vcn.inst[i].cur_state) + if (state == vinst->cur_state) return 0; if (state == AMD_PG_STATE_GATE) @@ -1038,7 +1036,7 @@ static int vcn_v5_0_1_set_powergating_state_inst(struct amdgpu_ip_block *ip_bloc ret = vcn_v5_0_1_start(vinst); if (!ret) - adev->vcn.inst[i].cur_state = state; + vinst->cur_state = state; return ret; } @@ -1057,8 +1055,11 @@ static int vcn_v5_0_1_set_powergating_state(struct amdgpu_ip_block *ip_block, struct amdgpu_device *adev = ip_block->adev; int ret = 0, i; - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) - vcn_v5_0_1_set_powergating_state_inst(ip_block, state, i); + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { + struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; + + ret |= vinst->set_pg_state(vinst, state); + } return ret; } From 4ce4fe27205c1dea5e6d87edac4ccb0452a9d487 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 26 Nov 2024 12:26:32 -0500 Subject: [PATCH 106/235] drm/amdgpu/vcn: use per instance callbacks for idle work handler Use the vcn instance power gating callbacks rather than the IP powergating callback. This limits power gating to only the instance in use rather than all of the instances. Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 27 ++++++++++++------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c index a2250747a7c8..81bfd8a9d826 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c @@ -424,8 +424,7 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work) fences += fence[i]; if (!fences && !atomic_read(&vcn_inst->total_submission_cnt)) { - amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN, - AMD_PG_STATE_GATE); + vcn_inst->set_pg_state(vcn_inst, AMD_PG_STATE_GATE); r = amdgpu_dpm_switch_power_profile(adev, PP_SMC_POWER_PROFILE_VIDEO, false); if (r) @@ -438,45 +437,45 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work) void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring) { struct amdgpu_device *adev = ring->adev; + struct amdgpu_vcn_inst *vcn_inst = &adev->vcn.inst[ring->me]; int r = 0; - atomic_inc(&adev->vcn.inst[ring->me].total_submission_cnt); + atomic_inc(&vcn_inst->total_submission_cnt); - if (!cancel_delayed_work_sync(&adev->vcn.inst[ring->me].idle_work)) { + if (!cancel_delayed_work_sync(&vcn_inst->idle_work)) { r = amdgpu_dpm_switch_power_profile(adev, PP_SMC_POWER_PROFILE_VIDEO, true); if (r) dev_warn(adev->dev, "(%d) failed to switch to video power profile mode\n", r); } - mutex_lock(&adev->vcn.inst[ring->me].vcn_pg_lock); - amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN, - AMD_PG_STATE_UNGATE); + mutex_lock(&vcn_inst->vcn_pg_lock); + vcn_inst->set_pg_state(vcn_inst, AMD_PG_STATE_UNGATE); /* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */ if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG && - !adev->vcn.inst[ring->me].using_unified_queue) { + !vcn_inst->using_unified_queue) { struct dpg_pause_state new_state; if (ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC) { - atomic_inc(&adev->vcn.inst[ring->me].dpg_enc_submission_cnt); + atomic_inc(&vcn_inst->dpg_enc_submission_cnt); new_state.fw_based = VCN_DPG_STATE__PAUSE; } else { unsigned int fences = 0; unsigned int i; - for (i = 0; i < adev->vcn.inst[ring->me].num_enc_rings; ++i) - fences += amdgpu_fence_count_emitted(&adev->vcn.inst[ring->me].ring_enc[i]); + for (i = 0; i < vcn_inst->num_enc_rings; ++i) + fences += amdgpu_fence_count_emitted(&vcn_inst->ring_enc[i]); - if (fences || atomic_read(&adev->vcn.inst[ring->me].dpg_enc_submission_cnt)) + if (fences || atomic_read(&vcn_inst->dpg_enc_submission_cnt)) new_state.fw_based = VCN_DPG_STATE__PAUSE; else new_state.fw_based = VCN_DPG_STATE__UNPAUSE; } - adev->vcn.inst[ring->me].pause_dpg_mode(&adev->vcn.inst[ring->me], &new_state); + vcn_inst->pause_dpg_mode(vcn_inst, &new_state); } - mutex_unlock(&adev->vcn.inst[ring->me].vcn_pg_lock); + mutex_unlock(&vcn_inst->vcn_pg_lock); } void amdgpu_vcn_ring_end_use(struct amdgpu_ring *ring) From a2cf2a883c24ed582d829fc8ea6b4f5f09dc7b49 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 26 Nov 2024 12:30:30 -0500 Subject: [PATCH 107/235] drm/amdgpu/vcn: add a generic helper for set_power_gating_state It's common for all VCN variants. Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 23 +++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h | 3 +++ 2 files changed, 26 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c index 81bfd8a9d826..e4ef0fb970b2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c @@ -1397,3 +1397,26 @@ void amdgpu_debugfs_vcn_sched_mask_init(struct amdgpu_device *adev) &amdgpu_debugfs_vcn_sched_mask_fops); #endif } + +/** + * vcn_set_powergating_state - set VCN block powergating state + * + * @ip_block: amdgpu_ip_block pointer + * @state: power gating state + * + * Set VCN block powergating state + */ +int vcn_set_powergating_state(struct amdgpu_ip_block *ip_block, + enum amd_powergating_state state) +{ + struct amdgpu_device *adev = ip_block->adev; + int ret = 0, i; + + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { + struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; + + ret |= vinst->set_pg_state(vinst, state); + } + + return ret; +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h index 508fa022df78..a023f46ec904 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h @@ -546,4 +546,7 @@ int amdgpu_vcn_sysfs_reset_mask_init(struct amdgpu_device *adev); void amdgpu_vcn_sysfs_reset_mask_fini(struct amdgpu_device *adev); void amdgpu_debugfs_vcn_sched_mask_init(struct amdgpu_device *adev); +int vcn_set_powergating_state(struct amdgpu_ip_block *ip_block, + enum amd_powergating_state state); + #endif From cac3dc89f2104281b5c7c4ab4435953f7a754f58 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 26 Nov 2024 12:32:12 -0500 Subject: [PATCH 108/235] drm/amdgpu/vcn1.0: use generic set_power_gating_state helper No need for an IP specific version. Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c index f017c33e663d..8bad63282de4 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c @@ -87,8 +87,6 @@ static void vcn_v1_0_set_enc_ring_funcs(struct amdgpu_device *adev); static void vcn_v1_0_set_irq_funcs(struct amdgpu_device *adev); static int vcn_v1_0_set_pg_state(struct amdgpu_vcn_inst *vinst, enum amd_powergating_state state); -static int vcn_v1_0_set_powergating_state(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state); static int vcn_v1_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst, struct dpg_pause_state *new_state); @@ -1848,15 +1846,6 @@ static int vcn_v1_0_set_pg_state(struct amdgpu_vcn_inst *vinst, return ret; } -static int vcn_v1_0_set_powergating_state(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state) -{ - struct amdgpu_device *adev = ip_block->adev; - struct amdgpu_vcn_inst *vinst = adev->vcn.inst; - - return vinst->set_pg_state(vinst, state); -} - static void vcn_v1_0_idle_work_handler(struct work_struct *work) { struct amdgpu_vcn_inst *vcn_inst = @@ -2029,7 +2018,7 @@ static const struct amd_ip_funcs vcn_v1_0_ip_funcs = { .is_idle = vcn_v1_0_is_idle, .wait_for_idle = vcn_v1_0_wait_for_idle, .set_clockgating_state = vcn_v1_0_set_clockgating_state, - .set_powergating_state = vcn_v1_0_set_powergating_state, + .set_powergating_state = vcn_set_powergating_state, .dump_ip_state = vcn_v1_0_dump_ip_state, .print_ip_state = vcn_v1_0_print_ip_state, }; From 3389dd059fff2dfd9b13e218c9f65e4bb5dc98a3 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 26 Nov 2024 12:33:58 -0500 Subject: [PATCH 109/235] drm/amdgpu/vcn2.0: use generic set_power_gating_state helper No need for an IP specific version. Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c index 3b41c9c625c6..f53feb60772e 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c @@ -94,8 +94,6 @@ static void vcn_v2_0_set_enc_ring_funcs(struct amdgpu_device *adev); static void vcn_v2_0_set_irq_funcs(struct amdgpu_device *adev); static int vcn_v2_0_set_pg_state(struct amdgpu_vcn_inst *vinst, enum amd_powergating_state state); -static int vcn_v2_0_set_powergating_state(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state); static int vcn_v2_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst, struct dpg_pause_state *new_state); static int vcn_v2_0_start_sriov(struct amdgpu_device *adev); @@ -1846,15 +1844,6 @@ static int vcn_v2_0_set_pg_state(struct amdgpu_vcn_inst *vinst, return ret; } -static int vcn_v2_0_set_powergating_state(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state) -{ - struct amdgpu_device *adev = ip_block->adev; - struct amdgpu_vcn_inst *vinst = adev->vcn.inst; - - return vinst->set_pg_state(vinst, state); -} - static int vcn_v2_0_start_mmsch(struct amdgpu_device *adev, struct amdgpu_mm_table *table) { @@ -2132,7 +2121,7 @@ static const struct amd_ip_funcs vcn_v2_0_ip_funcs = { .is_idle = vcn_v2_0_is_idle, .wait_for_idle = vcn_v2_0_wait_for_idle, .set_clockgating_state = vcn_v2_0_set_clockgating_state, - .set_powergating_state = vcn_v2_0_set_powergating_state, + .set_powergating_state = vcn_set_powergating_state, .dump_ip_state = vcn_v2_0_dump_ip_state, .print_ip_state = vcn_v2_0_print_ip_state, }; From bd32af6faa7b22efcdaf7743ea06639d0985c25c Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 26 Nov 2024 12:35:42 -0500 Subject: [PATCH 110/235] drm/amdgpu/vcn2.5: use generic set_power_gating_state helper No need for an IP specific version. Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c index 435161d246b6..dff1a8859036 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c @@ -97,8 +97,6 @@ static void vcn_v2_5_set_enc_ring_funcs(struct amdgpu_device *adev); static void vcn_v2_5_set_irq_funcs(struct amdgpu_device *adev); static int vcn_v2_5_set_pg_state(struct amdgpu_vcn_inst *vinst, enum amd_powergating_state state); -static int vcn_v2_5_set_powergating_state(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state); static int vcn_v2_5_pause_dpg_mode(struct amdgpu_vcn_inst *vinst, struct dpg_pause_state *new_state); static int vcn_v2_5_sriov_start(struct amdgpu_device *adev); @@ -1874,21 +1872,6 @@ static int vcn_v2_5_set_pg_state(struct amdgpu_vcn_inst *vinst, return ret; } -static int vcn_v2_5_set_powergating_state(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state) -{ - struct amdgpu_device *adev = ip_block->adev; - int ret = 0, i; - - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { - struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; - - ret |= vinst->set_pg_state(vinst, state); - } - - return ret; -} - static int vcn_v2_5_set_interrupt_state(struct amdgpu_device *adev, struct amdgpu_irq_src *source, unsigned type, @@ -2041,7 +2024,7 @@ static const struct amd_ip_funcs vcn_v2_5_ip_funcs = { .is_idle = vcn_v2_5_is_idle, .wait_for_idle = vcn_v2_5_wait_for_idle, .set_clockgating_state = vcn_v2_5_set_clockgating_state, - .set_powergating_state = vcn_v2_5_set_powergating_state, + .set_powergating_state = vcn_set_powergating_state, .dump_ip_state = vcn_v2_5_dump_ip_state, .print_ip_state = vcn_v2_5_print_ip_state, }; @@ -2058,7 +2041,7 @@ static const struct amd_ip_funcs vcn_v2_6_ip_funcs = { .is_idle = vcn_v2_5_is_idle, .wait_for_idle = vcn_v2_5_wait_for_idle, .set_clockgating_state = vcn_v2_5_set_clockgating_state, - .set_powergating_state = vcn_v2_5_set_powergating_state, + .set_powergating_state = vcn_set_powergating_state, .dump_ip_state = vcn_v2_5_dump_ip_state, .print_ip_state = vcn_v2_5_print_ip_state, }; From 38c0d9882a6ae60e3ac7b00b00efd61f3a7ffbe7 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 26 Nov 2024 12:40:47 -0500 Subject: [PATCH 111/235] drm/amdgpu/vcn3.0: use generic set_power_gating_state helper No need for an IP specific version. Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c index 78438541c29a..a3f16fd69927 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c @@ -107,8 +107,6 @@ static void vcn_v3_0_set_enc_ring_funcs(struct amdgpu_device *adev); static void vcn_v3_0_set_irq_funcs(struct amdgpu_device *adev); static int vcn_v3_0_set_pg_state(struct amdgpu_vcn_inst *vinst, enum amd_powergating_state state); -static int vcn_v3_0_set_powergating_state(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state); static int vcn_v3_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst, struct dpg_pause_state *new_state); @@ -2233,21 +2231,6 @@ static int vcn_v3_0_set_pg_state(struct amdgpu_vcn_inst *vinst, return ret; } -static int vcn_v3_0_set_powergating_state(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state) -{ - struct amdgpu_device *adev = ip_block->adev; - int ret = 0, i; - - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { - struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; - - ret |= vinst->set_pg_state(vinst, state); - } - - return ret; -} - static int vcn_v3_0_set_interrupt_state(struct amdgpu_device *adev, struct amdgpu_irq_src *source, unsigned type, @@ -2386,7 +2369,7 @@ static const struct amd_ip_funcs vcn_v3_0_ip_funcs = { .is_idle = vcn_v3_0_is_idle, .wait_for_idle = vcn_v3_0_wait_for_idle, .set_clockgating_state = vcn_v3_0_set_clockgating_state, - .set_powergating_state = vcn_v3_0_set_powergating_state, + .set_powergating_state = vcn_set_powergating_state, .dump_ip_state = vcn_v3_0_dump_ip_state, .print_ip_state = vcn_v3_0_print_ip_state, }; From 8bdfa5756b1b3e0880eb06a3b8fb262bb1e78341 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 26 Nov 2024 12:41:17 -0500 Subject: [PATCH 112/235] drm/amdgpu/vcn4.0: use generic set_power_gating_state helper No need for an IP specific version. Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c index 35cb93ff070c..c6f6392c1c20 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c @@ -98,8 +98,6 @@ static void vcn_v4_0_set_unified_ring_funcs(struct amdgpu_device *adev); static void vcn_v4_0_set_irq_funcs(struct amdgpu_device *adev); static int vcn_v4_0_set_pg_state(struct amdgpu_vcn_inst *vinst, enum amd_powergating_state state); -static int vcn_v4_0_set_powergating_state(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state); static int vcn_v4_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst, struct dpg_pause_state *new_state); static void vcn_v4_0_unified_ring_set_wptr(struct amdgpu_ring *ring); @@ -2111,29 +2109,6 @@ static int vcn_v4_0_set_pg_state(struct amdgpu_vcn_inst *vinst, return ret; } -/** - * vcn_v4_0_set_powergating_state - set VCN block powergating state - * - * @ip_block: amdgpu_ip_block pointer - * @state: power gating state - * - * Set VCN block powergating state - */ -static int vcn_v4_0_set_powergating_state(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state) -{ - struct amdgpu_device *adev = ip_block->adev; - int ret = 0, i; - - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { - struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; - - ret |= vinst->set_pg_state(vinst, state); - } - - return ret; -} - /** * vcn_v4_0_set_ras_interrupt_state - set VCN block RAS interrupt state * @@ -2302,7 +2277,7 @@ static const struct amd_ip_funcs vcn_v4_0_ip_funcs = { .is_idle = vcn_v4_0_is_idle, .wait_for_idle = vcn_v4_0_wait_for_idle, .set_clockgating_state = vcn_v4_0_set_clockgating_state, - .set_powergating_state = vcn_v4_0_set_powergating_state, + .set_powergating_state = vcn_set_powergating_state, .dump_ip_state = vcn_v4_0_dump_ip_state, .print_ip_state = vcn_v4_0_print_ip_state, }; From 1ee6b2bff2caadc318c0ae5da6014809bc9517cc Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 26 Nov 2024 12:41:45 -0500 Subject: [PATCH 113/235] drm/amdgpu/vcn4.0.3: use generic set_power_gating_state helper No need for an IP specific version. Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c | 27 +------------------------ 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c index 58da0505b4d7..2681c40704a1 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c @@ -89,8 +89,6 @@ static void vcn_v4_0_3_set_unified_ring_funcs(struct amdgpu_device *adev); static void vcn_v4_0_3_set_irq_funcs(struct amdgpu_device *adev); static int vcn_v4_0_3_set_pg_state(struct amdgpu_vcn_inst *vinst, enum amd_powergating_state state); -static int vcn_v4_0_3_set_powergating_state(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state); static int vcn_v4_0_3_pause_dpg_mode(struct amdgpu_vcn_inst *vinst, struct dpg_pause_state *new_state); static void vcn_v4_0_3_unified_ring_set_wptr(struct amdgpu_ring *ring); @@ -1713,29 +1711,6 @@ static int vcn_v4_0_3_set_pg_state(struct amdgpu_vcn_inst *vinst, return ret; } -/** - * vcn_v4_0_3_set_powergating_state - set VCN block powergating state - * - * @ip_block: amdgpu_ip_block pointer - * @state: power gating state - * - * Set VCN block powergating state - */ -static int vcn_v4_0_3_set_powergating_state(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state) -{ - struct amdgpu_device *adev = ip_block->adev; - int ret = 0, i; - - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { - struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; - - ret |= vinst->set_pg_state(vinst, state); - } - - return ret; -} - /** * vcn_v4_0_3_set_interrupt_state - set VCN block interrupt state * @@ -1893,7 +1868,7 @@ static const struct amd_ip_funcs vcn_v4_0_3_ip_funcs = { .is_idle = vcn_v4_0_3_is_idle, .wait_for_idle = vcn_v4_0_3_wait_for_idle, .set_clockgating_state = vcn_v4_0_3_set_clockgating_state, - .set_powergating_state = vcn_v4_0_3_set_powergating_state, + .set_powergating_state = vcn_set_powergating_state, .dump_ip_state = vcn_v4_0_3_dump_ip_state, .print_ip_state = vcn_v4_0_3_print_ip_state, }; From 4bb58793223d18be30f9673ea3294ed4e9740c5f Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 10 Dec 2024 14:22:25 -0500 Subject: [PATCH 114/235] drm/amdgpu/vcn4.0.5: use generic set_power_gating_state helper No need for an IP specific version. Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c | 27 +------------------------ 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c index 3a988639fd51..0aac132a56d3 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c @@ -97,8 +97,6 @@ static void vcn_v4_0_5_set_unified_ring_funcs(struct amdgpu_device *adev); static void vcn_v4_0_5_set_irq_funcs(struct amdgpu_device *adev); static int vcn_v4_0_5_set_pg_state(struct amdgpu_vcn_inst *vinst, enum amd_powergating_state state); -static int vcn_v4_0_5_set_powergating_state(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state); static int vcn_v4_0_5_pause_dpg_mode(struct amdgpu_vcn_inst *vinst, struct dpg_pause_state *new_state); static void vcn_v4_0_5_unified_ring_set_wptr(struct amdgpu_ring *ring); @@ -1585,29 +1583,6 @@ static int vcn_v4_0_5_set_pg_state(struct amdgpu_vcn_inst *vinst, return ret; } -/** - * vcn_v4_0_5_set_powergating_state - set VCN block powergating state - * - * @ip_block: amdgpu_ip_block pointer - * @state: power gating state - * - * Set VCN block powergating state - */ -static int vcn_v4_0_5_set_powergating_state(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state) -{ - struct amdgpu_device *adev = ip_block->adev; - int ret = 0, i; - - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { - struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; - - ret |= vinst->set_pg_state(vinst, state); - } - - return ret; -} - /** * vcn_v4_0_5_process_interrupt - process VCN block interrupt * @@ -1749,7 +1724,7 @@ static const struct amd_ip_funcs vcn_v4_0_5_ip_funcs = { .is_idle = vcn_v4_0_5_is_idle, .wait_for_idle = vcn_v4_0_5_wait_for_idle, .set_clockgating_state = vcn_v4_0_5_set_clockgating_state, - .set_powergating_state = vcn_v4_0_5_set_powergating_state, + .set_powergating_state = vcn_set_powergating_state, .dump_ip_state = vcn_v4_0_5_dump_ip_state, .print_ip_state = vcn_v4_0_5_print_ip_state, }; From 9b648fa54c5410278edeaa5697c6461d058f6448 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 10 Dec 2024 14:22:53 -0500 Subject: [PATCH 115/235] drm/amdgpu/vcn5.0.0: use generic set_power_gating_state helper No need for an IP specific version. Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c | 27 +------------------------ 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c index 0ed6a49722ba..e07b500235b5 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c @@ -80,8 +80,6 @@ static void vcn_v5_0_0_set_unified_ring_funcs(struct amdgpu_device *adev); static void vcn_v5_0_0_set_irq_funcs(struct amdgpu_device *adev); static int vcn_v5_0_0_set_pg_state(struct amdgpu_vcn_inst *vinst, enum amd_powergating_state state); -static int vcn_v5_0_0_set_powergating_state(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state); static int vcn_v5_0_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst, struct dpg_pause_state *new_state); static void vcn_v5_0_0_unified_ring_set_wptr(struct amdgpu_ring *ring); @@ -1321,29 +1319,6 @@ static int vcn_v5_0_0_set_pg_state(struct amdgpu_vcn_inst *vinst, return ret; } -/** - * vcn_v5_0_0_set_powergating_state - set VCN block powergating state - * - * @ip_block: amdgpu_ip_block pointer - * @state: power gating state - * - * Set VCN block powergating state - */ -static int vcn_v5_0_0_set_powergating_state(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state) -{ - struct amdgpu_device *adev = ip_block->adev; - int ret = 0, i; - - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { - struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; - - ret |= vinst->set_pg_state(vinst, state); - } - - return ret; -} - /** * vcn_v5_0_0_process_interrupt - process VCN block interrupt * @@ -1485,7 +1460,7 @@ static const struct amd_ip_funcs vcn_v5_0_0_ip_funcs = { .is_idle = vcn_v5_0_0_is_idle, .wait_for_idle = vcn_v5_0_0_wait_for_idle, .set_clockgating_state = vcn_v5_0_0_set_clockgating_state, - .set_powergating_state = vcn_v5_0_0_set_powergating_state, + .set_powergating_state = vcn_set_powergating_state, .dump_ip_state = vcn_v5_0_0_dump_ip_state, .print_ip_state = vcn_v5_0_0_print_ip_state, }; From 31a37dfc8f0be35b3668a3e5092d8788b94b6607 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 10 Dec 2024 14:25:46 -0500 Subject: [PATCH 116/235] drm/amdgpu/vcn5.0.1: use generic set_power_gating_state helper No need for an IP specific version. Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c | 27 +------------------------ 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c index da6cbb172f62..900702b1a3bb 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c @@ -42,8 +42,6 @@ static void vcn_v5_0_1_set_unified_ring_funcs(struct amdgpu_device *adev); static void vcn_v5_0_1_set_irq_funcs(struct amdgpu_device *adev); static int vcn_v5_0_1_set_pg_state(struct amdgpu_vcn_inst *vinst, enum amd_powergating_state state); -static int vcn_v5_0_1_set_powergating_state(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state); static void vcn_v5_0_1_unified_ring_set_wptr(struct amdgpu_ring *ring); /** @@ -1041,29 +1039,6 @@ static int vcn_v5_0_1_set_pg_state(struct amdgpu_vcn_inst *vinst, return ret; } -/** - * vcn_v5_0_1_set_powergating_state - set VCN block powergating state - * - * @ip_block: Pointer to the amdgpu_ip_block for this hw instance. - * @state: power gating state - * - * Set VCN block powergating state - */ -static int vcn_v5_0_1_set_powergating_state(struct amdgpu_ip_block *ip_block, - enum amd_powergating_state state) -{ - struct amdgpu_device *adev = ip_block->adev; - int ret = 0, i; - - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { - struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; - - ret |= vinst->set_pg_state(vinst, state); - } - - return ret; -} - /** * vcn_v5_0_1_process_interrupt - process VCN block interrupt * @@ -1142,7 +1117,7 @@ static const struct amd_ip_funcs vcn_v5_0_1_ip_funcs = { .soft_reset = NULL, .post_soft_reset = NULL, .set_clockgating_state = vcn_v5_0_1_set_clockgating_state, - .set_powergating_state = vcn_v5_0_1_set_powergating_state, + .set_powergating_state = vcn_set_powergating_state, .dump_ip_state = vcn_v5_0_0_dump_ip_state, .print_ip_state = vcn_v5_0_0_print_ip_state, }; From c51aa7923e28f30519a16bf89ed3c4f27460835c Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 7 Jan 2025 12:16:28 -0500 Subject: [PATCH 117/235] drm/amdgpu/vcn: optimize firmware storage If each instance uses the same fw image, only store one copy in the driver. Acked-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 30 +++++++++++++++++-------- drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h | 4 +++- drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c | 3 +++ 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c index e4ef0fb970b2..edbcb11c382a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c @@ -102,18 +102,25 @@ int amdgpu_vcn_early_init(struct amdgpu_device *adev, int i) adev->vcn.inst[i].inst = i; amdgpu_ucode_ip_version_decode(adev, UVD_HWIP, ucode_prefix, sizeof(ucode_prefix)); - if (i == 1 && amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(4, 0, 6)) + if (i != 0 && adev->vcn.per_inst_fw) { r = amdgpu_ucode_request(adev, &adev->vcn.inst[i].fw, AMDGPU_UCODE_REQUIRED, "amdgpu/%s_%d.bin", ucode_prefix, i); - else - r = amdgpu_ucode_request(adev, &adev->vcn.inst[i].fw, - AMDGPU_UCODE_REQUIRED, - "amdgpu/%s.bin", ucode_prefix); - if (r) { - amdgpu_ucode_release(&adev->vcn.inst[i].fw); - return r; + if (r) + amdgpu_ucode_release(&adev->vcn.inst[i].fw); + } else { + if (!adev->vcn.inst[0].fw) { + r = amdgpu_ucode_request(adev, &adev->vcn.inst[0].fw, + AMDGPU_UCODE_REQUIRED, + "amdgpu/%s.bin", ucode_prefix); + if (r) + amdgpu_ucode_release(&adev->vcn.inst[0].fw); + } else { + r = 0; + } + adev->vcn.inst[i].fw = adev->vcn.inst[0].fw; } + return r; } @@ -270,7 +277,12 @@ int amdgpu_vcn_sw_fini(struct amdgpu_device *adev, int i) for (j = 0; j < adev->vcn.inst[i].num_enc_rings; ++j) amdgpu_ring_fini(&adev->vcn.inst[i].ring_enc[j]); - amdgpu_ucode_release(&adev->vcn.inst[i].fw); + if (adev->vcn.per_inst_fw) { + amdgpu_ucode_release(&adev->vcn.inst[i].fw); + } else { + amdgpu_ucode_release(&adev->vcn.inst[0].fw); + adev->vcn.inst[i].fw = NULL; + } mutex_destroy(&adev->vcn.inst[i].vcn_pg_lock); mutex_destroy(&adev->vcn.inst[i].vcn1_jpeg1_workaround); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h index a023f46ec904..26c9c2d90f45 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h @@ -339,7 +339,6 @@ struct amdgpu_vcn_ras { }; struct amdgpu_vcn { - unsigned fw_version; uint8_t num_vcn_inst; struct amdgpu_vcn_inst inst[AMDGPU_MAX_VCN_INSTANCES]; @@ -356,6 +355,9 @@ struct amdgpu_vcn { uint32_t supported_reset; uint32_t caps; + + bool per_inst_fw; + unsigned fw_version; }; struct amdgpu_fw_shared_rb_ptrs_struct { diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c index 0aac132a56d3..ba603b2246e2 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c @@ -114,6 +114,9 @@ static int vcn_v4_0_5_early_init(struct amdgpu_ip_block *ip_block) struct amdgpu_device *adev = ip_block->adev; int i, r; + if (amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(4, 0, 6)) + adev->vcn.per_inst_fw = true; + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) /* re-use enc ring as unified ring */ adev->vcn.inst[i].num_enc_rings = 1; From 4d1b653571c09f63a5970aea5efdbdee7a1520dc Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 7 Jan 2025 12:26:46 -0500 Subject: [PATCH 118/235] drm/amdgpu/vcn: use dev_info() for firmware information To properly handle multiple GPUs. Reviewed-by: Boyuan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c index edbcb11c382a..8d8b39e6d197 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c @@ -182,7 +182,8 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev, int i) enc_major = fw_check; dec_ver = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xf; vep = (le32_to_cpu(hdr->ucode_version) >> 28) & 0xf; - DRM_INFO("Found VCN firmware Version ENC: %u.%u DEC: %u VEP: %u Revision: %u\n", + dev_info(adev->dev, + "Found VCN firmware Version ENC: %u.%u DEC: %u VEP: %u Revision: %u\n", enc_major, enc_minor, dec_ver, vep, fw_rev); } else { unsigned int version_major, version_minor, family_id; @@ -190,7 +191,7 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev, int i) family_id = le32_to_cpu(hdr->ucode_version) & 0xff; version_major = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xff; version_minor = (le32_to_cpu(hdr->ucode_version) >> 8) & 0xff; - DRM_INFO("Found VCN firmware Version: %u.%u Family ID: %u\n", + dev_info(adev->dev, "Found VCN firmware Version: %u.%u Family ID: %u\n", version_major, version_minor, family_id); } From b5838d1517e229111453ef9177bacafa39f3f1c2 Mon Sep 17 00:00:00 2001 From: Luan Arcanjo Date: Mon, 24 Feb 2025 22:55:29 -0300 Subject: [PATCH 119/235] drm/amd/display/dc: Refactor remove duplications All dce command_table_helper's shares a copy-pasted collection of copy-pasted functions, which are: phy_id_to_atom, clock_source_id_to_atom_phy_clk_src_id, and engine_bp_to_atom. This patch removes the multiple copy-pasted by moving them to the command_table_helper.c and make the command_table_helper's calls the functions implemented by the command_table_helper.c instead. The changes were not tested on actual hardware. I am only able to verify that the changes keep the code compileable and do my best to to look repeatedly if I am not actually changing any code. This is the version 4 of the PATCH, fixed comments about licence in the new files and the matches From email to Signed-off-by email. Fixed comments about using command_table_helper instead of creating a dce_common Signed-off-by: Luan Icaro Pinto Arcanjo Signed-off-by: Alex Deucher --- .../display/dc/bios/command_table_helper.c | 104 +++++++++++++++++ .../display/dc/bios/command_table_helper.h | 8 ++ .../bios/dce110/command_table_helper_dce110.c | 104 ----------------- .../dce112/command_table_helper2_dce112.c | 106 +----------------- .../bios/dce112/command_table_helper_dce112.c | 104 ----------------- .../bios/dce60/command_table_helper_dce60.c | 104 ----------------- .../bios/dce80/command_table_helper_dce80.c | 104 ----------------- 7 files changed, 114 insertions(+), 520 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.c b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.c index e317a3615147..91bc8a06e2cf 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.c @@ -293,3 +293,107 @@ uint8_t dal_cmd_table_helper_encoder_id_to_atom( return ENCODER_OBJECT_ID_NONE; } } + +uint8_t phy_id_to_atom(enum transmitter t) +{ + uint8_t atom_phy_id; + + switch (t) { + case TRANSMITTER_UNIPHY_A: + atom_phy_id = ATOM_PHY_ID_UNIPHYA; + break; + case TRANSMITTER_UNIPHY_B: + atom_phy_id = ATOM_PHY_ID_UNIPHYB; + break; + case TRANSMITTER_UNIPHY_C: + atom_phy_id = ATOM_PHY_ID_UNIPHYC; + break; + case TRANSMITTER_UNIPHY_D: + atom_phy_id = ATOM_PHY_ID_UNIPHYD; + break; + case TRANSMITTER_UNIPHY_E: + atom_phy_id = ATOM_PHY_ID_UNIPHYE; + break; + case TRANSMITTER_UNIPHY_F: + atom_phy_id = ATOM_PHY_ID_UNIPHYF; + break; + case TRANSMITTER_UNIPHY_G: + atom_phy_id = ATOM_PHY_ID_UNIPHYG; + break; + default: + atom_phy_id = ATOM_PHY_ID_UNIPHYA; + break; + } + return atom_phy_id; +} + +uint8_t clock_source_id_to_atom_phy_clk_src_id( + enum clock_source_id id) +{ + uint8_t atom_phy_clk_src_id = 0; + + switch (id) { + case CLOCK_SOURCE_ID_PLL0: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P0PLL; + break; + case CLOCK_SOURCE_ID_PLL1: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; + break; + case CLOCK_SOURCE_ID_PLL2: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P2PLL; + break; + case CLOCK_SOURCE_ID_EXTERNAL: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_REFCLK_SRC_EXT; + break; + default: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; + break; + } + + return atom_phy_clk_src_id >> 2; +} + +bool engine_bp_to_atom(enum engine_id id, uint32_t *atom_engine_id) +{ + bool result = false; + + if (atom_engine_id != NULL) + switch (id) { + case ENGINE_ID_DIGA: + *atom_engine_id = ASIC_INT_DIG1_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGB: + *atom_engine_id = ASIC_INT_DIG2_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGC: + *atom_engine_id = ASIC_INT_DIG3_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGD: + *atom_engine_id = ASIC_INT_DIG4_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGE: + *atom_engine_id = ASIC_INT_DIG5_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGF: + *atom_engine_id = ASIC_INT_DIG6_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGG: + *atom_engine_id = ASIC_INT_DIG7_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DACA: + *atom_engine_id = ASIC_INT_DAC1_ENCODER_ID; + result = true; + break; + default: + break; + } + + return result; +} diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.h b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.h index dfd30aaf4032..547700e119a6 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.h +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.h @@ -59,4 +59,12 @@ uint8_t dal_cmd_table_helper_transmitter_bp_to_atom( uint8_t dal_cmd_table_helper_encoder_id_to_atom( enum encoder_id id); + +uint8_t phy_id_to_atom(enum transmitter t); + +uint8_t clock_source_id_to_atom_phy_clk_src_id( + enum clock_source_id id); + +bool engine_bp_to_atom(enum engine_id id, uint32_t *atom_engine_id); + #endif diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c b/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c index 11bf247bb180..3099128223df 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c @@ -31,39 +31,6 @@ #include "../command_table_helper.h" -static uint8_t phy_id_to_atom(enum transmitter t) -{ - uint8_t atom_phy_id; - - switch (t) { - case TRANSMITTER_UNIPHY_A: - atom_phy_id = ATOM_PHY_ID_UNIPHYA; - break; - case TRANSMITTER_UNIPHY_B: - atom_phy_id = ATOM_PHY_ID_UNIPHYB; - break; - case TRANSMITTER_UNIPHY_C: - atom_phy_id = ATOM_PHY_ID_UNIPHYC; - break; - case TRANSMITTER_UNIPHY_D: - atom_phy_id = ATOM_PHY_ID_UNIPHYD; - break; - case TRANSMITTER_UNIPHY_E: - atom_phy_id = ATOM_PHY_ID_UNIPHYE; - break; - case TRANSMITTER_UNIPHY_F: - atom_phy_id = ATOM_PHY_ID_UNIPHYF; - break; - case TRANSMITTER_UNIPHY_G: - atom_phy_id = ATOM_PHY_ID_UNIPHYG; - break; - default: - atom_phy_id = ATOM_PHY_ID_UNIPHYA; - break; - } - return atom_phy_id; -} - static uint8_t signal_type_to_atom_dig_mode(enum signal_type s) { uint8_t atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DP; @@ -94,32 +61,6 @@ static uint8_t signal_type_to_atom_dig_mode(enum signal_type s) return atom_dig_mode; } -static uint8_t clock_source_id_to_atom_phy_clk_src_id( - enum clock_source_id id) -{ - uint8_t atom_phy_clk_src_id = 0; - - switch (id) { - case CLOCK_SOURCE_ID_PLL0: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P0PLL; - break; - case CLOCK_SOURCE_ID_PLL1: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; - break; - case CLOCK_SOURCE_ID_PLL2: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P2PLL; - break; - case CLOCK_SOURCE_ID_EXTERNAL: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_REFCLK_SRC_EXT; - break; - default: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; - break; - } - - return atom_phy_clk_src_id >> 2; -} - static uint8_t hpd_sel_to_atom(enum hpd_source_id id) { uint8_t atom_hpd_sel = 0; @@ -207,51 +148,6 @@ static bool clock_source_id_to_atom( return result; } -static bool engine_bp_to_atom(enum engine_id id, uint32_t *atom_engine_id) -{ - bool result = false; - - if (atom_engine_id != NULL) - switch (id) { - case ENGINE_ID_DIGA: - *atom_engine_id = ASIC_INT_DIG1_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGB: - *atom_engine_id = ASIC_INT_DIG2_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGC: - *atom_engine_id = ASIC_INT_DIG3_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGD: - *atom_engine_id = ASIC_INT_DIG4_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGE: - *atom_engine_id = ASIC_INT_DIG5_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGF: - *atom_engine_id = ASIC_INT_DIG6_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGG: - *atom_engine_id = ASIC_INT_DIG7_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DACA: - *atom_engine_id = ASIC_INT_DAC1_ENCODER_ID; - result = true; - break; - default: - break; - } - - return result; -} - static uint8_t encoder_action_to_atom(enum bp_encoder_control_action action) { uint8_t atom_action = 0; diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c index 755b6e33140a..349f0e5d5856 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c +++ b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c @@ -29,41 +29,10 @@ #include "include/bios_parser_types.h" +#include "../command_table_helper.h" + #include "../command_table_helper2.h" -static uint8_t phy_id_to_atom(enum transmitter t) -{ - uint8_t atom_phy_id; - - switch (t) { - case TRANSMITTER_UNIPHY_A: - atom_phy_id = ATOM_PHY_ID_UNIPHYA; - break; - case TRANSMITTER_UNIPHY_B: - atom_phy_id = ATOM_PHY_ID_UNIPHYB; - break; - case TRANSMITTER_UNIPHY_C: - atom_phy_id = ATOM_PHY_ID_UNIPHYC; - break; - case TRANSMITTER_UNIPHY_D: - atom_phy_id = ATOM_PHY_ID_UNIPHYD; - break; - case TRANSMITTER_UNIPHY_E: - atom_phy_id = ATOM_PHY_ID_UNIPHYE; - break; - case TRANSMITTER_UNIPHY_F: - atom_phy_id = ATOM_PHY_ID_UNIPHYF; - break; - case TRANSMITTER_UNIPHY_G: - atom_phy_id = ATOM_PHY_ID_UNIPHYG; - break; - default: - atom_phy_id = ATOM_PHY_ID_UNIPHYA; - break; - } - return atom_phy_id; -} - static uint8_t signal_type_to_atom_dig_mode(enum signal_type s) { uint8_t atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DP; @@ -91,32 +60,6 @@ static uint8_t signal_type_to_atom_dig_mode(enum signal_type s) return atom_dig_mode; } -static uint8_t clock_source_id_to_atom_phy_clk_src_id( - enum clock_source_id id) -{ - uint8_t atom_phy_clk_src_id = 0; - - switch (id) { - case CLOCK_SOURCE_ID_PLL0: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P0PLL; - break; - case CLOCK_SOURCE_ID_PLL1: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; - break; - case CLOCK_SOURCE_ID_PLL2: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P2PLL; - break; - case CLOCK_SOURCE_ID_EXTERNAL: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_REFCLK_SRC_EXT; - break; - default: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; - break; - } - - return atom_phy_clk_src_id >> 2; -} - static uint8_t hpd_sel_to_atom(enum hpd_source_id id) { uint8_t atom_hpd_sel = 0; @@ -209,51 +152,6 @@ static bool clock_source_id_to_atom( return result; } -static bool engine_bp_to_atom(enum engine_id id, uint32_t *atom_engine_id) -{ - bool result = false; - - if (atom_engine_id != NULL) - switch (id) { - case ENGINE_ID_DIGA: - *atom_engine_id = ASIC_INT_DIG1_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGB: - *atom_engine_id = ASIC_INT_DIG2_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGC: - *atom_engine_id = ASIC_INT_DIG3_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGD: - *atom_engine_id = ASIC_INT_DIG4_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGE: - *atom_engine_id = ASIC_INT_DIG5_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGF: - *atom_engine_id = ASIC_INT_DIG6_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGG: - *atom_engine_id = ASIC_INT_DIG7_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DACA: - *atom_engine_id = ASIC_INT_DAC1_ENCODER_ID; - result = true; - break; - default: - break; - } - - return result; -} - static uint8_t encoder_action_to_atom(enum bp_encoder_control_action action) { uint8_t atom_action = 0; diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c index 06b4f7fa4a50..1a5fefcde8af 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c +++ b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c @@ -31,39 +31,6 @@ #include "../command_table_helper.h" -static uint8_t phy_id_to_atom(enum transmitter t) -{ - uint8_t atom_phy_id; - - switch (t) { - case TRANSMITTER_UNIPHY_A: - atom_phy_id = ATOM_PHY_ID_UNIPHYA; - break; - case TRANSMITTER_UNIPHY_B: - atom_phy_id = ATOM_PHY_ID_UNIPHYB; - break; - case TRANSMITTER_UNIPHY_C: - atom_phy_id = ATOM_PHY_ID_UNIPHYC; - break; - case TRANSMITTER_UNIPHY_D: - atom_phy_id = ATOM_PHY_ID_UNIPHYD; - break; - case TRANSMITTER_UNIPHY_E: - atom_phy_id = ATOM_PHY_ID_UNIPHYE; - break; - case TRANSMITTER_UNIPHY_F: - atom_phy_id = ATOM_PHY_ID_UNIPHYF; - break; - case TRANSMITTER_UNIPHY_G: - atom_phy_id = ATOM_PHY_ID_UNIPHYG; - break; - default: - atom_phy_id = ATOM_PHY_ID_UNIPHYA; - break; - } - return atom_phy_id; -} - static uint8_t signal_type_to_atom_dig_mode(enum signal_type s) { uint8_t atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DP; @@ -91,32 +58,6 @@ static uint8_t signal_type_to_atom_dig_mode(enum signal_type s) return atom_dig_mode; } -static uint8_t clock_source_id_to_atom_phy_clk_src_id( - enum clock_source_id id) -{ - uint8_t atom_phy_clk_src_id = 0; - - switch (id) { - case CLOCK_SOURCE_ID_PLL0: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P0PLL; - break; - case CLOCK_SOURCE_ID_PLL1: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; - break; - case CLOCK_SOURCE_ID_PLL2: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P2PLL; - break; - case CLOCK_SOURCE_ID_EXTERNAL: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_REFCLK_SRC_EXT; - break; - default: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; - break; - } - - return atom_phy_clk_src_id >> 2; -} - static uint8_t hpd_sel_to_atom(enum hpd_source_id id) { uint8_t atom_hpd_sel = 0; @@ -209,51 +150,6 @@ static bool clock_source_id_to_atom( return result; } -static bool engine_bp_to_atom(enum engine_id id, uint32_t *atom_engine_id) -{ - bool result = false; - - if (atom_engine_id != NULL) - switch (id) { - case ENGINE_ID_DIGA: - *atom_engine_id = ASIC_INT_DIG1_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGB: - *atom_engine_id = ASIC_INT_DIG2_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGC: - *atom_engine_id = ASIC_INT_DIG3_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGD: - *atom_engine_id = ASIC_INT_DIG4_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGE: - *atom_engine_id = ASIC_INT_DIG5_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGF: - *atom_engine_id = ASIC_INT_DIG6_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGG: - *atom_engine_id = ASIC_INT_DIG7_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DACA: - *atom_engine_id = ASIC_INT_DAC1_ENCODER_ID; - result = true; - break; - default: - break; - } - - return result; -} - static uint8_t encoder_action_to_atom(enum bp_encoder_control_action action) { uint8_t atom_action = 0; diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce60/command_table_helper_dce60.c b/drivers/gpu/drm/amd/display/dc/bios/dce60/command_table_helper_dce60.c index 710221b4f5c5..01ccc803040c 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/dce60/command_table_helper_dce60.c +++ b/drivers/gpu/drm/amd/display/dc/bios/dce60/command_table_helper_dce60.c @@ -58,51 +58,6 @@ static uint8_t encoder_action_to_atom(enum bp_encoder_control_action action) return atom_action; } -static bool engine_bp_to_atom(enum engine_id id, uint32_t *atom_engine_id) -{ - bool result = false; - - if (atom_engine_id != NULL) - switch (id) { - case ENGINE_ID_DIGA: - *atom_engine_id = ASIC_INT_DIG1_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGB: - *atom_engine_id = ASIC_INT_DIG2_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGC: - *atom_engine_id = ASIC_INT_DIG3_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGD: - *atom_engine_id = ASIC_INT_DIG4_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGE: - *atom_engine_id = ASIC_INT_DIG5_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGF: - *atom_engine_id = ASIC_INT_DIG6_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGG: - *atom_engine_id = ASIC_INT_DIG7_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DACA: - *atom_engine_id = ASIC_INT_DAC1_ENCODER_ID; - result = true; - break; - default: - break; - } - - return result; -} - static bool clock_source_id_to_atom( enum clock_source_id id, uint32_t *atom_pll_id) @@ -149,32 +104,6 @@ static bool clock_source_id_to_atom( return result; } -static uint8_t clock_source_id_to_atom_phy_clk_src_id( - enum clock_source_id id) -{ - uint8_t atom_phy_clk_src_id = 0; - - switch (id) { - case CLOCK_SOURCE_ID_PLL0: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P0PLL; - break; - case CLOCK_SOURCE_ID_PLL1: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; - break; - case CLOCK_SOURCE_ID_PLL2: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P2PLL; - break; - case CLOCK_SOURCE_ID_EXTERNAL: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_REFCLK_SRC_EXT; - break; - default: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; - break; - } - - return atom_phy_clk_src_id >> 2; -} - static uint8_t signal_type_to_atom_dig_mode(enum signal_type s) { uint8_t atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DP; @@ -270,39 +199,6 @@ static uint8_t dig_encoder_sel_to_atom(enum engine_id id) return atom_dig_encoder_sel; } -static uint8_t phy_id_to_atom(enum transmitter t) -{ - uint8_t atom_phy_id; - - switch (t) { - case TRANSMITTER_UNIPHY_A: - atom_phy_id = ATOM_PHY_ID_UNIPHYA; - break; - case TRANSMITTER_UNIPHY_B: - atom_phy_id = ATOM_PHY_ID_UNIPHYB; - break; - case TRANSMITTER_UNIPHY_C: - atom_phy_id = ATOM_PHY_ID_UNIPHYC; - break; - case TRANSMITTER_UNIPHY_D: - atom_phy_id = ATOM_PHY_ID_UNIPHYD; - break; - case TRANSMITTER_UNIPHY_E: - atom_phy_id = ATOM_PHY_ID_UNIPHYE; - break; - case TRANSMITTER_UNIPHY_F: - atom_phy_id = ATOM_PHY_ID_UNIPHYF; - break; - case TRANSMITTER_UNIPHY_G: - atom_phy_id = ATOM_PHY_ID_UNIPHYG; - break; - default: - atom_phy_id = ATOM_PHY_ID_UNIPHYA; - break; - } - return atom_phy_id; -} - static uint8_t disp_power_gating_action_to_atom( enum bp_pipe_control_action action) { diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.c b/drivers/gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.c index 8b30b558cf1f..2ec5264536c7 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.c +++ b/drivers/gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.c @@ -58,51 +58,6 @@ static uint8_t encoder_action_to_atom(enum bp_encoder_control_action action) return atom_action; } -static bool engine_bp_to_atom(enum engine_id id, uint32_t *atom_engine_id) -{ - bool result = false; - - if (atom_engine_id != NULL) - switch (id) { - case ENGINE_ID_DIGA: - *atom_engine_id = ASIC_INT_DIG1_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGB: - *atom_engine_id = ASIC_INT_DIG2_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGC: - *atom_engine_id = ASIC_INT_DIG3_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGD: - *atom_engine_id = ASIC_INT_DIG4_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGE: - *atom_engine_id = ASIC_INT_DIG5_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGF: - *atom_engine_id = ASIC_INT_DIG6_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGG: - *atom_engine_id = ASIC_INT_DIG7_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DACA: - *atom_engine_id = ASIC_INT_DAC1_ENCODER_ID; - result = true; - break; - default: - break; - } - - return result; -} - static bool clock_source_id_to_atom( enum clock_source_id id, uint32_t *atom_pll_id) @@ -149,32 +104,6 @@ static bool clock_source_id_to_atom( return result; } -static uint8_t clock_source_id_to_atom_phy_clk_src_id( - enum clock_source_id id) -{ - uint8_t atom_phy_clk_src_id = 0; - - switch (id) { - case CLOCK_SOURCE_ID_PLL0: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P0PLL; - break; - case CLOCK_SOURCE_ID_PLL1: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; - break; - case CLOCK_SOURCE_ID_PLL2: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P2PLL; - break; - case CLOCK_SOURCE_ID_EXTERNAL: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_REFCLK_SRC_EXT; - break; - default: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; - break; - } - - return atom_phy_clk_src_id >> 2; -} - static uint8_t signal_type_to_atom_dig_mode(enum signal_type s) { uint8_t atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DP; @@ -270,39 +199,6 @@ static uint8_t dig_encoder_sel_to_atom(enum engine_id id) return atom_dig_encoder_sel; } -static uint8_t phy_id_to_atom(enum transmitter t) -{ - uint8_t atom_phy_id; - - switch (t) { - case TRANSMITTER_UNIPHY_A: - atom_phy_id = ATOM_PHY_ID_UNIPHYA; - break; - case TRANSMITTER_UNIPHY_B: - atom_phy_id = ATOM_PHY_ID_UNIPHYB; - break; - case TRANSMITTER_UNIPHY_C: - atom_phy_id = ATOM_PHY_ID_UNIPHYC; - break; - case TRANSMITTER_UNIPHY_D: - atom_phy_id = ATOM_PHY_ID_UNIPHYD; - break; - case TRANSMITTER_UNIPHY_E: - atom_phy_id = ATOM_PHY_ID_UNIPHYE; - break; - case TRANSMITTER_UNIPHY_F: - atom_phy_id = ATOM_PHY_ID_UNIPHYF; - break; - case TRANSMITTER_UNIPHY_G: - atom_phy_id = ATOM_PHY_ID_UNIPHYG; - break; - default: - atom_phy_id = ATOM_PHY_ID_UNIPHYA; - break; - } - return atom_phy_id; -} - static uint8_t disp_power_gating_action_to_atom( enum bp_pipe_control_action action) { From a67e75beff5613fe1aef5d4649a8df0e8353819d Mon Sep 17 00:00:00 2001 From: Pratap Nirujogi Date: Wed, 19 Feb 2025 17:01:26 -0500 Subject: [PATCH 120/235] drm/amdgpu: Replace DRM_ERROR() with drm_err() DRM_ERROR() is no longer preferred. Replace DRM_ERROR() usage with drm_err() in isp driver. Signed-off-by: Pratap Nirujogi Reviewed-by: Mario Limonciello Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.c | 15 ++++++++++----- drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c | 15 ++++++++++----- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.c b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.c index 964c29ef25dc..2475564b2c08 100644 --- a/drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.c @@ -53,7 +53,8 @@ static int isp_v4_1_0_hw_init(struct amdgpu_isp *isp) isp->isp_cell = kcalloc(2, sizeof(struct mfd_cell), GFP_KERNEL); if (!isp->isp_cell) { r = -ENOMEM; - DRM_ERROR("%s: isp mfd cell alloc failed\n", __func__); + drm_err(&adev->ddev, + "%s: isp mfd cell alloc failed\n", __func__); goto failure; } @@ -62,14 +63,16 @@ static int isp_v4_1_0_hw_init(struct amdgpu_isp *isp) GFP_KERNEL); if (!isp->isp_res) { r = -ENOMEM; - DRM_ERROR("%s: isp mfd res alloc failed\n", __func__); + drm_err(&adev->ddev, + "%s: isp mfd res alloc failed\n", __func__); goto failure; } isp->isp_pdata = kzalloc(sizeof(*isp->isp_pdata), GFP_KERNEL); if (!isp->isp_pdata) { r = -ENOMEM; - DRM_ERROR("%s: isp platform data alloc failed\n", __func__); + drm_err(&adev->ddev, + "%s: isp platform data alloc failed\n", __func__); goto failure; } @@ -114,7 +117,8 @@ static int isp_v4_1_0_hw_init(struct amdgpu_isp *isp) GFP_KERNEL); if (!isp->isp_i2c_res) { r = -ENOMEM; - DRM_ERROR("%s: isp mfd res alloc failed\n", __func__); + drm_err(&adev->ddev, + "%s: isp mfd res alloc failed\n", __func__); goto failure; } @@ -131,7 +135,8 @@ static int isp_v4_1_0_hw_init(struct amdgpu_isp *isp) r = mfd_add_hotplug_devices(isp->parent, isp->isp_cell, 2); if (r) { - DRM_ERROR("%s: add mfd hotplug device failed\n", __func__); + drm_err(&adev->ddev, + "%s: add mfd hotplug device failed\n", __func__); goto failure; } diff --git a/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c index b56f27295468..3ee5942bc24d 100644 --- a/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c +++ b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c @@ -53,7 +53,8 @@ static int isp_v4_1_1_hw_init(struct amdgpu_isp *isp) isp->isp_cell = kcalloc(2, sizeof(struct mfd_cell), GFP_KERNEL); if (!isp->isp_cell) { r = -ENOMEM; - DRM_ERROR("%s: isp mfd cell alloc failed\n", __func__); + drm_err(&adev->ddev, + "%s: isp mfd cell alloc failed\n", __func__); goto failure; } @@ -63,14 +64,16 @@ static int isp_v4_1_1_hw_init(struct amdgpu_isp *isp) GFP_KERNEL); if (!isp->isp_res) { r = -ENOMEM; - DRM_ERROR("%s: isp mfd res alloc failed\n", __func__); + drm_err(&adev->ddev, + "%s: isp mfd res alloc failed\n", __func__); goto failure; } isp->isp_pdata = kzalloc(sizeof(*isp->isp_pdata), GFP_KERNEL); if (!isp->isp_pdata) { r = -ENOMEM; - DRM_ERROR("%s: isp platform data alloc failed\n", __func__); + drm_err(&adev->ddev, + "%s: isp platform data alloc failed\n", __func__); goto failure; } @@ -114,7 +117,8 @@ static int isp_v4_1_1_hw_init(struct amdgpu_isp *isp) isp->isp_i2c_res = kcalloc(1, sizeof(struct resource), GFP_KERNEL); if (!isp->isp_i2c_res) { r = -ENOMEM; - DRM_ERROR("%s: isp mfd res alloc failed\n", __func__); + drm_err(&adev->ddev, + "%s: isp mfd res alloc failed\n", __func__); goto failure; } @@ -131,7 +135,8 @@ static int isp_v4_1_1_hw_init(struct amdgpu_isp *isp) r = mfd_add_hotplug_devices(isp->parent, isp->isp_cell, 2); if (r) { - DRM_ERROR("%s: add mfd hotplug device failed\n", __func__); + drm_err(&adev->ddev, + "%s: add mfd hotplug device failed\n", __func__); goto failure; } From 82c13da746d24af7f2179bdceca46f950879896b Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Mon, 24 Feb 2025 01:49:42 +0000 Subject: [PATCH 121/235] drm/amd/display: Remove unused optc3_fpu_set_vrr_m_const The last use of optc3_fpu_set_vrr_m_const() was removed in 2022's commit 64f991590ff4 ("drm/amd/display: Fix a compilation failure on PowerPC caused by FPU code") which removed the only caller (with a similar) name. Remove it. Signed-off-by: Dr. David Alan Gilbert Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dml/dcn30/dcn30_fpu.c | 76 ------------------- .../drm/amd/display/dc/dml/dcn30/dcn30_fpu.h | 3 - 2 files changed, 79 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c index aac0a0ae2966..88789987bdbc 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c @@ -178,82 +178,6 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_0_soc = { }; -void optc3_fpu_set_vrr_m_const(struct timing_generator *optc, - double vtotal_avg) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - double vtotal_min, vtotal_max; - double ratio, modulo, phase; - uint32_t vblank_start; - uint32_t v_total_mask_value = 0; - - dc_assert_fp_enabled(); - - /* Compute VTOTAL_MIN and VTOTAL_MAX, so that - * VOTAL_MAX - VTOTAL_MIN = 1 - */ - v_total_mask_value = 16; - vtotal_min = dcn_bw_floor(vtotal_avg); - vtotal_max = dcn_bw_ceil(vtotal_avg); - - /* Check that bottom VBLANK is at least 2 lines tall when running with - * VTOTAL_MIN. Note that VTOTAL registers are defined as 'total number - * of lines in a frame - 1'. - */ - REG_GET(OTG_V_BLANK_START_END, OTG_V_BLANK_START, - &vblank_start); - ASSERT(vtotal_min >= vblank_start + 1); - - /* Special case where the average frame rate can be achieved - * without using the DTO - */ - if (vtotal_min == vtotal_max) { - REG_SET(OTG_V_TOTAL, 0, OTG_V_TOTAL, (uint32_t)vtotal_min); - - optc->funcs->set_vtotal_min_max(optc, 0, 0); - REG_SET(OTG_M_CONST_DTO0, 0, OTG_M_CONST_DTO_PHASE, 0); - REG_SET(OTG_M_CONST_DTO1, 0, OTG_M_CONST_DTO_MODULO, 0); - REG_UPDATE_3(OTG_V_TOTAL_CONTROL, - OTG_V_TOTAL_MIN_SEL, 0, - OTG_V_TOTAL_MAX_SEL, 0, - OTG_SET_V_TOTAL_MIN_MASK_EN, 0); - return; - } - - ratio = vtotal_max - vtotal_avg; - modulo = 65536.0 * 65536.0 - 1.0; /* 2^32 - 1 */ - phase = ratio * modulo; - - /* Special cases where the DTO phase gets rounded to 0 or - * to DTO modulo - */ - if (phase <= 0 || phase >= modulo) { - REG_SET(OTG_V_TOTAL, 0, OTG_V_TOTAL, - phase <= 0 ? - (uint32_t)vtotal_max : (uint32_t)vtotal_min); - REG_SET(OTG_V_TOTAL_MIN, 0, OTG_V_TOTAL_MIN, 0); - REG_SET(OTG_V_TOTAL_MAX, 0, OTG_V_TOTAL_MAX, 0); - REG_SET(OTG_M_CONST_DTO0, 0, OTG_M_CONST_DTO_PHASE, 0); - REG_SET(OTG_M_CONST_DTO1, 0, OTG_M_CONST_DTO_MODULO, 0); - REG_UPDATE_3(OTG_V_TOTAL_CONTROL, - OTG_V_TOTAL_MIN_SEL, 0, - OTG_V_TOTAL_MAX_SEL, 0, - OTG_SET_V_TOTAL_MIN_MASK_EN, 0); - return; - } - REG_UPDATE_6(OTG_V_TOTAL_CONTROL, - OTG_V_TOTAL_MIN_SEL, 1, - OTG_V_TOTAL_MAX_SEL, 1, - OTG_SET_V_TOTAL_MIN_MASK_EN, 1, - OTG_SET_V_TOTAL_MIN_MASK, v_total_mask_value, - OTG_VTOTAL_MID_REPLACING_MIN_EN, 0, - OTG_VTOTAL_MID_REPLACING_MAX_EN, 0); - REG_SET(OTG_V_TOTAL, 0, OTG_V_TOTAL, (uint32_t)vtotal_min); - optc->funcs->set_vtotal_min_max(optc, vtotal_min, vtotal_max); - REG_SET(OTG_M_CONST_DTO0, 0, OTG_M_CONST_DTO_PHASE, (uint32_t)phase); - REG_SET(OTG_M_CONST_DTO1, 0, OTG_M_CONST_DTO_MODULO, (uint32_t)modulo); -} - void dcn30_fpu_populate_dml_writeback_from_context( struct dc *dc, struct resource_context *res_ctx, display_e2e_pipe_params_st *pipes) { diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.h index cab864095ce7..e3b6ad6a8784 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.h @@ -29,9 +29,6 @@ #include "core_types.h" #include "dcn20/dcn20_optc.h" -void optc3_fpu_set_vrr_m_const(struct timing_generator *optc, - double vtotal_avg); - void dcn30_fpu_populate_dml_writeback_from_context( struct dc *dc, struct resource_context *res_ctx, display_e2e_pipe_params_st *pipes); From 4343f814e53f461c3040dfd3481aa7d8fcd02449 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 20 Feb 2025 09:58:25 -0500 Subject: [PATCH 122/235] drm/amdgpu/mes12: drop amdgpu_mes_suspend()/amdgpu_mes_resume() calls They are noops on GFX12. There is no suspend/resume all support in firmware so the function doesn't do anything. KFD already handles its own queues and they should already be unmapped at this point so even if this runs, it's not doing anything. Reviewed-by: Shaoyun.liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/mes_v12_0.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c index 12ea344ee5d4..fdc435b62012 100644 --- a/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c @@ -1789,24 +1789,12 @@ static int mes_v12_0_hw_fini(struct amdgpu_ip_block *ip_block) static int mes_v12_0_suspend(struct amdgpu_ip_block *ip_block) { - int r; - - r = amdgpu_mes_suspend(ip_block->adev); - if (r) - return r; - return mes_v12_0_hw_fini(ip_block); } static int mes_v12_0_resume(struct amdgpu_ip_block *ip_block) { - int r; - - r = mes_v12_0_hw_init(ip_block); - if (r) - return r; - - return amdgpu_mes_resume(ip_block->adev); + return mes_v12_0_hw_init(ip_block); } static int mes_v12_0_early_init(struct amdgpu_ip_block *ip_block) From dce1b8239803c456e5c6a9f45164d16cf11e3470 Mon Sep 17 00:00:00 2001 From: Benjamin Chan Date: Fri, 31 Jan 2025 14:03:46 -0500 Subject: [PATCH 123/235] drm/amdgpu: Add amdisp pinctrl MFD resource AMDISP GPIO control uses a dedicated pinctrl driver, and requires MFD hotadd GPIO resources. Co-developed-by: Pratap Nirujogi Signed-off-by: Benjamin Chan Signed-off-by: Pratap Nirujogi Reviewed-by: Mario Limonciello Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_isp.h | 1 + drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.c | 42 +++++++++++++++++-------- drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.h | 4 +-- drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c | 39 ++++++++++++++++------- drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.h | 5 ++- 5 files changed, 62 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.h index b03664c66dd6..4f3b7b5d9c1f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.h @@ -50,6 +50,7 @@ struct amdgpu_isp { struct mfd_cell *isp_cell; struct resource *isp_res; struct resource *isp_i2c_res; + struct resource *isp_gpio_res; struct isp_platform_data *isp_pdata; unsigned int harvest_config; const struct firmware *fw; diff --git a/drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.c b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.c index 2475564b2c08..0027a639c7e6 100644 --- a/drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.c @@ -50,7 +50,7 @@ static int isp_v4_1_0_hw_init(struct amdgpu_isp *isp) isp_base = adev->rmmio_base; - isp->isp_cell = kcalloc(2, sizeof(struct mfd_cell), GFP_KERNEL); + isp->isp_cell = kcalloc(3, sizeof(struct mfd_cell), GFP_KERNEL); if (!isp->isp_cell) { r = -ENOMEM; drm_err(&adev->ddev, @@ -58,7 +58,7 @@ static int isp_v4_1_0_hw_init(struct amdgpu_isp *isp) goto failure; } - num_res = MAX_ISP410_MEM_RES + MAX_ISP410_SENSOR_RES + MAX_ISP410_INT_SRC; + num_res = MAX_ISP410_MEM_RES + MAX_ISP410_INT_SRC; isp->isp_res = kcalloc(num_res, sizeof(struct resource), GFP_KERNEL); if (!isp->isp_res) { @@ -91,14 +91,7 @@ static int isp_v4_1_0_hw_init(struct amdgpu_isp *isp) isp->isp_res[1].start = isp_base + ISP410_PHY0_OFFSET; isp->isp_res[1].end = isp_base + ISP410_PHY0_OFFSET + ISP410_PHY0_SIZE; - isp->isp_res[2].name = "isp_gpio_sensor0_reg"; - isp->isp_res[2].flags = IORESOURCE_MEM; - isp->isp_res[2].start = isp_base + ISP410_GPIO_SENSOR0_OFFSET; - isp->isp_res[2].end = isp_base + ISP410_GPIO_SENSOR0_OFFSET + - ISP410_GPIO_SENSOR0_SIZE; - - for (idx = MAX_ISP410_MEM_RES + MAX_ISP410_SENSOR_RES, int_idx = 0; - idx < num_res; idx++, int_idx++) { + for (idx = MAX_ISP410_MEM_RES, int_idx = 0; idx < num_res; idx++, int_idx++) { isp->isp_res[idx].name = "isp_4_1_0_irq"; isp->isp_res[idx].flags = IORESOURCE_IRQ; isp->isp_res[idx].start = @@ -113,8 +106,8 @@ static int isp_v4_1_0_hw_init(struct amdgpu_isp *isp) isp->isp_cell[0].platform_data = isp->isp_pdata; isp->isp_cell[0].pdata_size = sizeof(struct isp_platform_data); - isp->isp_i2c_res = kcalloc(1, sizeof(struct resource), - GFP_KERNEL); + /* initialize isp i2c platform data */ + isp->isp_i2c_res = kcalloc(1, sizeof(struct resource), GFP_KERNEL); if (!isp->isp_i2c_res) { r = -ENOMEM; drm_err(&adev->ddev, @@ -133,7 +126,28 @@ static int isp_v4_1_0_hw_init(struct amdgpu_isp *isp) isp->isp_cell[1].platform_data = isp->isp_pdata; isp->isp_cell[1].pdata_size = sizeof(struct isp_platform_data); - r = mfd_add_hotplug_devices(isp->parent, isp->isp_cell, 2); + /* initialize isp gpiochip platform data */ + isp->isp_gpio_res = kcalloc(1, sizeof(struct resource), GFP_KERNEL); + if (!isp->isp_gpio_res) { + r = -ENOMEM; + drm_err(&adev->ddev, + "%s: isp gpio res alloc failed\n", __func__); + goto failure; + } + + isp->isp_gpio_res[0].name = "isp_gpio_reg"; + isp->isp_gpio_res[0].flags = IORESOURCE_MEM; + isp->isp_gpio_res[0].start = isp_base + ISP410_GPIO_SENSOR_OFFSET; + isp->isp_gpio_res[0].end = isp_base + ISP410_GPIO_SENSOR_OFFSET + + ISP410_GPIO_SENSOR_SIZE; + + isp->isp_cell[2].name = "amdisp-pinctrl"; + isp->isp_cell[2].num_resources = 1; + isp->isp_cell[2].resources = &isp->isp_gpio_res[0]; + isp->isp_cell[2].platform_data = isp->isp_pdata; + isp->isp_cell[2].pdata_size = sizeof(struct isp_platform_data); + + r = mfd_add_hotplug_devices(isp->parent, isp->isp_cell, 3); if (r) { drm_err(&adev->ddev, "%s: add mfd hotplug device failed\n", __func__); @@ -148,6 +162,7 @@ static int isp_v4_1_0_hw_init(struct amdgpu_isp *isp) kfree(isp->isp_res); kfree(isp->isp_cell); kfree(isp->isp_i2c_res); + kfree(isp->isp_gpio_res); return r; } @@ -160,6 +175,7 @@ static int isp_v4_1_0_hw_fini(struct amdgpu_isp *isp) kfree(isp->isp_cell); kfree(isp->isp_pdata); kfree(isp->isp_i2c_res); + kfree(isp->isp_gpio_res); return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.h b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.h index 7db24c0f1080..4d239198edd0 100644 --- a/drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.h +++ b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.h @@ -42,8 +42,8 @@ #define ISP410_I2C0_OFFSET 0x66400 #define ISP410_I2C0_SIZE 0x100 -#define ISP410_GPIO_SENSOR0_OFFSET 0x6613C -#define ISP410_GPIO_SENSOR0_SIZE 0x4 +#define ISP410_GPIO_SENSOR_OFFSET 0x6613C +#define ISP410_GPIO_SENSOR_SIZE 0x54 void isp_v4_1_0_set_isp_funcs(struct amdgpu_isp *isp); diff --git a/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c index 3ee5942bc24d..69dd92f6e86d 100644 --- a/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c +++ b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c @@ -50,7 +50,7 @@ static int isp_v4_1_1_hw_init(struct amdgpu_isp *isp) isp_base = adev->rmmio_base; - isp->isp_cell = kcalloc(2, sizeof(struct mfd_cell), GFP_KERNEL); + isp->isp_cell = kcalloc(3, sizeof(struct mfd_cell), GFP_KERNEL); if (!isp->isp_cell) { r = -ENOMEM; drm_err(&adev->ddev, @@ -58,7 +58,7 @@ static int isp_v4_1_1_hw_init(struct amdgpu_isp *isp) goto failure; } - num_res = MAX_ISP411_MEM_RES + MAX_ISP411_SENSOR_RES + MAX_ISP411_INT_SRC; + num_res = MAX_ISP411_MEM_RES + MAX_ISP411_INT_SRC; isp->isp_res = kcalloc(num_res, sizeof(struct resource), GFP_KERNEL); @@ -92,14 +92,7 @@ static int isp_v4_1_1_hw_init(struct amdgpu_isp *isp) isp->isp_res[1].start = isp_base + ISP411_PHY0_OFFSET; isp->isp_res[1].end = isp_base + ISP411_PHY0_OFFSET + ISP411_PHY0_SIZE; - isp->isp_res[2].name = "isp_4_1_1_sensor0_reg"; - isp->isp_res[2].flags = IORESOURCE_MEM; - isp->isp_res[2].start = isp_base + ISP411_GPIO_SENSOR0_OFFSET; - isp->isp_res[2].end = isp_base + ISP411_GPIO_SENSOR0_OFFSET + - ISP411_GPIO_SENSOR0_SIZE; - - for (idx = MAX_ISP411_MEM_RES + MAX_ISP411_SENSOR_RES, int_idx = 0; - idx < num_res; idx++, int_idx++) { + for (idx = MAX_ISP411_MEM_RES, int_idx = 0; idx < num_res; idx++, int_idx++) { isp->isp_res[idx].name = "isp_4_1_1_irq"; isp->isp_res[idx].flags = IORESOURCE_IRQ; isp->isp_res[idx].start = @@ -114,6 +107,7 @@ static int isp_v4_1_1_hw_init(struct amdgpu_isp *isp) isp->isp_cell[0].platform_data = isp->isp_pdata; isp->isp_cell[0].pdata_size = sizeof(struct isp_platform_data); + /* initialize isp i2c platform data */ isp->isp_i2c_res = kcalloc(1, sizeof(struct resource), GFP_KERNEL); if (!isp->isp_i2c_res) { r = -ENOMEM; @@ -133,7 +127,28 @@ static int isp_v4_1_1_hw_init(struct amdgpu_isp *isp) isp->isp_cell[1].platform_data = isp->isp_pdata; isp->isp_cell[1].pdata_size = sizeof(struct isp_platform_data); - r = mfd_add_hotplug_devices(isp->parent, isp->isp_cell, 2); + /* initialize isp gpiochip platform data */ + isp->isp_gpio_res = kcalloc(1, sizeof(struct resource), GFP_KERNEL); + if (!isp->isp_gpio_res) { + r = -ENOMEM; + drm_err(&adev->ddev, + "%s: isp gpio res alloc failed\n", __func__); + goto failure; + } + + isp->isp_gpio_res[0].name = "isp_gpio_reg"; + isp->isp_gpio_res[0].flags = IORESOURCE_MEM; + isp->isp_gpio_res[0].start = isp_base + ISP411_GPIO_SENSOR_OFFSET; + isp->isp_gpio_res[0].end = isp_base + ISP411_GPIO_SENSOR_OFFSET + + ISP411_GPIO_SENSOR_SIZE; + + isp->isp_cell[2].name = "amdisp-pinctrl"; + isp->isp_cell[2].num_resources = 1; + isp->isp_cell[2].resources = &isp->isp_gpio_res[0]; + isp->isp_cell[2].platform_data = isp->isp_pdata; + isp->isp_cell[2].pdata_size = sizeof(struct isp_platform_data); + + r = mfd_add_hotplug_devices(isp->parent, isp->isp_cell, 3); if (r) { drm_err(&adev->ddev, "%s: add mfd hotplug device failed\n", __func__); @@ -148,6 +163,7 @@ static int isp_v4_1_1_hw_init(struct amdgpu_isp *isp) kfree(isp->isp_res); kfree(isp->isp_cell); kfree(isp->isp_i2c_res); + kfree(isp->isp_gpio_res); return r; } @@ -160,6 +176,7 @@ static int isp_v4_1_1_hw_fini(struct amdgpu_isp *isp) kfree(isp->isp_cell); kfree(isp->isp_pdata); kfree(isp->isp_i2c_res); + kfree(isp->isp_gpio_res); return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.h b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.h index 40887ddeb08c..fe45d70d87f1 100644 --- a/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.h +++ b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.h @@ -33,7 +33,6 @@ #include "ivsrcid/isp/irqsrcs_isp_4_1.h" #define MAX_ISP411_MEM_RES 2 -#define MAX_ISP411_SENSOR_RES 1 #define MAX_ISP411_INT_SRC 8 #define ISP411_PHY0_OFFSET 0x66700 @@ -42,8 +41,8 @@ #define ISP411_I2C0_OFFSET 0x66400 #define ISP411_I2C0_SIZE 0x100 -#define ISP411_GPIO_SENSOR0_OFFSET 0x6613C -#define ISP411_GPIO_SENSOR0_SIZE 0x4 +#define ISP411_GPIO_SENSOR_OFFSET 0x6613C +#define ISP411_GPIO_SENSOR_SIZE 0x54 void isp_v4_1_1_set_isp_funcs(struct amdgpu_isp *isp); From fddc45026311c05a5355fd34b9dc0a1d7eaef4a2 Mon Sep 17 00:00:00 2001 From: Srinivasan Shanmugam Date: Mon, 24 Feb 2025 13:46:32 +0530 Subject: [PATCH 124/235] drm/amdkfd: Fix Circular Locking Dependency in 'svm_range_cpu_invalidate_pagetables' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit addresses a circular locking dependency in the svm_range_cpu_invalidate_pagetables function. The function previously held a lock while determining whether to perform an unmap or eviction operation, which could lead to deadlocks. Fixes the below: [ 223.418794] ====================================================== [ 223.418820] WARNING: possible circular locking dependency detected [ 223.418845] 6.12.0-amdstaging-drm-next-lol-050225 #14 Tainted: G U OE [ 223.418869] ------------------------------------------------------ [ 223.418889] kfdtest/3939 is trying to acquire lock: [ 223.418906] ffff8957552eae38 (&dqm->lock_hidden){+.+.}-{3:3}, at: evict_process_queues_cpsch+0x43/0x210 [amdgpu] [ 223.419302] but task is already holding lock: [ 223.419303] ffff8957556b83b0 (&prange->lock){+.+.}-{3:3}, at: svm_range_cpu_invalidate_pagetables+0x9d/0x850 [amdgpu] [ 223.419447] Console: switching to colour dummy device 80x25 [ 223.419477] [IGT] amd_basic: executing [ 223.419599] which lock already depends on the new lock. [ 223.419611] the existing dependency chain (in reverse order) is: [ 223.419621] -> #2 (&prange->lock){+.+.}-{3:3}: [ 223.419636] __mutex_lock+0x85/0xe20 [ 223.419647] mutex_lock_nested+0x1b/0x30 [ 223.419656] svm_range_validate_and_map+0x2f1/0x15b0 [amdgpu] [ 223.419954] svm_range_set_attr+0xe8c/0x1710 [amdgpu] [ 223.420236] svm_ioctl+0x46/0x50 [amdgpu] [ 223.420503] kfd_ioctl_svm+0x50/0x90 [amdgpu] [ 223.420763] kfd_ioctl+0x409/0x6d0 [amdgpu] [ 223.421024] __x64_sys_ioctl+0x95/0xd0 [ 223.421036] x64_sys_call+0x1205/0x20d0 [ 223.421047] do_syscall_64+0x87/0x140 [ 223.421056] entry_SYSCALL_64_after_hwframe+0x76/0x7e [ 223.421068] -> #1 (reservation_ww_class_mutex){+.+.}-{3:3}: [ 223.421084] __ww_mutex_lock.constprop.0+0xab/0x1560 [ 223.421095] ww_mutex_lock+0x2b/0x90 [ 223.421103] amdgpu_amdkfd_alloc_gtt_mem+0xcc/0x2b0 [amdgpu] [ 223.421361] add_queue_mes+0x3bc/0x440 [amdgpu] [ 223.421623] unhalt_cpsch+0x1ae/0x240 [amdgpu] [ 223.421888] kgd2kfd_start_sched+0x5e/0xd0 [amdgpu] [ 223.422148] amdgpu_amdkfd_start_sched+0x3d/0x50 [amdgpu] [ 223.422414] amdgpu_gfx_enforce_isolation_handler+0x132/0x270 [amdgpu] [ 223.422662] process_one_work+0x21e/0x680 [ 223.422673] worker_thread+0x190/0x330 [ 223.422682] kthread+0xe7/0x120 [ 223.422690] ret_from_fork+0x3c/0x60 [ 223.422699] ret_from_fork_asm+0x1a/0x30 [ 223.422708] -> #0 (&dqm->lock_hidden){+.+.}-{3:3}: [ 223.422723] __lock_acquire+0x16f4/0x2810 [ 223.422734] lock_acquire+0xd1/0x300 [ 223.422742] __mutex_lock+0x85/0xe20 [ 223.422751] mutex_lock_nested+0x1b/0x30 [ 223.422760] evict_process_queues_cpsch+0x43/0x210 [amdgpu] [ 223.423025] kfd_process_evict_queues+0x8a/0x1d0 [amdgpu] [ 223.423285] kgd2kfd_quiesce_mm+0x43/0x90 [amdgpu] [ 223.423540] svm_range_cpu_invalidate_pagetables+0x4a7/0x850 [amdgpu] [ 223.423807] __mmu_notifier_invalidate_range_start+0x1f5/0x250 [ 223.423819] copy_page_range+0x1e94/0x1ea0 [ 223.423829] copy_process+0x172f/0x2ad0 [ 223.423839] kernel_clone+0x9c/0x3f0 [ 223.423847] __do_sys_clone+0x66/0x90 [ 223.423856] __x64_sys_clone+0x25/0x30 [ 223.423864] x64_sys_call+0x1d7c/0x20d0 [ 223.423872] do_syscall_64+0x87/0x140 [ 223.423880] entry_SYSCALL_64_after_hwframe+0x76/0x7e [ 223.423891] other info that might help us debug this: [ 223.423903] Chain exists of: &dqm->lock_hidden --> reservation_ww_class_mutex --> &prange->lock [ 223.423926] Possible unsafe locking scenario: [ 223.423935] CPU0 CPU1 [ 223.423942] ---- ---- [ 223.423949] lock(&prange->lock); [ 223.423958] lock(reservation_ww_class_mutex); [ 223.423970] lock(&prange->lock); [ 223.423981] lock(&dqm->lock_hidden); [ 223.423990] *** DEADLOCK *** [ 223.423999] 5 locks held by kfdtest/3939: [ 223.424006] #0: ffffffffb82b4fc0 (dup_mmap_sem){.+.+}-{0:0}, at: copy_process+0x1387/0x2ad0 [ 223.424026] #1: ffff89575eda81b0 (&mm->mmap_lock){++++}-{3:3}, at: copy_process+0x13a8/0x2ad0 [ 223.424046] #2: ffff89575edaf3b0 (&mm->mmap_lock/1){+.+.}-{3:3}, at: copy_process+0x13e4/0x2ad0 [ 223.424066] #3: ffffffffb82e76e0 (mmu_notifier_invalidate_range_start){+.+.}-{0:0}, at: copy_page_range+0x1cea/0x1ea0 [ 223.424088] #4: ffff8957556b83b0 (&prange->lock){+.+.}-{3:3}, at: svm_range_cpu_invalidate_pagetables+0x9d/0x850 [amdgpu] [ 223.424365] stack backtrace: [ 223.424374] CPU: 0 UID: 0 PID: 3939 Comm: kfdtest Tainted: G U OE 6.12.0-amdstaging-drm-next-lol-050225 #14 [ 223.424392] Tainted: [U]=USER, [O]=OOT_MODULE, [E]=UNSIGNED_MODULE [ 223.424401] Hardware name: Gigabyte Technology Co., Ltd. X570 AORUS PRO WIFI/X570 AORUS PRO WIFI, BIOS F36a 02/16/2022 [ 223.424416] Call Trace: [ 223.424423] [ 223.424430] dump_stack_lvl+0x9b/0xf0 [ 223.424441] dump_stack+0x10/0x20 [ 223.424449] print_circular_bug+0x275/0x350 [ 223.424460] check_noncircular+0x157/0x170 [ 223.424469] ? __bfs+0xfd/0x2c0 [ 223.424481] __lock_acquire+0x16f4/0x2810 [ 223.424490] ? srso_return_thunk+0x5/0x5f [ 223.424505] lock_acquire+0xd1/0x300 [ 223.424514] ? evict_process_queues_cpsch+0x43/0x210 [amdgpu] [ 223.424783] __mutex_lock+0x85/0xe20 [ 223.424792] ? evict_process_queues_cpsch+0x43/0x210 [amdgpu] [ 223.425058] ? srso_return_thunk+0x5/0x5f [ 223.425067] ? mark_held_locks+0x54/0x90 [ 223.425076] ? evict_process_queues_cpsch+0x43/0x210 [amdgpu] [ 223.425339] ? srso_return_thunk+0x5/0x5f [ 223.425350] mutex_lock_nested+0x1b/0x30 [ 223.425358] ? mutex_lock_nested+0x1b/0x30 [ 223.425367] evict_process_queues_cpsch+0x43/0x210 [amdgpu] [ 223.425631] kfd_process_evict_queues+0x8a/0x1d0 [amdgpu] [ 223.425893] kgd2kfd_quiesce_mm+0x43/0x90 [amdgpu] [ 223.426156] svm_range_cpu_invalidate_pagetables+0x4a7/0x850 [amdgpu] [ 223.426423] ? srso_return_thunk+0x5/0x5f [ 223.426436] __mmu_notifier_invalidate_range_start+0x1f5/0x250 [ 223.426450] copy_page_range+0x1e94/0x1ea0 [ 223.426461] ? srso_return_thunk+0x5/0x5f [ 223.426474] ? srso_return_thunk+0x5/0x5f [ 223.426484] ? lock_acquire+0xd1/0x300 [ 223.426494] ? copy_process+0x1718/0x2ad0 [ 223.426502] ? srso_return_thunk+0x5/0x5f [ 223.426510] ? sched_clock_noinstr+0x9/0x10 [ 223.426519] ? local_clock_noinstr+0xe/0xc0 [ 223.426528] ? copy_process+0x1718/0x2ad0 [ 223.426537] ? srso_return_thunk+0x5/0x5f [ 223.426550] copy_process+0x172f/0x2ad0 [ 223.426569] kernel_clone+0x9c/0x3f0 [ 223.426577] ? __schedule+0x4c9/0x1b00 [ 223.426586] ? srso_return_thunk+0x5/0x5f [ 223.426594] ? sched_clock_noinstr+0x9/0x10 [ 223.426602] ? srso_return_thunk+0x5/0x5f [ 223.426610] ? local_clock_noinstr+0xe/0xc0 [ 223.426619] ? schedule+0x107/0x1a0 [ 223.426629] __do_sys_clone+0x66/0x90 [ 223.426643] __x64_sys_clone+0x25/0x30 [ 223.426652] x64_sys_call+0x1d7c/0x20d0 [ 223.426661] do_syscall_64+0x87/0x140 [ 223.426671] ? srso_return_thunk+0x5/0x5f [ 223.426679] ? common_nsleep+0x44/0x50 [ 223.426690] ? srso_return_thunk+0x5/0x5f [ 223.426698] ? trace_hardirqs_off+0x52/0xd0 [ 223.426709] ? srso_return_thunk+0x5/0x5f [ 223.426717] ? syscall_exit_to_user_mode+0xcc/0x200 [ 223.426727] ? srso_return_thunk+0x5/0x5f [ 223.426736] ? do_syscall_64+0x93/0x140 [ 223.426748] ? srso_return_thunk+0x5/0x5f [ 223.426756] ? up_write+0x1c/0x1e0 [ 223.426765] ? srso_return_thunk+0x5/0x5f [ 223.426775] ? srso_return_thunk+0x5/0x5f [ 223.426783] ? trace_hardirqs_off+0x52/0xd0 [ 223.426792] ? srso_return_thunk+0x5/0x5f [ 223.426800] ? syscall_exit_to_user_mode+0xcc/0x200 [ 223.426810] ? srso_return_thunk+0x5/0x5f [ 223.426818] ? do_syscall_64+0x93/0x140 [ 223.426826] ? syscall_exit_to_user_mode+0xcc/0x200 [ 223.426836] ? srso_return_thunk+0x5/0x5f [ 223.426844] ? do_syscall_64+0x93/0x140 [ 223.426853] ? srso_return_thunk+0x5/0x5f [ 223.426861] ? irqentry_exit+0x6b/0x90 [ 223.426869] ? srso_return_thunk+0x5/0x5f [ 223.426877] ? exc_page_fault+0xa7/0x2c0 [ 223.426888] entry_SYSCALL_64_after_hwframe+0x76/0x7e [ 223.426898] RIP: 0033:0x7f46758eab57 [ 223.426906] Code: ba 04 00 f3 0f 1e fa 64 48 8b 04 25 10 00 00 00 45 31 c0 31 d2 31 f6 bf 11 00 20 01 4c 8d 90 d0 02 00 00 b8 38 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 41 41 89 c0 85 c0 75 2c 64 48 8b 04 25 10 00 [ 223.426930] RSP: 002b:00007fff5c3e5188 EFLAGS: 00000246 ORIG_RAX: 0000000000000038 [ 223.426943] RAX: ffffffffffffffda RBX: 00007f4675f8c040 RCX: 00007f46758eab57 [ 223.426954] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000001200011 [ 223.426965] RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000 [ 223.426975] R10: 00007f4675e81a50 R11: 0000000000000246 R12: 0000000000000001 [ 223.426986] R13: 00007fff5c3e5470 R14: 00007fff5c3e53e0 R15: 00007fff5c3e5410 [ 223.427004] v2: To resolve this issue, the allocation of the process context buffer (`proc_ctx_bo`) has been moved from the `add_queue_mes` function to the `pqm_create_queue` function. This change ensures that the buffer is allocated only when the first queue for a process is created and only if the Micro Engine Scheduler (MES) is enabled. (Felix) v3: Fix typo s/Memory Execution Scheduler (MES)/Micro Engine Scheduler in commit message. (Lijo) Fixes: 438b39ac74e2 ("drm/amdkfd: pause autosuspend when creating pdd") Cc: Jesse Zhang Cc: Yunxiang Li Cc: Philip Yang Cc: Alex Sierra Cc: Felix Kuehling Cc: Christian König Cc: Alex Deucher Signed-off-by: Srinivasan Shanmugam Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- .../drm/amd/amdkfd/kfd_device_queue_manager.c | 15 --------------- .../drm/amd/amdkfd/kfd_process_queue_manager.c | 16 ++++++++++++++++ 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index 195085079eb2..94b1ac8a4735 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -207,21 +207,6 @@ static int add_queue_mes(struct device_queue_manager *dqm, struct queue *q, if (!down_read_trylock(&adev->reset_domain->sem)) return -EIO; - if (!pdd->proc_ctx_cpu_ptr) { - r = amdgpu_amdkfd_alloc_gtt_mem(adev, - AMDGPU_MES_PROC_CTX_SIZE, - &pdd->proc_ctx_bo, - &pdd->proc_ctx_gpu_addr, - &pdd->proc_ctx_cpu_ptr, - false); - if (r) { - dev_err(adev->dev, - "failed to allocate process context bo\n"); - return r; - } - memset(pdd->proc_ctx_cpu_ptr, 0, AMDGPU_MES_PROC_CTX_SIZE); - } - memset(&queue_input, 0x0, sizeof(struct mes_add_queue_input)); queue_input.process_id = pdd->pasid; queue_input.page_table_base_addr = qpd->page_table_base; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c index d7947311cbbd..93647ee27325 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c @@ -363,10 +363,26 @@ int pqm_create_queue(struct process_queue_manager *pqm, if (retval != 0) return retval; + /* Register process if this is the first queue */ if (list_empty(&pdd->qpd.queues_list) && list_empty(&pdd->qpd.priv_queue_list)) dev->dqm->ops.register_process(dev->dqm, &pdd->qpd); + /* Allocate proc_ctx_bo only if MES is enabled and this is the first queue */ + if (!pdd->proc_ctx_cpu_ptr && dev->kfd->shared_resources.enable_mes) { + retval = amdgpu_amdkfd_alloc_gtt_mem(dev->adev, + AMDGPU_MES_PROC_CTX_SIZE, + &pdd->proc_ctx_bo, + &pdd->proc_ctx_gpu_addr, + &pdd->proc_ctx_cpu_ptr, + false); + if (retval) { + dev_err(dev->adev->dev, "failed to allocate process context bo\n"); + return retval; + } + memset(pdd->proc_ctx_cpu_ptr, 0, AMDGPU_MES_PROC_CTX_SIZE); + } + pqn = kzalloc(sizeof(*pqn), GFP_KERNEL); if (!pqn) { retval = -ENOMEM; From 906d2859e1c69ad3bd680fc02a2de00105ee827b Mon Sep 17 00:00:00 2001 From: Xiang Liu Date: Mon, 24 Feb 2025 15:13:40 +0800 Subject: [PATCH 125/235] drm/amdgpu: Disable fru_id field in CPER section The fru_id field is disabled cause of mis-matching defination between CPER spec and driver. Signed-off-by: Xiang Liu Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c index 5b6bdabb8012..0b288deb9b19 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c @@ -112,7 +112,6 @@ static int amdgpu_cper_entry_fill_section_desc(struct amdgpu_device *adev, section_desc->revision_major = CPER_SEC_MAJOR_REV_22; section_desc->sec_offset = section_offset; section_desc->sec_length = section_length; - section_desc->valid_bits.fru_id = 1; section_desc->valid_bits.fru_text = 1; section_desc->flag_bits.primary = 1; section_desc->severity = sev; @@ -122,8 +121,6 @@ static int amdgpu_cper_entry_fill_section_desc(struct amdgpu_device *adev, adev->smuio.funcs->get_socket_id) snprintf(section_desc->fru_text, 20, "OAM%d", adev->smuio.funcs->get_socket_id(adev)); - /* TODO: fru_id is 16 bytes in CPER spec, but driver defines it as 20 bytes */ - snprintf(section_desc->fru_id, 16, "%llx", adev->unique_id); if (bp_threshold) section_desc->flag_bits.exceed_err_threshold = 1; @@ -376,7 +373,7 @@ int amdgpu_cper_generate_ce_records(struct amdgpu_device *adev, amdgpu_cper_entry_fill_hdr(adev, corrected, AMDGPU_CPER_TYPE_RUNTIME, sev); - /* Combine CE and UE in cper record */ + /* Combine CE and DE in cper record */ list_for_each_entry(node, &banks->list, node) { bank = &node->bank; reg_data[CPER_ACA_REG_CTL_LO] = lower_32_bits(bank->regs[ACA_REG_IDX_CTL]); From b965e42530a815987a56d84b78c11e1852541ec0 Mon Sep 17 00:00:00 2001 From: Lijo Lazar Date: Tue, 25 Feb 2025 16:21:51 +0530 Subject: [PATCH 126/235] drm/amdgpu: Fix logic to fetch supported NPS modes Correct the logic to find supported NPS modes from firmware. Signed-off-by: Lijo Lazar Reported-by: Ava Zhang Reviewed-by: Hawking Zhang Fixes: 30eb41f5d1a7 ("drm/amdgpu: Use firmware supported NPS modes") Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index ccb31e724b55..783e0c3b86b4 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -1607,9 +1607,8 @@ static void gmc_v9_0_init_nps_details(struct amdgpu_device *adev) /* Mode detected by hardware and supported modes available */ if ((mode != UNKNOWN_MEMORY_PARTITION_MODE) && supp_modes) { - for (i = AMDGPU_NPS1_PARTITION_MODE; - supp_modes && i <= AMDGPU_NPS8_PARTITION_MODE; i++) { - if (supp_modes & BIT(i - 1)) + while ((i = ffs(supp_modes))) { + if (AMDGPU_ALL_NPS_MASK & BIT(i)) adev->gmc.supported_nps_modes |= BIT(i); supp_modes &= supp_modes - 1; } From d4bd7a50ca7c6199438cf19063464b4d6327a6c1 Mon Sep 17 00:00:00 2001 From: Xiang Liu Date: Wed, 26 Feb 2025 14:27:27 +0800 Subject: [PATCH 127/235] drm/amdgpu: Report generic instead of unknown boot time errors Change the DMESG reporting of unknown errors to "Boot Controller Generic Error" to align with the RAS SPEC and provide more clarity to customers. Signed-off-by: Xiang Liu Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 493dd004d6fa..285e3aa2bb2f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -5138,9 +5138,9 @@ static void amdgpu_ras_boot_time_error_reporting(struct amdgpu_device *adev, "socket: %d, aid: %d, fw_status: 0x%x, data abort exception\n", socket_id, aid_id, fw_status); - if (AMDGPU_RAS_GPU_ERR_UNKNOWN(boot_error)) + if (AMDGPU_RAS_GPU_ERR_GENERIC(boot_error)) dev_info(adev->dev, - "socket: %d, aid: %d, fw_status: 0x%x, unknown boot time errors\n", + "socket: %d, aid: %d, fw_status: 0x%x, Boot Controller Generic Error\n", socket_id, aid_id, fw_status); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h index cc4586581dba..764e9fa0a914 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h @@ -47,7 +47,7 @@ struct amdgpu_iv_entry; #define AMDGPU_RAS_GPU_ERR_AID_ID(x) AMDGPU_GET_REG_FIELD(x, 12, 11) #define AMDGPU_RAS_GPU_ERR_HBM_ID(x) AMDGPU_GET_REG_FIELD(x, 14, 13) #define AMDGPU_RAS_GPU_ERR_DATA_ABORT(x) AMDGPU_GET_REG_FIELD(x, 29, 29) -#define AMDGPU_RAS_GPU_ERR_UNKNOWN(x) AMDGPU_GET_REG_FIELD(x, 30, 30) +#define AMDGPU_RAS_GPU_ERR_GENERIC(x) AMDGPU_GET_REG_FIELD(x, 30, 30) #define AMDGPU_RAS_BOOT_STATUS_POLLING_LIMIT 100 #define AMDGPU_RAS_BOOT_STEADY_STATUS 0xBA From 7d37bcab9748134be668ec222ed630150eb32e8e Mon Sep 17 00:00:00 2001 From: Kenneth Feng Date: Wed, 26 Feb 2025 16:05:57 +0800 Subject: [PATCH 128/235] drm/amd/pm: disable gfxoff on the specific sku disable gfxoff on the specific sku based on the requirement Signed-off-by: Kenneth Feng Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c index 985355bf78b2..898487ad6cd2 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c @@ -3234,4 +3234,9 @@ void smu_v13_0_0_set_ppt_funcs(struct smu_context *smu) smu->workload_map = smu_v13_0_0_workload_map; smu->smc_driver_if_version = SMU13_0_0_DRIVER_IF_VERSION; smu_v13_0_0_set_smu_mailbox_registers(smu); + + if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == + IP_VERSION(13, 0, 10) && + !amdgpu_device_has_display_hardware(smu->adev)) + smu->adev->pm.pp_feature &= ~PP_GFXOFF_MASK; } From 5b5f01eff70f9fb0456c945b0309bb19c186491a Mon Sep 17 00:00:00 2001 From: Le Ma Date: Tue, 11 Feb 2025 14:06:54 +0800 Subject: [PATCH 129/235] drm/amdgpu: add sdma page queue irq processing for sdma442 Add the trap irq processing for page queue of sdma442 Signed-off-by: Le Ma Reviewed-by and Tested-by: Jesse Zhang Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c index ba43c8f46f45..03e47fad217f 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c @@ -1783,6 +1783,9 @@ static int sdma_v4_4_2_process_trap_irq(struct amdgpu_device *adev, case 0: amdgpu_fence_process(&adev->sdma.instance[i].ring); break; + case 1: + amdgpu_fence_process(&adev->sdma.instance[i].page); + break; default: break; } From 00f85667faf03591666a3a447dc0d489ea9f0cb4 Mon Sep 17 00:00:00 2001 From: Xiang Liu Date: Wed, 26 Feb 2025 11:36:55 +0800 Subject: [PATCH 130/235] drm/amdgpu: Decode deferred error type in aca bank parser In the case of poison inband log, the error type need to be specified by checking the deferred or poison bit of status register. v2: check both deferred and poison bit Signed-off-by: Xiang Liu Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_aca.h | 6 ++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c | 5 +++-- drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c | 4 ++-- 7 files changed, 19 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.h index b84a3489b116..6f62e5d80ed6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.h @@ -76,6 +76,12 @@ struct ras_query_context; #define mmSMNAID_XCD1_MCA_SMU 0x38430400 /* SMN AID XCD1 */ #define mmSMNXCD_XCD0_MCA_SMU 0x40430400 /* SMN XCD XCD0 */ +#define ACA_BANK_ERR_CE_DE_DECODE(bank) \ + ((ACA_REG__STATUS__POISON((bank)->regs[ACA_REG_IDX_STATUS]) || \ + ACA_REG__STATUS__DEFERRED((bank)->regs[ACA_REG_IDX_STATUS])) ? \ + ACA_ERROR_TYPE_DEFERRED : \ + ACA_ERROR_TYPE_CE) + enum aca_reg_idx { ACA_REG_IDX_CTL = 0, ACA_REG_IDX_STATUS = 1, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c index 49da137d42c9..c313c2cf6969 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c @@ -1169,8 +1169,8 @@ static int xgmi_v6_4_0_aca_bank_parser(struct aca_handle *handle, struct aca_ban break; case ACA_SMU_TYPE_CE: count = ext_error_code == 6 ? count : 0ULL; - bank->aca_err_type = ACA_ERROR_TYPE_CE; - ret = aca_error_cache_log_bank_error(handle, &info, ACA_ERROR_TYPE_CE, count); + bank->aca_err_type = ACA_BANK_ERR_CE_DE_DECODE(bank); + ret = aca_error_cache_log_bank_error(handle, &info, bank->aca_err_type, count); break; default: return -EINVAL; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c index 50eb856249d5..87add6274b98 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c @@ -883,9 +883,10 @@ static int gfx_v9_4_3_aca_bank_parser(struct aca_handle *handle, ACA_ERROR_TYPE_UE, 1ULL); break; case ACA_SMU_TYPE_CE: - bank->aca_err_type = ACA_ERROR_TYPE_CE; + bank->aca_err_type = ACA_BANK_ERR_CE_DE_DECODE(bank); ret = aca_error_cache_log_bank_error(handle, &info, - ACA_ERROR_TYPE_CE, ACA_REG__MISC0__ERRCNT(misc0)); + bank->aca_err_type, + ACA_REG__MISC0__ERRCNT(misc0)); break; default: return -EINVAL; diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c index b8f06e9c9e62..1fcab0ef21c3 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c @@ -1332,8 +1332,8 @@ static int jpeg_v4_0_3_aca_bank_parser(struct aca_handle *handle, struct aca_ban 1ULL); break; case ACA_SMU_TYPE_CE: - bank->aca_err_type = ACA_ERROR_TYPE_CE; - ret = aca_error_cache_log_bank_error(handle, &info, ACA_ERROR_TYPE_CE, + bank->aca_err_type = ACA_BANK_ERR_CE_DE_DECODE(bank); + ret = aca_error_cache_log_bank_error(handle, &info, bank->aca_err_type, ACA_REG__MISC0__ERRCNT(misc0)); break; default: diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c index 58d22f0d5a68..a54e7b929295 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c @@ -751,8 +751,8 @@ static int mmhub_v1_8_aca_bank_parser(struct aca_handle *handle, struct aca_bank 1ULL); break; case ACA_SMU_TYPE_CE: - bank->aca_err_type = ACA_ERROR_TYPE_CE; - ret = aca_error_cache_log_bank_error(handle, &info, ACA_ERROR_TYPE_CE, + bank->aca_err_type = ACA_BANK_ERR_CE_DE_DECODE(bank); + ret = aca_error_cache_log_bank_error(handle, &info, bank->aca_err_type, ACA_REG__MISC0__ERRCNT(misc0)); break; default: diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c index 03e47fad217f..fd34dc138081 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c @@ -2532,8 +2532,8 @@ static int sdma_v4_4_2_aca_bank_parser(struct aca_handle *handle, struct aca_ban 1ULL); break; case ACA_SMU_TYPE_CE: - bank->aca_err_type = ACA_ERROR_TYPE_CE; - ret = aca_error_cache_log_bank_error(handle, &info, ACA_ERROR_TYPE_CE, + bank->aca_err_type = ACA_BANK_ERR_CE_DE_DECODE(bank); + ret = aca_error_cache_log_bank_error(handle, &info, bank->aca_err_type, ACA_REG__MISC0__ERRCNT(misc0)); break; default: diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c index 2681c40704a1..20f6bd9255db 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c @@ -1963,8 +1963,8 @@ static int vcn_v4_0_3_aca_bank_parser(struct aca_handle *handle, struct aca_bank 1ULL); break; case ACA_SMU_TYPE_CE: - bank->aca_err_type = ACA_ERROR_TYPE_CE; - ret = aca_error_cache_log_bank_error(handle, &info, ACA_ERROR_TYPE_CE, + bank->aca_err_type = ACA_BANK_ERR_CE_DE_DECODE(bank); + ret = aca_error_cache_log_bank_error(handle, &info, bank->aca_err_type, ACA_REG__MISC0__ERRCNT(misc0)); break; default: From eaa3feb16d3b8fbb787cc6c0c16c45bf654d806a Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 26 Feb 2025 08:57:33 +0000 Subject: [PATCH 131/235] drm/amdgpu: Fix spelling mistake "initiailize" -> "initialize" and grammar There is a spelling mistake and a grammatical error in a dev_err message. Fix it. Reviewed-by: Tao Zhou Signed-off-by: Colin Ian King Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c index 0b288deb9b19..15cd0a007b71 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c @@ -542,7 +542,7 @@ int amdgpu_cper_init(struct amdgpu_device *adev) r = amdgpu_cper_ring_init(adev); if (r) { - dev_err(adev->dev, "fail to initiailize cper ring, r = %d\n", r); + dev_err(adev->dev, "failed to initialize cper ring, r = %d\n", r); return r; } From 1d72fc2e9e04e8f83599b309dbde06807273775f Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 20 Feb 2025 10:42:30 -0500 Subject: [PATCH 132/235] drm/amdgpu/mes11: drop amdgpu_mes_suspend()/amdgpu_mes_resume() calls They are noops on GFX11 for most firmware versions. KFD already handles its own queues and they should already be unmapped at this point so even if this runs, it's not doing anything. Reviewed-by: Shaoyun.liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/mes_v11_0.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c index cbe0dc9ca6d9..7eee41187b7c 100644 --- a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c @@ -1674,24 +1674,12 @@ static int mes_v11_0_hw_fini(struct amdgpu_ip_block *ip_block) static int mes_v11_0_suspend(struct amdgpu_ip_block *ip_block) { - int r; - - r = amdgpu_mes_suspend(ip_block->adev); - if (r) - return r; - return mes_v11_0_hw_fini(ip_block); } static int mes_v11_0_resume(struct amdgpu_ip_block *ip_block) { - int r; - - r = mes_v11_0_hw_init(ip_block); - if (r) - return r; - - return amdgpu_mes_resume(ip_block->adev); + return mes_v11_0_hw_init(ip_block); } static int mes_v11_0_early_init(struct amdgpu_ip_block *ip_block) From c0a01660de20bfc60b01f616e7aead727f12ba9e Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 26 Feb 2025 09:25:49 -0500 Subject: [PATCH 133/235] Documentation/gpu: remove duplicate entries in different glossaries Some items were defined in both the general and DC glossaries. Remove the duplicate entries. Fixes: 2df30ae0ba0b ("Documentation/gpu: Add acronyms for some firmware components") Reported-by: Stephen Rothwell Cc: Rodrigo Siqueira Reviewed-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- Documentation/gpu/amdgpu/display/dc-glossary.rst | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Documentation/gpu/amdgpu/display/dc-glossary.rst b/Documentation/gpu/amdgpu/display/dc-glossary.rst index 0b0ffd428dd2..7dc034e9e586 100644 --- a/Documentation/gpu/amdgpu/display/dc-glossary.rst +++ b/Documentation/gpu/amdgpu/display/dc-glossary.rst @@ -167,9 +167,6 @@ consider asking in the amdgfx and update this page. MALL Memory Access at Last Level - MC - Memory Controller - MPC/MPCC Multiple pipes and plane combine @@ -232,6 +229,3 @@ consider asking in the amdgfx and update this page. VRR Variable Refresh Rate - - UVD - Unified Video Decoder From 63e6a77ccf239337baa9b1e7787cde9fa0462092 Mon Sep 17 00:00:00 2001 From: Ma Ke Date: Wed, 26 Feb 2025 16:37:31 +0800 Subject: [PATCH 134/235] drm/amd/display: Fix null check for pipe_ctx->plane_state in resource_build_scaling_params Null pointer dereference issue could occur when pipe_ctx->plane_state is null. The fix adds a check to ensure 'pipe_ctx->plane_state' is not null before accessing. This prevents a null pointer dereference. Found by code review. Fixes: 3be5262e353b ("drm/amd/display: Rename more dc_surface stuff to plane_state") Reviewed-by: Alex Hung Signed-off-by: Ma Ke Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 0bd3e7c072a1..0f8a88220ec6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1472,7 +1472,8 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger); /* Invalid input */ - if (!plane_state->dst_rect.width || + if (!plane_state || + !plane_state->dst_rect.width || !plane_state->dst_rect.height || !plane_state->src_rect.width || !plane_state->src_rect.height) { From 9c696cc57c1a6dab6da6b51f4b30a7d16e233cbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Almeida?= Date: Wed, 26 Feb 2025 10:11:18 -0300 Subject: [PATCH 135/235] drm/amdgpu: Create a debug option to disable ring reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prior to the addition of ring reset, the debug option `debug_disable_soft_recovery` could be used to force a full device reset. Now that we have ring reset, create a debug option to disable them in amdgpu, forcing the driver to go with the full device reset path again when both options are combined. This option is useful for testing and debugging purposes when one wants to test the full reset from userspace. Signed-off-by: André Almeida Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 6 ++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 5 +++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 2b1990ea9639..2a9a41f4e748 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1192,6 +1192,7 @@ struct amdgpu_device { bool debug_use_vram_fw_buf; bool debug_enable_ras_aca; bool debug_exp_resets; + bool debug_disable_gpu_ring_reset; bool enforce_isolation[MAX_XCP]; /* Added this mutex for cleaner shader isolation between GFX and compute processes */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 1819166cb4cf..8c1aa9feda53 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -137,6 +137,7 @@ enum AMDGPU_DEBUG_MASK { AMDGPU_DEBUG_USE_VRAM_FW_BUF = BIT(3), AMDGPU_DEBUG_ENABLE_RAS_ACA = BIT(4), AMDGPU_DEBUG_ENABLE_EXP_RESETS = BIT(5), + AMDGPU_DEBUG_DISABLE_GPU_RING_RESET = BIT(6), }; unsigned int amdgpu_vram_limit = UINT_MAX; @@ -2223,6 +2224,11 @@ static void amdgpu_init_debug_options(struct amdgpu_device *adev) pr_info("debug: enable experimental reset features\n"); adev->debug_exp_resets = true; } + + if (amdgpu_debug_mask & AMDGPU_DEBUG_DISABLE_GPU_RING_RESET) { + pr_info("debug: ring reset disabled\n"); + adev->debug_disable_gpu_ring_reset = true; + } } static unsigned long amdgpu_fix_asic_type(struct pci_dev *pdev, unsigned long flags) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c index c37bc683253a..5537c8bfd227 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c @@ -131,8 +131,9 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job) } /* attempt a per ring reset */ - if (amdgpu_gpu_recovery && - ring->funcs->reset) { + if (unlikely(adev->debug_disable_gpu_ring_reset)) { + dev_err(adev->dev, "Ring reset disabled by debug mask\n"); + } else if (amdgpu_gpu_recovery && ring->funcs->reset) { bool is_guilty; dev_err(adev->dev, "Starting %s ring reset\n", s_job->sched->name); From e90711946b53590371ecce32e8fcc381a99d6333 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Tue, 25 Feb 2025 18:08:02 -0500 Subject: [PATCH 136/235] drm/amdkfd: clamp queue size to minimum If queue size is less than minimum, clamp it to minimum to prevent underflow when writing queue mqd. Signed-off-by: David Yat Sin Reviewed-by: Jay Cornwall Reviewed-by: Harish Kasiviswanathan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 10 ++++++++++ include/uapi/linux/kfd_ioctl.h | 2 ++ 2 files changed, 12 insertions(+) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 433de9e9a77e..8c2e92378b49 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -212,6 +212,11 @@ static int set_queue_properties_from_user(struct queue_properties *q_properties, return -EINVAL; } + if (args->ring_size < KFD_MIN_QUEUE_RING_SIZE) { + args->ring_size = KFD_MIN_QUEUE_RING_SIZE; + pr_debug("Size lower. clamped to KFD_MIN_QUEUE_RING_SIZE"); + } + if (!access_ok((const void __user *) args->read_pointer_address, sizeof(uint32_t))) { pr_err("Can't access read pointer\n"); @@ -461,6 +466,11 @@ static int kfd_ioctl_update_queue(struct file *filp, struct kfd_process *p, return -EINVAL; } + if (args->ring_size < KFD_MIN_QUEUE_RING_SIZE) { + args->ring_size = KFD_MIN_QUEUE_RING_SIZE; + pr_debug("Size lower. clamped to KFD_MIN_QUEUE_RING_SIZE"); + } + properties.queue_address = args->ring_base_address; properties.queue_size = args->ring_size; properties.queue_percent = args->queue_percentage & 0xFF; diff --git a/include/uapi/linux/kfd_ioctl.h b/include/uapi/linux/kfd_ioctl.h index fa9f9846b88e..b0160b09987c 100644 --- a/include/uapi/linux/kfd_ioctl.h +++ b/include/uapi/linux/kfd_ioctl.h @@ -62,6 +62,8 @@ struct kfd_ioctl_get_version_args { #define KFD_MAX_QUEUE_PERCENTAGE 100 #define KFD_MAX_QUEUE_PRIORITY 15 +#define KFD_MIN_QUEUE_RING_SIZE 1024 + struct kfd_ioctl_create_queue_args { __u64 ring_base_address; /* to KFD */ __u64 write_pointer_address; /* from KFD */ From 509d662a57ef5b1b460ec000913e9553423e7bd3 Mon Sep 17 00:00:00 2001 From: Xiaogang Chen Date: Mon, 24 Feb 2025 16:50:50 -0600 Subject: [PATCH 137/235] drm/amdkfd: remove kfd_pasid.c from amdgpu driver build Since kfd uses pasid values from graphic driver now do not need use kfd pasid fucntions. Signed-off-by: Xiaogang Chen Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/Makefile | 1 - drivers/gpu/drm/amd/amdkfd/kfd_pasid.c | 46 -------------------------- 2 files changed, 47 deletions(-) delete mode 100644 drivers/gpu/drm/amd/amdkfd/kfd_pasid.c diff --git a/drivers/gpu/drm/amd/amdkfd/Makefile b/drivers/gpu/drm/amd/amdkfd/Makefile index 0d3d8972240d..0ce08113c9f0 100644 --- a/drivers/gpu/drm/amd/amdkfd/Makefile +++ b/drivers/gpu/drm/amd/amdkfd/Makefile @@ -27,7 +27,6 @@ AMDKFD_FILES := $(AMDKFD_PATH)/kfd_module.o \ $(AMDKFD_PATH)/kfd_device.o \ $(AMDKFD_PATH)/kfd_chardev.o \ $(AMDKFD_PATH)/kfd_topology.o \ - $(AMDKFD_PATH)/kfd_pasid.o \ $(AMDKFD_PATH)/kfd_doorbell.o \ $(AMDKFD_PATH)/kfd_flat_memory.o \ $(AMDKFD_PATH)/kfd_process.o \ diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_pasid.c b/drivers/gpu/drm/amd/amdkfd/kfd_pasid.c deleted file mode 100644 index 8896426e0556..000000000000 --- a/drivers/gpu/drm/amd/amdkfd/kfd_pasid.c +++ /dev/null @@ -1,46 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 OR MIT -/* - * Copyright 2014-2022 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#include -#include "kfd_priv.h" -#include "amdgpu_ids.h" - -static unsigned int pasid_bits = 16; -static bool pasids_allocated; /* = false */ - -u32 kfd_pasid_alloc(void) -{ - int r = amdgpu_pasid_alloc(pasid_bits); - - if (r > 0) { - pasids_allocated = true; - return r; - } - - return 0; -} - -void kfd_pasid_free(u32 pasid) -{ - amdgpu_pasid_free(pasid); -} From 0107c595c5d0521c6397836be0767532121ef16c Mon Sep 17 00:00:00 2001 From: Kenneth Feng Date: Thu, 27 Feb 2025 10:13:53 +0800 Subject: [PATCH 138/235] drm/amd/pm: add fan abnormal detection add fan abnormal detection on smu v14.0.2&smu v14.0.3 Signed-off-by: Kenneth Feng Reviewed-by: Yang Wang Signed-off-by: Alex Deucher --- .../gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c index adbb6332376e..14a5760082b8 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c @@ -950,6 +950,14 @@ static int smu_v14_0_irq_process(struct amdgpu_device *adev, uint32_t client_id = entry->client_id; uint32_t src_id = entry->src_id; + /* + * ctxid is used to distinguish different + * events for SMCToHost interrupt. + */ + uint32_t ctxid = entry->src_data[0]; + uint32_t data; + uint32_t high; + if (client_id == SOC15_IH_CLIENTID_THM) { switch (src_id) { case THM_11_0__SRCID__THM_DIG_THERM_L2H: @@ -964,6 +972,50 @@ static int smu_v14_0_irq_process(struct amdgpu_device *adev, src_id); break; } + } else if (client_id == SOC15_IH_CLIENTID_MP1) { + if (src_id == SMU_IH_INTERRUPT_ID_TO_DRIVER) { + /* ACK SMUToHost interrupt */ + data = RREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL); + data = REG_SET_FIELD(data, MP1_SMN_IH_SW_INT_CTRL, INT_ACK, 1); + WREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL, data); + + switch (ctxid) { + case SMU_IH_INTERRUPT_CONTEXT_ID_FAN_ABNORMAL: + high = smu->thermal_range.software_shutdown_temp + + smu->thermal_range.software_shutdown_temp_offset; + high = min_t(typeof(high), + SMU_THERMAL_MAXIMUM_ALERT_TEMP, + high); + dev_emerg(adev->dev, "Reduce soft CTF limit to %d (by an offset %d)\n", + high, + smu->thermal_range.software_shutdown_temp_offset); + + data = RREG32_SOC15(THM, 0, regTHM_THERMAL_INT_CTRL); + data = REG_SET_FIELD(data, THM_THERMAL_INT_CTRL, + DIG_THERM_INTH, + (high & 0xff)); + data = data & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK); + WREG32_SOC15(THM, 0, regTHM_THERMAL_INT_CTRL, data); + break; + case SMU_IH_INTERRUPT_CONTEXT_ID_FAN_RECOVERY: + high = min_t(typeof(high), + SMU_THERMAL_MAXIMUM_ALERT_TEMP, + smu->thermal_range.software_shutdown_temp); + dev_emerg(adev->dev, "Recover soft CTF limit to %d\n", high); + + data = RREG32_SOC15(THM, 0, regTHM_THERMAL_INT_CTRL); + data = REG_SET_FIELD(data, THM_THERMAL_INT_CTRL, + DIG_THERM_INTH, + (high & 0xff)); + data = data & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK); + WREG32_SOC15(THM, 0, regTHM_THERMAL_INT_CTRL, data); + break; + default: + dev_dbg(adev->dev, "Unhandled context id %d from client:%d!\n", + ctxid, client_id); + break; + } + } } return 0; From 6f16d101dab5ec6e8fc9567769f73ae8baa3fe38 Mon Sep 17 00:00:00 2001 From: Lijo Lazar Date: Thu, 6 Feb 2025 16:16:43 +0530 Subject: [PATCH 139/235] drm/amdgpu: Move xgmi definitions to xgmi header Move definitions related to xgmi to amdgpu_xgmi header Signed-off-by: Lijo Lazar Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h | 23 +--------------- drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c | 8 ++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h | 35 +++++++++++++++++------- 3 files changed, 34 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h index 459a30fe239f..bd7fc123b8f9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h @@ -29,6 +29,7 @@ #include #include "amdgpu_irq.h" +#include "amdgpu_xgmi.h" #include "amdgpu_ras.h" /* VA hole for 48bit addresses on Vega10 */ @@ -174,28 +175,6 @@ struct amdgpu_gmc_funcs { bool (*need_reset_on_init)(struct amdgpu_device *adev); }; -struct amdgpu_xgmi_ras { - struct amdgpu_ras_block_object ras_block; -}; - -struct amdgpu_xgmi { - /* from psp */ - u64 node_id; - u64 hive_id; - /* fixed per family */ - u64 node_segment_size; - /* physical node (0-3) */ - unsigned physical_node_id; - /* number of nodes (0-4) */ - unsigned num_physical_nodes; - /* gpu list in the same hive */ - struct list_head head; - bool supported; - struct ras_common_if *ras_if; - bool connected_to_cpu; - struct amdgpu_xgmi_ras *ras; -}; - struct amdgpu_mem_partition_info { union { struct { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c index c313c2cf6969..59e44d20124f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c @@ -1714,3 +1714,11 @@ int amdgpu_xgmi_request_nps_change(struct amdgpu_device *adev, return r; } + +bool amdgpu_xgmi_same_hive(struct amdgpu_device *adev, + struct amdgpu_device *bo_adev) +{ + return (amdgpu_use_xgmi_p2p && adev != bo_adev && + adev->gmc.xgmi.hive_id && + adev->gmc.xgmi.hive_id == bo_adev->gmc.xgmi.hive_id); +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h index 924da0bec509..1d4e822652a1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h @@ -23,7 +23,6 @@ #define __AMDGPU_XGMI_H__ #include -#include "amdgpu_psp.h" #include "amdgpu_ras.h" struct amdgpu_hive_info { @@ -71,7 +70,29 @@ enum amdgpu_xgmi_bw_unit { AMDGPU_XGMI_BW_UNIT_MBYTES }; -extern struct amdgpu_xgmi_ras xgmi_ras; +struct amdgpu_xgmi_ras { + struct amdgpu_ras_block_object ras_block; +}; +extern struct amdgpu_xgmi_ras xgmi_ras; + +struct amdgpu_xgmi { + /* from psp */ + u64 node_id; + u64 hive_id; + /* fixed per family */ + u64 node_segment_size; + /* physical node (0-3) */ + unsigned physical_node_id; + /* number of nodes (0-4) */ + unsigned num_physical_nodes; + /* gpu list in the same hive */ + struct list_head head; + bool supported; + struct ras_common_if *ras_if; + bool connected_to_cpu; + struct amdgpu_xgmi_ras *ras; +}; + struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev); void amdgpu_put_xgmi_hive(struct amdgpu_hive_info *hive); int amdgpu_xgmi_update_topology(struct amdgpu_hive_info *hive, struct amdgpu_device *adev); @@ -86,14 +107,8 @@ bool amdgpu_xgmi_get_is_sharing_enabled(struct amdgpu_device *adev, struct amdgpu_device *peer_adev); uint64_t amdgpu_xgmi_get_relative_phy_addr(struct amdgpu_device *adev, uint64_t addr); -static inline bool amdgpu_xgmi_same_hive(struct amdgpu_device *adev, - struct amdgpu_device *bo_adev) -{ - return (amdgpu_use_xgmi_p2p && - adev != bo_adev && - adev->gmc.xgmi.hive_id && - adev->gmc.xgmi.hive_id == bo_adev->gmc.xgmi.hive_id); -} +bool amdgpu_xgmi_same_hive(struct amdgpu_device *adev, + struct amdgpu_device *bo_adev); int amdgpu_xgmi_ras_sw_init(struct amdgpu_device *adev); int amdgpu_xgmi_reset_on_init(struct amdgpu_device *adev); From 485993e2f1a6bf3d1e8fb5a38c82edd3ae697ad9 Mon Sep 17 00:00:00 2001 From: Lijo Lazar Date: Thu, 6 Feb 2025 17:24:51 +0530 Subject: [PATCH 140/235] drm/amdgpu: Add xgmi speed/width related info Add APIs to initialize XGMI speed, width details and get to max bandwidth supported. It is assumed that a device only supports same generation of XGMI links with uniform width. Signed-off-by: Lijo Lazar Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c | 23 +++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h | 11 +++++++++++ 2 files changed, 34 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c index 59e44d20124f..9c539f26e5fd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c @@ -1722,3 +1722,26 @@ bool amdgpu_xgmi_same_hive(struct amdgpu_device *adev, adev->gmc.xgmi.hive_id && adev->gmc.xgmi.hive_id == bo_adev->gmc.xgmi.hive_id); } + +void amdgpu_xgmi_early_init(struct amdgpu_device *adev) +{ + if (!adev->gmc.xgmi.supported) + return; + + switch (amdgpu_ip_version(adev, GC_HWIP, 0)) { + case IP_VERSION(9, 4, 0): + case IP_VERSION(9, 4, 1): + case IP_VERSION(9, 4, 2): + adev->gmc.xgmi.max_speed = XGMI_SPEED_25GT; + adev->gmc.xgmi.max_width = 16; + break; + case IP_VERSION(9, 4, 3): + case IP_VERSION(9, 4, 4): + case IP_VERSION(9, 5, 0): + adev->gmc.xgmi.max_speed = XGMI_SPEED_32GT; + adev->gmc.xgmi.max_width = 16; + break; + default: + break; + } +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h index 1d4e822652a1..32dabba4062f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h @@ -25,6 +25,12 @@ #include #include "amdgpu_ras.h" +enum amdgpu_xgmi_link_speed { + XGMI_SPEED_16GT = 16, + XGMI_SPEED_25GT = 25, + XGMI_SPEED_32GT = 32 +}; + struct amdgpu_hive_info { struct kobject kobj; uint64_t hive_id; @@ -91,6 +97,8 @@ struct amdgpu_xgmi { struct ras_common_if *ras_if; bool connected_to_cpu; struct amdgpu_xgmi_ras *ras; + enum amdgpu_xgmi_link_speed max_speed; + uint8_t max_width; }; struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev); @@ -118,4 +126,7 @@ int amdgpu_xgmi_request_nps_change(struct amdgpu_device *adev, int amdgpu_get_xgmi_link_status(struct amdgpu_device *adev, int global_link_num); +void amdgpu_xgmi_early_init(struct amdgpu_device *adev); +uint32_t amdgpu_xgmi_get_max_bandwidth(struct amdgpu_device *adev); + #endif From f9234217d0167f43cc0cdccc39353c37de1d028d Mon Sep 17 00:00:00 2001 From: Asad Kamal Date: Wed, 26 Feb 2025 12:52:50 +0800 Subject: [PATCH 141/235] drm/amd/amdgpu: Add support for xgmi_v6_4_1 Add support for xgmi_v6_4_1 and use it appropriate places Signed-off-by: Asad Kamal Reviewed-by: Lijo Lazar Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c index 9c539f26e5fd..7fdf30f1161c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c @@ -315,6 +315,7 @@ int amdgpu_get_xgmi_link_status(struct amdgpu_device *adev, int global_link_num) switch (amdgpu_ip_version(adev, XGMI_HWIP, 0)) { case IP_VERSION(6, 4, 0): + case IP_VERSION(6, 4, 1): xgmi_state_reg_val = xgmi_v6_4_get_link_status(adev, global_link_num); break; default: @@ -1205,6 +1206,7 @@ static int amdgpu_xgmi_ras_late_init(struct amdgpu_device *adev, struct ras_comm switch (amdgpu_ip_version(adev, XGMI_HWIP, 0)) { case IP_VERSION(6, 4, 0): + case IP_VERSION(6, 4, 1): r = amdgpu_ras_bind_aca(adev, AMDGPU_RAS_BLOCK__XGMI_WAFL, &xgmi_v6_4_0_aca_info, NULL); if (r) @@ -1264,6 +1266,7 @@ static void amdgpu_xgmi_legacy_reset_ras_error_count(struct amdgpu_device *adev) switch (amdgpu_ip_version(adev, XGMI_HWIP, 0)) { case IP_VERSION(6, 4, 0): + case IP_VERSION(6, 4, 1): for (i = 0; i < ARRAY_SIZE(xgmi3x16_pcs_err_status_reg_v6_4); i++) pcs_clear_status(adev, xgmi3x16_pcs_err_status_reg_v6_4[i]); @@ -1298,6 +1301,7 @@ static void amdgpu_xgmi_reset_ras_error_count(struct amdgpu_device *adev) { switch (amdgpu_ip_version(adev, XGMI_HWIP, 0)) { case IP_VERSION(6, 4, 0): + case IP_VERSION(6, 4, 1): xgmi_v6_4_0_reset_ras_error_count(adev); break; default: @@ -1323,7 +1327,9 @@ static int amdgpu_xgmi_query_pcs_error_status(struct amdgpu_device *adev, if (amdgpu_ip_version(adev, XGMI_HWIP, 0) == IP_VERSION(6, 1, 0) || amdgpu_ip_version(adev, XGMI_HWIP, 0) == - IP_VERSION(6, 4, 0)) { + IP_VERSION(6, 4, 0) || + amdgpu_ip_version(adev, XGMI_HWIP, 0) == + IP_VERSION(6, 4, 1)) { pcs_ras_fields = &xgmi3x16_pcs_ras_fields[0]; field_array_size = ARRAY_SIZE(xgmi3x16_pcs_ras_fields); } else { @@ -1431,6 +1437,7 @@ static void amdgpu_xgmi_legacy_query_ras_error_count(struct amdgpu_device *adev, switch (amdgpu_ip_version(adev, XGMI_HWIP, 0)) { case IP_VERSION(6, 4, 0): + case IP_VERSION(6, 4, 1): /* check xgmi3x16 pcs error */ for (i = 0; i < ARRAY_SIZE(xgmi3x16_pcs_err_status_reg_v6_4); i++) { data = RREG32_PCIE(xgmi3x16_pcs_err_status_reg_v6_4[i]); @@ -1527,6 +1534,7 @@ static void amdgpu_xgmi_query_ras_error_count(struct amdgpu_device *adev, { switch (amdgpu_ip_version(adev, XGMI_HWIP, 0)) { case IP_VERSION(6, 4, 0): + case IP_VERSION(6, 4, 1): xgmi_v6_4_0_query_ras_error_count(adev, ras_error_status); break; default: From ee3ed100663d2ae8280bd5fc63b3e2c13c689cce Mon Sep 17 00:00:00 2001 From: Philip Yang Date: Tue, 25 Feb 2025 10:04:06 -0500 Subject: [PATCH 142/235] drm/amdkfd: Remove kfd_process_hw_exception worker With GPU reset-domain worker implemented, KFD hw_exception worker is not needed any more, just call amdgpu_amdkfd_gpu_reset directly from kfd_hws_hang. Suggested-by: Felix Kuehling Signed-off-by: Philip Yang Reviewed-by: Lijo Lazar Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | 11 +---------- drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h | 1 - 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index 94b1ac8a4735..91e4988dc1e3 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -66,7 +66,6 @@ static inline void deallocate_hqd(struct device_queue_manager *dqm, static int allocate_hqd(struct device_queue_manager *dqm, struct queue *q); static int allocate_sdma_queue(struct device_queue_manager *dqm, struct queue *q, const uint32_t *restore_sdma_id); -static void kfd_process_hw_exception(struct work_struct *work); static inline enum KFD_MQD_TYPE get_mqd_type_from_queue_type(enum kfd_queue_type type) @@ -170,7 +169,7 @@ static void kfd_hws_hang(struct device_queue_manager *dqm) /* * Issue a GPU reset if HWS is unresponsive */ - schedule_work(&dqm->hw_exception_work); + amdgpu_amdkfd_gpu_reset(dqm->dev->adev); } static int convert_to_mes_queue_type(int queue_type) @@ -1740,7 +1739,6 @@ static int initialize_cpsch(struct device_queue_manager *dqm) dqm->active_cp_queue_count = 0; dqm->gws_queue_count = 0; dqm->active_runlist = false; - INIT_WORK(&dqm->hw_exception_work, kfd_process_hw_exception); dqm->trap_debug_vmid = 0; init_sdma_bitmaps(dqm); @@ -3080,13 +3078,6 @@ int kfd_evict_process_device(struct kfd_process_device *pdd) return ret; } -static void kfd_process_hw_exception(struct work_struct *work) -{ - struct device_queue_manager *dqm = container_of(work, - struct device_queue_manager, hw_exception_work); - amdgpu_amdkfd_gpu_reset(dqm->dev->adev); -} - int reserve_debug_trap_vmid(struct device_queue_manager *dqm, struct qcm_process_device *qpd) { diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h index 09ab36f8e8c6..7146e227e2c1 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h @@ -269,7 +269,6 @@ struct device_queue_manager { /* hw exception */ bool is_hws_hang; bool is_resetting; - struct work_struct hw_exception_work; struct kfd_mem_obj hiq_sdma_mqd; bool sched_running; bool sched_halt; From 1b9366c601039d60546794c63fbb83ce8e53b978 Mon Sep 17 00:00:00 2001 From: Philip Yang Date: Mon, 17 Feb 2025 20:08:29 -0500 Subject: [PATCH 143/235] drm/amdkfd: KFD release_work possible circular locking If waiting for gpu reset done in KFD release_work, thers is WARNING: possible circular locking dependency detected #2 kfd_create_process kfd_process_mutex flush kfd release work #1 kfd release work wait for amdgpu reset work #0 amdgpu_device_gpu_reset kgd2kfd_pre_reset kfd_process_mutex Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock((work_completion)(&p->release_work)); lock((wq_completion)kfd_process_wq); lock((work_completion)(&p->release_work)); lock((wq_completion)amdgpu-reset-dev); To fix this, KFD create process move flush release work outside kfd_process_mutex. Signed-off-by: Philip Yang Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_process.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index 1067afdb456e..2715ca53e9da 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -838,6 +838,14 @@ struct kfd_process *kfd_create_process(struct task_struct *thread) return ERR_PTR(-EINVAL); } + /* If the process just called exec(3), it is possible that the + * cleanup of the kfd_process (following the release of the mm + * of the old process image) is still in the cleanup work queue. + * Make sure to drain any job before trying to recreate any + * resource for this process. + */ + flush_workqueue(kfd_process_wq); + /* * take kfd processes mutex before starting of process creation * so there won't be a case where two threads of the same process @@ -858,14 +866,6 @@ struct kfd_process *kfd_create_process(struct task_struct *thread) if (process) { pr_debug("Process already found\n"); } else { - /* If the process just called exec(3), it is possible that the - * cleanup of the kfd_process (following the release of the mm - * of the old process image) is still in the cleanup work queue. - * Make sure to drain any job before trying to recreate any - * resource for this process. - */ - flush_workqueue(kfd_process_wq); - process = create_process(thread); if (IS_ERR(process)) goto out; From f0b4440cdc1807bb6ec3dce0d6de81170803569b Mon Sep 17 00:00:00 2001 From: Philip Yang Date: Thu, 6 Feb 2025 17:50:13 -0500 Subject: [PATCH 144/235] drm/amdkfd: Fix mode1 reset crash issue If HW scheduler hangs and mode1 reset is used to recover GPU, KFD signal user space to abort the processes. After process abort exit, user queues still use the GPU to access system memory before h/w is reset while KFD cleanup worker free system memory and free VRAM. There is use-after-free race bug that KFD allocate and reuse the freed system memory, and user queue write to the same system memory to corrupt the data structure and cause driver crash. To fix this race, KFD cleanup worker terminate user queues, then flush reset_domain wq to wait for any GPU ongoing reset complete, and then free outstanding BOs. Signed-off-by: Philip Yang Reviewed-by: Lijo Lazar Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_process.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index 2715ca53e9da..7c0c24732481 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -35,6 +35,7 @@ #include #include "amdgpu_amdkfd.h" #include "amdgpu.h" +#include "amdgpu_reset.h" struct mm_struct; @@ -1133,6 +1134,17 @@ static void kfd_process_remove_sysfs(struct kfd_process *p) p->kobj = NULL; } +/* + * If any GPU is ongoing reset, wait for reset complete. + */ +static void kfd_process_wait_gpu_reset_complete(struct kfd_process *p) +{ + int i; + + for (i = 0; i < p->n_pdds; i++) + flush_workqueue(p->pdds[i]->dev->adev->reset_domain->wq); +} + /* No process locking is needed in this function, because the process * is not findable any more. We must assume that no other thread is * using it any more, otherwise we couldn't safely free the process @@ -1147,6 +1159,11 @@ static void kfd_process_wq_release(struct work_struct *work) kfd_process_dequeue_from_all_devices(p); pqm_uninit(&p->pqm); + /* + * If GPU in reset, user queues may still running, wait for reset complete. + */ + kfd_process_wait_gpu_reset_complete(p); + /* Signal the eviction fence after user mode queues are * destroyed. This allows any BOs to be freed without * triggering pointless evictions or waiting for fences. From 0f3fda3117507e22e0c8bfe1849ea483a6e1d793 Mon Sep 17 00:00:00 2001 From: Srinivasan Shanmugam Date: Wed, 26 Feb 2025 07:10:38 +0530 Subject: [PATCH 145/235] drm/amdgpu: Fix parameter annotations for VCN clock gating functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous references to a non-existent `adev` parameter have been removed & corrected to reflect the use of the `vinst` pointer, which points to the VCN instance structure, in the below files: - vcn_v1_0.c - vcn_v2_0.c - vcn_v3_0.c Fixes the below with gcc W=1: drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c:624: warning: Function parameter or struct member 'vinst' not described in 'vcn_v1_0_enable_clock_gating' drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c:624: warning: Excess function parameter 'adev' description in 'vcn_v1_0_enable_clock_gating' drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c:376: warning: Function parameter or struct member 'vinst' not described in 'vcn_v2_0_mc_resume' drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c:376: warning: Excess function parameter 'adev' description in 'vcn_v2_0_mc_resume' drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c:776: warning: Function parameter or struct member 'vinst' not described in 'vcn_v3_0_disable_clock_gating' drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c:776: warning: Excess function parameter 'adev' description in 'vcn_v3_0_disable_clock_gating' drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c:776: warning: Excess function parameter 'inst' description in 'vcn_v3_0_disable_clock_gating' drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c:965: warning: Function parameter or struct member 'vinst' not described in 'vcn_v3_0_enable_clock_gating' drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c:965: warning: Excess function parameter 'adev' description in 'vcn_v3_0_enable_clock_gating' drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c:965: warning: Excess function parameter 'inst' description in 'vcn_v3_0_enable_clock_gating' Cc: Christian König Cc: Alex Deucher Signed-off-by: Srinivasan Shanmugam Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 6 ++---- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c index 8bad63282de4..21b57c29bf7d 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c @@ -616,7 +616,7 @@ static void vcn_v1_0_disable_clock_gating(struct amdgpu_vcn_inst *vinst) /** * vcn_v1_0_enable_clock_gating - enable VCN clock gating * - * @adev: amdgpu_device pointer + * @vinst: Pointer to the VCN instance structure * * Enable clock gating for VCN block */ diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c index f53feb60772e..8e7a36f26e9c 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c @@ -368,7 +368,7 @@ static int vcn_v2_0_resume(struct amdgpu_ip_block *ip_block) /** * vcn_v2_0_mc_resume - memory controller programming * - * @adev: amdgpu_device pointer + * @vinst: Pointer to the VCN instance structure * * Let the VCN memory controller know it's offsets */ diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c index a3f16fd69927..22ae1939476f 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c @@ -767,8 +767,7 @@ static void vcn_v3_0_enable_static_power_gating(struct amdgpu_vcn_inst *vinst) /** * vcn_v3_0_disable_clock_gating - disable VCN clock gating * - * @adev: amdgpu_device pointer - * @inst: instance number + * @vinst: Pointer to the VCN instance structure * * Disable clock gating for VCN block */ @@ -956,8 +955,7 @@ static void vcn_v3_0_clock_gating_dpg_mode(struct amdgpu_vcn_inst *vinst, /** * vcn_v3_0_enable_clock_gating - enable VCN clock gating * - * @adev: amdgpu_device pointer - * @inst: instance number + * @vinst: Pointer to the VCN instance structure * * Enable clock gating for VCN block */ From 7919b4cad5545ed93778f11881ceee72e4dbed66 Mon Sep 17 00:00:00 2001 From: Philip Yang Date: Thu, 20 Feb 2025 16:02:13 -0500 Subject: [PATCH 146/235] drm/amdkfd: Fix pqm_destroy_queue race with GPU reset If GPU in reset, destroy_queue return -EIO, pqm_destroy_queue should delete the queue from process_queue_list and free the resource. Signed-off-by: Philip Yang Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c index 93647ee27325..662c595ce783 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c @@ -548,7 +548,7 @@ int pqm_destroy_queue(struct process_queue_manager *pqm, unsigned int qid) pr_err("Pasid 0x%x destroy queue %d failed, ret %d\n", pdd->pasid, pqn->q->properties.queue_id, retval); - if (retval != -ETIME) + if (retval != -ETIME && retval != -EIO) goto err_destroy_queue; } kfd_procfs_del_queue(pqn->q); From fe9d0061c413f8fb8c529b18b592b04170850ded Mon Sep 17 00:00:00 2001 From: Philip Yang Date: Mon, 10 Feb 2025 09:42:31 -0500 Subject: [PATCH 147/235] drm/amdkfd: debugfs hang_hws skip GPU with MES debugfs hang_hws is used by GPU reset test with HWS, for MES this crash the kernel with NULL pointer access because dqm->packet_mgr is not setup for MES path. Skip GPU with MES for now, MES hang_hws debugfs interface will be supported later. Signed-off-by: Philip Yang Reviewed-by: Kent Russell Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_device.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index 095e73790dc4..b9c82be6ce13 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -1604,6 +1604,11 @@ int kfd_debugfs_hang_hws(struct kfd_node *dev) return -EINVAL; } + if (dev->kfd->shared_resources.enable_mes) { + dev_err(dev->adev->dev, "Inducing MES hang is not supported\n"); + return -EINVAL; + } + return dqm_debugfs_hang_hws(dev->dqm); } From 7d83c129a8d7df23334d4a35bca9090a26b0a118 Mon Sep 17 00:00:00 2001 From: Srinivasan Shanmugam Date: Wed, 26 Feb 2025 07:20:51 +0530 Subject: [PATCH 148/235] drm/amdgpu: Fix parameter annotation in vcn_v5_0_0_is_idle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update parameter description in the vcn_v5_0_0_is_idle function Fixes the below with gcc W=1: drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c:1231: warning: Function parameter or struct member 'ip_block' not described in 'vcn_v5_0_0_is_idle' drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c:1231: warning: Excess function parameter 'handle' description in 'vcn_v5_0_0_is_idle' Cc: Christian König Cc: Alex Deucher Signed-off-by: Srinivasan Shanmugam Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c index e07b500235b5..d99d05f42f1d 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c @@ -1223,7 +1223,7 @@ static void vcn_v5_0_0_set_unified_ring_funcs(struct amdgpu_device *adev) /** * vcn_v5_0_0_is_idle - check VCN block is idle * - * @handle: amdgpu_device pointer + * @ip_block: Pointer to the amdgpu_ip_block structure * * Check whether VCN block is idle */ From ce43abd7ec9464cf954f90e1c69e11768b02fa0a Mon Sep 17 00:00:00 2001 From: Alexandre Demers Date: Thu, 27 Feb 2025 00:05:04 -0500 Subject: [PATCH 149/235] drm/amdgpu: fix spelling typos Found some typos while exploring amdgpu code. Signed-off-by: Alexandre Demers Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 2 +- drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c | 3 ++- drivers/gpu/drm/amd/amdgpu/vce_v2_0.c | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c index c6e5c50a3322..4eefa17fa39b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c @@ -269,7 +269,7 @@ void amdgpu_gmc_sysvm_location(struct amdgpu_device *adev, struct amdgpu_gmc *mc * @mc: memory controller structure holding memory information * @gart_placement: GART placement policy with respect to VRAM * - * Function will place try to place GART before or after VRAM. + * Function will try to place GART before or after VRAM. * If GART size is bigger than space left then we ajust GART size. * Thus function will never fails. */ diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c b/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c index 6954848d34d4..5dbaebb592b3 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c @@ -98,7 +98,7 @@ static void uvd_v3_1_ring_emit_ib(struct amdgpu_ring *ring, } /** - * uvd_v3_1_ring_emit_fence - emit an fence & trap command + * uvd_v3_1_ring_emit_fence - emit a fence & trap command * * @ring: amdgpu_ring pointer * @addr: address @@ -242,7 +242,7 @@ static void uvd_v3_1_mc_resume(struct amdgpu_device *adev) uint64_t addr; uint32_t size; - /* programm the VCPU memory controller bits 0-27 */ + /* program the VCPU memory controller bits 0-27 */ addr = (adev->uvd.inst->gpu_addr + AMDGPU_UVD_FIRMWARE_OFFSET) >> 3; size = AMDGPU_UVD_FIRMWARE_SIZE(adev) >> 3; WREG32(mmUVD_VCPU_CACHE_OFFSET0, addr); @@ -416,7 +416,7 @@ static int uvd_v3_1_start(struct amdgpu_device *adev) /* Set the write pointer delay */ WREG32(mmUVD_RBC_RB_WPTR_CNTL, 0); - /* programm the 4GB memory segment for rptr and ring buffer */ + /* Program the 4GB memory segment for rptr and ring buffer */ WREG32(mmUVD_LMI_EXT40_ADDR, upper_32_bits(ring->gpu_addr) | (0x7 << 16) | (0x1 << 31)); diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c index db6644e3907c..4b96fd583772 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c @@ -302,7 +302,7 @@ static int uvd_v4_2_start(struct amdgpu_device *adev) /* enable VCPU clock */ WREG32(mmUVD_VCPU_CNTL, 1 << 9); - /* disable interupt */ + /* disable interrupt */ WREG32_P(mmUVD_MASTINT_EN, 0, ~(1 << 1)); #ifdef __BIG_ENDIAN @@ -312,6 +312,7 @@ static int uvd_v4_2_start(struct amdgpu_device *adev) #endif WREG32(mmUVD_LMI_SWAP_CNTL, lmi_swap_cntl); WREG32(mmUVD_MP_SWAP_CNTL, mp_swap_cntl); + /* initialize UVD memory controller */ WREG32(mmUVD_LMI_CTRL, 0x203108); diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c index a68fef65219d..8c8c02606d25 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c @@ -280,7 +280,7 @@ static int vce_v2_0_stop(struct amdgpu_device *adev) if (vce_v2_0_lmi_clean(adev)) { - DRM_INFO("vce is not idle \n"); + DRM_INFO("VCE is not idle \n"); return 0; } From edbf0f302dce5882424d37e460ad8c0f76126115 Mon Sep 17 00:00:00 2001 From: Alexandre Demers Date: Thu, 27 Feb 2025 00:05:05 -0500 Subject: [PATCH 150/235] drm/radeon: fix spelling typos Found some typos while exploring radeon code. Signed-off-by: Alexandre Demers Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_device.c | 6 +++--- drivers/gpu/drm/radeon/radeon_fence.c | 2 +- drivers/gpu/drm/radeon/si.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 6f071e61f764..bbd39348a7ab 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -530,7 +530,7 @@ int radeon_wb_init(struct radeon_device *rdev) * @mc: memory controller structure holding memory informations * @base: base address at which to put VRAM * - * Function will place try to place VRAM at base address provided + * Function will try to place VRAM at base address provided * as parameter (which is so far either PCI aperture address or * for IGP TOM base address). * @@ -557,7 +557,7 @@ int radeon_wb_init(struct radeon_device *rdev) * * Note 3: when limiting vram it's safe to overwritte real_vram_size because * we are not in case where real_vram_size is inferior to mc_vram_size (ie - * note afected by bogus hw of Novell bug 204882 + along with lots of ubuntu + * not affected by bogus hw of Novell bug 204882 + along with lots of ubuntu * ones) * * Note 4: IGP TOM addr should be the same as the aperture addr, we don't @@ -594,7 +594,7 @@ void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 * @rdev: radeon device structure holding all necessary informations * @mc: memory controller structure holding memory informations * - * Function will place try to place GTT before or after VRAM. + * Function will try to place GTT before or after VRAM. * * If GTT size is bigger than space left then we ajust GTT size. * Thus function will never fails. diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c index daff61586be5..8ff4f18b51a9 100644 --- a/drivers/gpu/drm/radeon/radeon_fence.c +++ b/drivers/gpu/drm/radeon/radeon_fence.c @@ -840,7 +840,7 @@ int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring) } radeon_fence_write(rdev, atomic64_read(&rdev->fence_drv[ring].last_seq), ring); rdev->fence_drv[ring].initialized = true; - dev_info(rdev->dev, "fence driver on ring %d use gpu addr 0x%016llx\n", + dev_info(rdev->dev, "fence driver on ring %d uses gpu addr 0x%016llx\n", ring, rdev->fence_drv[ring].gpu_addr); return 0; } diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 6c95575ce109..26197aceb001 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -6198,7 +6198,7 @@ static inline u32 si_get_ih_wptr(struct radeon_device *rdev) if (wptr & RB_OVERFLOW) { wptr &= ~RB_OVERFLOW; - /* When a ring buffer overflow happen start parsing interrupt + /* When a ring buffer overflow happens, start parsing interrupts * from the last not overwritten vector (wptr + 16). Hopefully * this should allow us to catchup. */ From 899634a57abcbdd62367db6194623b13372d9da8 Mon Sep 17 00:00:00 2001 From: Alexandre Demers Date: Thu, 27 Feb 2025 00:05:06 -0500 Subject: [PATCH 151/235] drm/amdgpu: fix spelling typos in SI Fix typos Signed-off-by: Alexandre Demers Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/si.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c index 026e8376e2c0..f90e07375396 100644 --- a/drivers/gpu/drm/amd/amdgpu/si.c +++ b/drivers/gpu/drm/amd/amdgpu/si.c @@ -909,7 +909,7 @@ static const u32 hainan_mgcg_cgcg_init[] = /* XXX: update when we support VCE */ #if 0 -/* tahiti, pitcarin, verde */ +/* tahiti, pitcairn, verde */ static const struct amdgpu_video_codec_info tahiti_video_codecs_encode_array[] = { { @@ -940,7 +940,7 @@ static const struct amdgpu_video_codecs hainan_video_codecs_encode = .codec_array = NULL, }; -/* tahiti, pitcarin, verde, oland */ +/* tahiti, pitcairn, verde, oland */ static const struct amdgpu_video_codec_info tahiti_video_codecs_decode_array[] = { { @@ -1888,7 +1888,7 @@ static int si_vce_send_vcepll_ctlreq(struct amdgpu_device *adev) WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL, 0, ~UPLL_CTLREQ_MASK); if (i == SI_MAX_CTLACKS_ASSERTION_WAIT) { - DRM_ERROR("Timeout setting UVD clocks!\n"); + DRM_ERROR("Timeout setting VCE clocks!\n"); return -ETIMEDOUT; } From 677ae51f4901e22517f8291a0263f794c104e167 Mon Sep 17 00:00:00 2001 From: Xiang Liu Date: Fri, 28 Feb 2025 11:11:08 +0800 Subject: [PATCH 152/235] drm/amdgpu: Free CPER entry after committing to ring Free CPER entry when it's committed to CPER ring to avoid memory leak. Signed-off-by: Xiang Liu Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c index 15cd0a007b71..0415ed222342 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c @@ -301,6 +301,7 @@ int amdgpu_cper_generate_ue_record(struct amdgpu_device *adev, return ret; amdgpu_cper_ring_write(ring, fatal, fatal->record_length); + kfree(fatal); return 0; } @@ -323,6 +324,7 @@ int amdgpu_cper_generate_bp_threshold_record(struct amdgpu_device *adev) return ret; amdgpu_cper_ring_write(ring, bp_threshold, bp_threshold->record_length); + kfree(bp_threshold); return 0; } @@ -399,6 +401,7 @@ int amdgpu_cper_generate_ce_records(struct amdgpu_device *adev, } amdgpu_cper_ring_write(ring, corrected, corrected->record_length); + kfree(corrected); return 0; } From b5a3fc54e8e3a3215d9771c2774555da431147bf Mon Sep 17 00:00:00 2001 From: Lijo Lazar Date: Thu, 20 Feb 2025 15:33:06 +0530 Subject: [PATCH 153/235] drm/amdgpu: Initialize RRMT status on VCN v5.0.1 Initialize RRMT status from register. Signed-off-by: Lijo Lazar Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c | 2 ++ drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.h | 3 +++ 2 files changed, 5 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c index 900702b1a3bb..0bd536371ad1 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c @@ -194,6 +194,8 @@ static int vcn_v5_0_1_hw_init(struct amdgpu_ip_block *ip_block) struct amdgpu_ring *ring; int i, r, vcn_inst; + if (RREG32_SOC15(VCN, GET_INST(VCN, 0), regVCN_RRMT_CNTL) & 0x100) + adev->vcn.caps |= AMDGPU_VCN_CAPS(RRMT_ENABLED); for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { vcn_inst = GET_INST(VCN, i); ring = &adev->vcn.inst[i].ring_enc[0]; diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.h b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.h index 82ac709f44bf..8fd90bd10807 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.h +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.h @@ -24,6 +24,9 @@ #ifndef __VCN_v5_0_1_H__ #define __VCN_v5_0_1_H__ +#define regVCN_RRMT_CNTL 0x0940 +#define regVCN_RRMT_CNTL_BASE_IDX 1 + extern const struct amdgpu_ip_block_version vcn_v5_0_1_ip_block; #endif /* __VCN_v5_0_1_H__ */ From 0b9647d40ef82837d5025de6daad64db775ea1c5 Mon Sep 17 00:00:00 2001 From: Lijo Lazar Date: Thu, 20 Feb 2025 13:40:31 +0530 Subject: [PATCH 154/235] drm/amdgpu: Add offset normalization in VCN v5.0.1 VCN v5.0.1 also will need register offset normalization. Reuse the logic from VCN v4.0.3. Also, avoid HDP flush similar to VCN v4.0.3 Signed-off-by: Lijo Lazar Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c | 14 ++++++++------ drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.h | 9 +++++++++ drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c | 20 +++++++++++--------- 3 files changed, 28 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c index 20f6bd9255db..7446ecc55714 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c @@ -31,6 +31,7 @@ #include "soc15d.h" #include "soc15_hw_ip.h" #include "vcn_v2_0.h" +#include "vcn_v4_0_3.h" #include "mmsch_v4_0_3.h" #include "vcn/vcn_4_0_3_offset.h" @@ -1494,8 +1495,8 @@ static uint64_t vcn_v4_0_3_unified_ring_get_wptr(struct amdgpu_ring *ring) regUVD_RB_WPTR); } -static void vcn_v4_0_3_enc_ring_emit_reg_wait(struct amdgpu_ring *ring, uint32_t reg, - uint32_t val, uint32_t mask) +void vcn_v4_0_3_enc_ring_emit_reg_wait(struct amdgpu_ring *ring, uint32_t reg, + uint32_t val, uint32_t mask) { /* Use normalized offsets when required */ if (vcn_v4_0_3_normalizn_reqd(ring->adev)) @@ -1507,7 +1508,8 @@ static void vcn_v4_0_3_enc_ring_emit_reg_wait(struct amdgpu_ring *ring, uint32_t amdgpu_ring_write(ring, val); } -static void vcn_v4_0_3_enc_ring_emit_wreg(struct amdgpu_ring *ring, uint32_t reg, uint32_t val) +void vcn_v4_0_3_enc_ring_emit_wreg(struct amdgpu_ring *ring, uint32_t reg, + uint32_t val) { /* Use normalized offsets when required */ if (vcn_v4_0_3_normalizn_reqd(ring->adev)) @@ -1518,8 +1520,8 @@ static void vcn_v4_0_3_enc_ring_emit_wreg(struct amdgpu_ring *ring, uint32_t reg amdgpu_ring_write(ring, val); } -static void vcn_v4_0_3_enc_ring_emit_vm_flush(struct amdgpu_ring *ring, - unsigned int vmid, uint64_t pd_addr) +void vcn_v4_0_3_enc_ring_emit_vm_flush(struct amdgpu_ring *ring, + unsigned int vmid, uint64_t pd_addr) { struct amdgpu_vmhub *hub = &ring->adev->vmhub[ring->vm_hub]; @@ -1531,7 +1533,7 @@ static void vcn_v4_0_3_enc_ring_emit_vm_flush(struct amdgpu_ring *ring, lower_32_bits(pd_addr), 0xffffffff); } -static void vcn_v4_0_3_ring_emit_hdp_flush(struct amdgpu_ring *ring) +void vcn_v4_0_3_ring_emit_hdp_flush(struct amdgpu_ring *ring) { /* VCN engine access for HDP flush doesn't work when RRMT is enabled. * This is a workaround to avoid any HDP flush through VCN ring. diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.h b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.h index 0b046114373a..03572a1d0c9c 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.h +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.h @@ -26,4 +26,13 @@ extern const struct amdgpu_ip_block_version vcn_v4_0_3_ip_block; +void vcn_v4_0_3_enc_ring_emit_reg_wait(struct amdgpu_ring *ring, uint32_t reg, + uint32_t val, uint32_t mask); + +void vcn_v4_0_3_enc_ring_emit_wreg(struct amdgpu_ring *ring, uint32_t reg, + uint32_t val); +void vcn_v4_0_3_enc_ring_emit_vm_flush(struct amdgpu_ring *ring, + unsigned int vmid, uint64_t pd_addr); +void vcn_v4_0_3_ring_emit_hdp_flush(struct amdgpu_ring *ring); + #endif /* __VCN_V4_0_3_H__ */ diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c index 0bd536371ad1..d29e8d685194 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c @@ -29,6 +29,7 @@ #include "soc15d.h" #include "soc15_hw_ip.h" #include "vcn_v2_0.h" +#include "vcn_v4_0_3.h" #include "vcn/vcn_5_0_0_offset.h" #include "vcn/vcn_5_0_0_sh_mask.h" @@ -911,16 +912,17 @@ static const struct amdgpu_ring_funcs vcn_v5_0_1_unified_ring_vm_funcs = { .get_rptr = vcn_v5_0_1_unified_ring_get_rptr, .get_wptr = vcn_v5_0_1_unified_ring_get_wptr, .set_wptr = vcn_v5_0_1_unified_ring_set_wptr, - .emit_frame_size = - SOC15_FLUSH_GPU_TLB_NUM_WREG * 3 + - SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 4 + - 4 + /* vcn_v2_0_enc_ring_emit_vm_flush */ - 5 + 5 + /* vcn_v2_0_enc_ring_emit_fence x2 vm fence */ - 1, /* vcn_v2_0_enc_ring_insert_end */ + .emit_frame_size = SOC15_FLUSH_GPU_TLB_NUM_WREG * 3 + + SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 4 + + 4 + /* vcn_v2_0_enc_ring_emit_vm_flush */ + 5 + + 5 + /* vcn_v2_0_enc_ring_emit_fence x2 vm fence */ + 1, /* vcn_v2_0_enc_ring_insert_end */ .emit_ib_size = 5, /* vcn_v2_0_enc_ring_emit_ib */ .emit_ib = vcn_v2_0_enc_ring_emit_ib, .emit_fence = vcn_v2_0_enc_ring_emit_fence, - .emit_vm_flush = vcn_v2_0_enc_ring_emit_vm_flush, + .emit_vm_flush = vcn_v4_0_3_enc_ring_emit_vm_flush, + .emit_hdp_flush = vcn_v4_0_3_ring_emit_hdp_flush, .test_ring = amdgpu_vcn_enc_ring_test_ring, .test_ib = amdgpu_vcn_unified_ring_test_ib, .insert_nop = amdgpu_ring_insert_nop, @@ -928,8 +930,8 @@ static const struct amdgpu_ring_funcs vcn_v5_0_1_unified_ring_vm_funcs = { .pad_ib = amdgpu_ring_generic_pad_ib, .begin_use = amdgpu_vcn_ring_begin_use, .end_use = amdgpu_vcn_ring_end_use, - .emit_wreg = vcn_v2_0_enc_ring_emit_wreg, - .emit_reg_wait = vcn_v2_0_enc_ring_emit_reg_wait, + .emit_wreg = vcn_v4_0_3_enc_ring_emit_wreg, + .emit_reg_wait = vcn_v4_0_3_enc_ring_emit_reg_wait, .emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper, }; From 77bd621d148e4fb73bc1710b84faeb602d3bf704 Mon Sep 17 00:00:00 2001 From: "Jesse.zhang@amd.com" Date: Thu, 13 Feb 2025 13:33:34 +0800 Subject: [PATCH 155/235] drm/amdgpu: Update SDMA scheduler mask handling to include page queue This patch updates the SDMA scheduler mask handling to include the page queue if it exists. The scheduler mask is calculated based on the number of SDMA instances and the presence of the page queue. The mask is updated to reflect the state of both the SDMA gfx ring and the page queue. Changes: - Add handling for the SDMA page queue in `amdgpu_debugfs_sdma_sched_mask_set`. - Update scheduler mask calculations to include the page queue. - Modify `amdgpu_debugfs_sdma_sched_mask_get` to return the correct mask value. This change is necessary to verify multiple queues (SDMA gfx queue + page queue) and ensure proper scheduling and state management for SDMA instances. Signed-off-by: Jesse Zhang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c | 56 +++++++++++++++++++++--- 1 file changed, 49 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c index 42a7b86e41c3..39669f8788a7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c @@ -356,23 +356,44 @@ int amdgpu_sdma_ras_sw_init(struct amdgpu_device *adev) static int amdgpu_debugfs_sdma_sched_mask_set(void *data, u64 val) { struct amdgpu_device *adev = (struct amdgpu_device *)data; - u32 i; + u64 i, num_ring; u64 mask = 0; - struct amdgpu_ring *ring; + struct amdgpu_ring *ring, *page = NULL; if (!adev) return -ENODEV; - mask = BIT_ULL(adev->sdma.num_instances) - 1; + /* Determine the number of rings per SDMA instance + * (1 for sdma gfx ring, 2 if page queue exists) + */ + if (adev->sdma.has_page_queue) + num_ring = 2; + else + num_ring = 1; + + /* Calculate the maximum possible mask value + * based on the number of SDMA instances and rings + */ + mask = BIT_ULL(adev->sdma.num_instances * num_ring) - 1; + if ((val & mask) == 0) return -EINVAL; for (i = 0; i < adev->sdma.num_instances; ++i) { ring = &adev->sdma.instance[i].ring; - if (val & BIT_ULL(i)) + if (adev->sdma.has_page_queue) + page = &adev->sdma.instance[i].page; + if (val & BIT_ULL(i * num_ring)) ring->sched.ready = true; else ring->sched.ready = false; + + if (page) { + if (val & BIT_ULL(i * num_ring + 1)) + page->sched.ready = true; + else + page->sched.ready = false; + } } /* publish sched.ready flag update effective immediately across smp */ smp_rmb(); @@ -382,16 +403,37 @@ static int amdgpu_debugfs_sdma_sched_mask_set(void *data, u64 val) static int amdgpu_debugfs_sdma_sched_mask_get(void *data, u64 *val) { struct amdgpu_device *adev = (struct amdgpu_device *)data; - u32 i; + u64 i, num_ring; u64 mask = 0; - struct amdgpu_ring *ring; + struct amdgpu_ring *ring, *page = NULL; if (!adev) return -ENODEV; + + /* Determine the number of rings per SDMA instance + * (1 for sdma gfx ring, 2 if page queue exists) + */ + if (adev->sdma.has_page_queue) + num_ring = 2; + else + num_ring = 1; + for (i = 0; i < adev->sdma.num_instances; ++i) { ring = &adev->sdma.instance[i].ring; + if (adev->sdma.has_page_queue) + page = &adev->sdma.instance[i].page; + if (ring->sched.ready) - mask |= 1 << i; + mask |= BIT_ULL(i * num_ring); + else + mask &= ~BIT_ULL(i * num_ring); + + if (page) { + if (page->sched.ready) + mask |= BIT_ULL(i * num_ring + 1); + else + mask &= ~BIT_ULL(i * num_ring + 1); + } } *val = mask; From 6fcfaac604dbb840c3be38ee8c7b1e3e974daace Mon Sep 17 00:00:00 2001 From: Lijo Lazar Date: Thu, 20 Feb 2025 15:25:53 +0530 Subject: [PATCH 156/235] drm/amdgpu: Initialize RRMT status on JPEG v5.0.1 Initialize RRMT enablement status from register. Signed-off-by: Lijo Lazar Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c | 3 +++ drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.h | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c index 6b8ef8e8c0eb..daa982bf36cd 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c @@ -249,6 +249,9 @@ static int jpeg_v5_0_1_hw_init(struct amdgpu_ip_block *ip_block) } return 0; } + if (RREG32_SOC15(VCN, GET_INST(VCN, 0), regVCN_RRMT_CNTL) & 0x100) + adev->jpeg.caps |= AMDGPU_JPEG_CAPS(RRMT_ENABLED); + for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) { jpeg_inst = GET_INST(JPEG, i); ring = adev->jpeg.inst[i].ring_dec; diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.h b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.h index d5c63d8074ab..efdab57324e4 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.h +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.h @@ -95,4 +95,7 @@ extern const struct amdgpu_ip_block_version jpeg_v5_0_1_ip_block; #define regJPEG_CORE_RST_CTRL 0x072e #define regJPEG_CORE_RST_CTRL_BASE_IDX 1 -#endif /* __JPEG_V5_0_0_H__ */ +#define regVCN_RRMT_CNTL 0x0940 +#define regVCN_RRMT_CNTL_BASE_IDX 1 + +#endif /* __JPEG_V5_0_1_H__ */ From a734a717dcfe1ce618301775034e598cb456665b Mon Sep 17 00:00:00 2001 From: Lijo Lazar Date: Thu, 20 Feb 2025 13:38:06 +0530 Subject: [PATCH 157/235] drm/amdgpu: Avoid HDP flush on JPEG v5.0.1 Similar to JPEG v4.0.3, HDP flush shouldn't be performed by JPEG engine. Keep it empty. Signed-off-by: Lijo Lazar Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c | 2 +- drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.h | 1 + drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c index 1fcab0ef21c3..de46dbf86477 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c @@ -686,7 +686,7 @@ static uint64_t jpeg_v4_0_3_dec_ring_get_wptr(struct amdgpu_ring *ring) jpeg_v4_0_3_core_reg_offset(ring->pipe)); } -static void jpeg_v4_0_3_ring_emit_hdp_flush(struct amdgpu_ring *ring) +void jpeg_v4_0_3_ring_emit_hdp_flush(struct amdgpu_ring *ring) { /* JPEG engine access for HDP flush doesn't work when RRMT is enabled. * This is a workaround to avoid any HDP flush through JPEG ring. diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.h b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.h index 747a3e5f6856..a90bf370a002 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.h +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.h @@ -56,6 +56,7 @@ void jpeg_v4_0_3_dec_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq unsigned int flags); void jpeg_v4_0_3_dec_ring_emit_vm_flush(struct amdgpu_ring *ring, unsigned int vmid, uint64_t pd_addr); +void jpeg_v4_0_3_ring_emit_hdp_flush(struct amdgpu_ring *ring); void jpeg_v4_0_3_dec_ring_nop(struct amdgpu_ring *ring, uint32_t count); void jpeg_v4_0_3_dec_ring_insert_start(struct amdgpu_ring *ring); void jpeg_v4_0_3_dec_ring_insert_end(struct amdgpu_ring *ring); diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c index daa982bf36cd..56c01d207e20 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c @@ -740,6 +740,7 @@ static const struct amdgpu_ring_funcs jpeg_v5_0_1_dec_ring_vm_funcs = { .emit_ib = jpeg_v4_0_3_dec_ring_emit_ib, .emit_fence = jpeg_v4_0_3_dec_ring_emit_fence, .emit_vm_flush = jpeg_v4_0_3_dec_ring_emit_vm_flush, + .emit_hdp_flush = jpeg_v4_0_3_ring_emit_hdp_flush, .test_ring = amdgpu_jpeg_dec_ring_test_ring, .test_ib = amdgpu_jpeg_dec_ring_test_ib, .insert_nop = jpeg_v4_0_3_dec_ring_nop, From c3c584c18c90a024a54716229809ba36424f9660 Mon Sep 17 00:00:00 2001 From: Vitaliy Shevtsov Date: Thu, 27 Feb 2025 01:28:51 +0500 Subject: [PATCH 158/235] drm/amd/display: fix type mismatch in CalculateDynamicMetadataParameters() There is a type mismatch between what CalculateDynamicMetadataParameters() takes and what is passed to it. Currently this function accepts several args as signed long but it's called with unsigned integers and integer. On some systems where long is 32 bits and one of these unsigned int params is greater than INT_MAX it may cause passing input params as negative values. Fix this by changing these argument types from long to unsigned int and to int respectively. Also this will align the function's definition with similar functions in other dcn* drivers. Found by Linux Verification Center (linuxtesting.org) with Svace. Fixes: 6725a88f88a7 ("drm/amd/display: Add DCN3 DML") Signed-off-by: Vitaliy Shevtsov Reviewed-by: Alex Hung Signed-off-by: Alex Deucher --- .../amd/display/dc/dml/dcn30/display_mode_vba_30.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c index cee1b351e105..f1fe49401bc0 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c @@ -281,10 +281,10 @@ static void CalculateDynamicMetadataParameters( double DISPCLK, double DCFClkDeepSleep, double PixelClock, - long HTotal, - long VBlank, - long DynamicMetadataTransmittedBytes, - long DynamicMetadataLinesBeforeActiveRequired, + unsigned int HTotal, + unsigned int VBlank, + unsigned int DynamicMetadataTransmittedBytes, + int DynamicMetadataLinesBeforeActiveRequired, int InterlaceEnable, bool ProgressiveToInterlaceUnitInOPP, double *Tsetup, @@ -3265,8 +3265,8 @@ static double CalculateWriteBackDelay( static void CalculateDynamicMetadataParameters(int MaxInterDCNTileRepeaters, double DPPCLK, double DISPCLK, - double DCFClkDeepSleep, double PixelClock, long HTotal, long VBlank, long DynamicMetadataTransmittedBytes, - long DynamicMetadataLinesBeforeActiveRequired, int InterlaceEnable, bool ProgressiveToInterlaceUnitInOPP, + double DCFClkDeepSleep, double PixelClock, unsigned int HTotal, unsigned int VBlank, unsigned int DynamicMetadataTransmittedBytes, + int DynamicMetadataLinesBeforeActiveRequired, int InterlaceEnable, bool ProgressiveToInterlaceUnitInOPP, double *Tsetup, double *Tdmbf, double *Tdmec, double *Tdmsks) { double TotalRepeaterDelayTime = 0; From b74f46f3ce1e5f6336645f1e9ff47c56d5dfdef1 Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Thu, 23 Jan 2025 16:39:52 -0500 Subject: [PATCH 159/235] drm/amd/display: Request HW cursor on DCN3.2 with SubVP [why] When SubVP is active the HW cursor size is limited to 64x64, and anything larger will force composition which is bad for gaming on DCN3.2 if the game uses a larger cursor. [how] If HW cursor is requested, typically by a fullscreen game, do not enable SubVP so that up to 256x256 cursor sizes are available for DCN3.2. Reviewed-by: Aric Cyr Signed-off-by: Aric Cyr Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 3 ++- drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 05ad7a9af4ff..a99ce7c86781 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -4937,7 +4937,8 @@ static bool full_update_required(struct dc *dc, stream_update->lut3d_func || stream_update->pending_test_pattern || stream_update->crtc_timing_adjust || - stream_update->scaler_sharpener_update)) + stream_update->scaler_sharpener_update || + stream_update->hw_cursor_req)) return true; if (stream) { diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c index 6f490d8d7038..56dda686e299 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c @@ -626,6 +626,7 @@ static bool dcn32_assign_subvp_pipe(struct dc *dc, * - Not TMZ surface */ if (pipe->plane_state && !pipe->top_pipe && !pipe->prev_odm_pipe && !dcn32_is_center_timing(pipe) && + !pipe->stream->hw_cursor_req && !(pipe->stream->timing.pix_clk_100hz / 10000 > DCN3_2_MAX_SUBVP_PIXEL_RATE_MHZ) && (!dcn32_is_psr_capable(pipe) || (context->stream_count == 1 && dc->caps.dmub_caps.subvp_psr)) && dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_NONE && From a025f424af0407b7561bd5e6217295dde3abbc2e Mon Sep 17 00:00:00 2001 From: Dillon Varone Date: Wed, 12 Feb 2025 17:06:42 -0500 Subject: [PATCH 160/235] drm/amd/display: Fix p-state type when p-state is unsupported [WHY&HOW] P-state type would remain on previously used when unsupported which causes confusion in logging and visual confirm, so set back to zero when unsupported. Reviewed-by: Aric Cyr Signed-off-by: Dillon Varone Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c index 6b514fd03f16..367c6b794412 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c @@ -564,6 +564,7 @@ void set_p_state_switch_method( if (!dc->ctx || !dc->ctx->dmub_srv || !pipe_ctx || !vba) return; + pipe_ctx->p_state_type = P_STATE_UNKNOWN; if (vba->DRAMClockChangeSupport[vba->VoltageLevel][vba->maxMpcComb] != dm_dram_clock_change_unsupported) { /* MCLK switching is supported */ From 0dfcc2bf269010a6e093793034c048049a40ee93 Mon Sep 17 00:00:00 2001 From: Dillon Varone Date: Thu, 13 Feb 2025 13:10:41 -0500 Subject: [PATCH 161/235] drm/amd/display: Fix DMUB reset sequence for DCN401 [WHY] It should no longer use DMCUB_SOFT_RESET as it can result in the memory request path becoming desynchronized. [HOW] To ensure robustness in the reset sequence: 1) Extend timeout on the "halt" command sent via gpint, and check for controller to enter "wait" as a stronger guarantee that there are no requests to memory still in flight. 2) Remove usage of DMCUB_SOFT_RESET 3) Rely on PSP to reset the controller safely Reviewed-by: Nicholas Kazlauskas Signed-off-by: Dillon Varone Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../drm/amd/display/dmub/src/dmub_dcn401.c | 47 ++++++++++++------- .../drm/amd/display/dmub/src/dmub_dcn401.h | 3 +- 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.c index 39a8cb6d7523..e1c4fe1c6e3e 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.c @@ -63,8 +63,10 @@ static inline void dmub_dcn401_translate_addr(const union dmub_addr *addr_in, void dmub_dcn401_reset(struct dmub_srv *dmub) { union dmub_gpint_data_register cmd; - const uint32_t timeout = 30; - uint32_t in_reset, scratch, i; + const uint32_t timeout_us = 1 * 1000 * 1000; //1s + const uint32_t poll_delay_us = 1; //1us + uint32_t i = 0; + uint32_t in_reset, scratch, pwait_mode; REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &in_reset); @@ -75,32 +77,35 @@ void dmub_dcn401_reset(struct dmub_srv *dmub) dmub->hw_funcs.set_gpint(dmub, cmd); - /** - * Timeout covers both the ACK and the wait - * for remaining work to finish. - * - * This is mostly bound by the PHY disable sequence. - * Each register check will be greater than 1us, so - * don't bother using udelay. - */ - - for (i = 0; i < timeout; ++i) { + for (i = 0; i < timeout_us; i++) { if (dmub->hw_funcs.is_gpint_acked(dmub, cmd)) break; + + udelay(poll_delay_us); } - for (i = 0; i < timeout; ++i) { + for (; i < timeout_us; i++) { scratch = dmub->hw_funcs.get_gpint_response(dmub); if (scratch == DMUB_GPINT__STOP_FW_RESPONSE) break; + + udelay(poll_delay_us); } - /* Force reset in case we timed out, DMCUB is likely hung. */ + for (; i < timeout_us; i++) { + REG_GET(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS, &pwait_mode); + if (pwait_mode & (1 << 0)) + break; + + udelay(poll_delay_us); + } + } + + if (i >= timeout_us) { + /* timeout should never occur */ + BREAK_TO_DEBUGGER(); } - REG_UPDATE(DMCUB_CNTL2, DMCUB_SOFT_RESET, 1); - REG_UPDATE(DMCUB_CNTL, DMCUB_ENABLE, 0); - REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 1); REG_WRITE(DMCUB_INBOX1_RPTR, 0); REG_WRITE(DMCUB_INBOX1_WPTR, 0); REG_WRITE(DMCUB_OUTBOX1_RPTR, 0); @@ -131,7 +136,10 @@ void dmub_dcn401_backdoor_load(struct dmub_srv *dmub, dmub_dcn401_get_fb_base_offset(dmub, &fb_base, &fb_offset); + /* reset and disable DMCUB and MMHUBBUB DMUIF */ REG_UPDATE(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 1); + REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 1); + REG_UPDATE(DMCUB_CNTL, DMCUB_ENABLE, 0); dmub_dcn401_translate_addr(&cw0->offset, fb_base, fb_offset, &offset); @@ -151,6 +159,7 @@ void dmub_dcn401_backdoor_load(struct dmub_srv *dmub, DMCUB_REGION3_CW1_TOP_ADDRESS, cw1->region.top, DMCUB_REGION3_CW1_ENABLE, 1); + /* release DMCUB reset only to prevent premature execution */ REG_UPDATE_2(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 0, DMCUB_MEM_UNIT_ID, 0x20); } @@ -161,7 +170,10 @@ void dmub_dcn401_backdoor_load_zfb_mode(struct dmub_srv *dmub, { union dmub_addr offset; + /* reset and disable DMCUB and MMHUBBUB DMUIF */ REG_UPDATE(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 1); + REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 1); + REG_UPDATE(DMCUB_CNTL, DMCUB_ENABLE, 0); offset = cw0->offset; @@ -181,6 +193,7 @@ void dmub_dcn401_backdoor_load_zfb_mode(struct dmub_srv *dmub, DMCUB_REGION3_CW1_TOP_ADDRESS, cw1->region.top, DMCUB_REGION3_CW1_ENABLE, 1); + /* release DMCUB reset only to prevent premature execution */ REG_UPDATE_2(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 0, DMCUB_MEM_UNIT_ID, 0x20); } diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.h index 4c8843b79695..31f95b27e227 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.h +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.h @@ -169,7 +169,8 @@ struct dmub_srv; DMUB_SF(HOST_INTERRUPT_CSR, HOST_REG_INBOX0_RSP_INT_EN) \ DMUB_SF(HOST_INTERRUPT_CSR, HOST_REG_OUTBOX0_RDY_INT_ACK) \ DMUB_SF(HOST_INTERRUPT_CSR, HOST_REG_OUTBOX0_RDY_INT_STAT) \ - DMUB_SF(HOST_INTERRUPT_CSR, HOST_REG_OUTBOX0_RDY_INT_EN) + DMUB_SF(HOST_INTERRUPT_CSR, HOST_REG_OUTBOX0_RDY_INT_EN) \ + DMUB_SF(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS) struct dmub_srv_dcn401_reg_offset { #define DMUB_SR(reg) uint32_t reg; From fc215e83d0480e8af58fd8ad2282c3c319ebcf4e Mon Sep 17 00:00:00 2001 From: Hansen Dsouza Date: Fri, 24 Jan 2025 15:12:37 -0500 Subject: [PATCH 162/235] drm/amd/display: read mso dpcd caps [Why & How] Read if panel support multi-sst links Reviewed-by: Charlene Liu Signed-off-by: Hansen Dsouza Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_dp_types.h | 2 ++ .../display/dc/link/protocols/link_dp_capability.c | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h index 8bb628ab7855..22c2173c687f 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h @@ -1220,6 +1220,8 @@ struct dpcd_caps { struct replay_info pr_info; uint16_t edp_oled_emission_rate; union dp_receive_port0_cap receive_port0_cap; + /* Indicates the number of SST links supported by MSO (Multi-Stream Output) */ + uint8_t mso_cap_sst_links_supported; }; union dpcd_sink_ext_caps { diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c index 0785c030f6a6..da19f6a3b42b 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c @@ -2100,6 +2100,17 @@ void detect_edp_sink_caps(struct dc_link *link) core_link_read_dpcd(link, DP_SINK_EMISSION_RATE, (uint8_t *)&link->dpcd_caps.edp_oled_emission_rate, sizeof(link->dpcd_caps.edp_oled_emission_rate)); + + /* + * Read Multi-SST (Single Stream Transport) capability + * for eDP version 1.4 or higher. + */ + if (link->dpcd_caps.dpcd_rev.raw >= DP_EDP_14) + core_link_read_dpcd( + link, + DP_EDP_MSO_LINK_CAPABILITIES, + (uint8_t *)&link->dpcd_caps.mso_cap_sst_links_supported, + sizeof(link->dpcd_caps.mso_cap_sst_links_supported)); } bool dp_get_max_link_enc_cap(const struct dc_link *link, struct dc_link_settings *max_link_enc_cap) From 54743ca151a0050e0e9fd89a562392ddbaef4330 Mon Sep 17 00:00:00 2001 From: Peichen Huang Date: Tue, 11 Feb 2025 14:41:11 +0800 Subject: [PATCH 163/235] drm/amd/display: misc for dio encoder refactor [WHY] These are left required changes for dio encoder refactor. [HOW] 1. original logic is separated by config option 2. new link encoder dp enable/disable code for dcn35 3. process fec only for DP 8b10b encoding Reviewed-by: Cruise Hung Signed-off-by: Peichen Huang Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c | 20 ++++++-- drivers/gpu/drm/amd/display/dc/core/dc.c | 3 +- .../gpu/drm/amd/display/dc/core/dc_resource.c | 5 +- .../gpu/drm/amd/display/dc/core/dc_stream.c | 3 +- .../dc/dio/dcn35/dcn35_dio_link_encoder.c | 50 +++++++++++++++++-- .../dc/dio/dcn35/dcn35_dio_link_encoder.h | 23 +++++++++ .../amd/display/dc/hwss/dcn31/dcn31_hwseq.c | 3 +- .../amd/display/dc/link/hwss/link_hwss_dio.c | 5 +- .../amd/display/dc/link/hwss/link_hwss_dpia.c | 40 +++++++-------- .../drm/amd/display/dc/link/link_detection.c | 5 +- .../dc/link/protocols/link_dp_training.c | 3 +- .../dc/link/protocols/link_dp_training_dpia.c | 13 +++-- 12 files changed, 133 insertions(+), 40 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c index df29d28d89c9..af722519a1fa 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c @@ -201,16 +201,26 @@ static void dcn35_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state * struct pipe_ctx *pipe = safe_to_lower ? &context->res_ctx.pipe_ctx[i] : &dc->current_state->res_ctx.pipe_ctx[i]; + struct link_encoder *new_pipe_link_enc = new_pipe->link_res.dio_link_enc; + struct link_encoder *pipe_link_enc = pipe->link_res.dio_link_enc; bool stream_changed_otg_dig_on = false; if (pipe->top_pipe || pipe->prev_odm_pipe) continue; + + if (!dc->config.unify_link_enc_assignment) { + if (new_pipe->stream) + new_pipe_link_enc = new_pipe->stream->link_enc; + if (pipe->stream) + pipe_link_enc = pipe->stream->link_enc; + } + stream_changed_otg_dig_on = old_pipe->stream && new_pipe->stream && old_pipe->stream != new_pipe->stream && old_pipe->stream_res.tg == new_pipe->stream_res.tg && - new_pipe->stream->link_enc && !new_pipe->stream->dpms_off && - new_pipe->stream->link_enc->funcs->is_dig_enabled && - new_pipe->stream->link_enc->funcs->is_dig_enabled( - new_pipe->stream->link_enc) && + new_pipe_link_enc && !new_pipe->stream->dpms_off && + new_pipe_link_enc->funcs->is_dig_enabled && + new_pipe_link_enc->funcs->is_dig_enabled( + new_pipe_link_enc) && new_pipe->stream_res.stream_enc && new_pipe->stream_res.stream_enc->funcs->is_fifo_enabled && new_pipe->stream_res.stream_enc->funcs->is_fifo_enabled(new_pipe->stream_res.stream_enc); @@ -226,7 +236,7 @@ static void dcn35_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state * if (!has_active_hpo && !dccg->ctx->dc->link_srv->dp_is_128b_132b_signal(pipe) && (pipe->stream && (pipe->stream->dpms_off || dc_is_virtual_signal(pipe->stream->signal) || - !pipe->stream->link_enc) && !stream_changed_otg_dig_on)) { + !pipe_link_enc) && !stream_changed_otg_dig_on)) { /* This w/a should not trigger when we have a dig active */ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index a99ce7c86781..fe59649d3e15 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -905,7 +905,8 @@ void dc_stream_set_static_screen_params(struct dc *dc, static void dc_destruct(struct dc *dc) { // reset link encoder assignment table on destruct - if (dc->res_pool && dc->res_pool->funcs->link_encs_assign) + if (dc->res_pool && dc->res_pool->funcs->link_encs_assign && + !dc->config.unify_link_enc_assignment) link_enc_cfg_init(dc, dc->current_state); if (dc->current_state) { diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 0f8a88220ec6..ea404435c9b9 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -4926,7 +4926,10 @@ bool pipe_need_reprogram( return true; /* DIG link encoder resource assignment for stream changed. */ - if (pipe_ctx_old->stream->ctx->dc->res_pool->funcs->link_encs_assign) { + if (pipe_ctx_old->stream->ctx->dc->config.unify_link_enc_assignment) { + if (pipe_ctx_old->link_res.dio_link_enc != pipe_ctx->link_res.dio_link_enc) + return true; + } else if (pipe_ctx_old->stream->ctx->dc->res_pool->funcs->link_encs_assign) { bool need_reprogram = false; struct dc *dc = pipe_ctx_old->stream->ctx->dc; struct link_encoder *link_enc_prev = diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index e8134c47fe0d..0478dd856d8c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -201,7 +201,8 @@ struct dc_stream_state *dc_copy_stream(const struct dc_stream_state *stream) dc_stream_assign_stream_id(new_stream); /* If using dynamic encoder assignment, wait till stream committed to assign encoder. */ - if (new_stream->ctx->dc->res_pool->funcs->link_encs_assign) + if (new_stream->ctx->dc->res_pool->funcs->link_encs_assign && + !new_stream->ctx->dc->config.unify_link_enc_assignment) new_stream->link_enc = NULL; kref_init(&new_stream->refcount); diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_link_encoder.c index ea0c9a9d0bd6..9972911330b6 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_link_encoder.c @@ -137,9 +137,9 @@ static const struct link_encoder_funcs dcn35_link_enc_funcs = { .hw_init = dcn35_link_encoder_init, .setup = dcn35_link_encoder_setup, .enable_tmds_output = dcn10_link_encoder_enable_tmds_output, - .enable_dp_output = dcn31_link_encoder_enable_dp_output, - .enable_dp_mst_output = dcn31_link_encoder_enable_dp_mst_output, - .disable_output = dcn31_link_encoder_disable_output, + .enable_dp_output = dcn35_link_encoder_enable_dp_output, + .enable_dp_mst_output = dcn35_link_encoder_enable_dp_mst_output, + .disable_output = dcn35_link_encoder_disable_output, .dp_set_lane_settings = dcn10_link_encoder_dp_set_lane_settings, .dp_set_phy_pattern = dcn10_link_encoder_dp_set_phy_pattern, .update_mst_stream_allocation_table = @@ -297,6 +297,50 @@ static void link_encoder_disable(struct dcn10_link_encoder *enc10) REG_UPDATE(DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, 0); } +void dcn35_link_encoder_enable_dp_output( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + + if (!enc->ctx->dc->config.unify_link_enc_assignment) + dcn31_link_encoder_enable_dp_output(enc, link_settings, clock_source); + else { + DC_LOG_DEBUG("%s: enc_id(%d)\n", __func__, enc->preferred_engine); + dcn20_link_encoder_enable_dp_output(enc, link_settings, clock_source); + } +} + +void dcn35_link_encoder_enable_dp_mst_output( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + + if (!enc->ctx->dc->config.unify_link_enc_assignment) + dcn31_link_encoder_enable_dp_mst_output(enc, link_settings, clock_source); + else { + DC_LOG_DEBUG("%s: enc_id(%d)\n", __func__, enc->preferred_engine); + dcn10_link_encoder_enable_dp_mst_output(enc, link_settings, clock_source); + } +} + +void dcn35_link_encoder_disable_output( + struct link_encoder *enc, + enum signal_type signal) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + + if (!enc->ctx->dc->config.unify_link_enc_assignment) + dcn31_link_encoder_disable_output(enc, signal); + else { + DC_LOG_DEBUG("%s: enc_id(%d)\n", __func__, enc->preferred_engine); + dcn10_link_encoder_disable_output(enc, signal); + } +} + void dcn35_link_encoder_enable_dpia_output( struct link_encoder *enc, const struct dc_link_settings *link_settings, diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_link_encoder.h index f9d4221f4b43..5712e6553fab 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_link_encoder.h @@ -144,6 +144,29 @@ bool dcn35_is_dig_enabled(struct link_encoder *enc); enum signal_type dcn35_get_dig_mode(struct link_encoder *enc); void dcn35_link_encoder_setup(struct link_encoder *enc, enum signal_type signal); +/* + * Enable DP transmitter and its encoder. + */ +void dcn35_link_encoder_enable_dp_output( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source); + +/* + * Enable DP transmitter and its encoder in MST mode. + */ +void dcn35_link_encoder_enable_dp_mst_output( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source); + +/* + * Disable transmitter and its encoder. + */ +void dcn35_link_encoder_disable_output( + struct link_encoder *enc, + enum signal_type signal); + /* * Enable DP transmitter and its encoder for dpia port. */ diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c index f698062f1e90..288e9dd9205d 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c @@ -621,7 +621,8 @@ void dcn31_reset_hw_ctx_wrap( } /* New dc_state in the process of being applied to hardware. */ - link_enc_cfg_set_transient_mode(dc, dc->current_state, context); + if (!dc->config.unify_link_enc_assignment) + link_enc_cfg_set_transient_mode(dc, dc->current_state, context); } void dcn31_setup_hpo_hw_control(const struct dce_hwseq *hws, bool enable) diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c index 4a3578a9586e..b68bcc9fca0a 100644 --- a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c +++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c @@ -328,7 +328,10 @@ static const struct link_hwss dio_link_hwss = { bool can_use_dio_link_hwss(const struct dc_link *link, const struct link_resource *link_res) { - return link->link_enc != NULL; + if (!link->dc->config.unify_link_enc_assignment) + return link->link_enc != NULL; + else + return link_res->dio_link_enc != NULL; } /** diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dpia.c b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dpia.c index 81d5085e322f..81bf3c5e1fdf 100644 --- a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dpia.c +++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dpia.c @@ -90,33 +90,27 @@ static void enable_dpia_link_output(struct dc_link *link, const struct dc_link_settings *link_settings) { struct link_encoder *link_enc = link_res->dio_link_enc; + DC_LOGGER_INIT(link->ctx->logger); if (!link->dc->config.unify_link_enc_assignment) link_enc = link_enc_cfg_get_link_enc(link); if (link_enc != NULL) { - if (link->dc->config.enable_dpia_pre_training && link_enc->funcs->enable_dpia_output) { + if (link->dc->config.enable_dpia_pre_training || link->dc->config.unify_link_enc_assignment) { uint8_t fec_rdy = link->dc->link_srv->dp_should_enable_fec(link); uint8_t digmode = dc_is_dp_sst_signal(signal) ? DIG_SST_MODE : DIG_MST_MODE; - link_enc->funcs->enable_dpia_output( - link_enc, - link_settings, - link->ddc_hw_inst, - digmode, - fec_rdy); - } else { - if (dc_is_dp_sst_signal(signal)) - link_enc->funcs->enable_dp_output( + if (link_enc->funcs->enable_dpia_output) + link_enc->funcs->enable_dpia_output( link_enc, link_settings, - clock_source); + link->ddc_hw_inst, + digmode, + fec_rdy); else - link_enc->funcs->enable_dp_mst_output( - link_enc, - link_settings, - clock_source); - } + DC_LOG_ERROR("%s: link encoder does not support enable_dpia_output\n", __func__); + } else + enable_dio_dp_link_output(link, link_res, signal, clock_source, link_settings); } @@ -129,15 +123,19 @@ static void disable_dpia_link_output(struct dc_link *link, enum signal_type signal) { struct link_encoder *link_enc = link_res->dio_link_enc; + DC_LOGGER_INIT(link->ctx->logger); if (!link->dc->config.unify_link_enc_assignment) link_enc = link_enc_cfg_get_link_enc(link); if (link_enc != NULL) { - if (link->dc->config.enable_dpia_pre_training && link_enc->funcs->disable_dpia_output) { + if (link->dc->config.enable_dpia_pre_training || link->dc->config.unify_link_enc_assignment) { uint8_t digmode = dc_is_dp_sst_signal(signal) ? DIG_SST_MODE : DIG_MST_MODE; - link_enc->funcs->disable_dpia_output(link_enc, link->ddc_hw_inst, digmode); + if (link_enc->funcs->disable_dpia_output) + link_enc->funcs->disable_dpia_output(link_enc, link->ddc_hw_inst, digmode); + else + DC_LOG_ERROR("%s: link encoder does not support disable_dpia_output\n", __func__); } else link_enc->funcs->disable_output(link_enc, signal); } @@ -166,8 +164,10 @@ static const struct link_hwss dpia_link_hwss = { bool can_use_dpia_link_hwss(const struct dc_link *link, const struct link_resource *link_res) { - return link->is_dig_mapping_flexible && - link->dc->res_pool->funcs->link_encs_assign; + if (!link->dc->config.unify_link_enc_assignment) + return link->is_dig_mapping_flexible && link->dc->res_pool->funcs->link_encs_assign; + else + return link->is_dig_mapping_flexible && link_res->dio_link_enc != NULL; } const struct link_hwss *get_dpia_link_hwss(void) diff --git a/drivers/gpu/drm/amd/display/dc/link/link_detection.c b/drivers/gpu/drm/amd/display/dc/link/link_detection.c index 550e1a098fa2..cc9191a5c9e6 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_detection.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_detection.c @@ -816,7 +816,10 @@ static bool should_verify_link_capability_destructively(struct dc_link *link, { bool destrictive = false; struct dc_link_settings max_link_cap; - bool is_link_enc_unavailable = link->link_enc && + bool is_link_enc_unavailable = false; + + if (!link->dc->config.unify_link_enc_assignment) + is_link_enc_unavailable = link->link_enc && link->dc->res_pool->funcs->link_encs_assign && !link_enc_cfg_is_link_enc_avail( link->ctx->dc, diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c index 40ac17ba9479..613298d21d03 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c @@ -1575,7 +1575,8 @@ enum link_training_result dp_perform_link_training( /* configure link prior to entering training mode */ dpcd_configure_lttpr_mode(link, <_settings); - dp_set_fec_ready(link, link_res, lt_settings.should_set_fec_ready); + if (link_dp_get_encoding_format(link_settings) == DP_8b_10b_ENCODING) + dp_set_fec_ready(link, link_res, lt_settings.should_set_fec_ready); dpcd_configure_channel_coding(link, <_settings); /* enter training mode: diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c index 6e2d08cfc546..603537ffd128 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c @@ -130,11 +130,14 @@ static enum link_training_result dpia_configure_link( if (status != DC_OK && link->is_hpd_pending) return LINK_TRAINING_ABORT; - if (link->preferred_training_settings.fec_enable != NULL) - fec_enable = *link->preferred_training_settings.fec_enable; - else - fec_enable = true; - status = dp_set_fec_ready(link, link_res, fec_enable); + if (link_dp_get_encoding_format(link_setting) == DP_8b_10b_ENCODING) { + if (link->preferred_training_settings.fec_enable != NULL) + fec_enable = *link->preferred_training_settings.fec_enable; + else + fec_enable = true; + status = dp_set_fec_ready(link, link_res, fec_enable); + } + if (status != DC_OK && link->is_hpd_pending) return LINK_TRAINING_ABORT; From 0584bbcf0c53c133081100e4f4c9fe41e598d045 Mon Sep 17 00:00:00 2001 From: George Shen Date: Fri, 14 Feb 2025 22:00:13 -0500 Subject: [PATCH 164/235] drm/amd/display: Skip checking FRL_MODE bit for PCON BW determination [Why/How] Certain PCON will clear the FRL_MODE bit despite supporting the link BW indicated in the other bits. Thus, skip checking the FRL_MODE bit when interpreting the hdmi_encoded_link_bw struct. Reviewed-by: Wenjing Liu Signed-off-by: George Shen Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../dc/link/protocols/link_dp_capability.c | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c index da19f6a3b42b..a77410122636 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c @@ -250,21 +250,21 @@ static uint32_t intersect_frl_link_bw_support( { uint32_t supported_bw_in_kbps = max_supported_frl_bw_in_kbps; - // HDMI_ENCODED_LINK_BW bits are only valid if HDMI Link Configuration bit is 1 (FRL mode) - if (hdmi_encoded_link_bw.bits.FRL_MODE) { - if (hdmi_encoded_link_bw.bits.BW_48Gbps) - supported_bw_in_kbps = 48000000; - else if (hdmi_encoded_link_bw.bits.BW_40Gbps) - supported_bw_in_kbps = 40000000; - else if (hdmi_encoded_link_bw.bits.BW_32Gbps) - supported_bw_in_kbps = 32000000; - else if (hdmi_encoded_link_bw.bits.BW_24Gbps) - supported_bw_in_kbps = 24000000; - else if (hdmi_encoded_link_bw.bits.BW_18Gbps) - supported_bw_in_kbps = 18000000; - else if (hdmi_encoded_link_bw.bits.BW_9Gbps) - supported_bw_in_kbps = 9000000; - } + /* Skip checking FRL_MODE bit, as certain PCON will clear + * it despite supporting the link BW indicated in the other bits. + */ + if (hdmi_encoded_link_bw.bits.BW_48Gbps) + supported_bw_in_kbps = 48000000; + else if (hdmi_encoded_link_bw.bits.BW_40Gbps) + supported_bw_in_kbps = 40000000; + else if (hdmi_encoded_link_bw.bits.BW_32Gbps) + supported_bw_in_kbps = 32000000; + else if (hdmi_encoded_link_bw.bits.BW_24Gbps) + supported_bw_in_kbps = 24000000; + else if (hdmi_encoded_link_bw.bits.BW_18Gbps) + supported_bw_in_kbps = 18000000; + else if (hdmi_encoded_link_bw.bits.BW_9Gbps) + supported_bw_in_kbps = 9000000; return supported_bw_in_kbps; } From 79fc4e856ea8f62ff7a46cd0ce5ad3a895d39298 Mon Sep 17 00:00:00 2001 From: George Shen Date: Fri, 14 Feb 2025 10:57:08 -0500 Subject: [PATCH 165/235] drm/amd/display: Remove unused struct definition [Why/How] The struct is not and will not be used, as it is no longer relevant nor supported. Reviewed-by: Wenjing Liu Signed-off-by: George Shen Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_dp_types.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h index 22c2173c687f..d988c00f5ca4 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h @@ -410,14 +410,6 @@ union dwnstream_port_caps_byte3_hdmi { uint8_t raw; }; -union hdmi_sink_encoded_link_bw_support { - struct { - uint8_t HDMI_SINK_ENCODED_LINK_BW_SUPPORT:3; - uint8_t RESERVED:5; - } bits; - uint8_t raw; -}; - union hdmi_encoded_link_bw { struct { uint8_t FRL_MODE:1; // Bit 0 From 02b2c97824df69f5a8618b28fcb7060be6166436 Mon Sep 17 00:00:00 2001 From: Alex Hung Date: Tue, 18 Feb 2025 21:14:47 -0700 Subject: [PATCH 166/235] drm/amd/display: Check NULL connector before it is used [Why & How] amdgpu_dm_find_first_crtc_matching_connector can return NULL. It is necessary to the returned connector before passing it drm_atomic_get_new_connector_state which always assumes connector is not NULL. Reviewed-by: Roman Li Signed-off-by: Alex Hung Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 056b17198956..7ceedf626d23 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -1632,6 +1632,9 @@ int pre_validate_dsc(struct drm_atomic_state *state, connector = amdgpu_dm_find_first_crtc_matching_connector(state, state->crtcs[ind].ptr); + if (!connector) + continue; + drm_new_conn_state = drm_atomic_get_new_connector_state(state, connector); From a2f72c0717ff2316b106436d8188a75e7886eed0 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Wed, 19 Feb 2025 09:46:55 -0500 Subject: [PATCH 167/235] drm/amd/display: Revert "Increase halt timeout for DMCUB to 1s" This reverts commit 50f040c53ea9 ("drm/amd/display: Increase halt timeout for DMCUB to 1s") There's two issues here: 1. Each poll is closer to 10us than 1us so it stalls for 15s on PNP. 2. We're reading the wrong scratch register to check for the HALT code. Reviewed-by: Dillon Varone Signed-off-by: Nicholas Kazlauskas Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c | 15 +++++---------- drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c | 2 +- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c index 1fac75dfc650..3d0bba602b53 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c @@ -83,8 +83,8 @@ static inline void dmub_dcn31_translate_addr(const union dmub_addr *addr_in, void dmub_dcn31_reset(struct dmub_srv *dmub) { union dmub_gpint_data_register cmd; - const uint32_t timeout = 1000000; - uint32_t in_reset, is_enabled, scratch, i, pwait_mode; + const uint32_t timeout = 100; + uint32_t in_reset, scratch, i, pwait_mode; REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &in_reset); @@ -125,14 +125,9 @@ void dmub_dcn31_reset(struct dmub_srv *dmub) /* Force reset in case we timed out, DMCUB is likely hung. */ } - REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_enabled); - - if (is_enabled) { - REG_UPDATE(DMCUB_CNTL2, DMCUB_SOFT_RESET, 1); - REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 1); - REG_UPDATE(DMCUB_CNTL, DMCUB_ENABLE, 0); - } - + REG_UPDATE(DMCUB_CNTL2, DMCUB_SOFT_RESET, 1); + REG_UPDATE(DMCUB_CNTL, DMCUB_ENABLE, 0); + REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 1); REG_WRITE(DMCUB_INBOX1_RPTR, 0); REG_WRITE(DMCUB_INBOX1_WPTR, 0); REG_WRITE(DMCUB_OUTBOX1_RPTR, 0); diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c index 652173b10401..e5e77bd3c31e 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c @@ -88,7 +88,7 @@ static inline void dmub_dcn35_translate_addr(const union dmub_addr *addr_in, void dmub_dcn35_reset(struct dmub_srv *dmub) { union dmub_gpint_data_register cmd; - const uint32_t timeout = 1000000; + const uint32_t timeout = 100; uint32_t in_reset, is_enabled, scratch, i, pwait_mode; REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &in_reset); From c707ea82c79dbd1d295ec94cc6529a5248c77757 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Wed, 19 Feb 2025 09:56:53 -0500 Subject: [PATCH 168/235] drm/amd/display: Ensure DMCUB idle before reset on DCN31/DCN35 [Why] If we soft reset before halt finishes and there are outstanding memory transactions then the memory interface may produce unexpected results, such as out of order transactions when the firmware next runs. These can manifest as random or unexpected load/store violations. [How] Increase the timeout before soft reset to ensure the DMCUB has quiesced. This is effectively 1s maximum based on experimentation. Use the enable bit check on DCN31 like we're doing on DCN35 and reorder the reset writes to follow the HW programming guide. Ensure we're reading SCRATCH7 instead of SCRATCH8 for the HALT code. No current versions of DMCUB firmware use the SCRATCH8 boot bit to dynamically switch where the HALT code goes to maintain backwards compatibility with PSP. Reviewed-by: Dillon Varone Signed-off-by: Nicholas Kazlauskas Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dmub/src/dmub_dcn31.c | 17 +++++++++++------ .../gpu/drm/amd/display/dmub/src/dmub_dcn35.c | 4 ++-- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c index 3d0bba602b53..9796077885c9 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c @@ -83,8 +83,8 @@ static inline void dmub_dcn31_translate_addr(const union dmub_addr *addr_in, void dmub_dcn31_reset(struct dmub_srv *dmub) { union dmub_gpint_data_register cmd; - const uint32_t timeout = 100; - uint32_t in_reset, scratch, i, pwait_mode; + const uint32_t timeout = 100000; + uint32_t in_reset, is_enabled, scratch, i, pwait_mode; REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &in_reset); @@ -108,7 +108,7 @@ void dmub_dcn31_reset(struct dmub_srv *dmub) } for (i = 0; i < timeout; ++i) { - scratch = dmub->hw_funcs.get_gpint_response(dmub); + scratch = REG_READ(DMCUB_SCRATCH7); if (scratch == DMUB_GPINT__STOP_FW_RESPONSE) break; @@ -125,9 +125,14 @@ void dmub_dcn31_reset(struct dmub_srv *dmub) /* Force reset in case we timed out, DMCUB is likely hung. */ } - REG_UPDATE(DMCUB_CNTL2, DMCUB_SOFT_RESET, 1); - REG_UPDATE(DMCUB_CNTL, DMCUB_ENABLE, 0); - REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 1); + REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_enabled); + + if (is_enabled) { + REG_UPDATE(DMCUB_CNTL2, DMCUB_SOFT_RESET, 1); + REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 1); + REG_UPDATE(DMCUB_CNTL, DMCUB_ENABLE, 0); + } + REG_WRITE(DMCUB_INBOX1_RPTR, 0); REG_WRITE(DMCUB_INBOX1_WPTR, 0); REG_WRITE(DMCUB_OUTBOX1_RPTR, 0); diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c index e5e77bd3c31e..01d013a12b94 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c @@ -88,7 +88,7 @@ static inline void dmub_dcn35_translate_addr(const union dmub_addr *addr_in, void dmub_dcn35_reset(struct dmub_srv *dmub) { union dmub_gpint_data_register cmd; - const uint32_t timeout = 100; + const uint32_t timeout = 100000; uint32_t in_reset, is_enabled, scratch, i, pwait_mode; REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &in_reset); @@ -113,7 +113,7 @@ void dmub_dcn35_reset(struct dmub_srv *dmub) } for (i = 0; i < timeout; ++i) { - scratch = dmub->hw_funcs.get_gpint_response(dmub); + scratch = REG_READ(DMCUB_SCRATCH7); if (scratch == DMUB_GPINT__STOP_FW_RESPONSE) break; From 5ad8eed17232410edd127a00c3ed8ab1c03972e1 Mon Sep 17 00:00:00 2001 From: Leo Zeng Date: Wed, 19 Feb 2025 10:29:39 -0500 Subject: [PATCH 169/235] drm/amd/display: Added visual confirm for DCC [WHY] We want to add a visual confirm mode for DCC and MCache for debugging purpose. [HOW] color pipes based on whether DCC is enabled and what MCache id is used. black - DCC disabled red - DCC enabled grey - 2 different MCaches used other colors - 1 MCache used Reviewed-by: Dillon Varone Signed-off-by: Leo Zeng Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 8 ++-- .../drm/amd/display/dc/core/dc_hw_sequencer.c | 48 +++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dc.h | 1 + .../drm/amd/display/dc/hwss/hw_sequencer.h | 5 ++ 4 files changed, 59 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index fe59649d3e15..e71ea21401f5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1202,6 +1202,8 @@ static void dc_update_visual_confirm_color(struct dc *dc, struct dc_state *conte get_surface_tile_visual_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color)); else if (dc->debug.visual_confirm == VISUAL_CONFIRM_HW_CURSOR) get_cursor_visual_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color)); + else if (dc->debug.visual_confirm == VISUAL_CONFIRM_DCC) + get_dcc_visual_confirm_color(dc, pipe_ctx, &(pipe_ctx->visual_confirm_color)); else { if (dc->ctx->dce_version < DCN_VERSION_2_0) color_space_to_black_color( @@ -3956,6 +3958,9 @@ static void commit_planes_for_stream(struct dc *dc, if (update_type == UPDATE_TYPE_FULL && dc->optimized_required) hwss_process_outstanding_hw_updates(dc, dc->current_state); + if (update_type != UPDATE_TYPE_FAST && dc->res_pool->funcs->prepare_mcache_programming) + dc->res_pool->funcs->prepare_mcache_programming(dc, context); + for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; @@ -4014,9 +4019,6 @@ static void commit_planes_for_stream(struct dc *dc, odm_pipe->ttu_regs.min_ttu_vblank = MAX_TTU; } - if (update_type != UPDATE_TYPE_FAST && dc->res_pool->funcs->prepare_mcache_programming) - dc->res_pool->funcs->prepare_mcache_programming(dc, context); - if ((update_type != UPDATE_TYPE_FAST) && stream->update_flags.bits.dsc_changed) if (top_pipe_to_program && top_pipe_to_program->stream_res.tg->funcs->lock_doublebuffer_enable) { diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c index 367c6b794412..e0277728268a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c @@ -34,6 +34,7 @@ #include "dc_state_priv.h" #define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0])) +#define MAX_NUM_MCACHE 8 /* used as index in array of black_color_format */ enum black_color_format { @@ -553,6 +554,53 @@ void get_cursor_visual_confirm_color( } } +void get_dcc_visual_confirm_color( + struct dc *dc, + struct pipe_ctx *pipe_ctx, + struct tg_color *color) +{ + const uint32_t MCACHE_ID_UNASSIGNED = 0xF; + + if (!pipe_ctx->plane_state->dcc.enable) { + color->color_r_cr = 0; /* black - DCC disabled */ + color->color_g_y = 0; + color->color_b_cb = 0; + return; + } + + if (dc->ctx->dce_version < DCN_VERSION_4_01) { + color->color_r_cr = MAX_TG_COLOR_VALUE; /* red - DCC enabled */ + color->color_g_y = 0; + color->color_b_cb = 0; + return; + } + + uint32_t first_id = pipe_ctx->mcache_regs.main.p0.mcache_id_first; + uint32_t second_id = pipe_ctx->mcache_regs.main.p0.mcache_id_second; + + if (first_id != MCACHE_ID_UNASSIGNED && second_id != MCACHE_ID_UNASSIGNED && first_id != second_id) { + color->color_r_cr = MAX_TG_COLOR_VALUE/2; /* grey - 2 mcache */ + color->color_g_y = MAX_TG_COLOR_VALUE/2; + color->color_b_cb = MAX_TG_COLOR_VALUE/2; + } + + else if (first_id != MCACHE_ID_UNASSIGNED || second_id != MCACHE_ID_UNASSIGNED) { + const struct tg_color id_colors[MAX_NUM_MCACHE] = { + {0, MAX_TG_COLOR_VALUE, 0}, /* green */ + {0, 0, MAX_TG_COLOR_VALUE}, /* blue */ + {MAX_TG_COLOR_VALUE, MAX_TG_COLOR_VALUE, 0}, /* yellow */ + {MAX_TG_COLOR_VALUE, 0, MAX_TG_COLOR_VALUE}, /* magenta */ + {0, MAX_TG_COLOR_VALUE, MAX_TG_COLOR_VALUE}, /* cyan */ + {MAX_TG_COLOR_VALUE, MAX_TG_COLOR_VALUE, MAX_TG_COLOR_VALUE}, /* white */ + {MAX_TG_COLOR_VALUE/2, 0, 0}, /* dark red */ + {0, MAX_TG_COLOR_VALUE/2, 0}, /* dark green */ + }; + + uint32_t assigned_id = (first_id != MCACHE_ID_UNASSIGNED) ? first_id : second_id; + *color = id_colors[assigned_id]; + } +} + void set_p_state_switch_method( struct dc *dc, struct dc_state *context, diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index f646f537a3dc..02bf6fe51a0d 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -495,6 +495,7 @@ enum visual_confirm { VISUAL_CONFIRM_FAMS2 = 19, VISUAL_CONFIRM_HW_CURSOR = 20, VISUAL_CONFIRM_VABC = 21, + VISUAL_CONFIRM_DCC = 22, }; enum dc_psr_power_opts { diff --git a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h index 599fa41fd75f..2b1a2a00648a 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h @@ -517,6 +517,11 @@ void get_cursor_visual_confirm_color( struct pipe_ctx *pipe_ctx, struct tg_color *color); +void get_dcc_visual_confirm_color( + struct dc *dc, + struct pipe_ctx *pipe_ctx, + struct tg_color *color); + void set_p_state_switch_method( struct dc *dc, struct dc_state *context, From c286e8501adedc2a22620a5c60dcd14286b38514 Mon Sep 17 00:00:00 2001 From: Cruise Hung Date: Thu, 20 Feb 2025 11:29:50 +0800 Subject: [PATCH 170/235] drm/amd/display: Add tunneling IRQ handler USB4 DP BW Allocation uses DP_TUNNELING_IRQ to indicate the status update. The DP_TUNNELING_IRQ is defined in LINK_SERVICE_IRQ_VECTOR_ESI0. When receiving DP HPD IRQ in USB4, read the LINK_SERVICE_IRQ_VECTOR_ESI0. Reviewed-by: Wenjing Liu Signed-off-by: Cruise Hung Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_dp_types.h | 40 +++++++++++++++-- .../dc/link/protocols/link_dp_dpia_bw.c | 26 +++++++++++ .../dc/link/protocols/link_dp_dpia_bw.h | 10 +++++ .../dc/link/protocols/link_dp_irq_handler.c | 43 +++++++++++++++++-- 4 files changed, 112 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h index d988c00f5ca4..1f4f11adc491 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h @@ -300,6 +300,19 @@ union lane_align_status_updated { uint8_t raw; }; +union link_service_irq_vector_esi0 { + struct { + uint8_t DP_LINK_RX_CAP_CHANGED:1; + uint8_t DP_LINK_STATUS_CHANGED:1; + uint8_t DP_LINK_STREAM_STATUS_CHANGED:1; + uint8_t DP_LINK_HDMI_LINK_STATUS_CHANGED:1; + uint8_t DP_LINK_CONNECTED_OFF_ENTRY_REQUESTED:1; + uint8_t DP_LINK_TUNNELING_IRQ:1; + uint8_t reserved:2; + } bits; + uint8_t raw; +}; + union lane_adjust { struct { uint8_t VOLTAGE_SWING_LANE:2; @@ -462,8 +475,10 @@ union sink_status { uint8_t raw; }; -/*6-byte structure corresponding to 6 registers (200h-205h) -read during handling of HPD-IRQ*/ +/* 7-byte structure corresponding to 6 registers (200h-205h) + * and LINK_SERVICE_IRQ_ESI0 (2005h) for tunneling IRQ + * read during handling of HPD-IRQ + */ union hpd_irq_data { struct { union sink_count sink_cnt;/* 200h */ @@ -471,9 +486,10 @@ union hpd_irq_data { union lane_status lane01_status;/* 202h */ union lane_status lane23_status;/* 203h */ union lane_align_status_updated lane_status_updated;/* 204h */ - union sink_status sink_status; + union sink_status sink_status;/* 205h */ + union link_service_irq_vector_esi0 link_service_irq_esi0;/* 2005h */ } bytes; - uint8_t raw[6]; + uint8_t raw[7]; }; union down_stream_port_count { @@ -1430,4 +1446,20 @@ struct dp_trace { #ifndef REQUESTED_BW #define REQUESTED_BW 0xE0031 /* 1.4a */ #endif +# ifndef DP_TUNNELING_BW_ALLOC_BITS_MASK +# define DP_TUNNELING_BW_ALLOC_BITS_MASK (0x0F << 0) +# endif +# ifndef DP_TUNNELING_BW_REQUEST_FAILED +# define DP_TUNNELING_BW_REQUEST_FAILED (1 << 0) +# endif +# ifndef DP_TUNNELING_BW_REQUEST_SUCCEEDED +# define DP_TUNNELING_BW_REQUEST_SUCCEEDED (1 << 1) +# endif +# ifndef DP_TUNNELING_ESTIMATED_BW_CHANGED +# define DP_TUNNELING_ESTIMATED_BW_CHANGED (1 << 2) +# endif +# ifndef DP_TUNNELING_BW_ALLOC_CAP_CHANGED +# define DP_TUNNELING_BW_ALLOC_CAP_CHANGED (1 << 3) +# endif + #endif /* DC_DP_TYPES_H */ diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c index 0f1c411523a2..a5541b8fc95b 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c @@ -356,6 +356,32 @@ bool link_dp_dpia_set_dptx_usb4_bw_alloc_support(struct dc_link *link) return ret; } +/* + * Handle DP BW allocation status register + * + * @link: pointer to the dc_link struct instance + * @status: content of DP tunneling status DPCD register + * + * return: none + */ +void link_dp_dpia_handle_bw_alloc_status(struct dc_link *link, uint8_t status) +{ + if (status & DP_TUNNELING_BW_REQUEST_SUCCEEDED) { + DC_LOG_DEBUG("%s: BW Allocation request succeeded on link(%d)", + __func__, link->link_index); + } else if (status & DP_TUNNELING_BW_REQUEST_FAILED) { + DC_LOG_DEBUG("%s: BW Allocation request failed on link(%d) allocated/estimated BW=%d", + __func__, link->link_index, link->dpia_bw_alloc_config.estimated_bw); + } else if (status & DP_TUNNELING_ESTIMATED_BW_CHANGED) { + DC_LOG_DEBUG("%s: Estimated BW changed on link(%d) new estimated BW=%d", + __func__, link->link_index, link->dpia_bw_alloc_config.estimated_bw); + } + + core_link_write_dpcd( + link, DP_TUNNELING_STATUS, + &status, sizeof(status)); +} + void dpia_handle_bw_alloc_response(struct dc_link *link, uint8_t bw, uint8_t result) { int bw_needed = 0; diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.h index 3b6d8494f9d5..1b240a2f6ce0 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.h +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.h @@ -108,4 +108,14 @@ bool dpia_validate_usb4_bw(struct dc_link **link, int *bw_needed, const unsigned */ int link_dp_dpia_get_dp_overhead_in_dp_tunneling(struct dc_link *link); +/* + * Handle DP BW allocation status register + * + * @link: pointer to the dc_link struct instance + * @status: content of DP tunneling status register + * + * return: none + */ +void link_dp_dpia_handle_bw_alloc_status(struct dc_link *link, uint8_t status); + #endif /* DC_INC_LINK_DP_DPIA_BW_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c index a08403c022ea..5be00e4ce10b 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c @@ -37,6 +37,7 @@ #include "link/accessories/link_dp_trace.h" #include "link/link_dpms.h" #include "dm_helpers.h" +#include "link_dp_dpia_bw.h" #define DC_LOGGER \ link->ctx->logger @@ -286,6 +287,30 @@ void dp_handle_link_loss(struct dc_link *link) } } +static void dp_handle_tunneling_irq(struct dc_link *link) +{ + enum dc_status retval; + uint8_t tunneling_status = 0; + + retval = core_link_read_dpcd( + link, DP_TUNNELING_STATUS, + &tunneling_status, + sizeof(tunneling_status)); + + if (retval == DC_OK) { + DC_LOG_HW_HPD_IRQ("%s: Got DP tunneling status on link %d status=0x%x", + __func__, link->link_index, tunneling_status); + + if (tunneling_status & DP_TUNNELING_BW_ALLOC_BITS_MASK) + link_dp_dpia_handle_bw_alloc_status(link, tunneling_status); + } + + tunneling_status = DP_TUNNELING_IRQ; + core_link_write_dpcd( + link, DP_LINK_SERVICE_IRQ_VECTOR_ESI0, + &tunneling_status, 1); +} + static void read_dpcd204h_on_irq_hpd(struct dc_link *link, union hpd_irq_data *irq_data) { enum dc_status retval; @@ -319,13 +344,19 @@ enum dc_status dp_read_hpd_rx_irq_data( * * For DP 1.4 we need to read those from 2002h range. */ - if (link->dpcd_caps.dpcd_rev.raw < DPCD_REV_14) + if (link->dpcd_caps.dpcd_rev.raw < DPCD_REV_14) { retval = core_link_read_dpcd( link, DP_SINK_COUNT, irq_data->raw, - sizeof(union hpd_irq_data)); - else { + DP_SINK_STATUS - DP_SINK_COUNT + 1); + + if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) { + retval = core_link_read_dpcd( + link, DP_LINK_SERVICE_IRQ_VECTOR_ESI0, + &irq_data->bytes.link_service_irq_esi0.raw, 1); + } + } else { /* Read 14 bytes in a single read and then copy only the required fields. * This is more efficient than doing it in two separate AUX reads. */ @@ -346,6 +377,7 @@ enum dc_status dp_read_hpd_rx_irq_data( irq_data->bytes.lane23_status.raw = tmp[DP_LANE2_3_STATUS_ESI - DP_SINK_COUNT_ESI]; irq_data->bytes.lane_status_updated.raw = tmp[DP_LANE_ALIGN_STATUS_UPDATED_ESI - DP_SINK_COUNT_ESI]; irq_data->bytes.sink_status.raw = tmp[DP_SINK_STATUS_ESI - DP_SINK_COUNT_ESI]; + irq_data->bytes.link_service_irq_esi0.raw = tmp[DP_LINK_SERVICE_IRQ_VECTOR_ESI0 - DP_SINK_COUNT_ESI]; /* * This display doesn't have correct values in DPCD200Eh. @@ -488,6 +520,11 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link, dp_trace_link_loss_increment(link); } + if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) { + if (hpd_irq_dpcd_data.bytes.link_service_irq_esi0.bits.DP_LINK_TUNNELING_IRQ) + dp_handle_tunneling_irq(link); + } + if (link->type == dc_connection_sst_branch && hpd_irq_dpcd_data.bytes.sink_cnt.bits.SINK_COUNT != link->dpcd_sink_count) From 20ea0477686d69721a68315c971378884787fc23 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Mon, 17 Feb 2025 22:58:28 -0600 Subject: [PATCH 171/235] drm/amd/display: Change amdgpu_dm_irq_suspend() to void amdgpu_dm_irq_suspend() doesn't have any error flows and always returns zero. Change the function to void. Reviewed-by: Alex Hung Signed-off-by: Mario Limonciello Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c | 3 +-- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c index c4a7fd453e5f..34cd39488ad0 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c @@ -473,7 +473,7 @@ void amdgpu_dm_irq_fini(struct amdgpu_device *adev) unregister_all_irq_handlers(adev); } -int amdgpu_dm_irq_suspend(struct amdgpu_device *adev) +void amdgpu_dm_irq_suspend(struct amdgpu_device *adev) { int src; struct list_head *hnd_list_h; @@ -511,7 +511,6 @@ int amdgpu_dm_irq_suspend(struct amdgpu_device *adev) } DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags); - return 0; } int amdgpu_dm_irq_resume_early(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h index 2349238a626b..c37bcd631e10 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h @@ -90,7 +90,7 @@ void amdgpu_dm_hpd_fini(struct amdgpu_device *adev); * amdgpu_dm_irq_suspend - disable ASIC interrupt during suspend. * */ -int amdgpu_dm_irq_suspend(struct amdgpu_device *adev); +void amdgpu_dm_irq_suspend(struct amdgpu_device *adev); /** * amdgpu_dm_irq_resume_early - enable HPDRX ASIC interrupts during resume. From 65890cad2edb53b6c3fdb289fbf071faac842070 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Mon, 17 Feb 2025 22:58:29 -0600 Subject: [PATCH 172/235] drm/amd/display: Drop `ret` variable from dm_suspend() The `ret` variable in dm_suspend() doesn't get set and is just used to return 0. Drop the needless declaration. Reviewed-by: Alex Hung Signed-off-by: Mario Limonciello Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index d0af935557c4..c0887693f7d0 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3145,7 +3145,6 @@ static int dm_suspend(struct amdgpu_ip_block *ip_block) { struct amdgpu_device *adev = ip_block->adev; struct amdgpu_display_manager *dm = &adev->dm; - int ret = 0; if (amdgpu_in_reset(adev)) { mutex_lock(&dm->dc_lock); @@ -3163,7 +3162,7 @@ static int dm_suspend(struct amdgpu_ip_block *ip_block) hpd_rx_irq_work_suspend(dm); - return ret; + return 0; } WARN_ON(adev->dm.cached_state); From 3cf7a0bc87f028b6bc63a43a80d9d6026ae4d85f Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Mon, 17 Feb 2025 22:58:30 -0600 Subject: [PATCH 173/235] drm/amd/display: Catch failures for amdgpu_dm_commit_zero_streams() amdgpu_dm_commit_zero_streams() returns a DC error code that isn't checked. Add an explicit check to this and fail dm_suspend() if it is not DC_OK. Reviewed-by: Alex Hung Signed-off-by: Mario Limonciello Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index c0887693f7d0..80503d084b82 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3147,6 +3147,8 @@ static int dm_suspend(struct amdgpu_ip_block *ip_block) struct amdgpu_display_manager *dm = &adev->dm; if (amdgpu_in_reset(adev)) { + enum dc_status res; + mutex_lock(&dm->dc_lock); dc_allow_idle_optimizations(adev->dm.dc, false); @@ -3156,7 +3158,11 @@ static int dm_suspend(struct amdgpu_ip_block *ip_block) if (dm->cached_dc_state) dm_gpureset_toggle_interrupts(adev, dm->cached_dc_state, false); - amdgpu_dm_commit_zero_streams(dm->dc); + res = amdgpu_dm_commit_zero_streams(dm->dc); + if (res != DC_OK) { + drm_err(adev_to_drm(adev), "Failed to commit zero streams: %d\n", res); + return -EINVAL; + } amdgpu_dm_irq_suspend(adev); From e3bc320c4b0e1c2f45d00b917c27e474c90dcd9f Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Mon, 17 Feb 2025 22:58:31 -0600 Subject: [PATCH 174/235] drm/amd/display: Use _free() macro for amdgpu_dm_commit_zero_streams() All cases except a failure to create a copy of the current context will call dc_state_release() on the copied context. Use a _free() macro to free the context and then adjust the error handling flow to drop the unnecessary use of goto statements. Reviewed-by: Alex Hung Signed-off-by: Mario Limonciello Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 80503d084b82..e41d1ab34705 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3086,10 +3086,11 @@ static void dm_gpureset_toggle_interrupts(struct amdgpu_device *adev, } +DEFINE_FREE(state_release, struct dc_state *, if (_T) dc_state_release(_T)) + static enum dc_status amdgpu_dm_commit_zero_streams(struct dc *dc) { - struct dc_state *context = NULL; - enum dc_status res = DC_ERROR_UNEXPECTED; + struct dc_state *context __free(state_release) = NULL; int i; struct dc_stream_state *del_streams[MAX_PIPES]; int del_streams_count = 0; @@ -3099,7 +3100,7 @@ static enum dc_status amdgpu_dm_commit_zero_streams(struct dc *dc) context = dc_state_create_current_copy(dc); if (context == NULL) - goto context_alloc_fail; + return DC_ERROR_UNEXPECTED; /* First remove from context all streams */ for (i = 0; i < context->stream_count; i++) { @@ -3110,25 +3111,20 @@ static enum dc_status amdgpu_dm_commit_zero_streams(struct dc *dc) /* Remove all planes for removed streams and then remove the streams */ for (i = 0; i < del_streams_count; i++) { - if (!dc_state_rem_all_planes_for_stream(dc, del_streams[i], context)) { - res = DC_FAIL_DETACH_SURFACES; - goto fail; - } + enum dc_status res; + + if (!dc_state_rem_all_planes_for_stream(dc, del_streams[i], context)) + return DC_FAIL_DETACH_SURFACES; res = dc_state_remove_stream(dc, context, del_streams[i]); if (res != DC_OK) - goto fail; + return res; } params.streams = context->streams; params.stream_count = context->stream_count; - res = dc_commit_streams(dc, ¶ms); -fail: - dc_state_release(context); - -context_alloc_fail: - return res; + return dc_commit_streams(dc, ¶ms); } static void hpd_rx_irq_work_suspend(struct amdgpu_display_manager *dm) From 180998bf307f78efff43f4067c09156e0f33c8fd Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Mon, 17 Feb 2025 22:58:32 -0600 Subject: [PATCH 175/235] drm/amd/display: Use drm_err() instead of DRM_ERROR in dm_resume() drm_err() is helpful to show which device had the error. Adjust to using this instead for error messages. Reviewed-by: Alex Hung Signed-off-by: Mario Limonciello Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index e41d1ab34705..9c96841387dd 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3379,7 +3379,7 @@ static int dm_resume(struct amdgpu_ip_block *ip_block) r = dm_dmub_hw_init(adev); if (r) - DRM_ERROR("DMUB interface failed to initialize: status=%d\n", r); + drm_err(adev_to_drm(adev), "DMUB interface failed to initialize: status=%d\n", r); dc_dmub_srv_set_power_state(dm->dc->ctx->dmub_srv, DC_ACPI_CM_POWER_STATE_D0); dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D0); @@ -3472,7 +3472,7 @@ static int dm_resume(struct amdgpu_ip_block *ip_block) mutex_lock(&aconnector->hpd_lock); if (!dc_link_detect_connection_type(aconnector->dc_link, &new_connection_type)) - DRM_ERROR("KMS: Failed to detect connector\n"); + drm_err(adev_to_drm(adev), "KMS: Failed to detect connector\n"); if (aconnector->base.force && new_connection_type == dc_connection_none) { emulated_link_detect(aconnector->dc_link); From f24a74d59e147dad6eee7f132a9765c5fec22dea Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Mon, 17 Feb 2025 22:58:33 -0600 Subject: [PATCH 176/235] drm/amd/display: Use scoped guard for dm_resume() Scoped guards will release the mutex when they go out of scope. Adjust the code to use these instead. Reviewed-by: Alex Hung Signed-off-by: Mario Limonciello Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 9c96841387dd..900ac463078c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3470,17 +3470,16 @@ static int dm_resume(struct amdgpu_ip_block *ip_block) if (aconnector->mst_root) continue; - mutex_lock(&aconnector->hpd_lock); + guard(mutex)(&aconnector->hpd_lock); if (!dc_link_detect_connection_type(aconnector->dc_link, &new_connection_type)) drm_err(adev_to_drm(adev), "KMS: Failed to detect connector\n"); if (aconnector->base.force && new_connection_type == dc_connection_none) { emulated_link_detect(aconnector->dc_link); } else { - mutex_lock(&dm->dc_lock); + guard(mutex)(&dm->dc_lock); dc_exit_ips_for_hw_access(dm->dc); dc_link_detect(aconnector->dc_link, DETECT_REASON_RESUMEFROMS3S4); - mutex_unlock(&dm->dc_lock); } if (aconnector->fake_enable && aconnector->dc_link->local_sink) @@ -3490,7 +3489,6 @@ static int dm_resume(struct amdgpu_ip_block *ip_block) dc_sink_release(aconnector->dc_sink); aconnector->dc_sink = NULL; amdgpu_dm_update_connector_after_detect(aconnector); - mutex_unlock(&aconnector->hpd_lock); } drm_connector_list_iter_end(&iter); From c2bd614bf8286c40dcd9a7d0b3cbcc4d0321a9c1 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Mon, 17 Feb 2025 22:58:34 -0600 Subject: [PATCH 177/235] drm/amd/display: Change amdgpu_dm_irq_resume_*() to use drm_dbg() drm_dbg() is helpful to show which device had the debug statement. Adjust to using this instead for debug messages. Reviewed-by: Alex Hung Signed-off-by: Mario Limonciello Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c index 34cd39488ad0..adbbc43adde8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c @@ -521,7 +521,7 @@ int amdgpu_dm_irq_resume_early(struct amdgpu_device *adev) DM_IRQ_TABLE_LOCK(adev, irq_table_flags); - DRM_DEBUG_KMS("DM_IRQ: early resume\n"); + drm_dbg(adev_to_drm(adev), "DM_IRQ: early resume\n"); /* re-enable short pulse interrupts HW interrupt */ for (src = DC_IRQ_SOURCE_HPD1RX; src <= DC_IRQ_SOURCE_HPD6RX; src++) { @@ -544,7 +544,7 @@ int amdgpu_dm_irq_resume_late(struct amdgpu_device *adev) DM_IRQ_TABLE_LOCK(adev, irq_table_flags); - DRM_DEBUG_KMS("DM_IRQ: resume\n"); + drm_dbg(adev_to_drm(adev), "DM_IRQ: resume\n"); /** * Renable HW interrupt for HPD and only since FLIP and VBLANK From 7b3e14acc1f205d05d001bdceb884c5568ef10b7 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Mon, 17 Feb 2025 22:58:35 -0600 Subject: [PATCH 178/235] drm/amd/display: Change amdgpu_dm_irq_resume_*() to void amdgpu_dm_irq_resume_early() and amdgpu_dm_irq_resume_late() don't have any error flows. Change the return type from integer to void. Reviewed-by: Alex Hung Signed-off-by: Mario Limonciello Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c | 7 ++----- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h | 4 ++-- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c index adbbc43adde8..2b63cbab0e87 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c @@ -513,7 +513,7 @@ void amdgpu_dm_irq_suspend(struct amdgpu_device *adev) DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags); } -int amdgpu_dm_irq_resume_early(struct amdgpu_device *adev) +void amdgpu_dm_irq_resume_early(struct amdgpu_device *adev) { int src; struct list_head *hnd_list_h, *hnd_list_l; @@ -532,11 +532,9 @@ int amdgpu_dm_irq_resume_early(struct amdgpu_device *adev) } DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags); - - return 0; } -int amdgpu_dm_irq_resume_late(struct amdgpu_device *adev) +void amdgpu_dm_irq_resume_late(struct amdgpu_device *adev) { int src; struct list_head *hnd_list_h, *hnd_list_l; @@ -558,7 +556,6 @@ int amdgpu_dm_irq_resume_late(struct amdgpu_device *adev) } DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags); - return 0; } /* diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h index c37bcd631e10..ba17c23b2706 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h @@ -97,7 +97,7 @@ void amdgpu_dm_irq_suspend(struct amdgpu_device *adev); * amdgpu_dm_irq_resume - enable ASIC interrupt during resume. * */ -int amdgpu_dm_irq_resume_early(struct amdgpu_device *adev); -int amdgpu_dm_irq_resume_late(struct amdgpu_device *adev); +void amdgpu_dm_irq_resume_early(struct amdgpu_device *adev); +void amdgpu_dm_irq_resume_late(struct amdgpu_device *adev); #endif /* __AMDGPU_DM_IRQ_H__ */ From d13fbeb74b7c22e2a22c3d2b8e39a9b8142128a9 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Mon, 17 Feb 2025 22:58:36 -0600 Subject: [PATCH 179/235] drm/amd/display: Use _free(kfree) for dm_gpureset_commit_state() Using a _free(kfree) macro drops the need for a goto statement as it will be freed when it goes out of scope. Reviewed-by: Alex Hung Signed-off-by: Mario Limonciello Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 900ac463078c..4ad9178228d4 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3301,14 +3301,14 @@ static void dm_gpureset_commit_state(struct dc_state *dc_state, struct dc_scaling_info scaling_infos[MAX_SURFACES]; struct dc_flip_addrs flip_addrs[MAX_SURFACES]; struct dc_stream_update stream_update; - } *bundle; + } *bundle __free(kfree); int k, m; bundle = kzalloc(sizeof(*bundle), GFP_KERNEL); if (!bundle) { drm_err(dm->ddev, "Failed to allocate update bundle\n"); - goto cleanup; + return; } for (k = 0; k < dc_state->stream_count; k++) { @@ -3328,9 +3328,6 @@ static void dm_gpureset_commit_state(struct dc_state *dc_state, &bundle->stream_update, bundle->surface_updates); } - -cleanup: - kfree(bundle); } static int dm_resume(struct amdgpu_ip_block *ip_block) From aca9ec9b050c0900c3657ea4aba63d6d95073b22 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Mon, 17 Feb 2025 22:58:37 -0600 Subject: [PATCH 180/235] drm/amd/display: Use scoped guard for amdgpu_dm_update_connector_after_detect() A scoped guard will release the mutex when it goes out of scope. Reviewed-by: Alex Hung Signed-off-by: Mario Limonciello Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 4ad9178228d4..1b754c49896b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3681,7 +3681,7 @@ void amdgpu_dm_update_connector_after_detect( * For S3 resume with headless use eml_sink to fake stream * because on resume connector->sink is set to NULL */ - mutex_lock(&dev->mode_config.mutex); + guard(mutex)(&dev->mode_config.mutex); if (sink) { if (aconnector->dc_sink) { @@ -3706,8 +3706,6 @@ void amdgpu_dm_update_connector_after_detect( } } - mutex_unlock(&dev->mode_config.mutex); - if (sink) dc_sink_release(sink); return; @@ -3737,7 +3735,7 @@ void amdgpu_dm_update_connector_after_detect( drm_dbg_kms(dev, "DCHPD: connector_id=%d: Old sink=%p New sink=%p\n", aconnector->connector_id, aconnector->dc_sink, sink); - mutex_lock(&dev->mode_config.mutex); + guard(mutex)(&dev->mode_config.mutex); /* * 1. Update status of the drm connector @@ -3799,8 +3797,6 @@ void amdgpu_dm_update_connector_after_detect( connector->state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; } - mutex_unlock(&dev->mode_config.mutex); - update_subconnector_property(aconnector); if (sink) From 981a47429e875693e24da8f7bdc3345e935e32dc Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Mon, 17 Feb 2025 22:58:38 -0600 Subject: [PATCH 181/235] drm/amd/display: Use _free() macro for amdgpu_dm_update_connector_after_detect() By using a _free() macro multiple duplicated snippets of code to free the sink can be dropped. The sink will be released when leaving scope. Reviewed-by: Alex Hung Signed-off-by: Mario Limonciello Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 1b754c49896b..c73e194cb027 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3654,12 +3654,14 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector) caps->min_input_signal = min_input_signal_override; } +DEFINE_FREE(sink_release, struct dc_sink *, if (_T) dc_sink_release(_T)) + void amdgpu_dm_update_connector_after_detect( struct amdgpu_dm_connector *aconnector) { struct drm_connector *connector = &aconnector->base; + struct dc_sink *sink __free(sink_release) = NULL; struct drm_device *dev = connector->dev; - struct dc_sink *sink; /* MST handled by drm_mst framework */ if (aconnector->mst_mgr.mst_state == true) @@ -3706,8 +3708,6 @@ void amdgpu_dm_update_connector_after_detect( } } - if (sink) - dc_sink_release(sink); return; } @@ -3715,10 +3715,8 @@ void amdgpu_dm_update_connector_after_detect( * TODO: temporary guard to look for proper fix * if this sink is MST sink, we should not do anything */ - if (sink && sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { - dc_sink_release(sink); + if (sink && sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT_MST) return; - } if (aconnector->dc_sink == sink) { /* @@ -3727,8 +3725,6 @@ void amdgpu_dm_update_connector_after_detect( */ drm_dbg_kms(dev, "DCHPD: connector_id=%d: dc_sink didn't change.\n", aconnector->connector_id); - if (sink) - dc_sink_release(sink); return; } @@ -3798,9 +3794,6 @@ void amdgpu_dm_update_connector_after_detect( } update_subconnector_property(aconnector); - - if (sink) - dc_sink_release(sink); } static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector) From f123fda197525385a58c4cb88a0dd3f6facd5ad1 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Mon, 17 Feb 2025 22:58:39 -0600 Subject: [PATCH 182/235] drm/amd/display: Use scoped guards for handle_hpd_irq_helper() Scoped guards will release the mutex when they go out of scope. Reviewed-by: Alex Hung Signed-off-by: Mario Limonciello Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index c73e194cb027..4945f89bf2f6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3813,7 +3813,7 @@ static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector) * In case of failure or MST no need to update connector status or notify the OS * since (for MST case) MST does this in its own context. */ - mutex_lock(&aconnector->hpd_lock); + guard(mutex)(&aconnector->hpd_lock); if (adev->dm.hdcp_workqueue) { hdcp_reset_display(adev->dm.hdcp_workqueue, aconnector->dc_link->link_index); @@ -3837,10 +3837,10 @@ static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector) if (aconnector->base.force == DRM_FORCE_UNSPECIFIED) drm_kms_helper_connector_hotplug_event(connector); } else { - mutex_lock(&adev->dm.dc_lock); - dc_exit_ips_for_hw_access(dc); - ret = dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD); - mutex_unlock(&adev->dm.dc_lock); + scoped_guard(mutex, &adev->dm.dc_lock) { + dc_exit_ips_for_hw_access(dc); + ret = dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD); + } if (ret) { amdgpu_dm_update_connector_after_detect(aconnector); @@ -3852,8 +3852,6 @@ static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector) drm_kms_helper_connector_hotplug_event(connector); } } - mutex_unlock(&aconnector->hpd_lock); - } static void handle_hpd_irq(void *param) From 130d8324ea95a8cb5bc7e1ec01ff249892352dc3 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Mon, 17 Feb 2025 22:58:40 -0600 Subject: [PATCH 183/235] drm/amd/display: Use drm_err() for handle_hpd_irq_helper() drm_err() will show which device has the error. Reviewed-by: Alex Hung Signed-off-by: Mario Limonciello Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 4945f89bf2f6..9a5663ee1fb8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3825,7 +3825,7 @@ static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector) aconnector->timing_changed = false; if (!dc_link_detect_connection_type(aconnector->dc_link, &new_connection_type)) - DRM_ERROR("KMS: Failed to detect connector\n"); + drm_err(adev_to_drm(adev), "KMS: Failed to detect connector\n"); if (aconnector->base.force && new_connection_type == dc_connection_none) { emulated_link_detect(aconnector->dc_link); From 43e88e20d3f3107b0f49f41200e315c9dc8a921d Mon Sep 17 00:00:00 2001 From: Taimur Hassan Date: Sun, 23 Feb 2025 20:39:00 -0500 Subject: [PATCH 184/235] drm/amd/display: Promote DAL to 3.2.323 This version brings along following fixes: - Various cleanups to amdgpu dm - Add DP tunneling IRQ handler - Fix display corruption for dcn35 - Fix dmcub reset problem - Adjust BW determination for PCON - DIO encoder refactor - Fix performance with SubVP under gaming Acked-by: Tom Chung Signed-off-by: Taimur Hassan Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 02bf6fe51a0d..a62c4893e5ff 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -53,7 +53,7 @@ struct aux_payload; struct set_config_cmd_payload; struct dmub_notification; -#define DC_VER "3.2.322" +#define DC_VER "3.2.323" /** * MAX_SURFACES - representative of the upper bound of surfaces that can be piped to a single CRTC From 1c79b5fcdf1a29525dbb6e8243d0e63c0e9a5000 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Fri, 28 Feb 2025 12:51:41 -0600 Subject: [PATCH 185/235] drm/amd: Copy entire structure in amdgpu_acpi_get_backlight_caps() As new members are introduced to the structure copying the entire structure will help avoid missing them. Reviewed-by: Alex Hung Link: https://lore.kernel.org/r/20250228185145.186319-2-mario.limonciello@amd.com Signed-off-by: Mario Limonciello Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c index b8d4e07d2043..515c6f32448d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c @@ -1277,11 +1277,7 @@ void amdgpu_acpi_get_backlight_caps(struct amdgpu_dm_backlight_caps *caps) { struct amdgpu_atif *atif = &amdgpu_acpi_priv.atif; - caps->caps_valid = atif->backlight_caps.caps_valid; - caps->min_input_signal = atif->backlight_caps.min_input_signal; - caps->max_input_signal = atif->backlight_caps.max_input_signal; - caps->ac_level = atif->backlight_caps.ac_level; - caps->dc_level = atif->backlight_caps.dc_level; + memcpy(caps, &atif->backlight_caps, sizeof(*caps)); } /** From f729e63743f0fbd504a1464e9495c456f63ff7ef Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Fri, 28 Feb 2025 12:51:42 -0600 Subject: [PATCH 186/235] drm/amd: Pass luminance data to amdgpu_dm_backlight_caps The ATIF method on some systems will provide a backlight curve. Pass this curve into amdgpu_dm add it to the structures. Reviewed-by: Alex Hung Link: https://lore.kernel.org/r/20250228185145.186319-3-mario.limonciello@amd.com Signed-off-by: Mario Limonciello Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c | 4 ++++ .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 20 +++++++++++++++++++ drivers/gpu/drm/amd/include/amd_acpi.h | 4 +++- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c index 515c6f32448d..b7f8f2ff143d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c @@ -394,6 +394,10 @@ static int amdgpu_atif_query_backlight_caps(struct amdgpu_atif *atif) characteristics.max_input_signal; atif->backlight_caps.ac_level = characteristics.ac_level; atif->backlight_caps.dc_level = characteristics.dc_level; + atif->backlight_caps.data_points = characteristics.number_of_points; + memcpy(atif->backlight_caps.luminance_data, + characteristics.data_points, + sizeof(atif->backlight_caps.luminance_data)); out: kfree(info); return err; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index f3bc00e587ad..85b64c457ed6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -151,6 +151,18 @@ struct idle_workqueue { bool running; }; +#define MAX_LUMINANCE_DATA_POINTS 99 + +/** + * struct amdgpu_dm_luminance_data - Custom luminance data + * @luminance: Luminance in percent + * @input_signal: Input signal in range 0-255 + */ +struct amdgpu_dm_luminance_data { + u8 luminance; + u8 input_signal; +} __packed; + /** * struct amdgpu_dm_backlight_caps - Information about backlight * @@ -195,6 +207,14 @@ struct amdgpu_dm_backlight_caps { * @dc_level: the default brightness if booted on DC */ u8 dc_level; + /** + * @data_points: the number of custom luminance data points + */ + u8 data_points; + /** + * @luminance_data: custom luminance data + */ + struct amdgpu_dm_luminance_data luminance_data[MAX_LUMINANCE_DATA_POINTS]; }; /** diff --git a/drivers/gpu/drm/amd/include/amd_acpi.h b/drivers/gpu/drm/amd/include/amd_acpi.h index 2d089d30518f..06badbf0c5b9 100644 --- a/drivers/gpu/drm/amd/include/amd_acpi.h +++ b/drivers/gpu/drm/amd/include/amd_acpi.h @@ -61,7 +61,7 @@ struct atif_qbtc_arguments { struct atif_qbtc_data_point { u8 luminance; /* luminance in percent */ - u8 ipnut_signal; /* input signal in range 0-255 */ + u8 input_signal; /* input signal in range 0-255 */ } __packed; struct atif_qbtc_output { @@ -75,6 +75,8 @@ struct atif_qbtc_output { u8 number_of_points; /* number of data points */ struct atif_qbtc_data_point data_points[ATIF_QBTC_MAX_DATA_POINTS]; } __packed; +static_assert(ATIF_QBTC_MAX_DATA_POINTS == MAX_LUMINANCE_DATA_POINTS); +static_assert(sizeof(struct atif_qbtc_data_point) == sizeof(struct amdgpu_dm_luminance_data)); #define ATIF_NOTIFY_MASK 0x3 #define ATIF_NOTIFY_NONE 0 From f25c0f0d4f99df9725e50d282c9143fa51e84645 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Fri, 28 Feb 2025 12:51:43 -0600 Subject: [PATCH 187/235] drm/amd/display: Avoid operating on copies of backlight caps Making a copy of the backlight caps structure between uses is unnecessary. Refer to pointers to the same structure when using it. Reviewed-by: Alex Hung Link: https://lore.kernel.org/r/20250228185145.186319-4-mario.limonciello@amd.com Signed-off-by: Mario Limonciello Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 52 ++++++++----------- 1 file changed, 22 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 9a5663ee1fb8..8d5daa96eeae 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4691,48 +4691,40 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev) static void amdgpu_dm_update_backlight_caps(struct amdgpu_display_manager *dm, int bl_idx) { -#if defined(CONFIG_ACPI) - struct amdgpu_dm_backlight_caps caps; + struct amdgpu_dm_backlight_caps *caps = &dm->backlight_caps[bl_idx]; - memset(&caps, 0, sizeof(caps)); - - if (dm->backlight_caps[bl_idx].caps_valid) + if (caps->caps_valid) return; - amdgpu_acpi_get_backlight_caps(&caps); +#if defined(CONFIG_ACPI) + amdgpu_acpi_get_backlight_caps(caps); /* validate the firmware value is sane */ - if (caps.caps_valid) { - int spread = caps.max_input_signal - caps.min_input_signal; + if (caps->caps_valid) { + int spread = caps->max_input_signal - caps->min_input_signal; - if (caps.max_input_signal > AMDGPU_DM_DEFAULT_MAX_BACKLIGHT || - caps.min_input_signal < 0 || + if (caps->max_input_signal > AMDGPU_DM_DEFAULT_MAX_BACKLIGHT || + caps->min_input_signal < 0 || spread > AMDGPU_DM_DEFAULT_MAX_BACKLIGHT || spread < AMDGPU_DM_MIN_SPREAD) { DRM_DEBUG_KMS("DM: Invalid backlight caps: min=%d, max=%d\n", - caps.min_input_signal, caps.max_input_signal); - caps.caps_valid = false; + caps->min_input_signal, caps->max_input_signal); + caps->caps_valid = false; } } - if (caps.caps_valid) { - dm->backlight_caps[bl_idx].caps_valid = true; - if (caps.aux_support) - return; - dm->backlight_caps[bl_idx].min_input_signal = caps.min_input_signal; - dm->backlight_caps[bl_idx].max_input_signal = caps.max_input_signal; - } else { - dm->backlight_caps[bl_idx].min_input_signal = - AMDGPU_DM_DEFAULT_MIN_BACKLIGHT; - dm->backlight_caps[bl_idx].max_input_signal = - AMDGPU_DM_DEFAULT_MAX_BACKLIGHT; + if (!caps->caps_valid) { + caps->min_input_signal = AMDGPU_DM_DEFAULT_MIN_BACKLIGHT; + caps->max_input_signal = AMDGPU_DM_DEFAULT_MAX_BACKLIGHT; + caps->caps_valid = true; } #else - if (dm->backlight_caps[bl_idx].aux_support) + if (caps->aux_support) return; - dm->backlight_caps[bl_idx].min_input_signal = AMDGPU_DM_DEFAULT_MIN_BACKLIGHT; - dm->backlight_caps[bl_idx].max_input_signal = AMDGPU_DM_DEFAULT_MAX_BACKLIGHT; + caps->min_input_signal = AMDGPU_DM_DEFAULT_MIN_BACKLIGHT; + caps->max_input_signal = AMDGPU_DM_DEFAULT_MAX_BACKLIGHT; + caps->caps_valid = true; #endif } @@ -4786,19 +4778,19 @@ static void amdgpu_dm_backlight_set_level(struct amdgpu_display_manager *dm, int bl_idx, u32 user_brightness) { - struct amdgpu_dm_backlight_caps caps; + struct amdgpu_dm_backlight_caps *caps; struct dc_link *link; u32 brightness; bool rc, reallow_idle = false; amdgpu_dm_update_backlight_caps(dm, bl_idx); - caps = dm->backlight_caps[bl_idx]; + caps = &dm->backlight_caps[bl_idx]; dm->brightness[bl_idx] = user_brightness; /* update scratch register */ if (bl_idx == 0) amdgpu_atombios_scratch_regs_set_backlight_level(dm->adev, dm->brightness[bl_idx]); - brightness = convert_brightness_from_user(&caps, dm->brightness[bl_idx]); + brightness = convert_brightness_from_user(caps, dm->brightness[bl_idx]); link = (struct dc_link *)dm->backlight_link[bl_idx]; /* Change brightness based on AUX property */ @@ -4808,7 +4800,7 @@ static void amdgpu_dm_backlight_set_level(struct amdgpu_display_manager *dm, reallow_idle = true; } - if (caps.aux_support) { + if (caps->aux_support) { rc = dc_link_set_backlight_level_nits(link, true, brightness, AUX_BL_DEFAULT_TRANSITION_TIME_MS); if (!rc) From 578df37b1b6a5bc41602cdab3d982072e5688222 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Fri, 28 Feb 2025 12:51:44 -0600 Subject: [PATCH 188/235] drm/amd/display: Add support for custom brightness curve Some systems specify in the firmware a brightness curve that better reflects the characteristics of the panel used. This is done in the form of data points and matching luminance percentage. When converting a userspace requested brightness value use that curve to convert to a firmware intended brightness value. Reviewed-by: Alex Hung Link: https://lore.kernel.org/r/20250228185145.186319-5-mario.limonciello@amd.com Signed-off-by: Mario Limonciello Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 8d5daa96eeae..5e049b8f877d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4750,10 +4750,35 @@ static u32 convert_brightness_from_user(const struct amdgpu_dm_backlight_caps *c uint32_t brightness) { unsigned int min, max; + u8 prev_signal = 0, prev_lum = 0; if (!get_brightness_range(caps, &min, &max)) return brightness; + for (int i = 0; i < caps->data_points; i++) { + u8 signal, lum; + + signal = caps->luminance_data[i].input_signal; + lum = caps->luminance_data[i].luminance; + + /* + * brightness == signal: luminance is percent numerator + * brightness < signal: interpolate between previous and current luminance numerator + * brightness > signal: find next data point + */ + if (brightness < signal) + lum = prev_lum + DIV_ROUND_CLOSEST((lum - prev_lum) * + (brightness - prev_signal), + signal - prev_signal); + else if (brightness > signal) { + prev_signal = signal; + prev_lum = lum; + continue; + } + brightness = DIV_ROUND_CLOSEST(lum * brightness, 101); + break; + } + // Rescale 0..255 to min..max return min + DIV_ROUND_CLOSEST((max - min) * brightness, AMDGPU_MAX_BL_LEVEL); From 36d63ce5dbc0dc37b5af90f6b7c3b92ab26403b7 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Fri, 28 Feb 2025 12:51:45 -0600 Subject: [PATCH 189/235] drm/amd/display: Add a new dcdebugmask to allow turning off brightness curve Upgrading the kernel may cause some systems that were previously not using a firmware specified brightness curve to use one. In the event of problems with this curve (for example an interpolation error) add a new dcdebugmask value that can be used to turn it off. Also add an info message to show that custom brightness curves are currently in use. Reviewed-by: Alex Hung Link: https://lore.kernel.org/r/20250228185145.186319-6-mario.limonciello@amd.com Signed-off-by: Mario Limonciello Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 5 +++++ drivers/gpu/drm/amd/include/amd_shared.h | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 5e049b8f877d..58848d6b475a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4758,6 +4758,9 @@ static u32 convert_brightness_from_user(const struct amdgpu_dm_backlight_caps *c for (int i = 0; i < caps->data_points; i++) { u8 signal, lum; + if (amdgpu_dc_debug_mask & DC_DISABLE_CUSTOM_BRIGHTNESS_CURVE) + break; + signal = caps->luminance_data[i].input_signal; lum = caps->luminance_data[i].luminance; @@ -4942,6 +4945,8 @@ amdgpu_dm_register_backlight_device(struct amdgpu_dm_connector *aconnector) } else props.brightness = AMDGPU_MAX_BL_LEVEL; + if (caps.data_points && !(amdgpu_dc_debug_mask & DC_DISABLE_CUSTOM_BRIGHTNESS_CURVE)) + drm_info(drm, "Using custom brightness curve\n"); props.max_brightness = AMDGPU_MAX_BL_LEVEL; props.type = BACKLIGHT_RAW; diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h index c0538763ec1a..485b713cfad0 100644 --- a/drivers/gpu/drm/amd/include/amd_shared.h +++ b/drivers/gpu/drm/amd/include/amd_shared.h @@ -354,6 +354,10 @@ enum DC_DEBUG_MASK { * @DC_DISABLE_SUBVP: If set, disable DCN Sub-Viewport feature in amdgpu driver. */ DC_DISABLE_SUBVP = 0x20000, + /** + * @DC_DISABLE_CUSTOM_BRIGHTNESS_CURVE: If set, disable support for custom brightness curves + */ + DC_DISABLE_CUSTOM_BRIGHTNESS_CURVE = 0x40000, }; enum amd_dpm_forced_level; From 044e59a85c4d84e3c8d004c486e5c479640563a6 Mon Sep 17 00:00:00 2001 From: Richard Thier Date: Mon, 17 Jun 2019 23:46:27 +0200 Subject: [PATCH 190/235] drm/radeon: Fix rs400_gpu_init for ATI mobility radeon Xpress 200M MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit num_gb_pipes was set to a wrong value using r420_pipe_config This have lead to HyperZ glitches on fast Z clearing. Closes: https://bugs.freedesktop.org/show_bug.cgi?id=110897 Reviewed-by: Marek Olšák Signed-off-by: Richard Thier Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/r300.c | 3 ++- drivers/gpu/drm/radeon/radeon_asic.h | 1 + drivers/gpu/drm/radeon/rs400.c | 18 ++++++++++++++++-- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index 05c13102a8cb..d22889fbfa9c 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -359,7 +359,8 @@ int r300_mc_wait_for_idle(struct radeon_device *rdev) return -1; } -static void r300_gpu_init(struct radeon_device *rdev) +/* rs400_gpu_init also calls this! */ +void r300_gpu_init(struct radeon_device *rdev) { uint32_t gb_tile_config, tmp; diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index 1e00f6b99f94..8f5e07834fcc 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -165,6 +165,7 @@ void r200_set_safe_registers(struct radeon_device *rdev); */ extern int r300_init(struct radeon_device *rdev); extern void r300_fini(struct radeon_device *rdev); +extern void r300_gpu_init(struct radeon_device *rdev); extern int r300_suspend(struct radeon_device *rdev); extern int r300_resume(struct radeon_device *rdev); extern int r300_asic_reset(struct radeon_device *rdev, bool hard); diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c index d6c18fd740ec..13cd0a688a65 100644 --- a/drivers/gpu/drm/radeon/rs400.c +++ b/drivers/gpu/drm/radeon/rs400.c @@ -256,8 +256,22 @@ int rs400_mc_wait_for_idle(struct radeon_device *rdev) static void rs400_gpu_init(struct radeon_device *rdev) { - /* FIXME: is this correct ? */ - r420_pipes_init(rdev); + /* Earlier code was calling r420_pipes_init and then + * rs400_mc_wait_for_idle(rdev). The problem is that + * at least on my Mobility Radeon Xpress 200M RC410 card + * that ends up in this code path ends up num_gb_pipes == 3 + * while the card seems to have only one pipe. With the + * r420 pipe initialization method. + * + * Problems shown up as HyperZ glitches, see: + * https://bugs.freedesktop.org/show_bug.cgi?id=110897 + * + * Delegating initialization to r300 code seems to work + * and results in proper pipe numbers. The rs400 cards + * are said to be not r400, but r300 kind of cards. + */ + r300_gpu_init(rdev); + if (rs400_mc_wait_for_idle(rdev)) { pr_warn("rs400: Failed to wait MC idle while programming pipes. Bad things might happen. %08x\n", RREG32(RADEON_MC_STATUS)); From 8d00cfd5e6e31df21efb257a6e379c66deff76f0 Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Mon, 3 Mar 2025 14:39:17 +0000 Subject: [PATCH 191/235] drm/amdgpu: Remove ppatomfwctrl deadcode pp_atomfwctrl_get_pp_assign_pin() and pp_atomfwctrl_get_pp_assign_pin() were added in 2017 by commit 0d2c7569e196 ("drm/amdgpu: add new atomfirmware based helpers for powerplay") but have remained unused. Remove them, and the helper functions they used. Signed-off-by: Dr. David Alan Gilbert Signed-off-by: Alex Deucher --- .../drm/amd/pm/powerplay/hwmgr/ppatomfwctrl.c | 78 ------------------- .../drm/amd/pm/powerplay/hwmgr/ppatomfwctrl.h | 3 - 2 files changed, 81 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomfwctrl.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomfwctrl.c index 82d540334318..6120f14caab0 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomfwctrl.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomfwctrl.c @@ -158,84 +158,6 @@ int pp_atomfwctrl_get_voltage_table_v4(struct pp_hwmgr *hwmgr, return result; } - -static struct atom_gpio_pin_lut_v2_1 *pp_atomfwctrl_get_gpio_lookup_table( - struct pp_hwmgr *hwmgr) -{ - const void *table_address; - uint16_t idx; - - idx = GetIndexIntoMasterDataTable(gpio_pin_lut); - table_address = smu_atom_get_data_table(hwmgr->adev, - idx, NULL, NULL, NULL); - PP_ASSERT_WITH_CODE(table_address, - "Error retrieving BIOS Table Address!", - return NULL); - - return (struct atom_gpio_pin_lut_v2_1 *)table_address; -} - -static bool pp_atomfwctrl_lookup_gpio_pin( - struct atom_gpio_pin_lut_v2_1 *gpio_lookup_table, - const uint32_t pin_id, - struct pp_atomfwctrl_gpio_pin_assignment *gpio_pin_assignment) -{ - unsigned int size = le16_to_cpu( - gpio_lookup_table->table_header.structuresize); - unsigned int offset = - offsetof(struct atom_gpio_pin_lut_v2_1, gpio_pin[0]); - unsigned long start = (unsigned long)gpio_lookup_table; - - while (offset < size) { - const struct atom_gpio_pin_assignment *pin_assignment = - (const struct atom_gpio_pin_assignment *)(start + offset); - - if (pin_id == pin_assignment->gpio_id) { - gpio_pin_assignment->uc_gpio_pin_bit_shift = - pin_assignment->gpio_bitshift; - gpio_pin_assignment->us_gpio_pin_aindex = - le16_to_cpu(pin_assignment->data_a_reg_index); - return true; - } - offset += offsetof(struct atom_gpio_pin_assignment, gpio_id) + 1; - } - return false; -} - -/* - * Returns TRUE if the given pin id find in lookup table. - */ -bool pp_atomfwctrl_get_pp_assign_pin(struct pp_hwmgr *hwmgr, - const uint32_t pin_id, - struct pp_atomfwctrl_gpio_pin_assignment *gpio_pin_assignment) -{ - bool ret = false; - struct atom_gpio_pin_lut_v2_1 *gpio_lookup_table = - pp_atomfwctrl_get_gpio_lookup_table(hwmgr); - - /* If we cannot find the table do NOT try to control this voltage. */ - PP_ASSERT_WITH_CODE(gpio_lookup_table, - "Could not find GPIO lookup Table in BIOS.", - return false); - - ret = pp_atomfwctrl_lookup_gpio_pin(gpio_lookup_table, - pin_id, gpio_pin_assignment); - - return ret; -} - -/* - * Enter to SelfRefresh mode. - * @param hwmgr - */ -int pp_atomfwctrl_enter_self_refresh(struct pp_hwmgr *hwmgr) -{ - /* 0 - no action - * 1 - leave power to video memory always on - */ - return 0; -} - /** pp_atomfwctrl_get_gpu_pll_dividers_vega10(). * * @param hwmgr input parameter: pointer to HwMgr diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomfwctrl.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomfwctrl.h index e86e05c786d9..0d62903d5676 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomfwctrl.h +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomfwctrl.h @@ -217,9 +217,6 @@ struct pp_atomfwctrl_smc_dpm_parameters { int pp_atomfwctrl_get_gpu_pll_dividers_vega10(struct pp_hwmgr *hwmgr, uint32_t clock_type, uint32_t clock_value, struct pp_atomfwctrl_clock_dividers_soc15 *dividers); -int pp_atomfwctrl_enter_self_refresh(struct pp_hwmgr *hwmgr); -bool pp_atomfwctrl_get_pp_assign_pin(struct pp_hwmgr *hwmgr, const uint32_t pin_id, - struct pp_atomfwctrl_gpio_pin_assignment *gpio_pin_assignment); int pp_atomfwctrl_get_voltage_table_v4(struct pp_hwmgr *hwmgr, uint8_t voltage_type, uint8_t voltage_mode, struct pp_atomfwctrl_voltage_table *voltage_table); From 51cd1bcfac4f1f8fae45249e08929d57b1d17bc4 Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Mon, 3 Mar 2025 14:39:18 +0000 Subject: [PATCH 192/235] drm/amdgpu: Remove phm_powerdown_uvd phm_powerdown_uvd() has been unused since 2017's commit 47047263c527 ("drm/amd/powerplay: delete eventmgr related files.") Remove it. Signed-off-by: Dr. David Alan Gilbert Signed-off-by: Alex Deucher --- .../gpu/drm/amd/pm/powerplay/hwmgr/hardwaremanager.c | 10 ---------- drivers/gpu/drm/amd/pm/powerplay/inc/hardwaremanager.h | 1 - 2 files changed, 11 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hardwaremanager.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hardwaremanager.c index 90452b66e107..a59677cf8dfc 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hardwaremanager.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hardwaremanager.c @@ -149,16 +149,6 @@ int phm_apply_clock_adjust_rules(struct pp_hwmgr *hwmgr) return 0; } -int phm_powerdown_uvd(struct pp_hwmgr *hwmgr) -{ - PHM_FUNC_CHECK(hwmgr); - - if (hwmgr->hwmgr_func->powerdown_uvd != NULL) - return hwmgr->hwmgr_func->powerdown_uvd(hwmgr); - return 0; -} - - int phm_disable_clock_power_gatings(struct pp_hwmgr *hwmgr) { PHM_FUNC_CHECK(hwmgr); diff --git a/drivers/gpu/drm/amd/pm/powerplay/inc/hardwaremanager.h b/drivers/gpu/drm/amd/pm/powerplay/inc/hardwaremanager.h index f4f9a104d170..915f1b8e4dba 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/inc/hardwaremanager.h +++ b/drivers/gpu/drm/amd/pm/powerplay/inc/hardwaremanager.h @@ -396,7 +396,6 @@ struct phm_odn_clock_levels { }; extern int phm_disable_clock_power_gatings(struct pp_hwmgr *hwmgr); -extern int phm_powerdown_uvd(struct pp_hwmgr *hwmgr); extern int phm_setup_asic(struct pp_hwmgr *hwmgr); extern int phm_enable_dynamic_state_management(struct pp_hwmgr *hwmgr); extern int phm_disable_dynamic_state_management(struct pp_hwmgr *hwmgr); From 7b111aaae0ef810d26520e278bc9f7644158cb99 Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Mon, 3 Mar 2025 14:39:19 +0000 Subject: [PATCH 193/235] drm/amdgpu: Remove powerdown_uvd member With phm_powerdown_uvd() gone in the previous patch, there's now no longer anything that reads the powerdown_uvd member of the pp_hwmgr_func. Remove it. There are a few assignments to it; a boring NULL which can just go, and two functions, but those functions are called explicitly anyway so the assignments to the member go. One of those (smu7_powerdown_uvd) wasn't static previously; make it static. Signed-off-by: Dr. David Alan Gilbert Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c | 1 - drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_clockpowergating.c | 2 +- drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_clockpowergating.h | 1 - drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c | 1 - drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c | 1 - drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h | 1 - 6 files changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c index a8c732e07006..9a821563bc8e 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c @@ -1642,7 +1642,6 @@ static const struct pp_hwmgr_func smu10_hwmgr_funcs = { .apply_state_adjust_rules = smu10_apply_state_adjust_rules, .force_dpm_level = smu10_dpm_force_dpm_level, .get_power_state_size = smu10_get_power_state_size, - .powerdown_uvd = NULL, .powergate_uvd = smu10_powergate_vcn, .powergate_vce = NULL, .get_mclk = smu10_dpm_get_mclk, diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_clockpowergating.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_clockpowergating.c index f2bda3bcbbde..5e4c80f7b20a 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_clockpowergating.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_clockpowergating.c @@ -55,7 +55,7 @@ static int smu7_update_vce_dpm(struct pp_hwmgr *hwmgr, bool bgate) return smu7_enable_disable_vce_dpm(hwmgr, !bgate); } -int smu7_powerdown_uvd(struct pp_hwmgr *hwmgr) +static int smu7_powerdown_uvd(struct pp_hwmgr *hwmgr) { if (phm_cf_want_uvd_power_gating(hwmgr)) return smum_send_msg_to_smc(hwmgr, diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_clockpowergating.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_clockpowergating.h index fc8f8a6acc72..e56abbadc78b 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_clockpowergating.h +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_clockpowergating.h @@ -28,7 +28,6 @@ void smu7_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate); void smu7_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate); -int smu7_powerdown_uvd(struct pp_hwmgr *hwmgr); int smu7_powergate_acp(struct pp_hwmgr *hwmgr, bool bgate); int smu7_disable_clock_power_gating(struct pp_hwmgr *hwmgr); int smu7_update_clock_gatings(struct pp_hwmgr *hwmgr, diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c index 632a25957477..8da882c51856 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c @@ -5754,7 +5754,6 @@ static const struct pp_hwmgr_func smu7_hwmgr_funcs = { .patch_boot_state = smu7_dpm_patch_boot_state, .get_pp_table_entry = smu7_get_pp_table_entry, .get_num_of_pp_table_entries = smu7_get_number_of_powerplay_table_entries, - .powerdown_uvd = smu7_powerdown_uvd, .powergate_uvd = smu7_powergate_uvd, .powergate_vce = smu7_powergate_vce, .disable_clock_power_gating = smu7_disable_clock_power_gating, diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c index 7e1197420873..9d3b33446adc 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c @@ -2044,7 +2044,6 @@ static const struct pp_hwmgr_func smu8_hwmgr_funcs = { .apply_state_adjust_rules = smu8_apply_state_adjust_rules, .force_dpm_level = smu8_dpm_force_dpm_level, .get_power_state_size = smu8_get_power_state_size, - .powerdown_uvd = smu8_dpm_powerdown_uvd, .powergate_uvd = smu8_dpm_powergate_uvd, .powergate_vce = smu8_dpm_powergate_vce, .powergate_acp = smu8_dpm_powergate_acp, diff --git a/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h index 227bf0e84a13..c661185753b4 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h @@ -257,7 +257,6 @@ struct pp_hwmgr_func { int (*get_pp_table_entry)(struct pp_hwmgr *hwmgr, unsigned long, struct pp_power_state *); int (*get_num_of_pp_table_entries)(struct pp_hwmgr *hwmgr); - int (*powerdown_uvd)(struct pp_hwmgr *hwmgr); void (*powergate_vce)(struct pp_hwmgr *hwmgr, bool bgate); void (*powergate_uvd)(struct pp_hwmgr *hwmgr, bool bgate); void (*powergate_acp)(struct pp_hwmgr *hwmgr, bool bgate); From f281a92abe2069f75775b2e9429f15190fbdab30 Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Mon, 3 Mar 2025 14:39:20 +0000 Subject: [PATCH 194/235] drm/amdgpu: Remove unused pre_surface_trace pre_surface_trace() has been unused since 2017's commit 745cc746da42 ("drm/amd/display: remove dc_pre_update_surfaces_to_stream from dc use") Remove it. Signed-off-by: Dr. David Alan Gilbert Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_debug.c | 120 ------------------ .../amd/display/include/logger_interface.h | 5 - 2 files changed, 125 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c index af1ea5792560..650e89825968 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c @@ -51,126 +51,6 @@ DC_LOG_BANDWIDTH_CALCS(__VA_ARGS__); \ } while (0) -void pre_surface_trace( - struct dc *dc, - const struct dc_plane_state *const *plane_states, - int surface_count) -{ - int i; - DC_LOGGER_INIT(dc->ctx->logger); - - for (i = 0; i < surface_count; i++) { - const struct dc_plane_state *plane_state = plane_states[i]; - - SURFACE_TRACE("Planes %d:\n", i); - - SURFACE_TRACE( - "plane_state->visible = %d;\n" - "plane_state->flip_immediate = %d;\n" - "plane_state->address.type = %d;\n" - "plane_state->address.grph.addr.quad_part = 0x%llX;\n" - "plane_state->address.grph.meta_addr.quad_part = 0x%llX;\n" - "plane_state->scaling_quality.h_taps = %d;\n" - "plane_state->scaling_quality.v_taps = %d;\n" - "plane_state->scaling_quality.h_taps_c = %d;\n" - "plane_state->scaling_quality.v_taps_c = %d;\n", - plane_state->visible, - plane_state->flip_immediate, - plane_state->address.type, - plane_state->address.grph.addr.quad_part, - plane_state->address.grph.meta_addr.quad_part, - plane_state->scaling_quality.h_taps, - plane_state->scaling_quality.v_taps, - plane_state->scaling_quality.h_taps_c, - plane_state->scaling_quality.v_taps_c); - - SURFACE_TRACE( - "plane_state->src_rect.x = %d;\n" - "plane_state->src_rect.y = %d;\n" - "plane_state->src_rect.width = %d;\n" - "plane_state->src_rect.height = %d;\n" - "plane_state->dst_rect.x = %d;\n" - "plane_state->dst_rect.y = %d;\n" - "plane_state->dst_rect.width = %d;\n" - "plane_state->dst_rect.height = %d;\n" - "plane_state->clip_rect.x = %d;\n" - "plane_state->clip_rect.y = %d;\n" - "plane_state->clip_rect.width = %d;\n" - "plane_state->clip_rect.height = %d;\n", - plane_state->src_rect.x, - plane_state->src_rect.y, - plane_state->src_rect.width, - plane_state->src_rect.height, - plane_state->dst_rect.x, - plane_state->dst_rect.y, - plane_state->dst_rect.width, - plane_state->dst_rect.height, - plane_state->clip_rect.x, - plane_state->clip_rect.y, - plane_state->clip_rect.width, - plane_state->clip_rect.height); - - SURFACE_TRACE( - "plane_state->plane_size.surface_size.x = %d;\n" - "plane_state->plane_size.surface_size.y = %d;\n" - "plane_state->plane_size.surface_size.width = %d;\n" - "plane_state->plane_size.surface_size.height = %d;\n" - "plane_state->plane_size.surface_pitch = %d;\n", - plane_state->plane_size.surface_size.x, - plane_state->plane_size.surface_size.y, - plane_state->plane_size.surface_size.width, - plane_state->plane_size.surface_size.height, - plane_state->plane_size.surface_pitch); - - - SURFACE_TRACE( - "plane_state->tiling_info.gfx8.num_banks = %d;\n" - "plane_state->tiling_info.gfx8.bank_width = %d;\n" - "plane_state->tiling_info.gfx8.bank_width_c = %d;\n" - "plane_state->tiling_info.gfx8.bank_height = %d;\n" - "plane_state->tiling_info.gfx8.bank_height_c = %d;\n" - "plane_state->tiling_info.gfx8.tile_aspect = %d;\n" - "plane_state->tiling_info.gfx8.tile_aspect_c = %d;\n" - "plane_state->tiling_info.gfx8.tile_split = %d;\n" - "plane_state->tiling_info.gfx8.tile_split_c = %d;\n" - "plane_state->tiling_info.gfx8.tile_mode = %d;\n" - "plane_state->tiling_info.gfx8.tile_mode_c = %d;\n", - plane_state->tiling_info.gfx8.num_banks, - plane_state->tiling_info.gfx8.bank_width, - plane_state->tiling_info.gfx8.bank_width_c, - plane_state->tiling_info.gfx8.bank_height, - plane_state->tiling_info.gfx8.bank_height_c, - plane_state->tiling_info.gfx8.tile_aspect, - plane_state->tiling_info.gfx8.tile_aspect_c, - plane_state->tiling_info.gfx8.tile_split, - plane_state->tiling_info.gfx8.tile_split_c, - plane_state->tiling_info.gfx8.tile_mode, - plane_state->tiling_info.gfx8.tile_mode_c); - - SURFACE_TRACE( - "plane_state->tiling_info.gfx8.pipe_config = %d;\n" - "plane_state->tiling_info.gfx8.array_mode = %d;\n" - "plane_state->color_space = %d;\n" - "plane_state->dcc.enable = %d;\n" - "plane_state->format = %d;\n" - "plane_state->rotation = %d;\n" - "plane_state->stereo_format = %d;\n", - plane_state->tiling_info.gfx8.pipe_config, - plane_state->tiling_info.gfx8.array_mode, - plane_state->color_space, - plane_state->dcc.enable, - plane_state->format, - plane_state->rotation, - plane_state->stereo_format); - - SURFACE_TRACE("plane_state->tiling_info.gfx9.swizzle = %d;\n", - plane_state->tiling_info.gfx9.swizzle); - - SURFACE_TRACE("\n"); - } - SURFACE_TRACE("\n"); -} - void update_surface_trace( struct dc *dc, const struct dc_surface_update *updates, diff --git a/drivers/gpu/drm/amd/display/include/logger_interface.h b/drivers/gpu/drm/amd/display/include/logger_interface.h index 058f882d5bdd..4c01514b926c 100644 --- a/drivers/gpu/drm/amd/display/include/logger_interface.h +++ b/drivers/gpu/drm/amd/display/include/logger_interface.h @@ -40,11 +40,6 @@ struct dc_state; * */ -void pre_surface_trace( - struct dc *dc, - const struct dc_plane_state *const *plane_states, - int surface_count); - void update_surface_trace( struct dc *dc, const struct dc_surface_update *updates, From dcb5bb06248d2406df2bc81bf8af72e9d7cc2ea4 Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Mon, 3 Mar 2025 14:39:21 +0000 Subject: [PATCH 195/235] drm/amdgpu: Remove unused print__rq_dlg_params_st print__rq_dlg_params_st() was added in 2017 by commit 061bfa06a42a ("drm/amdgpu/display: Add dml support for DCN") but has remained unused. Remove it. Signed-off-by: Dr. David Alan Gilbert Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dml/display_rq_dlg_helpers.c | 11 ----------- .../drm/amd/display/dc/dml/display_rq_dlg_helpers.h | 1 - 2 files changed, 12 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c index 412e75eb4704..12ff65b6a7e5 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c @@ -122,17 +122,6 @@ void print__data_rq_misc_params_st(struct display_mode_lib *mode_lib, const stru dml_print("DML_RQ_DLG_CALC: =====================================\n"); } -void print__rq_dlg_params_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_rq_dlg_params_st *rq_dlg_param) -{ - dml_print("DML_RQ_DLG_CALC: =====================================\n"); - dml_print("DML_RQ_DLG_CALC: DISPLAY_RQ_DLG_PARAM_ST\n"); - dml_print("DML_RQ_DLG_CALC: \n"); - print__data_rq_dlg_params_st(mode_lib, &rq_dlg_param->rq_l); - dml_print("DML_RQ_DLG_CALC: \n"); - print__data_rq_dlg_params_st(mode_lib, &rq_dlg_param->rq_c); - dml_print("DML_RQ_DLG_CALC: =====================================\n"); -} - void print__dlg_sys_params_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_dlg_sys_params_st *dlg_sys_param) { dml_print("DML_RQ_DLG_CALC: =====================================\n"); diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.h b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.h index ebcd717744e5..2bc64c4081dc 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.h @@ -35,7 +35,6 @@ void print__rq_params_st(struct display_mode_lib *mode_lib, const struct _vcs_dp void print__data_rq_sizing_params_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_data_rq_sizing_params_st *rq_sizing); void print__data_rq_dlg_params_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_data_rq_dlg_params_st *rq_dlg_param); void print__data_rq_misc_params_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_data_rq_misc_params_st *rq_misc_param); -void print__rq_dlg_params_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_rq_dlg_params_st *rq_dlg_param); void print__dlg_sys_params_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_dlg_sys_params_st *dlg_sys_param); void print__data_rq_regs_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_data_rq_regs_st *rq_regs); From 1092a4ea1b80a234e508a43364371302b7760b97 Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Mon, 3 Mar 2025 14:39:22 +0000 Subject: [PATCH 196/235] drm/amdgpu: Remove unused pqm_get_kernel_queue pqm_get_kernel_queue() has been unused since 2022's commit 5bdd3eb25354 ("drm/amdkfd: Remove unused old debugger implementation") Remove it. Signed-off-by: Dr. David Alan Gilbert Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 2 -- .../gpu/drm/amd/amdkfd/kfd_process_queue_manager.c | 13 ------------- 2 files changed, 15 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index 59619f794b6b..966d1c484d9f 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -1364,8 +1364,6 @@ int pqm_update_mqd(struct process_queue_manager *pqm, unsigned int qid, struct mqd_update_info *minfo); int pqm_set_gws(struct process_queue_manager *pqm, unsigned int qid, void *gws); -struct kernel_queue *pqm_get_kernel_queue(struct process_queue_manager *pqm, - unsigned int qid); struct queue *pqm_get_user_queue(struct process_queue_manager *pqm, unsigned int qid); int pqm_get_wave_state(struct process_queue_manager *pqm, diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c index 662c595ce783..7eb370b68159 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c @@ -668,19 +668,6 @@ int pqm_update_mqd(struct process_queue_manager *pqm, return 0; } -struct kernel_queue *pqm_get_kernel_queue( - struct process_queue_manager *pqm, - unsigned int qid) -{ - struct process_queue_node *pqn; - - pqn = get_queue_by_qid(pqm, qid); - if (pqn && pqn->kq) - return pqn->kq; - - return NULL; -} - struct queue *pqm_get_user_queue(struct process_queue_manager *pqm, unsigned int qid) { From 8df5f03be54cd2d7b37009168080f982e9ca7574 Mon Sep 17 00:00:00 2001 From: Asad Kamal Date: Thu, 27 Feb 2025 20:09:16 +0800 Subject: [PATCH 197/235] drm/amdgpu: Set PG state to gating for vcn_v_5_0_1 For vcn_v_5_0_1, set power state to gating during hw fini. Also there may be scenario where VCN engine hangs during a job execution, then it's not safe to assume that set_pg_state works fine during hw_fini to put the state to gated. After a reset, we can assume that it's in the default state, therefore reset the driver maintained state. Put the default state as gated during reset as per this assumption. Signed-off-by: Asad Kamal Suggested-by: Lijo Lazar Reviewed-by: Lijo Lazar Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c index d29e8d685194..25f3cd7ffe84 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c @@ -227,8 +227,13 @@ static int vcn_v5_0_1_hw_fini(struct amdgpu_ip_block *ip_block) struct amdgpu_device *adev = ip_block->adev; int i; - for (i = 0; i < adev->vcn.num_vcn_inst; ++i) + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { + struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; + cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work); + if (vinst->cur_state != AMD_PG_STATE_GATE) + vinst->set_pg_state(vinst, AMD_PG_STATE_GATE); + } return 0; } @@ -271,6 +276,11 @@ static int vcn_v5_0_1_resume(struct amdgpu_ip_block *ip_block) int r, i; for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; + + if (amdgpu_in_reset(adev)) + vinst->cur_state = AMD_PG_STATE_GATE; + r = amdgpu_vcn_resume(ip_block->adev, i); if (r) return r; From fb92daa33a6b59059ab0e3ae5941866a1f64934c Mon Sep 17 00:00:00 2001 From: Asad Kamal Date: Thu, 27 Feb 2025 22:58:33 +0800 Subject: [PATCH 198/235] drm/amd/pm: Fix indentation issue Fix indentation issue for smu_v_13_0_12 get_gpu_metrics Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202502272246.OISqUnC1-lkp@intel.com Signed-off-by: Asad Kamal Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c index 5e80b9aabfc9..285dbfe10303 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c @@ -469,7 +469,7 @@ ssize_t smu_v13_0_12_get_gpu_metrics(struct smu_context *smu, void **table) SMUQ10_ROUND(metrics->GfxBusy[inst]); gpu_metrics->xcp_stats[i].gfx_busy_acc[idx] = SMUQ10_ROUND(metrics->GfxBusyAcc[inst]); - idx++; + idx++; } } From 029ab8cabd941fe0d8076ddf1e74ebfc7d3ae86c Mon Sep 17 00:00:00 2001 From: Alexandre Demers Date: Fri, 28 Feb 2025 21:17:46 -0500 Subject: [PATCH 199/235] drm/amdgpu: add some comments in DCE6 Add some comments. Signed-off-by: Alexandre Demers Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/dce_v6_0.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c index 5c3f96630c10..ba9ccfba2959 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c @@ -206,9 +206,9 @@ static void dce_v6_0_page_flip(struct amdgpu_device *adev, /* update the scanout addresses */ WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset, upper_32_bits(crtc_base)); + /* writing to the low address triggers the update */ WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset, (u32)crtc_base); - /* post the write */ RREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset); } @@ -218,11 +218,11 @@ static int dce_v6_0_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc, { if ((crtc < 0) || (crtc >= adev->mode_info.num_crtc)) return -EINVAL; + *vbl = RREG32(mmCRTC_V_BLANK_START_END + crtc_offsets[crtc]); *position = RREG32(mmCRTC_STATUS_POSITION + crtc_offsets[crtc]); return 0; - } /** @@ -1006,6 +1006,18 @@ static void dce_v6_0_program_watermarks(struct amdgpu_device *adev, } /* watermark setup */ +/** + * dce_v6_0_line_buffer_adjust - Set up the line buffer + * + * @adev: amdgpu_device pointer + * @amdgpu_crtc: the selected display controller + * @mode: the current display mode on the selected display + * controller + * + * Setup up the line buffer allocation for + * the selected display controller (CIK). + * Returns the line buffer size in pixels. + */ static u32 dce_v6_0_line_buffer_adjust(struct amdgpu_device *adev, struct amdgpu_crtc *amdgpu_crtc, struct drm_display_mode *mode, @@ -1386,6 +1398,8 @@ static int dce_v6_0_audio_init(struct amdgpu_device *adev) adev->mode_info.audio.pin[i].connected = false; adev->mode_info.audio.pin[i].offset = pin_offsets[i]; adev->mode_info.audio.pin[i].id = i; + /* disable audio. it will be set up later */ + /* XXX remove once we switch to ip funcs */ dce_v6_0_audio_enable(adev, &adev->mode_info.audio.pin[i], false); } From 5f6021d52b159f5bdb0164e0ce0c31df40d5e2a9 Mon Sep 17 00:00:00 2001 From: Alexandre Demers Date: Fri, 28 Feb 2025 21:17:47 -0500 Subject: [PATCH 200/235] drm/amdgpu: fix style in DCE6 Whitespace cleanups. Signed-off-by: Alexandre Demers Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/dce_v6_0.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c index ba9ccfba2959..e95271766e1b 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c @@ -242,7 +242,8 @@ static bool dce_v6_0_hpd_sense(struct amdgpu_device *adev, if (hpd >= adev->mode_info.num_hpd) return connected; - if (RREG32(mmDC_HPD1_INT_STATUS + hpd_offsets[hpd]) & DC_HPD1_INT_STATUS__DC_HPD1_SENSE_MASK) + if (RREG32(mmDC_HPD1_INT_STATUS + hpd_offsets[hpd]) & + DC_HPD1_INT_STATUS__DC_HPD1_SENSE_MASK) connected = true; return connected; @@ -419,7 +420,6 @@ void dce_v6_0_disable_dce(struct amdgpu_device *adev) static void dce_v6_0_program_fmt(struct drm_encoder *encoder) { - struct drm_device *dev = encoder->dev; struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); @@ -895,8 +895,8 @@ static void dce_v6_0_program_watermarks(struct amdgpu_device *adev, wm_high.dram_channels = dram_channels; wm_high.num_heads = num_heads; - if (adev->pm.dpm_enabled) { /* watermark for low clocks */ + if (adev->pm.dpm_enabled) { wm_low.yclk = amdgpu_dpm_get_mclk(adev, true) * 10; wm_low.sclk = @@ -3162,7 +3162,6 @@ static int dce_v6_0_hpd_irq(struct amdgpu_device *adev, } return 0; - } static int dce_v6_0_set_clockgating_state(struct amdgpu_ip_block *ip_block, @@ -3295,8 +3294,7 @@ static void dce_v6_0_ext_commit(struct drm_encoder *encoder) } -static void -dce_v6_0_ext_mode_set(struct drm_encoder *encoder, +static void dce_v6_0_ext_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { @@ -3308,8 +3306,7 @@ static void dce_v6_0_ext_disable(struct drm_encoder *encoder) } -static void -dce_v6_0_ext_dpms(struct drm_encoder *encoder, int mode) +static void dce_v6_0_ext_dpms(struct drm_encoder *encoder, int mode) { } @@ -3380,7 +3377,6 @@ static void dce_v6_0_encoder_add(struct amdgpu_device *adev, amdgpu_encoder->devices |= supported_device; return; } - } /* add a new one */ From ab23db6d08efdda5d13d01a66c593d0e57f8917f Mon Sep 17 00:00:00 2001 From: Alexandre Demers Date: Fri, 28 Feb 2025 23:11:20 -0500 Subject: [PATCH 201/235] drm/amdgpu: add dce_v6_0_soft_reset() to DCE6 DCE6 was missing soft reset, but it was easily identifiable under radeon. This should be it, pretty much as it is done under DCE8 and DCE10. Signed-off-by: Alexandre Demers Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/dce_v6_0.c | 53 ++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c index e95271766e1b..315c098271af 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c @@ -371,13 +371,41 @@ static u32 dce_v6_0_hpd_get_gpio_reg(struct amdgpu_device *adev) return mmDC_GPIO_HPD_A; } +static bool dce_v6_0_is_display_hung(struct amdgpu_device *adev) +{ + u32 crtc_hung = 0; + u32 crtc_status[6]; + u32 i, j, tmp; + + for (i = 0; i < adev->mode_info.num_crtc; i++) { + if (RREG32(mmCRTC_CONTROL + crtc_offsets[i]) & CRTC_CONTROL__CRTC_MASTER_EN_MASK) { + crtc_status[i] = RREG32(mmCRTC_STATUS_HV_COUNT + crtc_offsets[i]); + crtc_hung |= (1 << i); + } + } + + for (j = 0; j < 10; j++) { + for (i = 0; i < adev->mode_info.num_crtc; i++) { + if (crtc_hung & (1 << i)) { + tmp = RREG32(mmCRTC_STATUS_HV_COUNT + crtc_offsets[i]); + if (tmp != crtc_status[i]) + crtc_hung &= ~(1 << i); + } + } + if (crtc_hung == 0) + return false; + udelay(100); + } + + return true; +} + static void dce_v6_0_set_vga_render_state(struct amdgpu_device *adev, bool render) { if (!render) WREG32(mmVGA_RENDER_CONTROL, RREG32(mmVGA_RENDER_CONTROL) & VGA_VSTATUS_CNTL); - } static int dce_v6_0_get_num_crtc(struct amdgpu_device *adev) @@ -2886,7 +2914,28 @@ static bool dce_v6_0_is_idle(struct amdgpu_ip_block *ip_block) static int dce_v6_0_soft_reset(struct amdgpu_ip_block *ip_block) { - DRM_INFO("xxxx: dce_v6_0_soft_reset --- no impl!!\n"); + u32 srbm_soft_reset = 0, tmp; + struct amdgpu_device *adev = ip_block->adev; + + if (dce_v6_0_is_display_hung(adev)) + srbm_soft_reset |= SRBM_SOFT_RESET__SOFT_RESET_DC_MASK; + + if (srbm_soft_reset) { + tmp = RREG32(mmSRBM_SOFT_RESET); + tmp |= srbm_soft_reset; + dev_info(adev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp); + WREG32(mmSRBM_SOFT_RESET, tmp); + tmp = RREG32(mmSRBM_SOFT_RESET); + + udelay(50); + + tmp &= ~srbm_soft_reset; + WREG32(mmSRBM_SOFT_RESET, tmp); + tmp = RREG32(mmSRBM_SOFT_RESET); + + /* Wait a little for things to settle down */ + udelay(50); + } return 0; } From 049e5bf3c8406f87c3d8e1958e0a16804fa1d530 Mon Sep 17 00:00:00 2001 From: Andrew Martin Date: Fri, 28 Feb 2025 11:26:48 -0500 Subject: [PATCH 202/235] drm/amdkfd: Fix NULL Pointer Dereference in KFD queue Through KFD IOCTL Fuzzing we encountered a NULL pointer derefrence when calling kfd_queue_acquire_buffers. Fixes: 629568d25fea ("drm/amdkfd: Validate queue cwsr area and eop buffer size") Signed-off-by: Andrew Martin Reviewed-by: Philip Yang Signed-off-by: Andrew Martin Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_queue.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_queue.c b/drivers/gpu/drm/amd/amdkfd/kfd_queue.c index 62c635e9d1aa..4afff7094caf 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_queue.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_queue.c @@ -276,8 +276,8 @@ int kfd_queue_acquire_buffers(struct kfd_process_device *pdd, struct queue_prope /* EOP buffer is not required for all ASICs */ if (properties->eop_ring_buffer_address) { if (properties->eop_ring_buffer_size != topo_dev->node_props.eop_buffer_size) { - pr_debug("queue eop bo size 0x%lx not equal to node eop buf size 0x%x\n", - properties->eop_buf_bo->tbo.base.size, + pr_debug("queue eop bo size 0x%x not equal to node eop buf size 0x%x\n", + properties->eop_ring_buffer_size, topo_dev->node_props.eop_buffer_size); err = -EINVAL; goto out_err_unreserve; From 6e09402098b5249a0f6684db8ce45ee1fc67eee9 Mon Sep 17 00:00:00 2001 From: Lijo Lazar Date: Wed, 26 Feb 2025 12:24:05 +0530 Subject: [PATCH 203/235] drm/amdgpu: Use the right struct for VCN v5.0.1 VCN IP versions >= 5.0 uses VCN5 fw shared struct. Signed-off-by: Lijo Lazar Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c index 25f3cd7ffe84..bb2519a95312 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c @@ -153,7 +153,7 @@ static int vcn_v5_0_1_sw_fini(struct amdgpu_ip_block *ip_block) if (drm_dev_enter(adev_to_drm(adev), &idx)) { for (i = 0; i < adev->vcn.num_vcn_inst; i++) { - volatile struct amdgpu_vcn4_fw_shared *fw_shared; + volatile struct amdgpu_vcn5_fw_shared *fw_shared; fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; fw_shared->present_flag_0 = 0; @@ -351,7 +351,7 @@ static void vcn_v5_0_1_mc_resume(struct amdgpu_vcn_inst *vinst) upper_32_bits(adev->vcn.inst[inst].fw_shared.gpu_addr)); WREG32_SOC15(VCN, vcn_inst, regUVD_VCPU_NONCACHE_OFFSET0, 0); WREG32_SOC15(VCN, vcn_inst, regUVD_VCPU_NONCACHE_SIZE0, - AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn4_fw_shared))); + AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn5_fw_shared))); } /** @@ -461,7 +461,7 @@ static void vcn_v5_0_1_mc_resume_dpg_mode(struct amdgpu_vcn_inst *vinst, VCN, 0, regUVD_VCPU_NONCACHE_OFFSET0), 0, 0, indirect); WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET( VCN, 0, regUVD_VCPU_NONCACHE_SIZE0), - AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn4_fw_shared)), 0, indirect); + AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn5_fw_shared)), 0, indirect); /* VCN global tiling registers */ WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET( @@ -503,7 +503,7 @@ static int vcn_v5_0_1_start_dpg_mode(struct amdgpu_vcn_inst *vinst, { struct amdgpu_device *adev = vinst->adev; int inst_idx = vinst->inst; - volatile struct amdgpu_vcn4_fw_shared *fw_shared = + volatile struct amdgpu_vcn5_fw_shared *fw_shared = adev->vcn.inst[inst_idx].fw_shared.cpu_addr; struct amdgpu_ring *ring; int vcn_inst; @@ -612,7 +612,7 @@ static int vcn_v5_0_1_start(struct amdgpu_vcn_inst *vinst) { struct amdgpu_device *adev = vinst->adev; int i = vinst->inst; - volatile struct amdgpu_vcn4_fw_shared *fw_shared; + volatile struct amdgpu_vcn5_fw_shared *fw_shared; struct amdgpu_ring *ring; uint32_t tmp; int j, k, r, vcn_inst; @@ -790,7 +790,7 @@ static int vcn_v5_0_1_stop(struct amdgpu_vcn_inst *vinst) { struct amdgpu_device *adev = vinst->adev; int i = vinst->inst; - volatile struct amdgpu_vcn4_fw_shared *fw_shared; + volatile struct amdgpu_vcn5_fw_shared *fw_shared; uint32_t tmp; int r = 0, vcn_inst; From 6ef5ccaad76d907d4257f20de992f89c0f7a7f8e Mon Sep 17 00:00:00 2001 From: Lijo Lazar Date: Wed, 26 Feb 2025 12:53:48 +0530 Subject: [PATCH 204/235] drm/amdgpu: Reinit FW shared flags on VCN v5.0.1 After a full device reset, shared memory region will clear out and it's not possible to reliably save the region in case of RAS errors. Reinitialize the flags if required. Signed-off-by: Lijo Lazar Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c | 28 ++++++++++++++++++------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c index bb2519a95312..581d8629b9d9 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c @@ -76,6 +76,22 @@ static int vcn_v5_0_1_early_init(struct amdgpu_ip_block *ip_block) return 0; } +static void vcn_v5_0_1_fw_shared_init(struct amdgpu_device *adev, int inst_idx) +{ + struct amdgpu_vcn5_fw_shared *fw_shared; + + fw_shared = adev->vcn.inst[inst_idx].fw_shared.cpu_addr; + + if (fw_shared->sq.is_enabled) + return; + fw_shared->present_flag_0 = + cpu_to_le32(AMDGPU_FW_SHARED_FLAG_0_UNIFIED_QUEUE); + fw_shared->sq.is_enabled = 1; + + if (amdgpu_vcnfw_log) + amdgpu_vcn_fwlog_init(&adev->vcn.inst[inst_idx]); +} + /** * vcn_v5_0_1_sw_init - sw init for VCN block * @@ -96,8 +112,6 @@ static int vcn_v5_0_1_sw_init(struct amdgpu_ip_block *ip_block) return r; for (i = 0; i < adev->vcn.num_vcn_inst; i++) { - volatile struct amdgpu_vcn5_fw_shared *fw_shared; - vcn_inst = GET_INST(VCN, i); r = amdgpu_vcn_sw_init(adev, i); @@ -122,12 +136,7 @@ static int vcn_v5_0_1_sw_init(struct amdgpu_ip_block *ip_block) if (r) return r; - fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; - fw_shared->present_flag_0 = cpu_to_le32(AMDGPU_FW_SHARED_FLAG_0_UNIFIED_QUEUE); - fw_shared->sq.is_enabled = true; - - if (amdgpu_vcnfw_log) - amdgpu_vcn_fwlog_init(&adev->vcn.inst[i]); + vcn_v5_0_1_fw_shared_init(adev, i); } /* TODO: Add queue reset mask when FW fully supports it */ @@ -207,6 +216,9 @@ static int vcn_v5_0_1_hw_init(struct amdgpu_ip_block *ip_block) 9 * vcn_inst), adev->vcn.inst[i].aid_id); + /* Re-init fw_shared, if required */ + vcn_v5_0_1_fw_shared_init(adev, i); + r = amdgpu_ring_test_helper(ring); if (r) return r; From a3199eba46c54324193607d9114a1e321292d7a1 Mon Sep 17 00:00:00 2001 From: Kenneth Feng Date: Fri, 28 Feb 2025 17:02:11 +0800 Subject: [PATCH 205/235] drm/amd/pm: always allow ih interrupt from fw always allow ih interrupt from fw on smu v14 based on the interface requirement Signed-off-by: Kenneth Feng Reviewed-by: Yang Wang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c index 14a5760082b8..76c1adda83db 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c @@ -1949,16 +1949,6 @@ static int smu_v14_0_allow_ih_interrupt(struct smu_context *smu) NULL); } -static int smu_v14_0_process_pending_interrupt(struct smu_context *smu) -{ - int ret = 0; - - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_ACDC_BIT)) - ret = smu_v14_0_allow_ih_interrupt(smu); - - return ret; -} - int smu_v14_0_enable_thermal_alert(struct smu_context *smu) { int ret = 0; @@ -1970,7 +1960,7 @@ int smu_v14_0_enable_thermal_alert(struct smu_context *smu) if (ret) return ret; - return smu_v14_0_process_pending_interrupt(smu); + return smu_v14_0_allow_ih_interrupt(smu); } int smu_v14_0_disable_thermal_alert(struct smu_context *smu) From d4c60219ac10242a1d5a621e7ba673d6128b7e13 Mon Sep 17 00:00:00 2001 From: Tony Yi Date: Wed, 26 Feb 2025 16:56:02 -0500 Subject: [PATCH 206/235] drm/amdgpu: Update headers for CPER support on SRIOV Update amdgv_sriovmsg.h and mxgpu_nv.h to add new definitions for CPER support on VFs. PMFW ACA messages are not available on VFs, and VFs must query CPERs from host. Signed-off-by: Tony Yi Reviewed-by: Tao Zhou Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h | 40 ++++++++++++++------- drivers/gpu/drm/amd/amdgpu/mxgpu_nv.h | 2 ++ 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h b/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h index b4f9c2f4e92c..d6ac2652f0ac 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h @@ -97,11 +97,12 @@ union amd_sriov_msg_feature_flags { uint32_t pp_one_vf_mode : 1; uint32_t reg_indirect_acc : 1; uint32_t av1_support : 1; - uint32_t vcn_rb_decouple : 1; + uint32_t vcn_rb_decouple : 1; uint32_t mes_info_dump_enable : 1; uint32_t ras_caps : 1; uint32_t ras_telemetry : 1; - uint32_t reserved : 21; + uint32_t ras_cper : 1; + uint32_t reserved : 20; } flags; uint32_t all; }; @@ -328,21 +329,25 @@ enum amd_sriov_mailbox_request_message { MB_REQ_MSG_READY_TO_RESET = 201, MB_REQ_MSG_RAS_POISON = 202, MB_REQ_RAS_ERROR_COUNT = 203, + MB_REQ_RAS_CPER_DUMP = 204, }; /* mailbox message send from host to guest */ enum amd_sriov_mailbox_response_message { - MB_RES_MSG_CLR_MSG_BUF = 0, - MB_RES_MSG_READY_TO_ACCESS_GPU = 1, - MB_RES_MSG_FLR_NOTIFICATION, - MB_RES_MSG_FLR_NOTIFICATION_COMPLETION, - MB_RES_MSG_SUCCESS, - MB_RES_MSG_FAIL, - MB_RES_MSG_QUERY_ALIVE, - MB_RES_MSG_GPU_INIT_DATA_READY, - MB_RES_MSG_RAS_ERROR_COUNT_READY = 11, - - MB_RES_MSG_TEXT_MESSAGE = 255 + MB_RES_MSG_CLR_MSG_BUF = 0, + MB_RES_MSG_READY_TO_ACCESS_GPU = 1, + MB_RES_MSG_FLR_NOTIFICATION = 2, + MB_RES_MSG_FLR_NOTIFICATION_COMPLETION = 3, + MB_RES_MSG_SUCCESS = 4, + MB_RES_MSG_FAIL = 5, + MB_RES_MSG_QUERY_ALIVE = 6, + MB_RES_MSG_GPU_INIT_DATA_READY = 7, + MB_RES_MSG_RAS_POISON_READY = 8, + MB_RES_MSG_PF_SOFT_FLR_NOTIFICATION = 9, + MB_RES_MSG_GPU_RMA = 10, + MB_RES_MSG_RAS_ERROR_COUNT_READY = 11, + MB_REQ_RAS_CPER_DUMP_READY = 14, + MB_RES_MSG_TEXT_MESSAGE = 255 }; enum amd_sriov_ras_telemetry_gpu_block { @@ -386,11 +391,20 @@ struct amd_sriov_ras_telemetry_error_count { } block[RAS_TELEMETRY_GPU_BLOCK_COUNT]; }; +struct amd_sriov_ras_cper_dump { + uint32_t more; + uint64_t overflow_count; + uint64_t count; + uint64_t wptr; + uint32_t buf[]; +}; + struct amdsriov_ras_telemetry { struct amd_sriov_ras_telemetry_header header; union { struct amd_sriov_ras_telemetry_error_count error_count; + struct amd_sriov_ras_cper_dump cper_dump; } body; }; diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.h b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.h index 9d61d76e1bf9..72c9fceb9d79 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.h +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.h @@ -41,6 +41,7 @@ enum idh_request { IDH_READY_TO_RESET = 201, IDH_RAS_POISON = 202, IDH_REQ_RAS_ERROR_COUNT = 203, + IDH_REQ_RAS_CPER_DUMP = 204, }; enum idh_event { @@ -56,6 +57,7 @@ enum idh_event { IDH_PF_SOFT_FLR_NOTIFICATION, IDH_RAS_ERROR_DETECTED, IDH_RAS_ERROR_COUNT_READY = 11, + IDH_RAS_CPER_DUMP_READY = 14, IDH_TEXT_MESSAGE = 255, }; From 41b830476009f50233e8df538113765c0a59308d Mon Sep 17 00:00:00 2001 From: Aurabindo Pillai Date: Mon, 24 Feb 2025 14:24:45 -0500 Subject: [PATCH 207/235] drm/amd/display: Add workaround for a panel Implement w/a for a panel which requires 10s delay after link detect. Signed-off-by: Aurabindo Pillai Reviewed-by: Alex Hung Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 27 ++++++++++++++++++- .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 10 +++++-- drivers/gpu/drm/amd/display/dc/dc_types.h | 1 + 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 58848d6b475a..7faf0d0cc23c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3330,6 +3330,24 @@ static void dm_gpureset_commit_state(struct dc_state *dc_state, } } +static void apply_delay_after_dpcd_poweroff(struct amdgpu_device *adev, + struct dc_sink *sink) +{ + struct dc_panel_patch *ppatch = NULL; + + if (!sink) + return; + + ppatch = &sink->edid_caps.panel_patch; + if (ppatch->wait_after_dpcd_poweroff_ms) { + msleep(ppatch->wait_after_dpcd_poweroff_ms); + drm_dbg_driver(adev_to_drm(adev), + "%s: adding a %ds delay as w/a for panel\n", + __func__, + ppatch->wait_after_dpcd_poweroff_ms / 1000); + } +} + static int dm_resume(struct amdgpu_ip_block *ip_block) { struct amdgpu_device *adev = ip_block->adev; @@ -3451,6 +3469,7 @@ static int dm_resume(struct amdgpu_ip_block *ip_block) /* Do detection*/ drm_connector_list_iter_begin(ddev, &iter); drm_for_each_connector_iter(connector, &iter) { + bool ret; if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK) continue; @@ -3476,7 +3495,11 @@ static int dm_resume(struct amdgpu_ip_block *ip_block) } else { guard(mutex)(&dm->dc_lock); dc_exit_ips_for_hw_access(dm->dc); - dc_link_detect(aconnector->dc_link, DETECT_REASON_RESUMEFROMS3S4); + ret = dc_link_detect(aconnector->dc_link, DETECT_REASON_RESUMEFROMS3S4); + if (ret) { + /* w/a delay for certain panels */ + apply_delay_after_dpcd_poweroff(adev, aconnector->dc_sink); + } } if (aconnector->fake_enable && aconnector->dc_link->local_sink) @@ -3842,6 +3865,8 @@ static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector) ret = dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD); } if (ret) { + /* w/a delay for certain panels */ + apply_delay_after_dpcd_poweroff(adev, aconnector->dc_sink); amdgpu_dm_update_connector_after_detect(aconnector); drm_modeset_lock_all(dev); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index fbd80d8545a8..253aac93e3d8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -55,11 +55,16 @@ static u32 edid_extract_panel_id(struct edid *edid) (u32)EDID_PRODUCT_ID(edid); } -static void apply_edid_quirks(struct edid *edid, struct dc_edid_caps *edid_caps) +static void apply_edid_quirks(struct drm_device *dev, struct edid *edid, struct dc_edid_caps *edid_caps) { uint32_t panel_id = edid_extract_panel_id(edid); switch (panel_id) { + /* Workaround for monitors that need a delay after detecting the link */ + case drm_edid_encode_panel_id('G', 'B', 'T', 0x3215): + drm_dbg_driver(dev, "Add 10s delay for link detection for panel id %X\n", panel_id); + edid_caps->panel_patch.wait_after_dpcd_poweroff_ms = 10000; + break; /* Workaround for some monitors which does not work well with FAMS */ case drm_edid_encode_panel_id('S', 'A', 'M', 0x0E5E): case drm_edid_encode_panel_id('S', 'A', 'M', 0x7053): @@ -101,6 +106,7 @@ enum dc_edid_status dm_helpers_parse_edid_caps( { struct amdgpu_dm_connector *aconnector = link->priv; struct drm_connector *connector = &aconnector->base; + struct drm_device *dev = connector->dev; struct edid *edid_buf = edid ? (struct edid *) edid->raw_edid : NULL; struct cea_sad *sads; int sad_count = -1; @@ -130,7 +136,7 @@ enum dc_edid_status dm_helpers_parse_edid_caps( edid_caps->edid_hdmi = connector->display_info.is_hdmi; - apply_edid_quirks(edid_buf, edid_caps); + apply_edid_quirks(dev, edid_buf, edid_caps); sad_count = drm_edid_to_sad((struct edid *) edid->raw_edid, &sads); if (sad_count <= 0) diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index e60898c2df01..acd3b373a18e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -181,6 +181,7 @@ struct dc_panel_patch { uint8_t blankstream_before_otg_off; bool oled_optimize_display_on; unsigned int force_mst_blocked_discovery; + unsigned int wait_after_dpcd_poweroff_ms; }; struct dc_edid_caps { From a89b530373b720a94aa97ec3c4ea79dd6ee59fa7 Mon Sep 17 00:00:00 2001 From: Aurabindo Pillai Date: Mon, 24 Feb 2025 14:27:54 -0500 Subject: [PATCH 208/235] drm/amd/display: use drm_* instead of DRM_ in apply_edid_quirks() drm_* macros are more helpful that DRM_* macros since the former indicates the associated DRM device that prints the error, which maybe helpful when debugging. Signed-off-by: Aurabindo Pillai Reviewed-by: Alex Hung Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index 253aac93e3d8..2cd35392e2da 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -69,7 +69,7 @@ static void apply_edid_quirks(struct drm_device *dev, struct edid *edid, struct case drm_edid_encode_panel_id('S', 'A', 'M', 0x0E5E): case drm_edid_encode_panel_id('S', 'A', 'M', 0x7053): case drm_edid_encode_panel_id('S', 'A', 'M', 0x71AC): - DRM_DEBUG_DRIVER("Disabling FAMS on monitor with panel id %X\n", panel_id); + drm_dbg_driver(dev, "Disabling FAMS on monitor with panel id %X\n", panel_id); edid_caps->panel_patch.disable_fams = true; break; /* Workaround for some monitors that do not clear DPCD 0x317 if FreeSync is unsupported */ @@ -78,11 +78,11 @@ static void apply_edid_quirks(struct drm_device *dev, struct edid *edid, struct case drm_edid_encode_panel_id('B', 'O', 'E', 0x092A): case drm_edid_encode_panel_id('L', 'G', 'D', 0x06D1): case drm_edid_encode_panel_id('M', 'S', 'F', 0x1003): - DRM_DEBUG_DRIVER("Clearing DPCD 0x317 on monitor with panel id %X\n", panel_id); + drm_dbg_driver(dev, "Clearing DPCD 0x317 on monitor with panel id %X\n", panel_id); edid_caps->panel_patch.remove_sink_ext_caps = true; break; case drm_edid_encode_panel_id('S', 'D', 'C', 0x4154): - DRM_DEBUG_DRIVER("Disabling VSC on monitor with panel id %X\n", panel_id); + drm_dbg_driver(dev, "Disabling VSC on monitor with panel id %X\n", panel_id); edid_caps->panel_patch.disable_colorimetry = true; break; default: From ca17c8e149112270b598791bbd98968fe9231115 Mon Sep 17 00:00:00 2001 From: James Zhu Date: Mon, 3 Mar 2025 13:10:33 -0500 Subject: [PATCH 209/235] drm/amdkfd: remove unnecessary cpu domain validation before move to GTT domain. Signed-off-by: James Zhu Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index 62ca12e94581..2ac6d4fa0601 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -595,12 +595,6 @@ kfd_mem_dmamap_dmabuf(struct kfd_mem_attachment *attachment) { struct ttm_operation_ctx ctx = {.interruptible = true}; struct amdgpu_bo *bo = attachment->bo_va->base.bo; - int ret; - - amdgpu_bo_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_CPU); - ret = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx); - if (ret) - return ret; amdgpu_bo_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_GTT); return ttm_bo_validate(&bo->tbo, &bo->placement, &ctx); From a91d91b6004796b868374394962331a1322da7ab Mon Sep 17 00:00:00 2001 From: Tony Yi Date: Wed, 26 Feb 2025 17:03:10 -0500 Subject: [PATCH 210/235] drm/amdgpu: Add support for CPERs on virtualization Add support for CPERs on VFs. VFs do not receive PMFW messages directly; as such, they need to query them from the host. To avoid hitting host event guard, CPER queries need to be rate limited. CPER queries share the same RAS telemetry buffer as error count query, so a mutex protecting the shared buffer was added as well. For readability, the amdgpu_detect_virtualization was refactored into multiple individual functions. Signed-off-by: Tony Yi Reviewed-by: Tao Zhou Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 7 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 31 ++++- drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 138 ++++++++++++++++++++- drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h | 18 ++- drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c | 14 +++ 5 files changed, 195 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 7b60646c6ad2..a755cc545c91 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -3099,7 +3099,8 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev) amdgpu_fru_get_product_info(adev); - r = amdgpu_cper_init(adev); + if (!amdgpu_sriov_vf(adev) || amdgpu_sriov_ras_cper_en(adev)) + r = amdgpu_cper_init(adev); init_failed: @@ -4333,10 +4334,8 @@ int amdgpu_device_init(struct amdgpu_device *adev, * for throttling interrupt) = 60 seconds. */ ratelimit_state_init(&adev->throttling_logging_rs, (60 - 1) * HZ, 1); - ratelimit_state_init(&adev->virt.ras_telemetry_rs, 5 * HZ, 1); ratelimit_set_flags(&adev->throttling_logging_rs, RATELIMIT_MSG_ON_RELEASE); - ratelimit_set_flags(&adev->virt.ras_telemetry_rs, RATELIMIT_MSG_ON_RELEASE); /* Registers mapping */ /* TODO: block userspace mapping of io register */ @@ -4368,7 +4367,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, return -ENOMEM; /* detect hw virtualization here */ - amdgpu_detect_virtualization(adev); + amdgpu_virt_init(adev); amdgpu_device_get_pcie_info(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c index 81a7d4faac9c..d55c8b7fdb59 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c @@ -578,12 +578,32 @@ static ssize_t amdgpu_debugfs_ring_read(struct file *f, char __user *buf, return result; } +static ssize_t amdgpu_debugfs_virt_ring_read(struct file *f, char __user *buf, + size_t size, loff_t *pos) +{ + struct amdgpu_ring *ring = file_inode(f)->i_private; + + if (*pos & 3 || size & 3) + return -EINVAL; + + if (ring->funcs->type == AMDGPU_RING_TYPE_CPER) + amdgpu_virt_req_ras_cper_dump(ring->adev, false); + + return amdgpu_debugfs_ring_read(f, buf, size, pos); +} + static const struct file_operations amdgpu_debugfs_ring_fops = { .owner = THIS_MODULE, .read = amdgpu_debugfs_ring_read, .llseek = default_llseek }; +static const struct file_operations amdgpu_debugfs_virt_ring_fops = { + .owner = THIS_MODULE, + .read = amdgpu_debugfs_virt_ring_read, + .llseek = default_llseek +}; + static ssize_t amdgpu_debugfs_mqd_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { @@ -671,9 +691,14 @@ void amdgpu_debugfs_ring_init(struct amdgpu_device *adev, char name[32]; sprintf(name, "amdgpu_ring_%s", ring->name); - debugfs_create_file_size(name, S_IFREG | 0444, root, ring, - &amdgpu_debugfs_ring_fops, - ring->ring_size + 12); + if (amdgpu_sriov_vf(adev)) + debugfs_create_file_size(name, S_IFREG | 0444, root, ring, + &amdgpu_debugfs_virt_ring_fops, + ring->ring_size + 12); + else + debugfs_create_file_size(name, S_IFREG | 0444, root, ring, + &amdgpu_debugfs_ring_fops, + ring->ring_size + 12); if (ring->mqd_obj) { sprintf(name, "amdgpu_mqd_%s", ring->name); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c index e6f0152e5b08..ab7e73d0e7b1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c @@ -739,7 +739,7 @@ void amdgpu_virt_exchange_data(struct amdgpu_device *adev) } } -void amdgpu_detect_virtualization(struct amdgpu_device *adev) +static u32 amdgpu_virt_init_detect_asic(struct amdgpu_device *adev) { uint32_t reg; @@ -775,8 +775,17 @@ void amdgpu_detect_virtualization(struct amdgpu_device *adev) adev->virt.caps |= AMDGPU_PASSTHROUGH_MODE; } + return reg; +} + +static bool amdgpu_virt_init_req_data(struct amdgpu_device *adev, u32 reg) +{ + bool is_sriov = false; + /* we have the ability to check now */ if (amdgpu_sriov_vf(adev)) { + is_sriov = true; + switch (adev->asic_type) { case CHIP_TONGA: case CHIP_FIJI: @@ -805,10 +814,39 @@ void amdgpu_detect_virtualization(struct amdgpu_device *adev) amdgpu_virt_request_init_data(adev); break; default: /* other chip doesn't support SRIOV */ + is_sriov = false; DRM_ERROR("Unknown asic type: %d!\n", adev->asic_type); break; } } + + return is_sriov; +} + +static void amdgpu_virt_init_ras(struct amdgpu_device *adev) +{ + ratelimit_state_init(&adev->virt.ras.ras_error_cnt_rs, 5 * HZ, 1); + ratelimit_state_init(&adev->virt.ras.ras_cper_dump_rs, 5 * HZ, 1); + + ratelimit_set_flags(&adev->virt.ras.ras_error_cnt_rs, + RATELIMIT_MSG_ON_RELEASE); + ratelimit_set_flags(&adev->virt.ras.ras_cper_dump_rs, + RATELIMIT_MSG_ON_RELEASE); + + mutex_init(&adev->virt.ras.ras_telemetry_mutex); + + adev->virt.ras.cper_rptr = 0; +} + +void amdgpu_virt_init(struct amdgpu_device *adev) +{ + bool is_sriov = false; + uint32_t reg = amdgpu_virt_init_detect_asic(adev); + + is_sriov = amdgpu_virt_init_req_data(adev, reg); + + if (is_sriov) + amdgpu_virt_init_ras(adev); } static bool amdgpu_virt_access_debugfs_is_mmio(struct amdgpu_device *adev) @@ -1288,10 +1326,12 @@ static int amdgpu_virt_req_ras_err_count_internal(struct amdgpu_device *adev, bo * will ignore incoming guest messages. Ratelimit the guest messages to * prevent guest self DOS. */ - if (__ratelimit(&adev->virt.ras_telemetry_rs) || force_update) { + if (__ratelimit(&virt->ras.ras_error_cnt_rs) || force_update) { + mutex_lock(&virt->ras.ras_telemetry_mutex); if (!virt->ops->req_ras_err_count(adev)) amdgpu_virt_cache_host_error_counts(adev, - adev->virt.fw_reserve.ras_telemetry); + virt->fw_reserve.ras_telemetry); + mutex_unlock(&virt->ras.ras_telemetry_mutex); } return 0; @@ -1322,6 +1362,98 @@ int amdgpu_virt_req_ras_err_count(struct amdgpu_device *adev, enum amdgpu_ras_bl return 0; } +static int +amdgpu_virt_write_cpers_to_ring(struct amdgpu_device *adev, + struct amdsriov_ras_telemetry *host_telemetry, + u32 *more) +{ + struct amd_sriov_ras_cper_dump *cper_dump = NULL; + struct cper_hdr *entry = NULL; + struct amdgpu_ring *ring = &adev->cper.ring_buf; + uint32_t checksum, used_size, i; + int ret = 0; + + checksum = host_telemetry->header.checksum; + used_size = host_telemetry->header.used_size; + + if (used_size > (AMD_SRIOV_RAS_TELEMETRY_SIZE_KB << 10)) + return 0; + + cper_dump = kmemdup(&host_telemetry->body.cper_dump, used_size, GFP_KERNEL); + if (!cper_dump) + return -ENOMEM; + + if (checksum != amd_sriov_msg_checksum(cper_dump, used_size, 0, 0)) + goto out; + + *more = cper_dump->more; + + if (cper_dump->wptr < adev->virt.ras.cper_rptr) { + dev_warn( + adev->dev, + "guest specified rptr that was too high! guest rptr: 0x%llx, host rptr: 0x%llx\n", + adev->virt.ras.cper_rptr, cper_dump->wptr); + + adev->virt.ras.cper_rptr = cper_dump->wptr; + goto out; + } + + entry = (struct cper_hdr *)&cper_dump->buf[0]; + + for (i = 0; i < cper_dump->count; i++) { + amdgpu_cper_ring_write(ring, entry, entry->record_length); + entry = (struct cper_hdr *)((char *)entry + + entry->record_length); + } + + if (cper_dump->overflow_count) + dev_warn(adev->dev, + "host reported CPER overflow of 0x%llx entries!\n", + cper_dump->overflow_count); + + adev->virt.ras.cper_rptr = cper_dump->wptr; +out: + kfree(cper_dump); + + return ret; +} + +static int amdgpu_virt_req_ras_cper_dump_internal(struct amdgpu_device *adev) +{ + struct amdgpu_virt *virt = &adev->virt; + int ret = 0; + uint32_t more = 0; + + if (!amdgpu_sriov_ras_cper_en(adev)) + return -EOPNOTSUPP; + + do { + if (!virt->ops->req_ras_cper_dump(adev, virt->ras.cper_rptr)) + ret = amdgpu_virt_write_cpers_to_ring( + adev, virt->fw_reserve.ras_telemetry, &more); + else + ret = 0; + } while (more); + + return ret; +} + +int amdgpu_virt_req_ras_cper_dump(struct amdgpu_device *adev, bool force_update) +{ + struct amdgpu_virt *virt = &adev->virt; + int ret = 0; + + if ((__ratelimit(&virt->ras.ras_cper_dump_rs) || force_update) && + down_read_trylock(&adev->reset_domain->sem)) { + mutex_lock(&virt->ras.ras_telemetry_mutex); + ret = amdgpu_virt_req_ras_cper_dump_internal(adev); + mutex_unlock(&virt->ras.ras_telemetry_mutex); + up_read(&adev->reset_domain->sem); + } + + return ret; +} + int amdgpu_virt_ras_telemetry_post_reset(struct amdgpu_device *adev) { unsigned long ue_count, ce_count; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h index 0f3ccae5c1ab..9f65487e60f5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h @@ -96,6 +96,7 @@ struct amdgpu_virt_ops { enum amdgpu_ras_block block); bool (*rcvd_ras_intr)(struct amdgpu_device *adev); int (*req_ras_err_count)(struct amdgpu_device *adev); + int (*req_ras_cper_dump)(struct amdgpu_device *adev, u64 vf_rptr); }; /* @@ -140,6 +141,7 @@ enum AMDGIM_FEATURE_FLAG { AMDGIM_FEATURE_MES_INFO_ENABLE = (1 << 8), AMDGIM_FEATURE_RAS_CAPS = (1 << 9), AMDGIM_FEATURE_RAS_TELEMETRY = (1 << 10), + AMDGIM_FEATURE_RAS_CPER = (1 << 11), }; enum AMDGIM_REG_ACCESS_FLAG { @@ -242,6 +244,13 @@ struct amdgpu_virt_ras_err_handler_data { int last_reserved; }; +struct amdgpu_virt_ras { + struct ratelimit_state ras_error_cnt_rs; + struct ratelimit_state ras_cper_dump_rs; + struct mutex ras_telemetry_mutex; + uint64_t cper_rptr; +}; + /* GPU virtualization */ struct amdgpu_virt { uint32_t caps; @@ -284,8 +293,7 @@ struct amdgpu_virt { union amd_sriov_ras_caps ras_en_caps; union amd_sriov_ras_caps ras_telemetry_en_caps; - - struct ratelimit_state ras_telemetry_rs; + struct amdgpu_virt_ras ras; struct amd_sriov_ras_telemetry_error_count count_cache; }; @@ -340,6 +348,9 @@ struct amdgpu_video_codec_info; #define amdgpu_sriov_ras_telemetry_block_en(adev, sriov_blk) \ (amdgpu_sriov_ras_telemetry_en((adev)) && (adev)->virt.ras_telemetry_en_caps.all & BIT(sriov_blk)) +#define amdgpu_sriov_ras_cper_en(adev) \ +((adev)->virt.gim_feature & AMDGIM_FEATURE_RAS_CPER) + static inline bool is_virtual_machine(void) { #if defined(CONFIG_X86) @@ -378,7 +389,7 @@ void amdgpu_virt_release_ras_err_handler_data(struct amdgpu_device *adev); void amdgpu_virt_init_data_exchange(struct amdgpu_device *adev); void amdgpu_virt_exchange_data(struct amdgpu_device *adev); void amdgpu_virt_fini_data_exchange(struct amdgpu_device *adev); -void amdgpu_detect_virtualization(struct amdgpu_device *adev); +void amdgpu_virt_init(struct amdgpu_device *adev); bool amdgpu_virt_can_access_debugfs(struct amdgpu_device *adev); int amdgpu_virt_enable_access_debugfs(struct amdgpu_device *adev); @@ -406,6 +417,7 @@ u32 amdgpu_virt_rlcg_reg_rw(struct amdgpu_device *adev, u32 offset, u32 v, u32 f bool amdgpu_virt_get_ras_capability(struct amdgpu_device *adev); int amdgpu_virt_req_ras_err_count(struct amdgpu_device *adev, enum amdgpu_ras_block block, struct ras_err_data *err_data); +int amdgpu_virt_req_ras_cper_dump(struct amdgpu_device *adev, bool force_update); int amdgpu_virt_ras_telemetry_post_reset(struct amdgpu_device *adev); bool amdgpu_virt_ras_telemetry_block_en(struct amdgpu_device *adev, enum amdgpu_ras_block block); diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c index 4dcb72d1bdda..5aadf24cb202 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c @@ -184,6 +184,9 @@ static int xgpu_nv_send_access_requests_with_param(struct amdgpu_device *adev, case IDH_REQ_RAS_ERROR_COUNT: event = IDH_RAS_ERROR_COUNT_READY; break; + case IDH_REQ_RAS_CPER_DUMP: + event = IDH_RAS_CPER_DUMP_READY; + break; default: break; } @@ -467,6 +470,16 @@ static int xgpu_nv_req_ras_err_count(struct amdgpu_device *adev) return xgpu_nv_send_access_requests(adev, IDH_REQ_RAS_ERROR_COUNT); } +static int xgpu_nv_req_ras_cper_dump(struct amdgpu_device *adev, u64 vf_rptr) +{ + uint32_t vf_rptr_hi, vf_rptr_lo; + + vf_rptr_hi = (uint32_t)(vf_rptr >> 32); + vf_rptr_lo = (uint32_t)(vf_rptr & 0xFFFFFFFF); + return xgpu_nv_send_access_requests_with_param( + adev, IDH_REQ_RAS_CPER_DUMP, vf_rptr_hi, vf_rptr_lo, 0); +} + const struct amdgpu_virt_ops xgpu_nv_virt_ops = { .req_full_gpu = xgpu_nv_request_full_gpu_access, .rel_full_gpu = xgpu_nv_release_full_gpu_access, @@ -478,4 +491,5 @@ const struct amdgpu_virt_ops xgpu_nv_virt_ops = { .ras_poison_handler = xgpu_nv_ras_poison_handler, .rcvd_ras_intr = xgpu_nv_rcvd_ras_intr, .req_ras_err_count = xgpu_nv_req_ras_err_count, + .req_ras_cper_dump = xgpu_nv_req_ras_cper_dump, }; From 20c34e5c4af0b4a0972ae8b237c3a3866f45b082 Mon Sep 17 00:00:00 2001 From: Sathishkumar S Date: Wed, 26 Feb 2025 15:48:39 +0530 Subject: [PATCH 211/235] drm/amdgpu: Fix core reset sequence for JPEG4_0_3 For cores 1 through 7 repair the core reset sequence by adjusting offsets to access the expected registers. Signed-off-by: Sathishkumar S Reviewed-by: Leo Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c index de46dbf86477..5598a35f72af 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c @@ -1104,24 +1104,20 @@ static void jpeg_v4_0_3_core_stall_reset(struct amdgpu_ring *ring) WREG32_SOC15_OFFSET(JPEG, jpeg_inst, regUVD_JMI0_UVD_JMI_CLIENT_STALL, reg_offset, 0x1F); - SOC15_WAIT_ON_RREG(JPEG, jpeg_inst, - regUVD_JMI0_UVD_JMI_CLIENT_CLEAN_STATUS, - 0x1F, 0x1F); + SOC15_WAIT_ON_RREG_OFFSET(JPEG, jpeg_inst, + regUVD_JMI0_UVD_JMI_CLIENT_CLEAN_STATUS, + reg_offset, 0x1F, 0x1F); WREG32_SOC15_OFFSET(JPEG, jpeg_inst, regUVD_JMI0_JPEG_LMI_DROP, reg_offset, 0x1F); - WREG32_SOC15_OFFSET(JPEG, jpeg_inst, - regJPEG_CORE_RST_CTRL, - reg_offset, 1 << ring->pipe); + WREG32_SOC15(JPEG, jpeg_inst, regJPEG_CORE_RST_CTRL, 1 << ring->pipe); WREG32_SOC15_OFFSET(JPEG, jpeg_inst, regUVD_JMI0_UVD_JMI_CLIENT_STALL, reg_offset, 0x00); WREG32_SOC15_OFFSET(JPEG, jpeg_inst, regUVD_JMI0_JPEG_LMI_DROP, reg_offset, 0x00); - WREG32_SOC15_OFFSET(JPEG, jpeg_inst, - regJPEG_CORE_RST_CTRL, - reg_offset, 0x00); + WREG32_SOC15(JPEG, jpeg_inst, regJPEG_CORE_RST_CTRL, 0x00); } static int jpeg_v4_0_3_ring_reset(struct amdgpu_ring *ring, unsigned int vmid) From 057fef20b8401110a7bc1c2fe9d804a8a0bf0d24 Mon Sep 17 00:00:00 2001 From: Victor Lu Date: Thu, 13 Feb 2025 18:38:28 -0500 Subject: [PATCH 212/235] drm/amdgpu: Do not program AGP BAR regs under SRIOV in gfxhub_v1_0.c SRIOV VF does not have write access to AGP BAR regs. Skip the writes to avoid a dmesg warning. Signed-off-by: Victor Lu Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c index 0e3ddea7b8e0..a7bfc9f41d0e 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c @@ -92,12 +92,12 @@ static void gfxhub_v1_0_init_system_aperture_regs(struct amdgpu_device *adev) { uint64_t value; - /* Program the AGP BAR */ - WREG32_SOC15_RLC(GC, 0, mmMC_VM_AGP_BASE, 0); - WREG32_SOC15_RLC(GC, 0, mmMC_VM_AGP_BOT, adev->gmc.agp_start >> 24); - WREG32_SOC15_RLC(GC, 0, mmMC_VM_AGP_TOP, adev->gmc.agp_end >> 24); - if (!amdgpu_sriov_vf(adev) || adev->asic_type <= CHIP_VEGA10) { + /* Program the AGP BAR */ + WREG32_SOC15_RLC(GC, 0, mmMC_VM_AGP_BASE, 0); + WREG32_SOC15_RLC(GC, 0, mmMC_VM_AGP_BOT, adev->gmc.agp_start >> 24); + WREG32_SOC15_RLC(GC, 0, mmMC_VM_AGP_TOP, adev->gmc.agp_end >> 24); + /* Program the system aperture low logical page number. */ WREG32_SOC15_RLC(GC, 0, mmMC_VM_SYSTEM_APERTURE_LOW_ADDR, min(adev->gmc.fb_start, adev->gmc.agp_start) >> 18); From bac38ca8c4755452fcd7e9f2603dea944bcfe76e Mon Sep 17 00:00:00 2001 From: Jonathan Kim Date: Wed, 15 Jan 2025 15:29:34 -0500 Subject: [PATCH 213/235] drm/amdkfd: implement per queue sdma reset for gfx 9.4+ To reset hung SDMA queues on GFX 9.4+ for the GFX9 family, a soft reset must be issued through SMU. Since soft resets will reset an entire SDMA engine, use a common KGD call to do the reset as the KGD will handle avoiding a reset of in flight GFX and paging queues on that engine. In addition, create a common call for all reset types to simplify the handling of module parameter settings that block gpu resets. Signed-off-by: Jonathan Kim Reviewed-by: Harish Kasiviswanathan Signed-off-by: Alex Deucher --- .../drm/amd/amdgpu/amdgpu_amdkfd_aldebaran.c | 1 + .../drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c | 3 +- .../drm/amd/amdgpu/amdgpu_amdkfd_gc_9_4_3.c | 14 +- .../drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c | 9 +- .../drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.h | 2 + .../drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c | 3 +- .../drm/amd/amdgpu/amdgpu_amdkfd_gfx_v11.c | 9 +- .../drm/amd/amdgpu/amdgpu_amdkfd_gfx_v12.c | 7 + .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c | 16 ++- .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.h | 2 + .../drm/amd/amdkfd/kfd_device_queue_manager.c | 128 ++++++++++++++++-- .../gpu/drm/amd/include/kgd_kfd_interface.h | 2 + 12 files changed, 171 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_aldebaran.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_aldebaran.c index 8dfdb18197c4..6e861d08d044 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_aldebaran.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_aldebaran.c @@ -193,4 +193,5 @@ const struct kfd2kgd_calls aldebaran_kfd2kgd = { .program_trap_handler_settings = kgd_gfx_v9_program_trap_handler_settings, .hqd_get_pq_addr = kgd_gfx_v9_hqd_get_pq_addr, .hqd_reset = kgd_gfx_v9_hqd_reset, + .hqd_sdma_get_doorbell = kgd_gfx_v9_hqd_sdma_get_doorbell }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c index 9abf29b58ac7..c820418e8ccd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c @@ -419,5 +419,6 @@ const struct kfd2kgd_calls arcturus_kfd2kgd = { .get_cu_occupancy = kgd_gfx_v9_get_cu_occupancy, .program_trap_handler_settings = kgd_gfx_v9_program_trap_handler_settings, .hqd_get_pq_addr = kgd_gfx_v9_hqd_get_pq_addr, - .hqd_reset = kgd_gfx_v9_hqd_reset + .hqd_reset = kgd_gfx_v9_hqd_reset, + .hqd_sdma_get_doorbell = kgd_gfx_v9_hqd_sdma_get_doorbell }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gc_9_4_3.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gc_9_4_3.c index e2ae714a700f..0c0998477598 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gc_9_4_3.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gc_9_4_3.c @@ -509,6 +509,17 @@ static uint32_t kgd_gfx_v9_4_3_clear_address_watch(struct amdgpu_device *adev, return 0; } +static uint32_t kgd_gfx_v9_4_3_hqd_sdma_get_doorbell(struct amdgpu_device *adev, + int engine, int queue) +{ + uint32_t reg_offset = get_sdma_rlc_reg_offset(adev, engine, queue); + uint32_t status = RREG32(regSDMA_RLC0_CONTEXT_STATUS + reg_offset); + uint32_t doorbell_off = RREG32(regSDMA_RLC0_DOORBELL_OFFSET + reg_offset); + bool is_active = !!REG_GET_FIELD(status, SDMA_RLC0_CONTEXT_STATUS, SELECTED); + + return is_active ? doorbell_off >> 2 : 0; +} + const struct kfd2kgd_calls gc_9_4_3_kfd2kgd = { .program_sh_mem_settings = kgd_gfx_v9_program_sh_mem_settings, .set_pasid_vmid_mapping = kgd_gfx_v9_4_3_set_pasid_vmid_mapping, @@ -543,5 +554,6 @@ const struct kfd2kgd_calls gc_9_4_3_kfd2kgd = { .set_address_watch = kgd_gfx_v9_4_3_set_address_watch, .clear_address_watch = kgd_gfx_v9_4_3_clear_address_watch, .hqd_get_pq_addr = kgd_gfx_v9_hqd_get_pq_addr, - .hqd_reset = kgd_gfx_v9_hqd_reset + .hqd_reset = kgd_gfx_v9_hqd_reset, + .hqd_sdma_get_doorbell = kgd_gfx_v9_4_3_hqd_sdma_get_doorbell }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c index 62176d607bef..2887b6f3eaa2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c @@ -1084,6 +1084,12 @@ uint64_t kgd_gfx_v10_hqd_reset(struct amdgpu_device *adev, return 0; } +uint32_t kgd_gfx_v10_hqd_sdma_get_doorbell(struct amdgpu_device *adev, + int engine, int queue) +{ + return 0; +} + const struct kfd2kgd_calls gfx_v10_kfd2kgd = { .program_sh_mem_settings = kgd_program_sh_mem_settings, .set_pasid_vmid_mapping = kgd_set_pasid_vmid_mapping, @@ -1112,5 +1118,6 @@ const struct kfd2kgd_calls gfx_v10_kfd2kgd = { .build_grace_period_packet_info = kgd_gfx_v10_build_grace_period_packet_info, .program_trap_handler_settings = program_trap_handler_settings, .hqd_get_pq_addr = kgd_gfx_v10_hqd_get_pq_addr, - .hqd_reset = kgd_gfx_v10_hqd_reset + .hqd_reset = kgd_gfx_v10_hqd_reset, + .hqd_sdma_get_doorbell = kgd_gfx_v10_hqd_sdma_get_doorbell }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.h index 9efd2dd4fdd7..db577c2a847a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.h @@ -65,3 +65,5 @@ uint64_t kgd_gfx_v10_hqd_reset(struct amdgpu_device *adev, uint32_t queue_id, uint32_t inst, unsigned int utimeout); +uint32_t kgd_gfx_v10_hqd_sdma_get_doorbell(struct amdgpu_device *adev, + int engine, int queue); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c index c718bedda0ca..ac9ad505f9d7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c @@ -682,5 +682,6 @@ const struct kfd2kgd_calls gfx_v10_3_kfd2kgd = { .set_address_watch = kgd_gfx_v10_set_address_watch, .clear_address_watch = kgd_gfx_v10_clear_address_watch, .hqd_get_pq_addr = kgd_gfx_v10_hqd_get_pq_addr, - .hqd_reset = kgd_gfx_v10_hqd_reset + .hqd_reset = kgd_gfx_v10_hqd_reset, + .hqd_sdma_get_doorbell = kgd_gfx_v10_hqd_sdma_get_doorbell }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v11.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v11.c index a4ba49cb22db..e0e6a6a49d90 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v11.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v11.c @@ -800,6 +800,12 @@ static uint64_t kgd_gfx_v11_hqd_reset(struct amdgpu_device *adev, return 0; } +static uint32_t kgd_gfx_v11_hqd_sdma_get_doorbell(struct amdgpu_device *adev, + int engine, int queue) +{ + return 0; +} + const struct kfd2kgd_calls gfx_v11_kfd2kgd = { .program_sh_mem_settings = program_sh_mem_settings_v11, .set_pasid_vmid_mapping = set_pasid_vmid_mapping_v11, @@ -824,5 +830,6 @@ const struct kfd2kgd_calls gfx_v11_kfd2kgd = { .set_address_watch = kgd_gfx_v11_set_address_watch, .clear_address_watch = kgd_gfx_v11_clear_address_watch, .hqd_get_pq_addr = kgd_gfx_v11_hqd_get_pq_addr, - .hqd_reset = kgd_gfx_v11_hqd_reset + .hqd_reset = kgd_gfx_v11_hqd_reset, + .hqd_sdma_get_doorbell = kgd_gfx_v11_hqd_sdma_get_doorbell }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v12.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v12.c index 0dfe7093bd8a..6f0dc23c901b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v12.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v12.c @@ -361,6 +361,12 @@ static uint32_t kgd_gfx_v12_clear_address_watch(struct amdgpu_device *adev, return 0; } +static uint32_t kgd_gfx_v12_hqd_sdma_get_doorbell(struct amdgpu_device *adev, + int engine, int queue) +{ + return 0; +} + const struct kfd2kgd_calls gfx_v12_kfd2kgd = { .init_interrupts = init_interrupts_v12, .hqd_dump = hqd_dump_v12, @@ -374,4 +380,5 @@ const struct kfd2kgd_calls gfx_v12_kfd2kgd = { .set_wave_launch_mode = kgd_gfx_v12_set_wave_launch_mode, .set_address_watch = kgd_gfx_v12_set_address_watch, .clear_address_watch = kgd_gfx_v12_clear_address_watch, + .hqd_sdma_get_doorbell = kgd_gfx_v12_hqd_sdma_get_doorbell }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c index 441568163e20..84135eb90660 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c @@ -1131,9 +1131,6 @@ uint64_t kgd_gfx_v9_hqd_get_pq_addr(struct amdgpu_device *adev, uint32_t low, high; uint64_t queue_addr = 0; - if (!amdgpu_gpu_recovery) - return 0; - kgd_gfx_v9_acquire_queue(adev, pipe_id, queue_id, inst); amdgpu_gfx_rlc_enter_safe_mode(adev, inst); @@ -1182,9 +1179,6 @@ uint64_t kgd_gfx_v9_hqd_reset(struct amdgpu_device *adev, uint32_t low, high, pipe_reset_data = 0; uint64_t queue_addr = 0; - if (!amdgpu_gpu_recovery) - return 0; - kgd_gfx_v9_acquire_queue(adev, pipe_id, queue_id, inst); amdgpu_gfx_rlc_enter_safe_mode(adev, inst); @@ -1229,6 +1223,13 @@ uint64_t kgd_gfx_v9_hqd_reset(struct amdgpu_device *adev, return queue_addr; } +uint32_t kgd_gfx_v9_hqd_sdma_get_doorbell(struct amdgpu_device *adev, + int engine, int queue) + +{ + return 0; +} + const struct kfd2kgd_calls gfx_v9_kfd2kgd = { .program_sh_mem_settings = kgd_gfx_v9_program_sh_mem_settings, .set_pasid_vmid_mapping = kgd_gfx_v9_set_pasid_vmid_mapping, @@ -1258,5 +1259,6 @@ const struct kfd2kgd_calls gfx_v9_kfd2kgd = { .get_cu_occupancy = kgd_gfx_v9_get_cu_occupancy, .program_trap_handler_settings = kgd_gfx_v9_program_trap_handler_settings, .hqd_get_pq_addr = kgd_gfx_v9_hqd_get_pq_addr, - .hqd_reset = kgd_gfx_v9_hqd_reset + .hqd_reset = kgd_gfx_v9_hqd_reset, + .hqd_sdma_get_doorbell = kgd_gfx_v9_hqd_sdma_get_doorbell }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.h index b6a91a552aa4..90c8fa13d519 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.h @@ -111,3 +111,5 @@ uint64_t kgd_gfx_v9_hqd_reset(struct amdgpu_device *adev, uint32_t queue_id, uint32_t inst, unsigned int utimeout); +uint32_t kgd_gfx_v9_hqd_sdma_get_doorbell(struct amdgpu_device *adev, + int engine, int queue); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index 91e4988dc1e3..f3f2fd6ee65c 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -36,6 +36,7 @@ #include "kfd_kernel_queue.h" #include "amdgpu_amdkfd.h" #include "amdgpu_reset.h" +#include "amdgpu_sdma.h" #include "mes_v11_api_def.h" #include "kfd_debug.h" @@ -67,6 +68,8 @@ static int allocate_hqd(struct device_queue_manager *dqm, struct queue *q); static int allocate_sdma_queue(struct device_queue_manager *dqm, struct queue *q, const uint32_t *restore_sdma_id); +static int reset_queues_on_hws_hang(struct device_queue_manager *dqm, bool is_sdma); + static inline enum KFD_MQD_TYPE get_mqd_type_from_queue_type(enum kfd_queue_type type) { @@ -2205,8 +2208,7 @@ static struct queue *find_queue_by_address(struct device_queue_manager *dqm, uin return NULL; } -/* only for compute queue */ -static int reset_queues_on_hws_hang(struct device_queue_manager *dqm) +static int reset_hung_queues(struct device_queue_manager *dqm) { int r = 0, reset_count = 0, i; @@ -2259,6 +2261,104 @@ static int reset_queues_on_hws_hang(struct device_queue_manager *dqm) return r; } +static bool sdma_has_hang(struct device_queue_manager *dqm) +{ + int engine_start = dqm->dev->node_id * get_num_all_sdma_engines(dqm); + int engine_end = engine_start + get_num_all_sdma_engines(dqm); + int num_queues_per_eng = dqm->dev->kfd->device_info.num_sdma_queues_per_engine; + int i, j; + + for (i = engine_start; i < engine_end; i++) { + for (j = 0; j < num_queues_per_eng; j++) { + if (!dqm->dev->kfd2kgd->hqd_sdma_get_doorbell(dqm->dev->adev, i, j)) + continue; + + return true; + } + } + + return false; +} + +static bool set_sdma_queue_as_reset(struct device_queue_manager *dqm, + uint32_t doorbell_off) +{ + struct device_process_node *cur; + struct qcm_process_device *qpd; + struct queue *q; + + list_for_each_entry(cur, &dqm->queues, list) { + qpd = cur->qpd; + list_for_each_entry(q, &qpd->queues_list, list) { + if ((q->properties.type == KFD_QUEUE_TYPE_SDMA || + q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI) && + q->properties.doorbell_off == doorbell_off) { + set_queue_as_reset(dqm, q, qpd); + return true; + } + } + } + + return false; +} + +static int reset_hung_queues_sdma(struct device_queue_manager *dqm) +{ + int engine_start = dqm->dev->node_id * get_num_all_sdma_engines(dqm); + int engine_end = engine_start + get_num_all_sdma_engines(dqm); + int num_queues_per_eng = dqm->dev->kfd->device_info.num_sdma_queues_per_engine; + int r = 0, i, j; + + if (dqm->is_hws_hang) + return -EIO; + + /* Scan for hung HW queues and reset engine. */ + dqm->detect_hang_count = 0; + for (i = engine_start; i < engine_end; i++) { + for (j = 0; j < num_queues_per_eng; j++) { + uint32_t doorbell_off = + dqm->dev->kfd2kgd->hqd_sdma_get_doorbell(dqm->dev->adev, i, j); + + if (!doorbell_off) + continue; + + /* Reset engine and check. */ + if (amdgpu_sdma_reset_engine(dqm->dev->adev, i, false) || + dqm->dev->kfd2kgd->hqd_sdma_get_doorbell(dqm->dev->adev, i, j) || + !set_sdma_queue_as_reset(dqm, doorbell_off)) { + r = -ENOTRECOVERABLE; + goto reset_fail; + } + + /* Should only expect one queue active per engine */ + dqm->detect_hang_count++; + break; + } + } + + /* Signal process reset */ + if (dqm->detect_hang_count) + kfd_signal_reset_event(dqm->dev); + else + r = -ENOTRECOVERABLE; + +reset_fail: + dqm->detect_hang_count = 0; + + return r; +} + +static int reset_queues_on_hws_hang(struct device_queue_manager *dqm, bool is_sdma) +{ + while (halt_if_hws_hang) + schedule(); + + if (!amdgpu_gpu_recovery) + return -ENOTRECOVERABLE; + + return is_sdma ? reset_hung_queues_sdma(dqm) : reset_hung_queues(dqm); +} + /* dqm->lock mutex has to be locked before calling this function */ static int unmap_queues_cpsch(struct device_queue_manager *dqm, enum kfd_unmap_queues_filter filter, @@ -2309,16 +2409,13 @@ static int unmap_queues_cpsch(struct device_queue_manager *dqm, * check those fields */ mqd_mgr = dqm->mqd_mgrs[KFD_MQD_TYPE_HIQ]; - if (mqd_mgr->check_preemption_failed(mqd_mgr, dqm->packet_mgr.priv_queue->queue->mqd)) { - while (halt_if_hws_hang) - schedule(); - if (reset_queues_on_hws_hang(dqm)) { - dqm->is_hws_hang = true; - kfd_hws_hang(dqm); - retval = -ETIME; - goto out; - } - } + if (mqd_mgr->check_preemption_failed(mqd_mgr, dqm->packet_mgr.priv_queue->queue->mqd) && + reset_queues_on_hws_hang(dqm, false)) + goto reset_fail; + + /* Check for SDMA hang and attempt SDMA reset */ + if (sdma_has_hang(dqm) && reset_queues_on_hws_hang(dqm, true)) + goto reset_fail; /* We need to reset the grace period value for this device */ if (grace_period != USE_DEFAULT_GRACE_PERIOD) { @@ -2329,10 +2426,15 @@ static int unmap_queues_cpsch(struct device_queue_manager *dqm, pm_release_ib(&dqm->packet_mgr); dqm->active_runlist = false; - out: up_read(&dqm->dev->adev->reset_domain->sem); return retval; + +reset_fail: + dqm->is_hws_hang = true; + kfd_hws_hang(dqm); + up_read(&dqm->dev->adev->reset_domain->sem); + return -ETIME; } /* only for compute queue */ diff --git a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h index e3e635a31b8a..1e8dfa6c0dc8 100644 --- a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h @@ -330,6 +330,8 @@ struct kfd2kgd_calls { uint64_t (*hqd_reset)(struct amdgpu_device *adev, uint32_t pipe_id, uint32_t queue_id, uint32_t inst, unsigned int utimeout); + uint32_t (*hqd_sdma_get_doorbell)(struct amdgpu_device *adev, + int engine, int queue); }; #endif /* KGD_KFD_INTERFACE_H_INCLUDED */ From ceb7114c961bd8d8605dfff8e18d1a39d99cdd30 Mon Sep 17 00:00:00 2001 From: Jonathan Kim Date: Wed, 26 Feb 2025 14:22:02 -0500 Subject: [PATCH 214/235] drm/amdkfd: flag per-sdma queue reset supported to user space Similar to compute queue reset, flag SDMA queue reset capabilities to user space for safe testing. Signed-off-by: Jonathan Kim Reviewed-by: Harish Kasiviswanathan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_topology.c | 5 +++++ drivers/gpu/drm/amd/amdkfd/kfd_topology.h | 1 + include/uapi/linux/kfd_sysfs.h | 3 +++ 3 files changed, 9 insertions(+) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c index dbc5595e999a..27e7356eed6f 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c @@ -519,6 +519,8 @@ static ssize_t node_show(struct kobject *kobj, struct attribute *attr, dev->gpu->kfd->mec_fw_version); sysfs_show_32bit_prop(buffer, offs, "capability", dev->node_props.capability); + sysfs_show_32bit_prop(buffer, offs, "capability2", + dev->node_props.capability2); sysfs_show_64bit_prop(buffer, offs, "debug_prop", dev->node_props.debug_prop); sysfs_show_32bit_prop(buffer, offs, "sdma_fw_version", @@ -1981,6 +1983,9 @@ static void kfd_topology_set_capabilities(struct kfd_topology_device *dev) if (kfd_dbg_has_ttmps_always_setup(dev->gpu)) dev->node_props.debug_prop |= HSA_DBG_DISPATCH_INFO_ALWAYS_VALID; + if (dev->gpu->adev->sdma.supported_reset & AMDGPU_RESET_TYPE_PER_QUEUE) + dev->node_props.capability2 |= HSA_CAP2_PER_SDMA_QUEUE_RESET_SUPPORTED; + if (KFD_GC_VERSION(dev->gpu) < IP_VERSION(10, 0, 0)) { if (KFD_GC_VERSION(dev->gpu) == IP_VERSION(9, 4, 3) || KFD_GC_VERSION(dev->gpu) == IP_VERSION(9, 4, 4)) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.h b/drivers/gpu/drm/amd/amdkfd/kfd_topology.h index f06c9db7ddde..3de8ec0043bb 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.h @@ -51,6 +51,7 @@ struct kfd_node_properties { uint32_t cpu_core_id_base; uint32_t simd_id_base; uint32_t capability; + uint32_t capability2; uint64_t debug_prop; uint32_t max_waves_per_simd; uint32_t lds_size_in_kb; diff --git a/include/uapi/linux/kfd_sysfs.h b/include/uapi/linux/kfd_sysfs.h index 859b8e91d4d3..1125fe47959f 100644 --- a/include/uapi/linux/kfd_sysfs.h +++ b/include/uapi/linux/kfd_sysfs.h @@ -63,6 +63,9 @@ #define HSA_CAP_PER_QUEUE_RESET_SUPPORTED 0x80000000 #define HSA_CAP_RESERVED 0x000f8000 +#define HSA_CAP2_PER_SDMA_QUEUE_RESET_SUPPORTED 0x00000001 +#define HSA_CAP2_RESERVED 0xfffffffe + /* debug_prop bits in node properties */ #define HSA_DBG_WATCH_ADDR_MASK_LO_BIT_MASK 0x0000000f #define HSA_DBG_WATCH_ADDR_MASK_LO_BIT_SHIFT 0 From a29936bcd21eea7ac87546e2107313cd0f62c4d7 Mon Sep 17 00:00:00 2001 From: Sathishkumar S Date: Wed, 26 Feb 2025 15:59:47 +0530 Subject: [PATCH 215/235] drm/amdgpu: Fix core reset sequence for JPEG5_0_1 For cores 1 through 9 repair the core reset sequence by adjusting offsets to access the expected registers. Signed-off-by: Sathishkumar S Reviewed-by: Leo Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c index 56c01d207e20..218e16b68f1d 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c @@ -672,24 +672,20 @@ static void jpeg_v5_0_1_core_stall_reset(struct amdgpu_ring *ring) WREG32_SOC15_OFFSET(JPEG, jpeg_inst, regUVD_JMI0_UVD_JMI_CLIENT_STALL, reg_offset, 0x1F); - SOC15_WAIT_ON_RREG(JPEG, jpeg_inst, - regUVD_JMI0_UVD_JMI_CLIENT_CLEAN_STATUS, - 0x1F, 0x1F); + SOC15_WAIT_ON_RREG_OFFSET(JPEG, jpeg_inst, + regUVD_JMI0_UVD_JMI_CLIENT_CLEAN_STATUS, + reg_offset, 0x1F, 0x1F); WREG32_SOC15_OFFSET(JPEG, jpeg_inst, regUVD_JMI0_JPEG_LMI_DROP, reg_offset, 0x1F); - WREG32_SOC15_OFFSET(JPEG, jpeg_inst, - regJPEG_CORE_RST_CTRL, - reg_offset, 1 << ring->pipe); + WREG32_SOC15(JPEG, jpeg_inst, regJPEG_CORE_RST_CTRL, 1 << ring->pipe); WREG32_SOC15_OFFSET(JPEG, jpeg_inst, regUVD_JMI0_UVD_JMI_CLIENT_STALL, reg_offset, 0x00); WREG32_SOC15_OFFSET(JPEG, jpeg_inst, regUVD_JMI0_JPEG_LMI_DROP, reg_offset, 0x00); - WREG32_SOC15_OFFSET(JPEG, jpeg_inst, - regJPEG_CORE_RST_CTRL, - reg_offset, 0x00); + WREG32_SOC15(JPEG, jpeg_inst, regJPEG_CORE_RST_CTRL, 0x00); } static int jpeg_v5_0_1_ring_reset(struct amdgpu_ring *ring, unsigned int vmid) From 3646cc65e2747ff112d7de1a05a2e756414b771e Mon Sep 17 00:00:00 2001 From: Victor Lu Date: Thu, 13 Feb 2025 18:41:26 -0500 Subject: [PATCH 216/235] drm/amdgpu: Do not write to GRBM_CNTL if Aldebaran SRIOV Aldebaran SRIOV VF does not have write permissions to GRBM_CTNL. This access can be skipped to avoid a dmesg warning. v2: Use GC IP version check instead of asic check Signed-off-by: Victor Lu Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index f7938d318f26..1f0f03108a82 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -2637,7 +2637,10 @@ static void gfx_v9_0_constants_init(struct amdgpu_device *adev) u32 tmp; int i; - WREG32_FIELD15_RLC(GC, 0, GRBM_CNTL, READ_TIMEOUT, 0xff); + if (!amdgpu_sriov_vf(adev) || + amdgpu_ip_version(adev, GC_HWIP, 0) != IP_VERSION(9, 4, 2)) { + WREG32_FIELD15_RLC(GC, 0, GRBM_CNTL, READ_TIMEOUT, 0xff); + } gfx_v9_0_tiling_mode_table_init(adev); From 571d36837c84707ea36fa37ab1373a124e328ed4 Mon Sep 17 00:00:00 2001 From: Charles Han Date: Wed, 5 Mar 2025 18:40:57 +0800 Subject: [PATCH 217/235] drm/amdgpu: fix inconsistent indenting warning Fix below inconsistent indenting smatch warning. smatch warnings: drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c:582 amdgpu_sdma_reset_engine() warn: inconsistent indenting Signed-off-by: Charles Han Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c index 39669f8788a7..3a4cef896018 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c @@ -621,5 +621,5 @@ int amdgpu_sdma_reset_engine(struct amdgpu_device *adev, uint32_t instance_id, b if (suspend_user_queues) amdgpu_amdkfd_resume(adev, false); - return ret; + return ret; } From 14c8097ba4db1b6e1c28b2ed65186b9199fe9155 Mon Sep 17 00:00:00 2001 From: Jonathan Kim Date: Thu, 27 Feb 2025 12:25:25 -0500 Subject: [PATCH 218/235] drm/amdkfd: remove unused debug gws support status variable Remove unused declaration of gws_debug_workaround. Signed-off-by: Jonathan Kim Reviewed-by: Amber Lin Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index 966d1c484d9f..bb09c873a9a5 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -289,7 +289,6 @@ struct kfd_node { /* Global GWS resource shared between processes */ void *gws; - bool gws_debug_workaround; /* Clients watching SMI events */ struct list_head smi_clients; From 94b0908b85524d467a00c6aa2a277ef98fd8b152 Mon Sep 17 00:00:00 2001 From: Victor Lu Date: Thu, 13 Feb 2025 18:49:46 -0500 Subject: [PATCH 219/235] drm/amdgpu: Do not set power brake sequence for Aldebaran SRIOV Aldebaran SRIOV VF cannot access the power brake feature regs. The accesses can be skipped to avoid a dmesg warning. v2: Remove redundant asic type check Signed-off-by: Victor Lu Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 1f0f03108a82..d345285ea885 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -4045,7 +4045,8 @@ static int gfx_v9_0_hw_init(struct amdgpu_ip_block *ip_block) if (r) return r; - if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 2)) + if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 2) && + !amdgpu_sriov_vf(adev)) gfx_v9_4_2_set_power_brake_sequence(adev); return r; From fe2fa3be3d59ba67d6de54a0064441ec233cb50c Mon Sep 17 00:00:00 2001 From: Emily Deng Date: Mon, 3 Mar 2025 15:10:22 +0800 Subject: [PATCH 220/235] drm/amdgpu: Fix missing drain retry fault the last entry While the entry get in svm_range_unmap_from_cpu is the last entry, and the entry is page fault, it also need to be dropped. So for equal case, it also need to be dropped. v2: Only modify the svm_range_restore_pages. Signed-off-by: Emily Deng Reviewed-by: Xiaogang Chen Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h | 3 +++ drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h index 7d4395a5d8ac..b0a88f92cd82 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h @@ -78,6 +78,9 @@ struct amdgpu_ih_ring { #define amdgpu_ih_ts_after(t1, t2) \ (((int64_t)((t2) << 16) - (int64_t)((t1) << 16)) > 0LL) +#define amdgpu_ih_ts_after_or_equal(t1, t2) \ + (((int64_t)((t2) << 16) - (int64_t)((t1) << 16)) >= 0LL) + /* provided by the ih block */ struct amdgpu_ih_funcs { /* ring read/write ptr handling, called from interrupt context */ diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c index db3034b00dac..1a38ac75abbd 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c @@ -3011,7 +3011,7 @@ svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid, /* check if this page fault time stamp is before svms->checkpoint_ts */ if (svms->checkpoint_ts[gpuidx] != 0) { - if (amdgpu_ih_ts_after(ts, svms->checkpoint_ts[gpuidx])) { + if (amdgpu_ih_ts_after_or_equal(ts, svms->checkpoint_ts[gpuidx])) { pr_debug("draining retry fault, drop fault 0x%llx\n", addr); r = 0; goto out; From 334dc5fcc3f177823115ec4e075259997c16d4a7 Mon Sep 17 00:00:00 2001 From: Tao Zhou Date: Thu, 6 Mar 2025 11:36:49 +0800 Subject: [PATCH 221/235] drm/amdgpu: increase RAS bad page threshold For default policy, driver will issue an RMA event when the number of bad pages is greater than 8 physical rows, rather than reaches 8 physical rows, don't rely on threshold configurable parameters in default mode. Signed-off-by: Tao Zhou Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c index ab27cecb5519..09a6f8bc1a5a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c @@ -747,7 +747,7 @@ amdgpu_ras_eeprom_update_header(struct amdgpu_ras_eeprom_control *control) /* Modify the header if it exceeds. */ if (amdgpu_bad_page_threshold != 0 && - control->ras_num_bad_pages >= ras->bad_page_cnt_threshold) { + control->ras_num_bad_pages > ras->bad_page_cnt_threshold) { dev_warn(adev->dev, "Saved bad pages %d reaches threshold value %d\n", control->ras_num_bad_pages, ras->bad_page_cnt_threshold); @@ -806,7 +806,7 @@ amdgpu_ras_eeprom_update_header(struct amdgpu_ras_eeprom_control *control) */ if (amdgpu_bad_page_threshold != 0 && control->tbl_hdr.version == RAS_TABLE_VER_V2_1 && - control->ras_num_bad_pages < ras->bad_page_cnt_threshold) + control->ras_num_bad_pages <= ras->bad_page_cnt_threshold) control->tbl_rai.health_percent = ((ras->bad_page_cnt_threshold - control->ras_num_bad_pages) * 100) / ras->bad_page_cnt_threshold; @@ -1456,7 +1456,7 @@ int amdgpu_ras_eeprom_check(struct amdgpu_ras_eeprom_control *control) res); return -EINVAL; } - if (ras->bad_page_cnt_threshold > control->ras_num_bad_pages) { + if (ras->bad_page_cnt_threshold >= control->ras_num_bad_pages) { /* This means that, the threshold was increased since * the last time the system was booted, and now, * ras->bad_page_cnt_threshold - control->num_recs > 0, From 3bc7bc73af7d167e564eb09ed17af0eed24b5110 Mon Sep 17 00:00:00 2001 From: Shiwu Zhang Date: Mon, 3 Mar 2025 21:03:03 +0800 Subject: [PATCH 222/235] drm/amdgpu: retire ip init code specific for A0 rev For aqua_vanjaram, A0 HW is retired so remove the code specific for it in gfx ip init. Signed-off-by: Shiwu Zhang Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c index 87add6274b98..b276a16a8121 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c @@ -349,18 +349,7 @@ static void gfx_v9_4_3_init_golden_registers(struct amdgpu_device *adev) WREG32_SOC15(GC, dev_inst, regGB_ADDR_CONFIG, GOLDEN_GB_ADDR_CONFIG); - if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 5, 0)) { - WREG32_FIELD15_PREREG(GC, dev_inst, TCP_UTCL1_CNTL2, SPARE, 0x1); - } else { - /* Golden settings applied by driver for ASIC with rev_id 0 */ - if (adev->rev_id == 0) { - WREG32_FIELD15_PREREG(GC, dev_inst, TCP_UTCL1_CNTL1, - REDUCE_FIFO_DEPTH_BY_2, 2); - } else { - WREG32_FIELD15_PREREG(GC, dev_inst, TCP_UTCL1_CNTL2, - SPARE, 0x1); - } - } + WREG32_FIELD15_PREREG(GC, dev_inst, TCP_UTCL1_CNTL2, SPARE, 0x1); } } From 216be476f14a8a129f1e3210d3c97b9a94942fea Mon Sep 17 00:00:00 2001 From: Shiwu Zhang Date: Tue, 4 Mar 2025 11:13:48 +0800 Subject: [PATCH 223/235] drm/amdgpu: fix the gb_addr_config_fields init value mismatch For gfx_v9_4_3 specifically, before regGB_ADDR_CONFIG is overwritten in gfx hw_init it is read out to popluate the gb_addr_config_fields in the sw_init stage, which causes mismatch. Fix it by using the golden value in sw_init as well. v2: This is a driver-set golden reg and keep as it is (Lijo) Signed-off-by: Shiwu Zhang Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c index b276a16a8121..476542b6e7b5 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c @@ -916,8 +916,6 @@ static const struct aca_info gfx_v9_4_3_aca_info = { static int gfx_v9_4_3_gpu_early_init(struct amdgpu_device *adev) { - u32 gb_addr_config; - adev->gfx.funcs = &gfx_v9_4_3_gfx_funcs; adev->gfx.ras = &gfx_v9_4_3_ras; @@ -926,9 +924,7 @@ static int gfx_v9_4_3_gpu_early_init(struct amdgpu_device *adev) adev->gfx.config.sc_prim_fifo_size_backend = 0x100; adev->gfx.config.sc_hiz_tile_fifo_size = 0x30; adev->gfx.config.sc_earlyz_tile_fifo_size = 0x4C0; - gb_addr_config = RREG32_SOC15(GC, GET_INST(GC, 0), regGB_ADDR_CONFIG); - - adev->gfx.config.gb_addr_config = gb_addr_config; + adev->gfx.config.gb_addr_config = GOLDEN_GB_ADDR_CONFIG; adev->gfx.config.gb_addr_config_fields.num_pipes = 1 << REG_GET_FIELD( From 148084bbb1e5131b3f1200c72c2b60d85e73aa75 Mon Sep 17 00:00:00 2001 From: Xiang Liu Date: Thu, 6 Mar 2025 15:23:34 +0800 Subject: [PATCH 224/235] drm/amdgpu: Use unique CPER record id across devices Encode socket id to CPER record id to be unique across devices. v2: add pointer check for adev->smuio.funcs->get_socket_id v2: set 0 if adev->smuio.funcs->get_socket_id is NULL Signed-off-by: Xiang Liu Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c index 0415ed222342..3f291b30b79f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c @@ -57,6 +57,8 @@ void amdgpu_cper_entry_fill_hdr(struct amdgpu_device *adev, enum amdgpu_cper_type type, enum cper_error_severity sev) { + char record_id[16]; + hdr->signature[0] = 'C'; hdr->signature[1] = 'P'; hdr->signature[2] = 'E'; @@ -71,7 +73,13 @@ void amdgpu_cper_entry_fill_hdr(struct amdgpu_device *adev, amdgpu_cper_get_timestamp(&hdr->timestamp); - snprintf(hdr->record_id, 8, "%d", atomic_inc_return(&adev->cper.unique_id)); + snprintf(record_id, 9, "%d:%X", + (adev->smuio.funcs && adev->smuio.funcs->get_socket_id) ? + adev->smuio.funcs->get_socket_id(adev) : + 0, + atomic_inc_return(&adev->cper.unique_id)); + memcpy(hdr->record_id, record_id, 8); + snprintf(hdr->platform_id, 16, "0x%04X:0x%04X", adev->pdev->vendor, adev->pdev->device); /* pmfw version should be part of creator_id according to CPER spec */ @@ -117,10 +125,10 @@ static int amdgpu_cper_entry_fill_section_desc(struct amdgpu_device *adev, section_desc->severity = sev; section_desc->sec_type = sec_type; - if (adev->smuio.funcs && - adev->smuio.funcs->get_socket_id) - snprintf(section_desc->fru_text, 20, "OAM%d", - adev->smuio.funcs->get_socket_id(adev)); + snprintf(section_desc->fru_text, 20, "OAM%d", + (adev->smuio.funcs && adev->smuio.funcs->get_socket_id) ? + adev->smuio.funcs->get_socket_id(adev) : + 0); if (bp_threshold) section_desc->flag_bits.exceed_err_threshold = 1; From ba795235a2b99ba9bbef647ab003b2f3145d9bbb Mon Sep 17 00:00:00 2001 From: David Rosca Date: Thu, 13 Feb 2025 15:30:37 +0100 Subject: [PATCH 225/235] drm/amdgpu/display: Allow DCC for video formats on GFX12 We advertise DCC as supported for NV12/P010 formats on GFX12, but it would fail on this check on atomic commit. Signed-off-by: David Rosca Reviewed-by: Ruijing Dong Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c index dcf2b98566ea..e1c1e71ac899 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c @@ -277,8 +277,11 @@ static int amdgpu_dm_plane_validate_dcc(struct amdgpu_device *adev, if (!dcc->enable) return 0; - if (format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN || - !dc->cap_funcs.get_dcc_compression_cap) + if (adev->family < AMDGPU_FAMILY_GC_12_0_0 && + format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) + return -EINVAL; + + if (!dc->cap_funcs.get_dcc_compression_cap) return -EINVAL; input.format = format; From bd4b125eb949785c6f8a53b0494e32795421209d Mon Sep 17 00:00:00 2001 From: Aliaksei Urbanski Date: Thu, 6 Mar 2025 13:36:03 +0300 Subject: [PATCH 226/235] drm/amd/display: fix missing .is_two_pixels_per_container Starting from 6.11, AMDGPU driver, while being loaded with amdgpu.dc=1, due to lack of .is_two_pixels_per_container function in dce60_tg_funcs, causes a NULL pointer dereference on PCs with old GPUs, such as R9 280X. So this fix adds missing .is_two_pixels_per_container to dce60_tg_funcs. Reported-by: Rosen Penev Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/3942 Fixes: e6a901a00822 ("drm/amd/display: use even ODM slice width for two pixels per container") Signed-off-by: Aliaksei Urbanski Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce60/dce60_timing_generator.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/dc/dce60/dce60_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce60/dce60_timing_generator.c index e5fb0e8333e4..e691a1cf3356 100644 --- a/drivers/gpu/drm/amd/display/dc/dce60/dce60_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce60/dce60_timing_generator.c @@ -239,6 +239,7 @@ static const struct timing_generator_funcs dce60_tg_funcs = { dce60_timing_generator_enable_advanced_request, .configure_crc = dce60_configure_crc, .get_crc = dce110_get_crc, + .is_two_pixels_per_container = dce110_is_two_pixels_per_container, }; void dce60_timing_generator_construct( From 1435e895d4fc967d64e9f5bf81e992ac32f5ac76 Mon Sep 17 00:00:00 2001 From: Wentao Liang Date: Thu, 6 Mar 2025 15:51:48 +0800 Subject: [PATCH 227/235] drm/amdgpu: handle amdgpu_cgs_create_device() errors in amd_powerplay_create() Add error handling to propagate amdgpu_cgs_create_device() failures to the caller. When amdgpu_cgs_create_device() fails, release hwmgr and return -ENOMEM to prevent null pointer dereference. [v1]->[v2]: Change error code from -EINVAL to -ENOMEM. Free hwmgr. Signed-off-by: Wentao Liang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c index be22ed30a3c1..b48a031cbba0 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c @@ -51,6 +51,11 @@ static int amd_powerplay_create(struct amdgpu_device *adev) hwmgr->adev = adev; hwmgr->not_vf = !amdgpu_sriov_vf(adev); hwmgr->device = amdgpu_cgs_create_device(adev); + if (!hwmgr->device) { + kfree(hwmgr); + return -ENOMEM; + } + mutex_init(&hwmgr->msg_lock); hwmgr->chip_family = adev->family; hwmgr->chip_id = adev->asic_type; From 9c551ca3dbb2d3e7e421aeca27eff52ed2fb23e9 Mon Sep 17 00:00:00 2001 From: Srinivasan Shanmugam Date: Wed, 5 Mar 2025 22:01:22 +0530 Subject: [PATCH 228/235] drm/amdgpu: Fix annotation for dce_v6_0_line_buffer_adjust function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updated description for the 'other_mode' parameter. This parameter is used to determine the display mode of another display controller that may be sharing the line buffer. Cc: Ken Wang Cc: Christian König Cc: Alex Deucher Signed-off-by: Srinivasan Shanmugam Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/dce_v6_0.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c index 315c098271af..ac51b7a6e8d4 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c @@ -1041,6 +1041,8 @@ static void dce_v6_0_program_watermarks(struct amdgpu_device *adev, * @amdgpu_crtc: the selected display controller * @mode: the current display mode on the selected display * controller + * @other_mode: the display mode of another display controller + * that may be sharing the line buffer * * Setup up the line buffer allocation for * the selected display controller (CIK). From 092da9fb25067a5b61237a7d5badca6e6872a951 Mon Sep 17 00:00:00 2001 From: Alexandre Demers Date: Wed, 5 Mar 2025 20:49:56 -0500 Subject: [PATCH 229/235] drm/amdgpu: add defines for pin_offsets in DCE8 Define pin_offsets values in the same way it is done in DCE8 Signed-off-by: Alexandre Demers Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/cikd.h | 9 +++++++++ drivers/gpu/drm/amd/amdgpu/dce_v8_0.c | 14 +++++++------- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/cikd.h b/drivers/gpu/drm/amd/amdgpu/cikd.h index 06088d52d81c..279288365940 100644 --- a/drivers/gpu/drm/amd/amdgpu/cikd.h +++ b/drivers/gpu/drm/amd/amdgpu/cikd.h @@ -51,6 +51,15 @@ #define HPD4_REGISTER_OFFSET (0x1813 - 0x1807) #define HPD5_REGISTER_OFFSET (0x1816 - 0x1807) +/* audio endpt instance offsets */ +#define AUD0_REGISTER_OFFSET (0x1780 - 0x1780) +#define AUD1_REGISTER_OFFSET (0x1786 - 0x1780) +#define AUD2_REGISTER_OFFSET (0x178c - 0x1780) +#define AUD3_REGISTER_OFFSET (0x1792 - 0x1780) +#define AUD4_REGISTER_OFFSET (0x1798 - 0x1780) +#define AUD5_REGISTER_OFFSET (0x179d - 0x1780) +#define AUD6_REGISTER_OFFSET (0x17a4 - 0x1780) + #define BONAIRE_GB_ADDR_CONFIG_GOLDEN 0x12010001 #define HAWAII_GB_ADDR_CONFIG_GOLDEN 0x12011003 diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c index d7bd32bfccd0..07358546581f 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c @@ -1395,13 +1395,13 @@ static void dce_v8_0_audio_enable(struct amdgpu_device *adev, } static const u32 pin_offsets[7] = { - (0x1780 - 0x1780), - (0x1786 - 0x1780), - (0x178c - 0x1780), - (0x1792 - 0x1780), - (0x1798 - 0x1780), - (0x179d - 0x1780), - (0x17a4 - 0x1780), + AUD0_REGISTER_OFFSET, + AUD1_REGISTER_OFFSET, + AUD2_REGISTER_OFFSET, + AUD3_REGISTER_OFFSET, + AUD4_REGISTER_OFFSET, + AUD5_REGISTER_OFFSET, + AUD6_REGISTER_OFFSET, }; static int dce_v8_0_audio_init(struct amdgpu_device *adev) From 59228c6631f902fa826dc61321ab377ba8aadec5 Mon Sep 17 00:00:00 2001 From: Alex Sierra Date: Thu, 16 May 2024 17:06:48 -0500 Subject: [PATCH 230/235] drm/amdkfd: clear F8_MODE for gfx950 Default F8_MODE should be OCP format on gfx950. Signed-off-by: Alex Sierra Reviewed-by: Harish Kasiviswanathan Signed-off-by: Amber Lin Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c index 67137e674f1d..210bcc048f4c 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c @@ -64,8 +64,7 @@ static int update_qpd_v9(struct device_queue_manager *dqm, qpd->sh_mem_config |= 1 << SH_MEM_CONFIG__RETRY_DISABLE__SHIFT; if (KFD_GC_VERSION(dqm->dev->kfd) == IP_VERSION(9, 4, 3) || - KFD_GC_VERSION(dqm->dev->kfd) == IP_VERSION(9, 4, 4) || - KFD_GC_VERSION(dqm->dev->kfd) == IP_VERSION(9, 5, 0)) + KFD_GC_VERSION(dqm->dev->kfd) == IP_VERSION(9, 4, 4)) qpd->sh_mem_config |= (1 << SH_MEM_CONFIG__F8_MODE__SHIFT); From 0d1a686b542aaabfcfd254bc7711624d4ec20df0 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Thu, 6 Mar 2025 12:31:56 -0500 Subject: [PATCH 231/235] drm/amd/amdgpu: Add missing GC 11.5.0 register Adds register needed for debugging purposes. Signed-off-by: Tom St Denis Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/include/asic_reg/gc/gc_11_5_0_offset.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_11_5_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_11_5_0_offset.h index abdb8728156e..d6c02cf815be 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_11_5_0_offset.h +++ b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_11_5_0_offset.h @@ -9478,6 +9478,8 @@ #define regRLC_GFX_IMU_CMD_BASE_IDX 1 #define regGFX_IMU_RLC_STATUS 0x4054 #define regGFX_IMU_RLC_STATUS_BASE_IDX 1 +#define regGFX_IMU_STATUS 0x4055 +#define regGFX_IMU_STATUS_BASE_IDX 1 #define regGFX_IMU_SOC_DATA 0x4059 #define regGFX_IMU_SOC_DATA_BASE_IDX 1 #define regGFX_IMU_SOC_ADDR 0x405a From 68bfdc8dc0a1a7fdd9ab61e69907ae71a6fd3d91 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Thu, 6 Mar 2025 12:51:24 -0600 Subject: [PATCH 232/235] drm/amd: Keep display off while going into S4 When userspace invokes S4 the flow is: 1) amdgpu_pmops_prepare() 2) amdgpu_pmops_freeze() 3) Create hibernation image 4) amdgpu_pmops_thaw() 5) Write out image to disk 6) Turn off system Then on resume amdgpu_pmops_restore() is called. This flow has a problem that because amdgpu_pmops_thaw() is called it will call amdgpu_device_resume() which will resume all of the GPU. This includes turning the display hardware back on and discovering connectors again. This is an unexpected experience for the display to turn back on. Adjust the flow so that during the S4 sequence display hardware is not turned back on. Reported-by: Xaver Hugl Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/2038 Cc: Muhammad Usama Anjum Tested-by: Muhammad Usama Anjum Acked-by: Alex Deucher Acked-by: Harry Wentland Link: https://lore.kernel.org/r/20250306185124.44780-1-mario.limonciello@amd.com Signed-off-by: Mario Limonciello Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 11 +++++++++-- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 5 +++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 8c1aa9feda53..ce08c428ba4c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -2563,7 +2563,6 @@ static int amdgpu_pmops_freeze(struct device *dev) int r; r = amdgpu_device_suspend(drm_dev, true); - adev->in_s4 = false; if (r) return r; @@ -2575,8 +2574,13 @@ static int amdgpu_pmops_freeze(struct device *dev) static int amdgpu_pmops_thaw(struct device *dev) { struct drm_device *drm_dev = dev_get_drvdata(dev); + struct amdgpu_device *adev = drm_to_adev(drm_dev); + int r; - return amdgpu_device_resume(drm_dev, true); + r = amdgpu_device_resume(drm_dev, true); + adev->in_s4 = false; + + return r; } static int amdgpu_pmops_poweroff(struct device *dev) @@ -2589,6 +2593,9 @@ static int amdgpu_pmops_poweroff(struct device *dev) static int amdgpu_pmops_restore(struct device *dev) { struct drm_device *drm_dev = dev_get_drvdata(dev); + struct amdgpu_device *adev = drm_to_adev(drm_dev); + + adev->in_s4 = false; return amdgpu_device_resume(drm_dev, true); } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 7faf0d0cc23c..bb3ac201c4fb 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3434,6 +3434,11 @@ static int dm_resume(struct amdgpu_ip_block *ip_block) return 0; } + + /* leave display off for S4 sequence */ + if (adev->in_s4) + return 0; + /* Recreate dc_state - DC invalidates it when setting power state to S3. */ dc_state_release(dm_state->context); dm_state->context = dc_state_create(dm->dc, NULL); From 289e68503a4533b014f8447e2af28ad44c92c221 Mon Sep 17 00:00:00 2001 From: Harish Kasiviswanathan Date: Tue, 14 Jan 2025 14:07:24 -0500 Subject: [PATCH 233/235] drm/amdkfd: Set per-process flags only once cik/vi Set per-process static sh_mem config only once during process initialization. Move all static changes from update_qpd() which is called each time a queue is created to set_cache_memory_policy() which is called once during process initialization. set_cache_memory_policy() is currently defined only for cik and vi family. So this commit only focuses on these two. A separate commit will address other asics. Signed-off-by: Harish Kasiviswanathan Reviewed-by: Amber Lin Signed-off-by: Alex Deucher --- .../drm/amd/amdkfd/kfd_device_queue_manager.c | 39 +--------- .../amd/amdkfd/kfd_device_queue_manager_cik.c | 69 +++++++++++------ .../amd/amdkfd/kfd_device_queue_manager_vi.c | 77 ++++++++++++------- 3 files changed, 97 insertions(+), 88 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index f3f2fd6ee65c..d23c6a358d34 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -2591,14 +2591,6 @@ static int destroy_queue_cpsch(struct device_queue_manager *dqm, return retval; } -/* - * Low bits must be 0000/FFFF as required by HW, high bits must be 0 to - * stay in user mode. - */ -#define APE1_FIXED_BITS_MASK 0xFFFF80000000FFFFULL -/* APE1 limit is inclusive and 64K aligned. */ -#define APE1_LIMIT_ALIGNMENT 0xFFFF - static bool set_cache_memory_policy(struct device_queue_manager *dqm, struct qcm_process_device *qpd, enum cache_policy default_policy, @@ -2613,34 +2605,6 @@ static bool set_cache_memory_policy(struct device_queue_manager *dqm, dqm_lock(dqm); - if (alternate_aperture_size == 0) { - /* base > limit disables APE1 */ - qpd->sh_mem_ape1_base = 1; - qpd->sh_mem_ape1_limit = 0; - } else { - /* - * In FSA64, APE1_Base[63:0] = { 16{SH_MEM_APE1_BASE[31]}, - * SH_MEM_APE1_BASE[31:0], 0x0000 } - * APE1_Limit[63:0] = { 16{SH_MEM_APE1_LIMIT[31]}, - * SH_MEM_APE1_LIMIT[31:0], 0xFFFF } - * Verify that the base and size parameters can be - * represented in this format and convert them. - * Additionally restrict APE1 to user-mode addresses. - */ - - uint64_t base = (uintptr_t)alternate_aperture_base; - uint64_t limit = base + alternate_aperture_size - 1; - - if (limit <= base || (base & APE1_FIXED_BITS_MASK) != 0 || - (limit & APE1_FIXED_BITS_MASK) != APE1_LIMIT_ALIGNMENT) { - retval = false; - goto out; - } - - qpd->sh_mem_ape1_base = base >> 16; - qpd->sh_mem_ape1_limit = limit >> 16; - } - retval = dqm->asic_ops.set_cache_memory_policy( dqm, qpd, @@ -2649,6 +2613,9 @@ static bool set_cache_memory_policy(struct device_queue_manager *dqm, alternate_aperture_base, alternate_aperture_size); + if (retval) + goto out; + if ((dqm->sched_policy == KFD_SCHED_POLICY_NO_HWS) && (qpd->vmid != 0)) program_sh_mem_settings(dqm, qpd); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_cik.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_cik.c index d4d95c7f2e5d..32bedef912b3 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_cik.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_cik.c @@ -27,6 +27,14 @@ #include "oss/oss_2_4_sh_mask.h" #include "gca/gfx_7_2_sh_mask.h" +/* + * Low bits must be 0000/FFFF as required by HW, high bits must be 0 to + * stay in user mode. + */ +#define APE1_FIXED_BITS_MASK 0xFFFF80000000FFFFULL +/* APE1 limit is inclusive and 64K aligned. */ +#define APE1_LIMIT_ALIGNMENT 0xFFFF + static bool set_cache_memory_policy_cik(struct device_queue_manager *dqm, struct qcm_process_device *qpd, enum cache_policy default_policy, @@ -84,6 +92,36 @@ static bool set_cache_memory_policy_cik(struct device_queue_manager *dqm, { uint32_t default_mtype; uint32_t ape1_mtype; + unsigned int temp; + bool retval = true; + + if (alternate_aperture_size == 0) { + /* base > limit disables APE1 */ + qpd->sh_mem_ape1_base = 1; + qpd->sh_mem_ape1_limit = 0; + } else { + /* + * In FSA64, APE1_Base[63:0] = { 16{SH_MEM_APE1_BASE[31]}, + * SH_MEM_APE1_BASE[31:0], 0x0000 } + * APE1_Limit[63:0] = { 16{SH_MEM_APE1_LIMIT[31]}, + * SH_MEM_APE1_LIMIT[31:0], 0xFFFF } + * Verify that the base and size parameters can be + * represented in this format and convert them. + * Additionally restrict APE1 to user-mode addresses. + */ + + uint64_t base = (uintptr_t)alternate_aperture_base; + uint64_t limit = base + alternate_aperture_size - 1; + + if (limit <= base || (base & APE1_FIXED_BITS_MASK) != 0 || + (limit & APE1_FIXED_BITS_MASK) != APE1_LIMIT_ALIGNMENT) { + retval = false; + goto out; + } + + qpd->sh_mem_ape1_base = base >> 16; + qpd->sh_mem_ape1_limit = limit >> 16; + } default_mtype = (default_policy == cache_policy_coherent) ? MTYPE_NONCACHED : @@ -97,37 +135,22 @@ static bool set_cache_memory_policy_cik(struct device_queue_manager *dqm, | ALIGNMENT_MODE(SH_MEM_ALIGNMENT_MODE_UNALIGNED) | DEFAULT_MTYPE(default_mtype) | APE1_MTYPE(ape1_mtype); - - return true; -} - -static int update_qpd_cik(struct device_queue_manager *dqm, - struct qcm_process_device *qpd) -{ - struct kfd_process_device *pdd; - unsigned int temp; - - pdd = qpd_to_pdd(qpd); - - /* check if sh_mem_config register already configured */ - if (qpd->sh_mem_config == 0) { - qpd->sh_mem_config = - ALIGNMENT_MODE(SH_MEM_ALIGNMENT_MODE_UNALIGNED) | - DEFAULT_MTYPE(MTYPE_NONCACHED) | - APE1_MTYPE(MTYPE_NONCACHED); - qpd->sh_mem_ape1_limit = 0; - qpd->sh_mem_ape1_base = 0; - } - /* On dGPU we're always in GPUVM64 addressing mode with 64-bit * aperture addresses. */ - temp = get_sh_mem_bases_nybble_64(pdd); + temp = get_sh_mem_bases_nybble_64(qpd_to_pdd(qpd)); qpd->sh_mem_bases = compute_sh_mem_bases_64bit(temp); pr_debug("is32bit process: %d sh_mem_bases nybble: 0x%X and register 0x%X\n", qpd->pqm->process->is_32bit_user_mode, temp, qpd->sh_mem_bases); +out: + return retval; +} + +static int update_qpd_cik(struct device_queue_manager *dqm, + struct qcm_process_device *qpd) +{ return 0; } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_vi.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_vi.c index b291ee0fab94..320518f41890 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_vi.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_vi.c @@ -27,6 +27,14 @@ #include "gca/gfx_8_0_sh_mask.h" #include "oss/oss_3_0_sh_mask.h" +/* + * Low bits must be 0000/FFFF as required by HW, high bits must be 0 to + * stay in user mode. + */ +#define APE1_FIXED_BITS_MASK 0xFFFF80000000FFFFULL +/* APE1 limit is inclusive and 64K aligned. */ +#define APE1_LIMIT_ALIGNMENT 0xFFFF + static bool set_cache_memory_policy_vi(struct device_queue_manager *dqm, struct qcm_process_device *qpd, enum cache_policy default_policy, @@ -85,6 +93,36 @@ static bool set_cache_memory_policy_vi(struct device_queue_manager *dqm, { uint32_t default_mtype; uint32_t ape1_mtype; + unsigned int temp; + bool retval = true; + + if (alternate_aperture_size == 0) { + /* base > limit disables APE1 */ + qpd->sh_mem_ape1_base = 1; + qpd->sh_mem_ape1_limit = 0; + } else { + /* + * In FSA64, APE1_Base[63:0] = { 16{SH_MEM_APE1_BASE[31]}, + * SH_MEM_APE1_BASE[31:0], 0x0000 } + * APE1_Limit[63:0] = { 16{SH_MEM_APE1_LIMIT[31]}, + * SH_MEM_APE1_LIMIT[31:0], 0xFFFF } + * Verify that the base and size parameters can be + * represented in this format and convert them. + * Additionally restrict APE1 to user-mode addresses. + */ + + uint64_t base = (uintptr_t)alternate_aperture_base; + uint64_t limit = base + alternate_aperture_size - 1; + + if (limit <= base || (base & APE1_FIXED_BITS_MASK) != 0 || + (limit & APE1_FIXED_BITS_MASK) != APE1_LIMIT_ALIGNMENT) { + retval = false; + goto out; + } + + qpd->sh_mem_ape1_base = base >> 16; + qpd->sh_mem_ape1_limit = limit >> 16; + } default_mtype = (default_policy == cache_policy_coherent) ? MTYPE_UC : @@ -100,40 +138,21 @@ static bool set_cache_memory_policy_vi(struct device_queue_manager *dqm, default_mtype << SH_MEM_CONFIG__DEFAULT_MTYPE__SHIFT | ape1_mtype << SH_MEM_CONFIG__APE1_MTYPE__SHIFT; - return true; + /* On dGPU we're always in GPUVM64 addressing mode with 64-bit + * aperture addresses. + */ + temp = get_sh_mem_bases_nybble_64(qpd_to_pdd(qpd)); + qpd->sh_mem_bases = compute_sh_mem_bases_64bit(temp); + + pr_debug("sh_mem_bases nybble: 0x%X and register 0x%X\n", + temp, qpd->sh_mem_bases); +out: + return retval; } static int update_qpd_vi(struct device_queue_manager *dqm, struct qcm_process_device *qpd) { - struct kfd_process_device *pdd; - unsigned int temp; - - pdd = qpd_to_pdd(qpd); - - /* check if sh_mem_config register already configured */ - if (qpd->sh_mem_config == 0) { - qpd->sh_mem_config = - SH_MEM_ALIGNMENT_MODE_UNALIGNED << - SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT | - MTYPE_UC << - SH_MEM_CONFIG__DEFAULT_MTYPE__SHIFT | - MTYPE_UC << - SH_MEM_CONFIG__APE1_MTYPE__SHIFT; - - qpd->sh_mem_ape1_limit = 0; - qpd->sh_mem_ape1_base = 0; - } - - /* On dGPU we're always in GPUVM64 addressing mode with 64-bit - * aperture addresses. - */ - temp = get_sh_mem_bases_nybble_64(pdd); - qpd->sh_mem_bases = compute_sh_mem_bases_64bit(temp); - - pr_debug("sh_mem_bases nybble: 0x%X and register 0x%X\n", - temp, qpd->sh_mem_bases); - return 0; } From 61972cd93af70738a6ad7f93e17cc7f68a01e182 Mon Sep 17 00:00:00 2001 From: Harish Kasiviswanathan Date: Tue, 14 Jan 2025 14:13:35 -0500 Subject: [PATCH 234/235] drm/amdkfd: Set per-process flags only once for gfx9/10/11/12 Define set_cache_memory_policy() for these asics and move all static changes from update_qpd() which is called each time a queue is created to set_cache_memory_policy() which is called once during process initialization Signed-off-by: Harish Kasiviswanathan Reviewed-by: Amber Lin Signed-off-by: Alex Deucher --- .../amd/amdkfd/kfd_device_queue_manager_v10.c | 43 ++++++++++-------- .../amd/amdkfd/kfd_device_queue_manager_v11.c | 45 +++++++++++-------- .../amd/amdkfd/kfd_device_queue_manager_v12.c | 45 +++++++++++-------- .../amd/amdkfd/kfd_device_queue_manager_v9.c | 36 ++++++++++++++- 4 files changed, 112 insertions(+), 57 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v10.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v10.c index 245a90dfc2f6..b5f5f141353b 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v10.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v10.c @@ -31,10 +31,17 @@ static int update_qpd_v10(struct device_queue_manager *dqm, struct qcm_process_device *qpd); static void init_sdma_vm_v10(struct device_queue_manager *dqm, struct queue *q, struct qcm_process_device *qpd); +static bool set_cache_memory_policy_v10(struct device_queue_manager *dqm, + struct qcm_process_device *qpd, + enum cache_policy default_policy, + enum cache_policy alternate_policy, + void __user *alternate_aperture_base, + uint64_t alternate_aperture_size); void device_queue_manager_init_v10( struct device_queue_manager_asic_ops *asic_ops) { + asic_ops->set_cache_memory_policy = set_cache_memory_policy_v10; asic_ops->update_qpd = update_qpd_v10; asic_ops->init_sdma_vm = init_sdma_vm_v10; asic_ops->mqd_manager_init = mqd_manager_init_v10; @@ -49,27 +56,27 @@ static uint32_t compute_sh_mem_bases_64bit(struct kfd_process_device *pdd) private_base; } +static bool set_cache_memory_policy_v10(struct device_queue_manager *dqm, + struct qcm_process_device *qpd, + enum cache_policy default_policy, + enum cache_policy alternate_policy, + void __user *alternate_aperture_base, + uint64_t alternate_aperture_size) +{ + qpd->sh_mem_config = (SH_MEM_ALIGNMENT_MODE_UNALIGNED << + SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) | + (3 << SH_MEM_CONFIG__INITIAL_INST_PREFETCH__SHIFT); + qpd->sh_mem_ape1_limit = 0; + qpd->sh_mem_ape1_base = 0; + qpd->sh_mem_bases = compute_sh_mem_bases_64bit(qpd_to_pdd(qpd)); + + pr_debug("sh_mem_bases 0x%X\n", qpd->sh_mem_bases); + return true; +} + static int update_qpd_v10(struct device_queue_manager *dqm, struct qcm_process_device *qpd) { - struct kfd_process_device *pdd; - - pdd = qpd_to_pdd(qpd); - - /* check if sh_mem_config register already configured */ - if (qpd->sh_mem_config == 0) { - qpd->sh_mem_config = - (SH_MEM_ALIGNMENT_MODE_UNALIGNED << - SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) | - (3 << SH_MEM_CONFIG__INITIAL_INST_PREFETCH__SHIFT); - qpd->sh_mem_ape1_limit = 0; - qpd->sh_mem_ape1_base = 0; - } - - qpd->sh_mem_bases = compute_sh_mem_bases_64bit(pdd); - - pr_debug("sh_mem_bases 0x%X\n", qpd->sh_mem_bases); - return 0; } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v11.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v11.c index 2e129da7acb4..f436878d0d62 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v11.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v11.c @@ -30,10 +30,17 @@ static int update_qpd_v11(struct device_queue_manager *dqm, struct qcm_process_device *qpd); static void init_sdma_vm_v11(struct device_queue_manager *dqm, struct queue *q, struct qcm_process_device *qpd); +static bool set_cache_memory_policy_v11(struct device_queue_manager *dqm, + struct qcm_process_device *qpd, + enum cache_policy default_policy, + enum cache_policy alternate_policy, + void __user *alternate_aperture_base, + uint64_t alternate_aperture_size); void device_queue_manager_init_v11( struct device_queue_manager_asic_ops *asic_ops) { + asic_ops->set_cache_memory_policy = set_cache_memory_policy_v11; asic_ops->update_qpd = update_qpd_v11; asic_ops->init_sdma_vm = init_sdma_vm_v11; asic_ops->mqd_manager_init = mqd_manager_init_v11; @@ -48,28 +55,28 @@ static uint32_t compute_sh_mem_bases_64bit(struct kfd_process_device *pdd) private_base; } +static bool set_cache_memory_policy_v11(struct device_queue_manager *dqm, + struct qcm_process_device *qpd, + enum cache_policy default_policy, + enum cache_policy alternate_policy, + void __user *alternate_aperture_base, + uint64_t alternate_aperture_size) +{ + qpd->sh_mem_config = (SH_MEM_ALIGNMENT_MODE_UNALIGNED << + SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) | + (3 << SH_MEM_CONFIG__INITIAL_INST_PREFETCH__SHIFT); + + qpd->sh_mem_ape1_limit = 0; + qpd->sh_mem_ape1_base = 0; + qpd->sh_mem_bases = compute_sh_mem_bases_64bit(qpd_to_pdd(qpd)); + + pr_debug("sh_mem_bases 0x%X\n", qpd->sh_mem_bases); + return true; +} + static int update_qpd_v11(struct device_queue_manager *dqm, struct qcm_process_device *qpd) { - struct kfd_process_device *pdd; - - pdd = qpd_to_pdd(qpd); - - /* check if sh_mem_config register already configured */ - if (qpd->sh_mem_config == 0) { - qpd->sh_mem_config = - (SH_MEM_ALIGNMENT_MODE_UNALIGNED << - SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) | - (3 << SH_MEM_CONFIG__INITIAL_INST_PREFETCH__SHIFT); - - qpd->sh_mem_ape1_limit = 0; - qpd->sh_mem_ape1_base = 0; - } - - qpd->sh_mem_bases = compute_sh_mem_bases_64bit(pdd); - - pr_debug("sh_mem_bases 0x%X\n", qpd->sh_mem_bases); - return 0; } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v12.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v12.c index 4f3295b29dfb..62ca1c8fcbaf 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v12.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v12.c @@ -30,10 +30,17 @@ static int update_qpd_v12(struct device_queue_manager *dqm, struct qcm_process_device *qpd); static void init_sdma_vm_v12(struct device_queue_manager *dqm, struct queue *q, struct qcm_process_device *qpd); +static bool set_cache_memory_policy_v12(struct device_queue_manager *dqm, + struct qcm_process_device *qpd, + enum cache_policy default_policy, + enum cache_policy alternate_policy, + void __user *alternate_aperture_base, + uint64_t alternate_aperture_size); void device_queue_manager_init_v12( struct device_queue_manager_asic_ops *asic_ops) { + asic_ops->set_cache_memory_policy = set_cache_memory_policy_v12; asic_ops->update_qpd = update_qpd_v12; asic_ops->init_sdma_vm = init_sdma_vm_v12; asic_ops->mqd_manager_init = mqd_manager_init_v12; @@ -48,28 +55,28 @@ static uint32_t compute_sh_mem_bases_64bit(struct kfd_process_device *pdd) private_base; } +static bool set_cache_memory_policy_v12(struct device_queue_manager *dqm, + struct qcm_process_device *qpd, + enum cache_policy default_policy, + enum cache_policy alternate_policy, + void __user *alternate_aperture_base, + uint64_t alternate_aperture_size) +{ + qpd->sh_mem_config = (SH_MEM_ALIGNMENT_MODE_UNALIGNED << + SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) | + (3 << SH_MEM_CONFIG__INITIAL_INST_PREFETCH__SHIFT); + + qpd->sh_mem_ape1_limit = 0; + qpd->sh_mem_ape1_base = 0; + qpd->sh_mem_bases = compute_sh_mem_bases_64bit(qpd_to_pdd(qpd)); + + pr_debug("sh_mem_bases 0x%X\n", qpd->sh_mem_bases); + return true; +} + static int update_qpd_v12(struct device_queue_manager *dqm, struct qcm_process_device *qpd) { - struct kfd_process_device *pdd; - - pdd = qpd_to_pdd(qpd); - - /* check if sh_mem_config register already configured */ - if (qpd->sh_mem_config == 0) { - qpd->sh_mem_config = - (SH_MEM_ALIGNMENT_MODE_UNALIGNED << - SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) | - (3 << SH_MEM_CONFIG__INITIAL_INST_PREFETCH__SHIFT); - - qpd->sh_mem_ape1_limit = 0; - qpd->sh_mem_ape1_base = 0; - } - - qpd->sh_mem_bases = compute_sh_mem_bases_64bit(pdd); - - pr_debug("sh_mem_bases 0x%X\n", qpd->sh_mem_bases); - return 0; } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c index 210bcc048f4c..3264509408bc 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c @@ -30,10 +30,17 @@ static int update_qpd_v9(struct device_queue_manager *dqm, struct qcm_process_device *qpd); static void init_sdma_vm_v9(struct device_queue_manager *dqm, struct queue *q, struct qcm_process_device *qpd); +static bool set_cache_memory_policy_v9(struct device_queue_manager *dqm, + struct qcm_process_device *qpd, + enum cache_policy default_policy, + enum cache_policy alternate_policy, + void __user *alternate_aperture_base, + uint64_t alternate_aperture_size); void device_queue_manager_init_v9( struct device_queue_manager_asic_ops *asic_ops) { + asic_ops->set_cache_memory_policy = set_cache_memory_policy_v9; asic_ops->update_qpd = update_qpd_v9; asic_ops->init_sdma_vm = init_sdma_vm_v9; asic_ops->mqd_manager_init = mqd_manager_init_v9; @@ -48,10 +55,37 @@ static uint32_t compute_sh_mem_bases_64bit(struct kfd_process_device *pdd) private_base; } +static bool set_cache_memory_policy_v9(struct device_queue_manager *dqm, + struct qcm_process_device *qpd, + enum cache_policy default_policy, + enum cache_policy alternate_policy, + void __user *alternate_aperture_base, + uint64_t alternate_aperture_size) +{ + qpd->sh_mem_config = SH_MEM_ALIGNMENT_MODE_UNALIGNED << + SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT; + + if (dqm->dev->kfd->noretry) + qpd->sh_mem_config |= 1 << SH_MEM_CONFIG__RETRY_DISABLE__SHIFT; + + if (KFD_GC_VERSION(dqm->dev->kfd) == IP_VERSION(9, 4, 3) || + KFD_GC_VERSION(dqm->dev->kfd) == IP_VERSION(9, 4, 4) || + KFD_GC_VERSION(dqm->dev->kfd) == IP_VERSION(9, 5, 0)) + qpd->sh_mem_config |= (1 << SH_MEM_CONFIG__F8_MODE__SHIFT); + + qpd->sh_mem_ape1_limit = 0; + qpd->sh_mem_ape1_base = 0; + qpd->sh_mem_bases = compute_sh_mem_bases_64bit(qpd_to_pdd(qpd)); + + pr_debug("sh_mem_bases 0x%X sh_mem_config 0x%X\n", qpd->sh_mem_bases, + qpd->sh_mem_config); + return true; +} + static int update_qpd_v9(struct device_queue_manager *dqm, struct qcm_process_device *qpd) { - struct kfd_process_device *pdd; + struct kfd_process_device *pdd = qpd_to_pdd(qpd); pdd = qpd_to_pdd(qpd); From cf6d949a409e09539477d32dbe7c954e4852e744 Mon Sep 17 00:00:00 2001 From: Harish Kasiviswanathan Date: Tue, 14 Jan 2025 16:02:21 -0500 Subject: [PATCH 235/235] drm/amdkfd: Add support for more per-process flag Add support for more per-process flags starting with option to configure MFMA precision for gfx 9.5 v2: Change flag name to KFD_PROC_FLAG_MFMA_HIGH_PRECISION Remove unused else condition v3: Bump the KFD API version v4: Missed SH_MEM_CONFIG__PRECISION_MODE__SHIFT define. Added it. Signed-off-by: Harish Kasiviswanathan Reviewed-by: Felix Kuehling Reviewed-by: Amber Lin Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 3 ++- drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | 6 ++++-- drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h | 6 ++++-- .../gpu/drm/amd/amdkfd/kfd_device_queue_manager_cik.c | 6 ++++-- .../gpu/drm/amd/amdkfd/kfd_device_queue_manager_v10.c | 6 ++++-- .../gpu/drm/amd/amdkfd/kfd_device_queue_manager_v11.c | 6 ++++-- .../gpu/drm/amd/amdkfd/kfd_device_queue_manager_v12.c | 6 ++++-- .../gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c | 11 +++++++++-- .../gpu/drm/amd/amdkfd/kfd_device_queue_manager_vi.c | 6 ++++-- .../drm/amd/include/asic_reg/gc/gc_9_4_3_sh_mask.h | 2 ++ include/uapi/linux/kfd_ioctl.h | 8 ++++++-- 11 files changed, 47 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 8c2e92378b49..1e9dd00620bf 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -606,7 +606,8 @@ static int kfd_ioctl_set_memory_policy(struct file *filep, default_policy, alternate_policy, (void __user *)args->alternate_aperture_base, - args->alternate_aperture_size)) + args->alternate_aperture_size, + args->misc_process_flag)) err = -EINVAL; out: diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index d23c6a358d34..2afcc1b4856a 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -2596,7 +2596,8 @@ static bool set_cache_memory_policy(struct device_queue_manager *dqm, enum cache_policy default_policy, enum cache_policy alternate_policy, void __user *alternate_aperture_base, - uint64_t alternate_aperture_size) + uint64_t alternate_aperture_size, + u32 misc_process_properties) { bool retval = true; @@ -2611,7 +2612,8 @@ static bool set_cache_memory_policy(struct device_queue_manager *dqm, default_policy, alternate_policy, alternate_aperture_base, - alternate_aperture_size); + alternate_aperture_size, + misc_process_properties); if (retval) goto out; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h index 7146e227e2c1..122eb745e9c4 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h @@ -174,7 +174,8 @@ struct device_queue_manager_ops { enum cache_policy default_policy, enum cache_policy alternate_policy, void __user *alternate_aperture_base, - uint64_t alternate_aperture_size); + uint64_t alternate_aperture_size, + u32 misc_process_properties); int (*process_termination)(struct device_queue_manager *dqm, struct qcm_process_device *qpd); @@ -210,7 +211,8 @@ struct device_queue_manager_asic_ops { enum cache_policy default_policy, enum cache_policy alternate_policy, void __user *alternate_aperture_base, - uint64_t alternate_aperture_size); + uint64_t alternate_aperture_size, + u32 misc_process_properties); void (*init_sdma_vm)(struct device_queue_manager *dqm, struct queue *q, struct qcm_process_device *qpd); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_cik.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_cik.c index 32bedef912b3..0508ef5a41d7 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_cik.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_cik.c @@ -40,7 +40,8 @@ static bool set_cache_memory_policy_cik(struct device_queue_manager *dqm, enum cache_policy default_policy, enum cache_policy alternate_policy, void __user *alternate_aperture_base, - uint64_t alternate_aperture_size); + uint64_t alternate_aperture_size, + u32 misc_process_properties); static int update_qpd_cik(struct device_queue_manager *dqm, struct qcm_process_device *qpd); static void init_sdma_vm(struct device_queue_manager *dqm, @@ -88,7 +89,8 @@ static bool set_cache_memory_policy_cik(struct device_queue_manager *dqm, enum cache_policy default_policy, enum cache_policy alternate_policy, void __user *alternate_aperture_base, - uint64_t alternate_aperture_size) + uint64_t alternate_aperture_size, + u32 misc_process_properties) { uint32_t default_mtype; uint32_t ape1_mtype; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v10.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v10.c index b5f5f141353b..ba6e3d747ccd 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v10.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v10.c @@ -36,7 +36,8 @@ static bool set_cache_memory_policy_v10(struct device_queue_manager *dqm, enum cache_policy default_policy, enum cache_policy alternate_policy, void __user *alternate_aperture_base, - uint64_t alternate_aperture_size); + uint64_t alternate_aperture_size, + u32 misc_process_properties); void device_queue_manager_init_v10( struct device_queue_manager_asic_ops *asic_ops) @@ -61,7 +62,8 @@ static bool set_cache_memory_policy_v10(struct device_queue_manager *dqm, enum cache_policy default_policy, enum cache_policy alternate_policy, void __user *alternate_aperture_base, - uint64_t alternate_aperture_size) + uint64_t alternate_aperture_size, + u32 misc_process_properties) { qpd->sh_mem_config = (SH_MEM_ALIGNMENT_MODE_UNALIGNED << SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) | diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v11.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v11.c index f436878d0d62..8b447d04558f 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v11.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v11.c @@ -35,7 +35,8 @@ static bool set_cache_memory_policy_v11(struct device_queue_manager *dqm, enum cache_policy default_policy, enum cache_policy alternate_policy, void __user *alternate_aperture_base, - uint64_t alternate_aperture_size); + uint64_t alternate_aperture_size, + u32 misc_process_properties); void device_queue_manager_init_v11( struct device_queue_manager_asic_ops *asic_ops) @@ -60,7 +61,8 @@ static bool set_cache_memory_policy_v11(struct device_queue_manager *dqm, enum cache_policy default_policy, enum cache_policy alternate_policy, void __user *alternate_aperture_base, - uint64_t alternate_aperture_size) + uint64_t alternate_aperture_size, + u32 misc_process_properties) { qpd->sh_mem_config = (SH_MEM_ALIGNMENT_MODE_UNALIGNED << SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) | diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v12.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v12.c index 62ca1c8fcbaf..3550da3a46f9 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v12.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v12.c @@ -35,7 +35,8 @@ static bool set_cache_memory_policy_v12(struct device_queue_manager *dqm, enum cache_policy default_policy, enum cache_policy alternate_policy, void __user *alternate_aperture_base, - uint64_t alternate_aperture_size); + uint64_t alternate_aperture_size, + u32 misc_process_properties); void device_queue_manager_init_v12( struct device_queue_manager_asic_ops *asic_ops) @@ -60,7 +61,8 @@ static bool set_cache_memory_policy_v12(struct device_queue_manager *dqm, enum cache_policy default_policy, enum cache_policy alternate_policy, void __user *alternate_aperture_base, - uint64_t alternate_aperture_size) + uint64_t alternate_aperture_size, + u32 misc_process_properties) { qpd->sh_mem_config = (SH_MEM_ALIGNMENT_MODE_UNALIGNED << SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) | diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c index 3264509408bc..d794c8172b40 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c @@ -35,7 +35,8 @@ static bool set_cache_memory_policy_v9(struct device_queue_manager *dqm, enum cache_policy default_policy, enum cache_policy alternate_policy, void __user *alternate_aperture_base, - uint64_t alternate_aperture_size); + uint64_t alternate_aperture_size, + u32 misc_process_properties); void device_queue_manager_init_v9( struct device_queue_manager_asic_ops *asic_ops) @@ -60,7 +61,8 @@ static bool set_cache_memory_policy_v9(struct device_queue_manager *dqm, enum cache_policy default_policy, enum cache_policy alternate_policy, void __user *alternate_aperture_base, - uint64_t alternate_aperture_size) + uint64_t alternate_aperture_size, + u32 misc_process_properties) { qpd->sh_mem_config = SH_MEM_ALIGNMENT_MODE_UNALIGNED << SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT; @@ -73,6 +75,11 @@ static bool set_cache_memory_policy_v9(struct device_queue_manager *dqm, KFD_GC_VERSION(dqm->dev->kfd) == IP_VERSION(9, 5, 0)) qpd->sh_mem_config |= (1 << SH_MEM_CONFIG__F8_MODE__SHIFT); + if (KFD_GC_VERSION(dqm->dev->kfd) == IP_VERSION(9, 5, 0)) { + if (misc_process_properties & KFD_PROC_FLAG_MFMA_HIGH_PRECISION) + qpd->sh_mem_config |= 1 << SH_MEM_CONFIG__PRECISION_MODE__SHIFT; + } + qpd->sh_mem_ape1_limit = 0; qpd->sh_mem_ape1_base = 0; qpd->sh_mem_bases = compute_sh_mem_bases_64bit(qpd_to_pdd(qpd)); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_vi.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_vi.c index 320518f41890..dad83356e976 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_vi.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_vi.c @@ -40,7 +40,8 @@ static bool set_cache_memory_policy_vi(struct device_queue_manager *dqm, enum cache_policy default_policy, enum cache_policy alternate_policy, void __user *alternate_aperture_base, - uint64_t alternate_aperture_size); + uint64_t alternate_aperture_size, + u32 misc_process_properties); static int update_qpd_vi(struct device_queue_manager *dqm, struct qcm_process_device *qpd); static void init_sdma_vm(struct device_queue_manager *dqm, @@ -89,7 +90,8 @@ static bool set_cache_memory_policy_vi(struct device_queue_manager *dqm, enum cache_policy default_policy, enum cache_policy alternate_policy, void __user *alternate_aperture_base, - uint64_t alternate_aperture_size) + uint64_t alternate_aperture_size, + u32 misc_process_properties) { uint32_t default_mtype; uint32_t ape1_mtype; diff --git a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_9_4_3_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_9_4_3_sh_mask.h index 2bd9f3f1026f..0122a21c50cf 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_9_4_3_sh_mask.h +++ b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_9_4_3_sh_mask.h @@ -2261,11 +2261,13 @@ #define SH_MEM_CONFIG__ADDRESS_MODE__SHIFT 0x0 #define SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT 0x3 #define SH_MEM_CONFIG__F8_MODE__SHIFT 0x8 +#define SH_MEM_CONFIG__PRECISION_MODE__SHIFT 0x9 #define SH_MEM_CONFIG__RETRY_DISABLE__SHIFT 0xc #define SH_MEM_CONFIG__PRIVATE_NV__SHIFT 0xd #define SH_MEM_CONFIG__ADDRESS_MODE_MASK 0x00000001L #define SH_MEM_CONFIG__ALIGNMENT_MODE_MASK 0x00000018L #define SH_MEM_CONFIG__F8_MODE_MASK 0x00000100L +#define SH_MEM_CONFIG__PRECISION_MODE_MASK 0x00000200L #define SH_MEM_CONFIG__RETRY_DISABLE_MASK 0x00001000L #define SH_MEM_CONFIG__PRIVATE_NV_MASK 0x00002000L //SP_MFMA_PORTD_RD_CONFIG diff --git a/include/uapi/linux/kfd_ioctl.h b/include/uapi/linux/kfd_ioctl.h index b0160b09987c..1e59344c5673 100644 --- a/include/uapi/linux/kfd_ioctl.h +++ b/include/uapi/linux/kfd_ioctl.h @@ -43,9 +43,10 @@ * - 1.15 - Enable managing mappings in compute VMs with GEM_VA ioctl * - 1.16 - Add contiguous VRAM allocation flag * - 1.17 - Add SDMA queue creation with target SDMA engine ID + * - 1.18 - Rename pad in set_memory_policy_args to misc_process_flag */ #define KFD_IOCTL_MAJOR_VERSION 1 -#define KFD_IOCTL_MINOR_VERSION 17 +#define KFD_IOCTL_MINOR_VERSION 18 struct kfd_ioctl_get_version_args { __u32 major_version; /* from KFD */ @@ -150,6 +151,9 @@ struct kfd_dbg_device_info_entry { #define KFD_IOC_CACHE_POLICY_COHERENT 0 #define KFD_IOC_CACHE_POLICY_NONCOHERENT 1 +/* Misc. per process flags */ +#define KFD_PROC_FLAG_MFMA_HIGH_PRECISION (1 << 0) + struct kfd_ioctl_set_memory_policy_args { __u64 alternate_aperture_base; /* to KFD */ __u64 alternate_aperture_size; /* to KFD */ @@ -157,7 +161,7 @@ struct kfd_ioctl_set_memory_policy_args { __u32 gpu_id; /* to KFD */ __u32 default_policy; /* to KFD */ __u32 alternate_policy; /* to KFD */ - __u32 pad; + __u32 misc_process_flag; /* to KFD */ }; /*