Skip to content

Commit f248d5d

Browse files
akhilpo-qcomRob Clark
authored andcommitted
drm/msm/a6xx: Fix PDC sleep sequence
Since the PDC resides out of the GPU subsystem and cannot be reset in case it enters bad state, utmost care must be taken to trigger the PDC wake/sleep routines in the correct order. The PDC wake sequence can be exercised only after a PDC sleep sequence. Additionally, GMU firmware should initialize a few registers before the KMD can trigger a PDC sleep sequence. So PDC sleep can't be done if the GMU firmware has not initialized. Track these dependencies using a new status variable and trigger PDC sleep/wake sequences appropriately. Cc: stable@vger.kernel.org Fixes: 4b565ca ("drm/msm: Add A6XX device support") Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com> Patchwork: https://patchwork.freedesktop.org/patch/673362/ Signed-off-by: Rob Clark <robin.clark@oss.qualcomm.com>
1 parent ea60150 commit f248d5d

2 files changed

Lines changed: 23 additions & 11 deletions

File tree

drivers/gpu/drm/msm/adreno/a6xx_gmu.c

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,8 @@ static int a6xx_gmu_start(struct a6xx_gmu *gmu)
279279
if (ret)
280280
DRM_DEV_ERROR(gmu->dev, "GMU firmware initialization timed out\n");
281281

282+
set_bit(GMU_STATUS_FW_START, &gmu->status);
283+
282284
return ret;
283285
}
284286

@@ -525,6 +527,9 @@ static int a6xx_rpmh_start(struct a6xx_gmu *gmu)
525527
int ret;
526528
u32 val;
527529

530+
if (!test_and_clear_bit(GMU_STATUS_PDC_SLEEP, &gmu->status))
531+
return 0;
532+
528533
gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, BIT(1));
529534

530535
ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_RSCC_CONTROL_ACK, val,
@@ -552,6 +557,9 @@ static void a6xx_rpmh_stop(struct a6xx_gmu *gmu)
552557
int ret;
553558
u32 val;
554559

560+
if (test_and_clear_bit(GMU_STATUS_FW_START, &gmu->status))
561+
return;
562+
555563
gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, 1);
556564

557565
ret = gmu_poll_timeout_rscc(gmu, REG_A6XX_GPU_RSCC_RSC_STATUS0_DRV0,
@@ -560,6 +568,8 @@ static void a6xx_rpmh_stop(struct a6xx_gmu *gmu)
560568
DRM_DEV_ERROR(gmu->dev, "Unable to power off the GPU RSC\n");
561569

562570
gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, 0);
571+
572+
set_bit(GMU_STATUS_PDC_SLEEP, &gmu->status);
563573
}
564574

565575
static inline void pdc_write(void __iomem *ptr, u32 offset, u32 value)
@@ -688,8 +698,6 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu)
688698
/* ensure no writes happen before the uCode is fully written */
689699
wmb();
690700

691-
a6xx_rpmh_stop(gmu);
692-
693701
err:
694702
if (!IS_ERR_OR_NULL(pdcptr))
695703
iounmap(pdcptr);
@@ -849,19 +857,15 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state)
849857
else
850858
gmu_write(gmu, REG_A6XX_GMU_GENERAL_7, 1);
851859

852-
if (state == GMU_WARM_BOOT) {
853-
ret = a6xx_rpmh_start(gmu);
854-
if (ret)
855-
return ret;
856-
} else {
860+
ret = a6xx_rpmh_start(gmu);
861+
if (ret)
862+
return ret;
863+
864+
if (state == GMU_COLD_BOOT) {
857865
if (WARN(!adreno_gpu->fw[ADRENO_FW_GMU],
858866
"GMU firmware is not loaded\n"))
859867
return -ENOENT;
860868

861-
ret = a6xx_rpmh_start(gmu);
862-
if (ret)
863-
return ret;
864-
865869
ret = a6xx_gmu_fw_load(gmu);
866870
if (ret)
867871
return ret;
@@ -1046,6 +1050,8 @@ static void a6xx_gmu_force_off(struct a6xx_gmu *gmu)
10461050

10471051
/* Reset GPU core blocks */
10481052
a6xx_gpu_sw_reset(gpu, true);
1053+
1054+
a6xx_rpmh_stop(gmu);
10491055
}
10501056

10511057
static void a6xx_gmu_set_initial_freq(struct msm_gpu *gpu, struct a6xx_gmu *gmu)

drivers/gpu/drm/msm/adreno/a6xx_gmu.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,12 @@ struct a6xx_gmu {
117117

118118
struct qmp *qmp;
119119
struct a6xx_hfi_msg_bw_table *bw_table;
120+
121+
/* To check if we can trigger sleep seq at PDC. Cleared in a6xx_rpmh_stop() */
122+
#define GMU_STATUS_FW_START 0
123+
/* To track if PDC sleep seq was done */
124+
#define GMU_STATUS_PDC_SLEEP 1
125+
unsigned long status;
120126
};
121127

122128
static inline u32 gmu_read(struct a6xx_gmu *gmu, u32 offset)

0 commit comments

Comments
 (0)