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 <akhi...@oss.qualcomm.com>
---
 drivers/gpu/drm/msm/adreno/a6xx_gpu.c     | 26 +++++++++++++++++---------
 drivers/gpu/drm/msm/adreno/a6xx_preempt.c | 20 ++++++++++++++++++++
 2 files changed, 37 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c 
b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index 
a63dad80ef461da45d5c41a042ed4f19d8282ef5..33a26bbd245ff49784bf1219a584936b4caa62b6
 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -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,
@@ -1829,9 +1820,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);
@@ -1868,6 +1874,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;
 }
 
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_preempt.c 
b/drivers/gpu/drm/msm/adreno/a6xx_preempt.c
index 
10625ffbc4cfc26edc36efcf11dbb4efd55ab3e0..2ce073d1cf8cfd7c774918851de03d6e367e5625
 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_preempt.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_preempt.c
@@ -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);

-- 
2.50.1

Reply via email to