mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-16 00:51:51 -04:00
drm/msm/a6xx: Poll AHB fence status in GPU IRQ handler
Even though the GX power domain is kept ON when there is a pending GPU interrupt, there is a small window of potential race with GMU where it may move the AHB fence to 'Drop' mode. Once the GMU sees the pending IRQ, it will move back the fence state to ALLOW mode. Close this race window by polling for AHB fence to ensure that it is in 'Allow' mode. Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com> Patchwork: https://patchwork.freedesktop.org/patch/673377/ Signed-off-by: Rob Clark <robin.clark@oss.qualcomm.com>
This commit is contained in:
committed by
Rob Clark
parent
f195421318
commit
04ca842ef2
@@ -167,6 +167,9 @@ static inline u64 gmu_read64(struct a6xx_gmu *gmu, u32 lo, u32 hi)
|
||||
#define gmu_poll_timeout(gmu, addr, val, cond, interval, timeout) \
|
||||
readl_poll_timeout((gmu)->mmio + ((addr) << 2), val, cond, \
|
||||
interval, timeout)
|
||||
#define gmu_poll_timeout_atomic(gmu, addr, val, cond, interval, timeout) \
|
||||
readl_poll_timeout_atomic((gmu)->mmio + ((addr) << 2), val, cond, \
|
||||
interval, timeout)
|
||||
|
||||
static inline u32 gmu_read_rscc(struct a6xx_gmu *gmu, u32 offset)
|
||||
{
|
||||
|
||||
@@ -1845,6 +1845,28 @@ static void a6xx_gpu_keepalive_vote(struct msm_gpu *gpu, bool on)
|
||||
gmu_write(&a6xx_gpu->gmu, REG_A6XX_GMU_GMU_PWR_COL_KEEPALIVE, on);
|
||||
}
|
||||
|
||||
static int irq_poll_fence(struct msm_gpu *gpu)
|
||||
{
|
||||
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
|
||||
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
|
||||
struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
|
||||
u32 status;
|
||||
|
||||
if (adreno_has_gmu_wrapper(adreno_gpu))
|
||||
return 0;
|
||||
|
||||
if (gmu_poll_timeout_atomic(gmu, REG_A6XX_GMU_AO_AHB_FENCE_CTRL, status, !status, 1, 100)) {
|
||||
u32 rbbm_unmasked = gmu_read(gmu, REG_A6XX_GMU_RBBM_INT_UNMASKED_STATUS);
|
||||
|
||||
dev_err_ratelimited(&gpu->pdev->dev,
|
||||
"irq fence poll timeout, fence_ctrl=0x%x, unmasked_status=0x%x\n",
|
||||
status, rbbm_unmasked);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t a6xx_irq(struct msm_gpu *gpu)
|
||||
{
|
||||
struct msm_drm_private *priv = gpu->dev->dev_private;
|
||||
@@ -1852,6 +1874,9 @@ static irqreturn_t a6xx_irq(struct msm_gpu *gpu)
|
||||
/* Set keepalive vote to avoid power collapse after RBBM_INT_0_STATUS is read */
|
||||
a6xx_gpu_keepalive_vote(gpu, true);
|
||||
|
||||
if (irq_poll_fence(gpu))
|
||||
goto done;
|
||||
|
||||
u32 status = gpu_read(gpu, REG_A6XX_RBBM_INT_0_STATUS);
|
||||
|
||||
gpu_write(gpu, REG_A6XX_RBBM_INT_CLEAR_CMD, status);
|
||||
@@ -1888,6 +1913,7 @@ static irqreturn_t a6xx_irq(struct msm_gpu *gpu)
|
||||
if (status & A6XX_RBBM_INT_0_MASK_CP_SW)
|
||||
a6xx_preempt_irq(gpu);
|
||||
|
||||
done:
|
||||
a6xx_gpu_keepalive_vote(gpu, false);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
|
||||
Reference in New Issue
Block a user