]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
drm/amdgpu: clear RB_OVERFLOW bit when enabling interrupts for vega20_ih
authorVictor Lu <victorchengchi.lu@amd.com>
Thu, 18 Jul 2024 22:01:23 +0000 (18:01 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 14 Dec 2024 18:51:38 +0000 (19:51 +0100)
[ Upstream commit 8b22f048331dfd45fdfbf0efdfb1d43deff7518d ]

Port this change to vega20_ih.c:
commit afbf7955ff01 ("drm/amdgpu: clear RB_OVERFLOW bit when enabling interrupts")

Original commit message:
"Why:
Setting IH_RB_WPTR register to 0 will not clear the RB_OVERFLOW bit
if RB_ENABLE is not set.

How to fix:
Set WPTR_OVERFLOW_CLEAR bit after RB_ENABLE bit is set.
The RB_ENABLE bit is required to be set, together with
WPTR_OVERFLOW_ENABLE bit so that setting WPTR_OVERFLOW_CLEAR bit
would clear the RB_OVERFLOW."

Signed-off-by: Victor Lu <victorchengchi.lu@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/gpu/drm/amd/amdgpu/vega20_ih.c

index 87edd1908e8b943d1b85c53e9197b953445390b3..9e1ed14cc3141c85e656ecccf695afd0514b78dc 100644 (file)
@@ -109,6 +109,33 @@ static int vega20_ih_toggle_ring_interrupts(struct amdgpu_device *adev,
        tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, RB_ENABLE, (enable ? 1 : 0));
        tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, RB_GPU_TS_ENABLE, 1);
 
+       if (enable) {
+               /* Unset the CLEAR_OVERFLOW bit to make sure the next step
+                * is switching the bit from 0 to 1
+                */
+               tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 0);
+               if (amdgpu_sriov_vf(adev) && amdgpu_sriov_reg_indirect_ih(adev)) {
+                       if (psp_reg_program(&adev->psp, ih_regs->psp_reg_id, tmp))
+                               return -ETIMEDOUT;
+               } else {
+                       WREG32_NO_KIQ(ih_regs->ih_rb_cntl, tmp);
+               }
+
+               /* Clear RB_OVERFLOW bit */
+               tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
+               if (amdgpu_sriov_vf(adev) && amdgpu_sriov_reg_indirect_ih(adev)) {
+                       if (psp_reg_program(&adev->psp, ih_regs->psp_reg_id, tmp))
+                               return -ETIMEDOUT;
+               } else {
+                       WREG32_NO_KIQ(ih_regs->ih_rb_cntl, tmp);
+               }
+
+               /* Unset the CLEAR_OVERFLOW bit immediately so new overflows
+                * can be detected.
+                */
+               tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 0);
+       }
+
        /* enable_intr field is only valid in ring0 */
        if (ih == &adev->irq.ih)
                tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, ENABLE_INTR, (enable ? 1 : 0));