drm/amdgpu: add timeout flush mechanism to update wptr for self interrupt (v2)

outstanding log reaches threshold will trigger IH ring1/2's wptr
reported, that will avoid generating interrupts to ring0 too frequent.
But if ring1/2's wptr hasn't been increased for a long time, the outstanding log
can't reach threshold so that driver can't get latest wptr info and
miss some interrupts.

v2: squash in warning fix

Signed-off-by: Chengming Gui <Jack.Gui@amd.com>
Reviewed-by: Feifei Xu <Feifei.Xu@amd.com>
Acked-by: Felix Kuehling <Felix.Kuehling@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Chengming Gui 2020-07-14 16:25:04 +08:00 committed by Alex Deucher
parent c652923afa
commit 5ea6f9c22c
1 changed files with 45 additions and 0 deletions

View File

@ -39,6 +39,48 @@
static void navi10_ih_set_interrupt_funcs(struct amdgpu_device *adev); static void navi10_ih_set_interrupt_funcs(struct amdgpu_device *adev);
/**
* force_update_wptr_for_self_int - Force update the wptr for self interrupt
*
* @adev: amdgpu_device pointer
* @threshold: threshold to trigger the wptr reporting
* @timeout: timeout to trigger the wptr reporting
* @enabled: Enable/disable timeout flush mechanism
*
* threshold input range: 0 ~ 15, default 0,
* real_threshold = 2^threshold
* timeout input range: 0 ~ 20, default 8,
* real_timeout = (2^timeout) * 1024 / (socclk_freq)
*
* Force update wptr for self interrupt ( >= SIENNA_CICHLID).
*/
static void
force_update_wptr_for_self_int(struct amdgpu_device *adev,
u32 threshold, u32 timeout, bool enabled)
{
u32 ih_cntl, ih_rb_cntl;
if (adev->asic_type < CHIP_SIENNA_CICHLID)
return;
ih_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_CNTL2);
ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1);
ih_cntl = REG_SET_FIELD(ih_cntl, IH_CNTL2,
SELF_IV_FORCE_WPTR_UPDATE_TIMEOUT, timeout);
ih_cntl = REG_SET_FIELD(ih_cntl, IH_CNTL2,
SELF_IV_FORCE_WPTR_UPDATE_ENABLE, enabled);
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING1,
RB_USED_INT_THRESHOLD, threshold);
WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1, ih_rb_cntl);
ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2);
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING2,
RB_USED_INT_THRESHOLD, threshold);
WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2, ih_rb_cntl);
WREG32_SOC15(OSSSYS, 0, mmIH_CNTL2, ih_cntl);
}
/** /**
* navi10_ih_enable_interrupts - Enable the interrupt ring buffer * navi10_ih_enable_interrupts - Enable the interrupt ring buffer
* *
@ -371,6 +413,8 @@ static int navi10_ih_irq_init(struct amdgpu_device *adev)
/* enable interrupts */ /* enable interrupts */
navi10_ih_enable_interrupts(adev); navi10_ih_enable_interrupts(adev);
/* enable wptr force update for self int */
force_update_wptr_for_self_int(adev, 0, 8, true);
return 0; return 0;
} }
@ -384,6 +428,7 @@ static int navi10_ih_irq_init(struct amdgpu_device *adev)
*/ */
static void navi10_ih_irq_disable(struct amdgpu_device *adev) static void navi10_ih_irq_disable(struct amdgpu_device *adev)
{ {
force_update_wptr_for_self_int(adev, 0, 8, false);
navi10_ih_disable_interrupts(adev); navi10_ih_disable_interrupts(adev);
/* Wait and acknowledge irq */ /* Wait and acknowledge irq */