]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
drm/msm/a6xx: Set Keep-alive votes to block IFPC
authorAkhil P Oommen <akhilpo@oss.qualcomm.com>
Mon, 8 Sep 2025 08:27:01 +0000 (13:57 +0530)
committerRob Clark <robin.clark@oss.qualcomm.com>
Mon, 8 Sep 2025 14:25:00 +0000 (07:25 -0700)
Set Keepalive votes at appropriate places to block IFPC power collapse
until we access all the required registers. This is required during gpu
IRQ handling and also during preemption.

Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
Patchwork: https://patchwork.freedesktop.org/patch/673369/
Signed-off-by: Rob Clark <robin.clark@oss.qualcomm.com>
drivers/gpu/drm/msm/adreno/a6xx_gpu.c
drivers/gpu/drm/msm/adreno/a6xx_preempt.c

index 536da1acf615ed6b5a1e219e536e527de9c1a7ab..2a2b29949e86d682a9020a0d0c55866b3bef94cc 100644 (file)
@@ -1771,8 +1771,6 @@ static void a6xx_cp_hw_err_irq(struct msm_gpu *gpu)
 
 static void a6xx_fault_detect_irq(struct msm_gpu *gpu)
 {
-       struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
-       struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
        struct msm_ringbuffer *ring = gpu->funcs->active_ring(gpu);
 
        /*
@@ -1784,13 +1782,6 @@ static void a6xx_fault_detect_irq(struct msm_gpu *gpu)
        if (gpu_read(gpu, REG_A6XX_RBBM_STATUS3) & A6XX_RBBM_STATUS3_SMMU_STALLED_ON_FAULT)
                return;
 
-       /*
-        * Force the GPU to stay on until after we finish
-        * collecting information
-        */
-       if (!adreno_has_gmu_wrapper(adreno_gpu))
-               gmu_write(&a6xx_gpu->gmu, REG_A6XX_GMU_GMU_PWR_COL_KEEPALIVE, 1);
-
        DRM_DEV_ERROR(&gpu->pdev->dev,
                "gpu fault ring %d fence %x status %8.8X rb %4.4x/%4.4x ib1 %16.16llX/%4.4x ib2 %16.16llX/%4.4x\n",
                ring ? ring->id : -1, ring ? ring->fctx->last_fence : 0,
@@ -1832,9 +1823,24 @@ static void a7xx_sw_fuse_violation_irq(struct msm_gpu *gpu)
        }
 }
 
+static void a6xx_gpu_keepalive_vote(struct msm_gpu *gpu, bool on)
+{
+       struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+       struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
+
+       if (adreno_has_gmu_wrapper(adreno_gpu))
+               return;
+
+       gmu_write(&a6xx_gpu->gmu, REG_A6XX_GMU_GMU_PWR_COL_KEEPALIVE, on);
+}
+
 static irqreturn_t a6xx_irq(struct msm_gpu *gpu)
 {
        struct msm_drm_private *priv = gpu->dev->dev_private;
+
+       /* Set keepalive vote to avoid power collapse after RBBM_INT_0_STATUS is read */
+       a6xx_gpu_keepalive_vote(gpu, true);
+
        u32 status = gpu_read(gpu, REG_A6XX_RBBM_INT_0_STATUS);
 
        gpu_write(gpu, REG_A6XX_RBBM_INT_CLEAR_CMD, status);
@@ -1871,6 +1877,8 @@ static irqreturn_t a6xx_irq(struct msm_gpu *gpu)
        if (status & A6XX_RBBM_INT_0_MASK_CP_SW)
                a6xx_preempt_irq(gpu);
 
+       a6xx_gpu_keepalive_vote(gpu, false);
+
        return IRQ_HANDLED;
 }
 
index 10625ffbc4cfc26edc36efcf11dbb4efd55ab3e0..2ce073d1cf8cfd7c774918851de03d6e367e5625 100644 (file)
@@ -136,6 +136,21 @@ static void preempt_disable_postamble(struct a6xx_gpu *a6xx_gpu)
        a6xx_gpu->postamble_enabled = false;
 }
 
+/*
+ * Set preemption keepalive vote. Please note that this vote is different from the one used in
+ * a6xx_irq()
+ */
+static void a6xx_preempt_keepalive_vote(struct msm_gpu *gpu, bool on)
+{
+       struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+       struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
+
+       if (adreno_has_gmu_wrapper(adreno_gpu))
+               return;
+
+       gmu_write(&a6xx_gpu->gmu, REG_A6XX_GMU_PWR_COL_PREEMPT_KEEPALIVE, on);
+}
+
 void a6xx_preempt_irq(struct msm_gpu *gpu)
 {
        uint32_t status;
@@ -176,6 +191,8 @@ void a6xx_preempt_irq(struct msm_gpu *gpu)
 
        set_preempt_state(a6xx_gpu, PREEMPT_NONE);
 
+       a6xx_preempt_keepalive_vote(gpu, false);
+
        trace_msm_gpu_preemption_irq(a6xx_gpu->cur_ring->id);
 
        /*
@@ -302,6 +319,9 @@ void a6xx_preempt_trigger(struct msm_gpu *gpu)
 
        spin_unlock_irqrestore(&ring->preempt_lock, flags);
 
+       /* Set the keepalive bit to keep the GPU ON until preemption is complete */
+       a6xx_preempt_keepalive_vote(gpu, true);
+
        a6xx_fenced_write(a6xx_gpu,
                REG_A6XX_CP_CONTEXT_SWITCH_SMMU_INFO, a6xx_gpu->preempt_smmu_iova[ring->id],
                BIT(1), true);