* [PATCH 00/17] drm/msm: Support for Inter Frame Power Collapse (IFPC) feature
@ 2025-07-20 12:16 Akhil P Oommen
2025-07-20 12:16 ` [PATCH 01/17] drm/msm: Update GMU register xml Akhil P Oommen
` (16 more replies)
0 siblings, 17 replies; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-20 12:16 UTC (permalink / raw)
To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Akhil P Oommen
This patch series introduces the IFPC feature to the DRM-MSM driver for
Adreno GPUs. IFPC enables GMU to quickly transition GPU into a low power
state when idle and quickly resume gpu to active state upon workload
submission, hence the name 'Inter Frame Power Collapse'. Since the KMD is
unaware of these transitions, it must perform a handshake with the
hardware (eg: fenced_write, OOB signaling etc) before accessing registers
in the GX power domain.
Initial patches address a few existing issues that were not exposed in the
absence of IFPC. With IFPC, msm_devfreq_idle becomes redundant and
therefore it is disabled for GPUs that support this feature. Additionally,
the DCVS tunings have been relaxed for GPUs with IFPC support to further
improve power savings.
This series also adds the necessary restore register list for X1-85 GPU
and enables IFPC support for it.
To: Rob Clark <robin.clark@oss.qualcomm.com>
To: Sean Paul <sean@poorly.run>
To: Konrad Dybcio <konradybcio@kernel.org>
To: Dmitry Baryshkov <lumag@kernel.org>
To: Abhinav Kumar <abhinav.kumar@linux.dev>
To: Jessica Zhang <jessica.zhang@oss.qualcomm.com>
To: Marijn Suijten <marijn.suijten@somainline.org>
To: David Airlie <airlied@gmail.com>
To: Simona Vetter <simona@ffwll.ch>
Cc: linux-arm-msm@vger.kernel.org
Cc: dri-devel@lists.freedesktop.org
Cc: freedreno@lists.freedesktop.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
---
Akhil P Oommen (17):
drm/msm: Update GMU register xml
drm/msm: a6xx: Refactor a6xx_sptprac_enable()
drm/msm: a6xx: Fix gx_is_on check for a7x family
drm/msm/a6xx: Poll additional DRV status
drm/msm/a6xx: Fix PDC sleep sequence
drm/msm: Add an ftrace for gpu register access
drm/msm/adreno: Add fenced regwrite support
drm/msm/a6xx: Set Keep-alive votes to block IFPC
drm/msm/a6xx: Switch to GMU AO counter
drm/msm/a6xx: Poll AHB fence status in GPU IRQ handler
drm/msm: Add support for IFPC
drm/msm: Skip devfreq IDLE when possible
drm/msm/a6xx: Fix hangcheck for IFPC
drm/msm/adreno: Disable IFPC when sysprof is active
drm/msm/a6xx: Make crashstate capture IFPC safe
drm/msm/a6xx: Enable IFPC on Adreno X1-85
drm/msm/adreno: Relax devfreq tunings
drivers/gpu/drm/msm/adreno/a6xx_catalog.c | 67 ++++++-
drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 107 ++++++++++--
drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 11 ++
drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 203 ++++++++++++++++++----
drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 3 +
drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c | 10 +-
drivers/gpu/drm/msm/adreno/a6xx_hfi.c | 33 +++-
drivers/gpu/drm/msm/adreno/a6xx_preempt.c | 40 +++--
drivers/gpu/drm/msm/adreno/adreno_gpu.h | 1 +
drivers/gpu/drm/msm/msm_gpu.h | 9 +
drivers/gpu/drm/msm/msm_gpu_devfreq.c | 13 ++
drivers/gpu/drm/msm/msm_gpu_trace.h | 12 ++
drivers/gpu/drm/msm/msm_submitqueue.c | 4 +
drivers/gpu/drm/msm/registers/adreno/a6xx_gmu.xml | 11 ++
14 files changed, 449 insertions(+), 75 deletions(-)
---
base-commit: 88bf743cabe5793d24f831ef8240a0bf90e5fd44
change-id: 20241216-ifpc-support-3b80167b3532
Best regards,
--
Akhil P Oommen <akhilpo@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 85+ messages in thread
* [PATCH 01/17] drm/msm: Update GMU register xml
2025-07-20 12:16 [PATCH 00/17] drm/msm: Support for Inter Frame Power Collapse (IFPC) feature Akhil P Oommen
@ 2025-07-20 12:16 ` Akhil P Oommen
2025-07-20 12:16 ` [PATCH 02/17] drm/msm: a6xx: Refactor a6xx_sptprac_enable() Akhil P Oommen
` (15 subsequent siblings)
16 siblings, 0 replies; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-20 12:16 UTC (permalink / raw)
To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Akhil P Oommen
Update GMU register xml with additional definitions for a7x family.
Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
---
drivers/gpu/drm/msm/registers/adreno/a6xx_gmu.xml | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/drivers/gpu/drm/msm/registers/adreno/a6xx_gmu.xml b/drivers/gpu/drm/msm/registers/adreno/a6xx_gmu.xml
index 3d2cc339b8f19c8d24b2c9144569b2364afc5ebc..b15a242d974d6b42133171c8484d3b0413f2d3a4 100644
--- a/drivers/gpu/drm/msm/registers/adreno/a6xx_gmu.xml
+++ b/drivers/gpu/drm/msm/registers/adreno/a6xx_gmu.xml
@@ -99,6 +99,10 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
<bitfield name="GX_HM_GDSC_POWER_OFF" pos="6" type="boolean"/>
<bitfield name="GX_HM_CLK_OFF" pos="7" type="boolean"/>
</reg32>
+ <reg32 offset="0x50d0" name="GMU_SPTPRAC_PWR_CLK_STATUS" variants="A7XX">
+ <bitfield name="GX_HM_GDSC_POWER_OFF" pos="0" type="boolean"/>
+ <bitfield name="GX_HM_CLK_OFF" pos="1" type="boolean"/>
+ </reg32>
<reg32 offset="0x50e4" name="GMU_GPU_NAP_CTRL">
<bitfield name="HW_NAP_ENABLE" pos="0"/>
<bitfield name="SID" low="4" high="8"/>
@@ -127,6 +131,7 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
<reg32 offset="0x5088" name="GMU_ALWAYS_ON_COUNTER_L"/>
<reg32 offset="0x5089" name="GMU_ALWAYS_ON_COUNTER_H"/>
<reg32 offset="0x50c3" name="GMU_GMU_PWR_COL_KEEPALIVE"/>
+ <reg32 offset="0x50c4" name="GMU_PWR_COL_PREEMPT_KEEPALIVE"/>
<reg32 offset="0x5180" name="GMU_HFI_CTRL_STATUS"/>
<reg32 offset="0x5181" name="GMU_HFI_VERSION_INFO"/>
<reg32 offset="0x5182" name="GMU_HFI_SFR_ADDR"/>
@@ -228,6 +233,12 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
<reg32 offset="0x03ee" name="RSCC_TCS1_DRV0_STATUS"/>
<reg32 offset="0x0496" name="RSCC_TCS2_DRV0_STATUS"/>
<reg32 offset="0x053e" name="RSCC_TCS3_DRV0_STATUS"/>
+ <reg32 offset="0x05e6" name="RSCC_TCS4_DRV0_STATUS" variants="A7XX"/>
+ <reg32 offset="0x068e" name="RSCC_TCS5_DRV0_STATUS" variants="A7XX"/>
+ <reg32 offset="0x0736" name="RSCC_TCS6_DRV0_STATUS" variants="A7XX"/>
+ <reg32 offset="0x07de" name="RSCC_TCS7_DRV0_STATUS" variants="A7XX"/>
+ <reg32 offset="0x0886" name="RSCC_TCS8_DRV0_STATUS" variants="A7XX"/>
+ <reg32 offset="0x092e" name="RSCC_TCS9_DRV0_STATUS" variants="A7XX"/>
</domain>
</database>
--
2.50.1
^ permalink raw reply related [flat|nested] 85+ messages in thread
* [PATCH 02/17] drm/msm: a6xx: Refactor a6xx_sptprac_enable()
2025-07-20 12:16 [PATCH 00/17] drm/msm: Support for Inter Frame Power Collapse (IFPC) feature Akhil P Oommen
2025-07-20 12:16 ` [PATCH 01/17] drm/msm: Update GMU register xml Akhil P Oommen
@ 2025-07-20 12:16 ` Akhil P Oommen
2025-07-22 14:30 ` Konrad Dybcio
2025-07-20 12:16 ` [PATCH 03/17] drm/msm: a6xx: Fix gx_is_on check for a7x family Akhil P Oommen
` (14 subsequent siblings)
16 siblings, 1 reply; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-20 12:16 UTC (permalink / raw)
To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Akhil P Oommen
A minor refactor to combine the subroutines for legacy a6xx GMUs under
a single check. This helps to avoid an unnecessary check and return
early from the subroutine for majority of a6xx gpus.
Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
---
drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index 38c0f8ef85c3d260864541d83abe43e49c772c52..41129692d127b70e9293b82bea5ccb6b911b0bfb 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -403,7 +403,10 @@ int a6xx_sptprac_enable(struct a6xx_gmu *gmu)
int ret;
u32 val;
- if (!gmu->legacy)
+ WARN_ON(!gmu->legacy);
+
+ /* Nothing to do if GMU does the power management */
+ if (gmu->idle_level > GMU_IDLE_STATE_ACTIVE)
return 0;
gmu_write(gmu, REG_A6XX_GMU_GX_SPTPRAC_POWER_CONTROL, 0x778000);
@@ -925,10 +928,7 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state)
ret = a6xx_gmu_gfx_rail_on(gmu);
if (ret)
return ret;
- }
- /* Enable SPTP_PC if the CPU is responsible for it */
- if (gmu->idle_level < GMU_IDLE_STATE_SPTP) {
ret = a6xx_sptprac_enable(gmu);
if (ret)
return ret;
--
2.50.1
^ permalink raw reply related [flat|nested] 85+ messages in thread
* [PATCH 03/17] drm/msm: a6xx: Fix gx_is_on check for a7x family
2025-07-20 12:16 [PATCH 00/17] drm/msm: Support for Inter Frame Power Collapse (IFPC) feature Akhil P Oommen
2025-07-20 12:16 ` [PATCH 01/17] drm/msm: Update GMU register xml Akhil P Oommen
2025-07-20 12:16 ` [PATCH 02/17] drm/msm: a6xx: Refactor a6xx_sptprac_enable() Akhil P Oommen
@ 2025-07-20 12:16 ` Akhil P Oommen
2025-07-20 18:46 ` Dmitry Baryshkov
2025-07-22 14:33 ` Konrad Dybcio
2025-07-20 12:16 ` [PATCH 04/17] drm/msm/a6xx: Poll additional DRV status Akhil P Oommen
` (13 subsequent siblings)
16 siblings, 2 replies; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-20 12:16 UTC (permalink / raw)
To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Akhil P Oommen
Bitfield definition for REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS register is
different in A7XX family. Check the correct bits to see if GX is
collapsed on A7XX series.
Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
---
drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index 41129692d127b70e9293b82bea5ccb6b911b0bfb..790ef2f94a0b0cd40433d7edb6a89e4f04408bf5 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -93,6 +93,8 @@ bool a6xx_gmu_sptprac_is_on(struct a6xx_gmu *gmu)
/* Check to see if the GX rail is still powered */
bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu)
{
+ struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu);
+ struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
u32 val;
/* This can be called from gpu state code so make sure GMU is valid */
@@ -101,6 +103,11 @@ bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu)
val = gmu_read(gmu, REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS);
+ if (adreno_is_a7xx(adreno_gpu))
+ return !(val &
+ (A7XX_GMU_SPTPRAC_PWR_CLK_STATUS_GX_HM_GDSC_POWER_OFF |
+ A7XX_GMU_SPTPRAC_PWR_CLK_STATUS_GX_HM_CLK_OFF));
+
return !(val &
(A6XX_GMU_SPTPRAC_PWR_CLK_STATUS_GX_HM_GDSC_POWER_OFF |
A6XX_GMU_SPTPRAC_PWR_CLK_STATUS_GX_HM_CLK_OFF));
--
2.50.1
^ permalink raw reply related [flat|nested] 85+ messages in thread
* [PATCH 04/17] drm/msm/a6xx: Poll additional DRV status
2025-07-20 12:16 [PATCH 00/17] drm/msm: Support for Inter Frame Power Collapse (IFPC) feature Akhil P Oommen
` (2 preceding siblings ...)
2025-07-20 12:16 ` [PATCH 03/17] drm/msm: a6xx: Fix gx_is_on check for a7x family Akhil P Oommen
@ 2025-07-20 12:16 ` Akhil P Oommen
2025-07-22 13:31 ` Dmitry Baryshkov
2025-07-23 10:01 ` Konrad Dybcio
2025-07-20 12:16 ` [PATCH 05/17] drm/msm/a6xx: Fix PDC sleep sequence Akhil P Oommen
` (12 subsequent siblings)
16 siblings, 2 replies; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-20 12:16 UTC (permalink / raw)
To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Akhil P Oommen
A7XX_GEN2 generation has additional TCS slots. Poll the respective
DRV status registers before pm suspend.
Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
---
drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index 790ef2f94a0b0cd40433d7edb6a89e4f04408bf5..3bebb6dd7059782ceca29f2efd2acee24d3fc930 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -987,6 +987,22 @@ static void a6xx_gmu_rpmh_off(struct a6xx_gmu *gmu)
val, (val & 1), 100, 10000);
gmu_poll_timeout_rscc(gmu, REG_A6XX_RSCC_TCS3_DRV0_STATUS + seqmem_off,
val, (val & 1), 100, 1000);
+
+ if (!adreno_is_a740_family(adreno_gpu))
+ return;
+
+ gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS4_DRV0_STATUS + seqmem_off,
+ val, (val & 1), 100, 10000);
+ gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS5_DRV0_STATUS + seqmem_off,
+ val, (val & 1), 100, 10000);
+ gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS6_DRV0_STATUS + seqmem_off,
+ val, (val & 1), 100, 10000);
+ gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS7_DRV0_STATUS + seqmem_off,
+ val, (val & 1), 100, 1000);
+ gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS8_DRV0_STATUS + seqmem_off,
+ val, (val & 1), 100, 10000);
+ gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS9_DRV0_STATUS + seqmem_off,
+ val, (val & 1), 100, 1000);
}
/* Force the GMU off in case it isn't responsive */
--
2.50.1
^ permalink raw reply related [flat|nested] 85+ messages in thread
* [PATCH 05/17] drm/msm/a6xx: Fix PDC sleep sequence
2025-07-20 12:16 [PATCH 00/17] drm/msm: Support for Inter Frame Power Collapse (IFPC) feature Akhil P Oommen
` (3 preceding siblings ...)
2025-07-20 12:16 ` [PATCH 04/17] drm/msm/a6xx: Poll additional DRV status Akhil P Oommen
@ 2025-07-20 12:16 ` Akhil P Oommen
2025-07-22 13:33 ` Dmitry Baryshkov
2025-08-07 13:51 ` Konrad Dybcio
2025-07-20 12:16 ` [PATCH 06/17] drm/msm: Add an ftrace for gpu register access Akhil P Oommen
` (11 subsequent siblings)
16 siblings, 2 replies; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-20 12:16 UTC (permalink / raw)
To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Akhil P Oommen
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.
Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
---
drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 30 +++++++++++++++++++-----------
drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 6 ++++++
2 files changed, 25 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index 3bebb6dd7059782ceca29f2efd2acee24d3fc930..4d6c70735e0892ed87d6a68d64f24bda844e5e16 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -279,6 +279,8 @@ static int a6xx_gmu_start(struct a6xx_gmu *gmu)
if (ret)
DRM_DEV_ERROR(gmu->dev, "GMU firmware initialization timed out\n");
+ set_bit(GMU_STATUS_FW_START, &gmu->status);
+
return ret;
}
@@ -528,6 +530,9 @@ static int a6xx_rpmh_start(struct a6xx_gmu *gmu)
int ret;
u32 val;
+ if (!test_and_clear_bit(GMU_STATUS_PDC_SLEEP, &gmu->status))
+ return 0;
+
gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, BIT(1));
ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_RSCC_CONTROL_ACK, val,
@@ -555,6 +560,11 @@ static void a6xx_rpmh_stop(struct a6xx_gmu *gmu)
int ret;
u32 val;
+ if (test_and_clear_bit(GMU_STATUS_FW_START, &gmu->status))
+ return;
+
+ /* TODO: should we skip if IFPC is not enabled */
+
gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, 1);
ret = gmu_poll_timeout_rscc(gmu, REG_A6XX_GPU_RSCC_RSC_STATUS0_DRV0,
@@ -563,6 +573,8 @@ static void a6xx_rpmh_stop(struct a6xx_gmu *gmu)
DRM_DEV_ERROR(gmu->dev, "Unable to power off the GPU RSC\n");
gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, 0);
+
+ set_bit(GMU_STATUS_PDC_SLEEP, &gmu->status);
}
static inline void pdc_write(void __iomem *ptr, u32 offset, u32 value)
@@ -691,8 +703,6 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu)
/* ensure no writes happen before the uCode is fully written */
wmb();
- a6xx_rpmh_stop(gmu);
-
err:
if (!IS_ERR_OR_NULL(pdcptr))
iounmap(pdcptr);
@@ -852,19 +862,15 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state)
else
gmu_write(gmu, REG_A6XX_GMU_GENERAL_7, 1);
- if (state == GMU_WARM_BOOT) {
- ret = a6xx_rpmh_start(gmu);
- if (ret)
- return ret;
- } else {
+ ret = a6xx_rpmh_start(gmu);
+ if (ret)
+ return ret;
+
+ if (state == GMU_COLD_BOOT) {
if (WARN(!adreno_gpu->fw[ADRENO_FW_GMU],
"GMU firmware is not loaded\n"))
return -ENOENT;
- ret = a6xx_rpmh_start(gmu);
- if (ret)
- return ret;
-
ret = a6xx_gmu_fw_load(gmu);
if (ret)
return ret;
@@ -1046,6 +1052,8 @@ static void a6xx_gmu_force_off(struct a6xx_gmu *gmu)
/* Reset GPU core blocks */
a6xx_gpu_sw_reset(gpu, true);
+
+ a6xx_rpmh_stop(gmu);
}
static void a6xx_gmu_set_initial_freq(struct msm_gpu *gpu, struct a6xx_gmu *gmu)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
index b2d4489b40249b1916ab4a42c89e3f4bdc5c4af9..034f1b4e5a3fb9cd601bfbe6d06d64e5ace3b6e7 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
@@ -117,6 +117,12 @@ struct a6xx_gmu {
struct qmp *qmp;
struct a6xx_hfi_msg_bw_table *bw_table;
+
+/* To check if we can trigger sleep seq at PDC. Cleared in a6xx_rpmh_stop() */
+#define GMU_STATUS_FW_START 0
+/* To track if PDC sleep seq was done */
+#define GMU_STATUS_PDC_SLEEP 1
+ unsigned long status;
};
static inline u32 gmu_read(struct a6xx_gmu *gmu, u32 offset)
--
2.50.1
^ permalink raw reply related [flat|nested] 85+ messages in thread
* [PATCH 06/17] drm/msm: Add an ftrace for gpu register access
2025-07-20 12:16 [PATCH 00/17] drm/msm: Support for Inter Frame Power Collapse (IFPC) feature Akhil P Oommen
` (4 preceding siblings ...)
2025-07-20 12:16 ` [PATCH 05/17] drm/msm/a6xx: Fix PDC sleep sequence Akhil P Oommen
@ 2025-07-20 12:16 ` Akhil P Oommen
2025-07-20 12:16 ` [PATCH 07/17] drm/msm/adreno: Add fenced regwrite support Akhil P Oommen
` (10 subsequent siblings)
16 siblings, 0 replies; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-20 12:16 UTC (permalink / raw)
To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Akhil P Oommen
With IFPC, there is a probability of accessing a GX domain register when
it is collapsed, which leads to gmu fence errors. To debug this, we need
to trace every gpu register accesses and identify the one just before a
gmu fence error. So, add an ftrace to track all gpu register accesses.
Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
---
drivers/gpu/drm/msm/msm_gpu.h | 8 ++++++++
drivers/gpu/drm/msm/msm_gpu_trace.h | 12 ++++++++++++
2 files changed, 20 insertions(+)
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index 5bf7cd985b9c50e38468fed695234f787919a8aa..a0a0cf9efb3a8035a80cbbbf30ad294a72ccbd48 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -16,6 +16,7 @@
#include "msm_drv.h"
#include "msm_fence.h"
+#include "msm_gpu_trace.h"
#include "msm_ringbuffer.h"
#include "msm_gem.h"
@@ -555,16 +556,19 @@ struct msm_gpu_state {
static inline void gpu_write(struct msm_gpu *gpu, u32 reg, u32 data)
{
+ trace_msm_gpu_regaccess(reg);
writel(data, gpu->mmio + (reg << 2));
}
static inline u32 gpu_read(struct msm_gpu *gpu, u32 reg)
{
+ trace_msm_gpu_regaccess(reg);
return readl(gpu->mmio + (reg << 2));
}
static inline void gpu_rmw(struct msm_gpu *gpu, u32 reg, u32 mask, u32 or)
{
+ trace_msm_gpu_regaccess(reg);
msm_rmw(gpu->mmio + (reg << 2), mask, or);
}
@@ -586,7 +590,9 @@ static inline u64 gpu_read64(struct msm_gpu *gpu, u32 reg)
* when the lo is read, so make sure to read the lo first to trigger
* that
*/
+ trace_msm_gpu_regaccess(reg);
val = (u64) readl(gpu->mmio + (reg << 2));
+ trace_msm_gpu_regaccess(reg+1);
val |= ((u64) readl(gpu->mmio + ((reg + 1) << 2)) << 32);
return val;
@@ -594,8 +600,10 @@ static inline u64 gpu_read64(struct msm_gpu *gpu, u32 reg)
static inline void gpu_write64(struct msm_gpu *gpu, u32 reg, u64 val)
{
+ trace_msm_gpu_regaccess(reg);
/* Why not a writeq here? Read the screed above */
writel(lower_32_bits(val), gpu->mmio + (reg << 2));
+ trace_msm_gpu_regaccess(reg+1);
writel(upper_32_bits(val), gpu->mmio + ((reg + 1) << 2));
}
diff --git a/drivers/gpu/drm/msm/msm_gpu_trace.h b/drivers/gpu/drm/msm/msm_gpu_trace.h
index 7f863282db0d7812c8fd53b3f1fc0cd5635028ba..193dc9c8a7705c8988b8c4b60aa78a74e00af932 100644
--- a/drivers/gpu/drm/msm/msm_gpu_trace.h
+++ b/drivers/gpu/drm/msm/msm_gpu_trace.h
@@ -205,6 +205,18 @@ TRACE_EVENT(msm_gpu_preemption_irq,
TP_printk("preempted to %u", __entry->ring_id)
);
+TRACE_EVENT(msm_gpu_regaccess,
+ TP_PROTO(u32 offset),
+ TP_ARGS(offset),
+ TP_STRUCT__entry(
+ __field(u32, offset)
+ ),
+ TP_fast_assign(
+ __entry->offset = offset;
+ ),
+ TP_printk("offset=0x%x", __entry->offset)
+);
+
#endif
#undef TRACE_INCLUDE_PATH
--
2.50.1
^ permalink raw reply related [flat|nested] 85+ messages in thread
* [PATCH 07/17] drm/msm/adreno: Add fenced regwrite support
2025-07-20 12:16 [PATCH 00/17] drm/msm: Support for Inter Frame Power Collapse (IFPC) feature Akhil P Oommen
` (5 preceding siblings ...)
2025-07-20 12:16 ` [PATCH 06/17] drm/msm: Add an ftrace for gpu register access Akhil P Oommen
@ 2025-07-20 12:16 ` Akhil P Oommen
2025-07-22 13:39 ` Dmitry Baryshkov
2025-07-20 12:16 ` [PATCH 08/17] drm/msm/a6xx: Set Keep-alive votes to block IFPC Akhil P Oommen
` (9 subsequent siblings)
16 siblings, 1 reply; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-20 12:16 UTC (permalink / raw)
To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Akhil P Oommen
There are some special registers which are accessible even when GX power
domain is collapsed during an IFPC sleep. Accessing these registers
wakes up GPU from power collapse and allow programming these registers
without additional handshake with GMU. This patch adds support for this
special register write sequence.
Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
---
drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 63 ++++++++++++++++++++++++++++++-
drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 1 +
drivers/gpu/drm/msm/adreno/a6xx_preempt.c | 20 +++++-----
3 files changed, 73 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index 491fde0083a202bec7c6b3bca88d0e5a717a6560..8c004fc3abd2896d467a9728b34e99e4ed944dc4 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -16,6 +16,67 @@
#define GPU_PAS_ID 13
+static bool fence_status_check(struct msm_gpu *gpu, u32 offset, u32 value, u32 status, u32 mask)
+{
+ /* Success if !writedropped0/1 */
+ if (!(status & mask))
+ return true;
+
+ udelay(10);
+
+ /* Try to update fenced register again */
+ gpu_write(gpu, offset, value);
+ return false;
+}
+
+static int fenced_write(struct a6xx_gpu *a6xx_gpu, u32 offset, u32 value, u32 mask)
+{
+ struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
+ struct msm_gpu *gpu = &adreno_gpu->base;
+ struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
+ u32 status;
+
+ gpu_write(gpu, offset, value);
+
+ /* Nothing else to be done in the case of no-GMU */
+ if (adreno_has_gmu_wrapper(adreno_gpu))
+ return 0;
+
+ if (!gmu_poll_timeout(gmu, REG_A6XX_GMU_AHB_FENCE_STATUS, status,
+ fence_status_check(gpu, offset, value, status, mask), 0, 1000))
+ return 0;
+
+ dev_err_ratelimited(gmu->dev, "delay in fenced register write (0x%x)\n",
+ offset);
+
+ /* Try again for another 1ms before failing */
+ gpu_write(gpu, offset, value);
+ if (!gmu_poll_timeout(gmu, REG_A6XX_GMU_AHB_FENCE_STATUS, status,
+ fence_status_check(gpu, offset, value, status, mask), 0, 1000))
+ return 0;
+
+ dev_err_ratelimited(gmu->dev, "fenced register write (0x%x) fail\n",
+ offset);
+
+ return -ETIMEDOUT;
+}
+
+int a6xx_fenced_write(struct a6xx_gpu *a6xx_gpu, u32 offset, u64 value, u32 mask, bool is_64b)
+{
+ int ret;
+
+ ret = fenced_write(a6xx_gpu, offset, lower_32_bits(value), mask);
+ if (ret)
+ return ret;
+
+ if (!is_64b)
+ return 0;
+
+ ret = fenced_write(a6xx_gpu, offset + 1, upper_32_bits(value), mask);
+
+ return ret;
+}
+
static inline bool _a6xx_check_idle(struct msm_gpu *gpu)
{
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
@@ -86,7 +147,7 @@ static void a6xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
/* Update HW if this is the current ring and we are not in preempt*/
if (!a6xx_in_preempt(a6xx_gpu)) {
if (a6xx_gpu->cur_ring == ring)
- gpu_write(gpu, REG_A6XX_CP_RB_WPTR, wptr);
+ a6xx_fenced_write(a6xx_gpu, REG_A6XX_CP_RB_WPTR, wptr, BIT(0), false);
else
ring->restore_wptr = true;
} else {
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
index 9201a53dd341bf432923ffb44947e015208a3d02..2be036a3faca58b4b559c30881e4b31d5929592a 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
@@ -291,5 +291,6 @@ int a6xx_gpu_state_put(struct msm_gpu_state *state);
void a6xx_bus_clear_pending_transactions(struct adreno_gpu *adreno_gpu, bool gx_off);
void a6xx_gpu_sw_reset(struct msm_gpu *gpu, bool assert);
+int a6xx_fenced_write(struct a6xx_gpu *gpu, u32 offset, u64 value, u32 mask, bool is_64b);
#endif /* __A6XX_GPU_H__ */
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_preempt.c b/drivers/gpu/drm/msm/adreno/a6xx_preempt.c
index 3b17fd2dba89115a8e48ba9469e52e4305b0cdbb..5b0fd510ff58d989ab285f1a2497f6f522a6b187 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_preempt.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_preempt.c
@@ -41,7 +41,7 @@ static inline void set_preempt_state(struct a6xx_gpu *gpu,
}
/* Write the most recent wptr for the given ring into the hardware */
-static inline void update_wptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
+static inline void update_wptr(struct a6xx_gpu *a6xx_gpu, struct msm_ringbuffer *ring)
{
unsigned long flags;
uint32_t wptr;
@@ -51,7 +51,7 @@ static inline void update_wptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
if (ring->restore_wptr) {
wptr = get_wptr(ring);
- gpu_write(gpu, REG_A6XX_CP_RB_WPTR, wptr);
+ a6xx_fenced_write(a6xx_gpu, REG_A6XX_CP_RB_WPTR, wptr, BIT(0), false);
ring->restore_wptr = false;
}
@@ -172,7 +172,7 @@ void a6xx_preempt_irq(struct msm_gpu *gpu)
set_preempt_state(a6xx_gpu, PREEMPT_FINISH);
- update_wptr(gpu, a6xx_gpu->cur_ring);
+ update_wptr(a6xx_gpu, a6xx_gpu->cur_ring);
set_preempt_state(a6xx_gpu, PREEMPT_NONE);
@@ -268,7 +268,7 @@ void a6xx_preempt_trigger(struct msm_gpu *gpu)
*/
if (!ring || (a6xx_gpu->cur_ring == ring)) {
set_preempt_state(a6xx_gpu, PREEMPT_FINISH);
- update_wptr(gpu, a6xx_gpu->cur_ring);
+ update_wptr(a6xx_gpu, a6xx_gpu->cur_ring);
set_preempt_state(a6xx_gpu, PREEMPT_NONE);
spin_unlock_irqrestore(&a6xx_gpu->eval_lock, flags);
return;
@@ -302,13 +302,13 @@ void a6xx_preempt_trigger(struct msm_gpu *gpu)
spin_unlock_irqrestore(&ring->preempt_lock, flags);
- gpu_write64(gpu,
- REG_A6XX_CP_CONTEXT_SWITCH_SMMU_INFO,
- a6xx_gpu->preempt_smmu_iova[ring->id]);
+ a6xx_fenced_write(a6xx_gpu,
+ REG_A6XX_CP_CONTEXT_SWITCH_SMMU_INFO, a6xx_gpu->preempt_smmu_iova[ring->id],
+ BIT(1), true);
- gpu_write64(gpu,
+ a6xx_fenced_write(a6xx_gpu,
REG_A6XX_CP_CONTEXT_SWITCH_PRIV_NON_SECURE_RESTORE_ADDR,
- a6xx_gpu->preempt_iova[ring->id]);
+ a6xx_gpu->preempt_iova[ring->id], BIT(1), true);
a6xx_gpu->next_ring = ring;
@@ -328,7 +328,7 @@ void a6xx_preempt_trigger(struct msm_gpu *gpu)
set_preempt_state(a6xx_gpu, PREEMPT_TRIGGERED);
/* Trigger the preemption */
- gpu_write(gpu, REG_A6XX_CP_CONTEXT_SWITCH_CNTL, cntl);
+ a6xx_fenced_write(a6xx_gpu, REG_A6XX_CP_CONTEXT_SWITCH_CNTL, cntl, BIT(1), false);
}
static int preempt_init_ring(struct a6xx_gpu *a6xx_gpu,
--
2.50.1
^ permalink raw reply related [flat|nested] 85+ messages in thread
* [PATCH 08/17] drm/msm/a6xx: Set Keep-alive votes to block IFPC
2025-07-20 12:16 [PATCH 00/17] drm/msm: Support for Inter Frame Power Collapse (IFPC) feature Akhil P Oommen
` (6 preceding siblings ...)
2025-07-20 12:16 ` [PATCH 07/17] drm/msm/adreno: Add fenced regwrite support Akhil P Oommen
@ 2025-07-20 12:16 ` Akhil P Oommen
2025-07-22 13:44 ` Dmitry Baryshkov
2025-07-20 12:16 ` [PATCH 09/17] drm/msm/a6xx: Switch to GMU AO counter Akhil P Oommen
` (8 subsequent siblings)
16 siblings, 1 reply; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-20 12:16 UTC (permalink / raw)
To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Akhil P Oommen
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>
---
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 8c004fc3abd2896d467a9728b34e99e4ed944dc4..6770f0363e7284e4596b1188637a4615d2c0779b 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -1752,8 +1752,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);
/*
@@ -1765,13 +1763,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,
@@ -1810,9 +1801,24 @@ static void a7xx_sw_fuse_violation_irq(struct msm_gpu *gpu)
}
}
+static void set_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 */
+ set_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);
@@ -1849,6 +1855,8 @@ static irqreturn_t a6xx_irq(struct msm_gpu *gpu)
if (status & A6XX_RBBM_INT_0_MASK_CP_SW)
a6xx_preempt_irq(gpu);
+ set_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 5b0fd510ff58d989ab285f1a2497f6f522a6b187..1c8ec1911010c00a000d195116fc950c4d947cac 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 set_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);
+ set_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 */
+ set_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
^ permalink raw reply related [flat|nested] 85+ messages in thread
* [PATCH 09/17] drm/msm/a6xx: Switch to GMU AO counter
2025-07-20 12:16 [PATCH 00/17] drm/msm: Support for Inter Frame Power Collapse (IFPC) feature Akhil P Oommen
` (7 preceding siblings ...)
2025-07-20 12:16 ` [PATCH 08/17] drm/msm/a6xx: Set Keep-alive votes to block IFPC Akhil P Oommen
@ 2025-07-20 12:16 ` Akhil P Oommen
2025-07-23 10:19 ` Konrad Dybcio
2025-07-20 12:16 ` [PATCH 10/17] drm/msm/a6xx: Poll AHB fence status in GPU IRQ handler Akhil P Oommen
` (7 subsequent siblings)
16 siblings, 1 reply; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-20 12:16 UTC (permalink / raw)
To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Akhil P Oommen
CP_ALWAYS_ON counter falls under GX domain which is collapsed during
IFPC. So switch to GMU_ALWAYS_ON counter for any CPU reads since it is
not impacted by IFPC. Both counters are clocked by same xo clock source.
Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
---
drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 30 ++++++++++++++++--------------
1 file changed, 16 insertions(+), 14 deletions(-)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index 6770f0363e7284e4596b1188637a4615d2c0779b..f000915a4c2698a85b45bd3c92e590f14999d10d 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -16,6 +16,19 @@
#define GPU_PAS_ID 13
+static u64 read_gmu_ao_counter(struct a6xx_gpu *a6xx_gpu)
+{
+ u64 count_hi, count_lo, temp;
+
+ do {
+ count_hi = gmu_read(&a6xx_gpu->gmu, REG_A6XX_GMU_ALWAYS_ON_COUNTER_H);
+ count_lo = gmu_read(&a6xx_gpu->gmu, REG_A6XX_GMU_ALWAYS_ON_COUNTER_L);
+ temp = gmu_read(&a6xx_gpu->gmu, REG_A6XX_GMU_ALWAYS_ON_COUNTER_H);
+ } while (count_hi != temp);
+
+ return (count_hi << 32) | count_lo;
+}
+
static bool fence_status_check(struct msm_gpu *gpu, u32 offset, u32 value, u32 status, u32 mask)
{
/* Success if !writedropped0/1 */
@@ -358,8 +371,7 @@ static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
OUT_RING(ring, upper_32_bits(rbmemptr(ring, fence)));
OUT_RING(ring, submit->seqno);
- trace_msm_gpu_submit_flush(submit,
- gpu_read64(gpu, REG_A6XX_CP_ALWAYS_ON_COUNTER));
+ trace_msm_gpu_submit_flush(submit, read_gmu_ao_counter(a6xx_gpu));
a6xx_flush(gpu, ring);
}
@@ -559,8 +571,7 @@ static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
}
- trace_msm_gpu_submit_flush(submit,
- gpu_read64(gpu, REG_A6XX_CP_ALWAYS_ON_COUNTER));
+ trace_msm_gpu_submit_flush(submit, read_gmu_ao_counter(a6xx_gpu));
a6xx_flush(gpu, ring);
@@ -2246,16 +2257,7 @@ static int a6xx_gmu_get_timestamp(struct msm_gpu *gpu, uint64_t *value)
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
- mutex_lock(&a6xx_gpu->gmu.lock);
-
- /* Force the GPU power on so we can read this register */
- a6xx_gmu_set_oob(&a6xx_gpu->gmu, GMU_OOB_PERFCOUNTER_SET);
-
- *value = gpu_read64(gpu, REG_A6XX_CP_ALWAYS_ON_COUNTER);
-
- a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_PERFCOUNTER_SET);
-
- mutex_unlock(&a6xx_gpu->gmu.lock);
+ *value = read_gmu_ao_counter(a6xx_gpu);
return 0;
}
--
2.50.1
^ permalink raw reply related [flat|nested] 85+ messages in thread
* [PATCH 10/17] drm/msm/a6xx: Poll AHB fence status in GPU IRQ handler
2025-07-20 12:16 [PATCH 00/17] drm/msm: Support for Inter Frame Power Collapse (IFPC) feature Akhil P Oommen
` (8 preceding siblings ...)
2025-07-20 12:16 ` [PATCH 09/17] drm/msm/a6xx: Switch to GMU AO counter Akhil P Oommen
@ 2025-07-20 12:16 ` Akhil P Oommen
2025-07-23 10:10 ` Konrad Dybcio
2025-07-20 12:16 ` [PATCH 11/17] drm/msm: Add support for IFPC Akhil P Oommen
` (6 subsequent siblings)
16 siblings, 1 reply; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-20 12:16 UTC (permalink / raw)
To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Akhil P Oommen
Even though 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. 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>
---
drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 3 +++
drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 26 ++++++++++++++++++++++++++
2 files changed, 29 insertions(+)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
index 034f1b4e5a3fb9cd601bfbe6d06d64e5ace3b6e7..62c98b198551f26b99bd6e094f8fa35e16ec550d 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
@@ -164,6 +164,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)
{
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index f000915a4c2698a85b45bd3c92e590f14999d10d..e331cbdb117df6cfa8ae0e4c44a5aa91ba93f8eb 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -1823,6 +1823,28 @@ static void set_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;
@@ -1830,6 +1852,9 @@ static irqreturn_t a6xx_irq(struct msm_gpu *gpu)
/* Set keepalive vote to avoid power collapse after RBBM_INT_0_STATUS is read */
set_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);
@@ -1866,6 +1891,7 @@ static irqreturn_t a6xx_irq(struct msm_gpu *gpu)
if (status & A6XX_RBBM_INT_0_MASK_CP_SW)
a6xx_preempt_irq(gpu);
+done:
set_keepalive_vote(gpu, false);
return IRQ_HANDLED;
--
2.50.1
^ permalink raw reply related [flat|nested] 85+ messages in thread
* [PATCH 11/17] drm/msm: Add support for IFPC
2025-07-20 12:16 [PATCH 00/17] drm/msm: Support for Inter Frame Power Collapse (IFPC) feature Akhil P Oommen
` (9 preceding siblings ...)
2025-07-20 12:16 ` [PATCH 10/17] drm/msm/a6xx: Poll AHB fence status in GPU IRQ handler Akhil P Oommen
@ 2025-07-20 12:16 ` Akhil P Oommen
2025-07-22 13:49 ` Dmitry Baryshkov
2025-07-23 10:22 ` Konrad Dybcio
2025-07-20 12:16 ` [PATCH 12/17] drm/msm: Skip devfreq IDLE when possible Akhil P Oommen
` (5 subsequent siblings)
16 siblings, 2 replies; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-20 12:16 UTC (permalink / raw)
To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Akhil P Oommen
Add a new quirk to denote IFPC (Inter-Frame Power Collapse) support
for a gpu. Based on this flag send the feature ctrl hfi message to
GMU to enable IFPC support.
Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
---
drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 5 +++--
drivers/gpu/drm/msm/adreno/a6xx_hfi.c | 33 +++++++++++++++++++++++++++------
drivers/gpu/drm/msm/adreno/adreno_gpu.h | 1 +
3 files changed, 31 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index 4d6c70735e0892ed87d6a68d64f24bda844e5e16..3bbcc78179c1cf1bfa21ff097e9350eb2f554011 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -1961,8 +1961,9 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
if (ret)
return ret;
- /* Fow now, don't do anything fancy until we get our feet under us */
- gmu->idle_level = GMU_IDLE_STATE_ACTIVE;
+ /* Set GMU idle level */
+ gmu->idle_level = (adreno_gpu->info->quirks & ADRENO_QUIRK_IFPC) ?
+ GMU_IDLE_STATE_IFPC : GMU_IDLE_STATE_ACTIVE;
pm_runtime_enable(gmu->dev);
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
index 8e69b1e8465711837151725c8f70e7b4b16a368e..20ade6b0558b016b581078f5cf7377e7e7c57f8e 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
@@ -21,6 +21,7 @@ static const char * const a6xx_hfi_msg_id[] = {
HFI_MSG_ID(HFI_H2F_MSG_PERF_TABLE),
HFI_MSG_ID(HFI_H2F_MSG_TEST),
HFI_MSG_ID(HFI_H2F_MSG_START),
+ HFI_MSG_ID(HFI_H2F_FEATURE_CTRL),
HFI_MSG_ID(HFI_H2F_MSG_CORE_FW_START),
HFI_MSG_ID(HFI_H2F_MSG_GX_BW_PERF_VOTE),
HFI_MSG_ID(HFI_H2F_MSG_PREPARE_SLUMBER),
@@ -765,23 +766,39 @@ static int a6xx_hfi_send_bw_table(struct a6xx_gmu *gmu)
NULL, 0);
}
+static int a6xx_hfi_feature_ctrl_msg(struct a6xx_gmu *gmu, u32 feature, u32 enable, u32 data)
+{
+ struct a6xx_hfi_msg_feature_ctrl msg = {
+ .feature = feature,
+ .enable = enable,
+ .data = data,
+ };
+
+ return a6xx_hfi_send_msg(gmu, HFI_H2F_FEATURE_CTRL, &msg, sizeof(msg), NULL, 0);
+}
+
+#define HFI_FEATURE_IFPC 9
+
+static int a6xx_hfi_enable_ifpc(struct a6xx_gmu *gmu)
+{
+ if (gmu->idle_level != GMU_IDLE_STATE_IFPC)
+ return 0;
+
+ return a6xx_hfi_feature_ctrl_msg(gmu, HFI_FEATURE_IFPC, 1, 0x1680);
+}
+
#define HFI_FEATURE_ACD 12
static int a6xx_hfi_enable_acd(struct a6xx_gmu *gmu)
{
struct a6xx_hfi_acd_table *acd_table = &gmu->acd_table;
- struct a6xx_hfi_msg_feature_ctrl msg = {
- .feature = HFI_FEATURE_ACD,
- .enable = 1,
- .data = 0,
- };
int ret;
if (!acd_table->enable_by_level)
return 0;
/* Enable ACD feature at GMU */
- ret = a6xx_hfi_send_msg(gmu, HFI_H2F_FEATURE_CTRL, &msg, sizeof(msg), NULL, 0);
+ ret = a6xx_hfi_feature_ctrl_msg(gmu, HFI_FEATURE_ACD, 1, 0);
if (ret) {
DRM_DEV_ERROR(gmu->dev, "Unable to enable ACD (%d)\n", ret);
return ret;
@@ -898,6 +915,10 @@ int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state)
if (ret)
return ret;
+ ret = a6xx_hfi_enable_ifpc(gmu);
+ if (ret)
+ return ret;
+
ret = a6xx_hfi_send_core_fw_start(gmu);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
index bc063594a359ee6b796381c5fd2c30e2aa12a26d..1135beafac464f3162a3a61938a7de0c7920455a 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
@@ -58,6 +58,7 @@ enum adreno_family {
#define ADRENO_QUIRK_HAS_CACHED_COHERENT BIT(4)
#define ADRENO_QUIRK_PREEMPTION BIT(5)
#define ADRENO_QUIRK_4GB_VA BIT(6)
+#define ADRENO_QUIRK_IFPC BIT(7)
/* Helper for formating the chip_id in the way that userspace tools like
* crashdec expect.
--
2.50.1
^ permalink raw reply related [flat|nested] 85+ messages in thread
* [PATCH 12/17] drm/msm: Skip devfreq IDLE when possible
2025-07-20 12:16 [PATCH 00/17] drm/msm: Support for Inter Frame Power Collapse (IFPC) feature Akhil P Oommen
` (10 preceding siblings ...)
2025-07-20 12:16 ` [PATCH 11/17] drm/msm: Add support for IFPC Akhil P Oommen
@ 2025-07-20 12:16 ` Akhil P Oommen
2025-07-21 4:00 ` kernel test robot
` (2 more replies)
2025-07-20 12:16 ` [PATCH 13/17] drm/msm/a6xx: Fix hangcheck for IFPC Akhil P Oommen
` (4 subsequent siblings)
16 siblings, 3 replies; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-20 12:16 UTC (permalink / raw)
To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Akhil P Oommen
When IFPC is supported, devfreq idling is redundant and adds
unnecessary pm suspend/wake latency. So skip it when IFPC is
supported.
Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
---
drivers/gpu/drm/msm/msm_gpu_devfreq.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/gpu/drm/msm/msm_gpu_devfreq.c b/drivers/gpu/drm/msm/msm_gpu_devfreq.c
index 2e1d5c3432728cde15d91f69da22bb915588fe86..53ef2add5047e7d6b6371af949cab36ce8409372 100644
--- a/drivers/gpu/drm/msm/msm_gpu_devfreq.c
+++ b/drivers/gpu/drm/msm/msm_gpu_devfreq.c
@@ -4,6 +4,7 @@
* Author: Rob Clark <robdclark@gmail.com>
*/
+#include "adreno/adreno_gpu.h"
#include "msm_gpu.h"
#include "msm_gpu_trace.h"
@@ -300,6 +301,8 @@ void msm_devfreq_active(struct msm_gpu *gpu)
if (!has_devfreq(gpu))
return;
+ if (to_adreno_gpu(gpu)->info->quirks & ADRENO_QUIRK_IFPC)
+ return;
/*
* Cancel any pending transition to idle frequency:
*/
@@ -370,6 +373,9 @@ void msm_devfreq_idle(struct msm_gpu *gpu)
if (!has_devfreq(gpu))
return;
+ if (to_adreno_gpu(gpu)->info->quirks & ADRENO_QUIRK_IFPC)
+ return;
+
msm_hrtimer_queue_work(&df->idle_work, ms_to_ktime(1),
HRTIMER_MODE_REL);
}
--
2.50.1
^ permalink raw reply related [flat|nested] 85+ messages in thread
* [PATCH 13/17] drm/msm/a6xx: Fix hangcheck for IFPC
2025-07-20 12:16 [PATCH 00/17] drm/msm: Support for Inter Frame Power Collapse (IFPC) feature Akhil P Oommen
` (11 preceding siblings ...)
2025-07-20 12:16 ` [PATCH 12/17] drm/msm: Skip devfreq IDLE when possible Akhil P Oommen
@ 2025-07-20 12:16 ` Akhil P Oommen
2025-07-22 13:52 ` Dmitry Baryshkov
2025-07-20 12:16 ` [PATCH 14/17] drm/msm/adreno: Disable IFPC when sysprof is active Akhil P Oommen
` (3 subsequent siblings)
16 siblings, 1 reply; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-20 12:16 UTC (permalink / raw)
To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Akhil P Oommen
From the hangcheck handler, KMD checks a few registers in GX
domain to see if the GPU made any progress. But it cannot access
those registers when IFPC is enabled. Since HW based hang detection
is pretty decent, lets rely on it instead of these registers when
IFPC is enabled.
Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
---
drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index e331cbdb117df6cfa8ae0e4c44a5aa91ba93f8eb..b3becb230a94163cccff4eaffb8eed44f1c29ad0 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -2399,13 +2399,23 @@ static uint32_t a6xx_get_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
static bool a6xx_progress(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
{
- struct msm_cp_state cp_state = {
+ struct msm_cp_state cp_state;
+ bool progress;
+
+ /*
+ * With IFPC, KMD doesn't know whether GX power domain is collapsed or not. So, we can't
+ * blindly read the below registers in GX domain. Lets trust the hang detection in HW and
+ * lie to the caller that there was progress.
+ */
+ if (to_adreno_gpu(gpu)->info->quirks & ADRENO_QUIRK_IFPC)
+ return true;
+
+ cp_state = (struct msm_cp_state) {
.ib1_base = gpu_read64(gpu, REG_A6XX_CP_IB1_BASE),
.ib2_base = gpu_read64(gpu, REG_A6XX_CP_IB2_BASE),
.ib1_rem = gpu_read(gpu, REG_A6XX_CP_IB1_REM_SIZE),
.ib2_rem = gpu_read(gpu, REG_A6XX_CP_IB2_REM_SIZE),
};
- bool progress;
/*
* Adjust the remaining data to account for what has already been
--
2.50.1
^ permalink raw reply related [flat|nested] 85+ messages in thread
* [PATCH 14/17] drm/msm/adreno: Disable IFPC when sysprof is active
2025-07-20 12:16 [PATCH 00/17] drm/msm: Support for Inter Frame Power Collapse (IFPC) feature Akhil P Oommen
` (12 preceding siblings ...)
2025-07-20 12:16 ` [PATCH 13/17] drm/msm/a6xx: Fix hangcheck for IFPC Akhil P Oommen
@ 2025-07-20 12:16 ` Akhil P Oommen
2025-07-20 12:16 ` [PATCH 15/17] drm/msm/a6xx: Make crashstate capture IFPC safe Akhil P Oommen
` (2 subsequent siblings)
16 siblings, 0 replies; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-20 12:16 UTC (permalink / raw)
To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Akhil P Oommen
Moving to IFPC state clears the 'Perfcounter Select' register setup
by the userspace. So, lets block the IFPC when sysprof is active by
using the perfcounter oob signal to the GMU.
Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
---
drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 37 +++++++++++++++++++++++++++++++++++
drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 2 ++
drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 2 ++
drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 1 +
drivers/gpu/drm/msm/msm_gpu.h | 1 +
drivers/gpu/drm/msm/msm_submitqueue.c | 4 ++++
6 files changed, 47 insertions(+)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index 3bbcc78179c1cf1bfa21ff097e9350eb2f554011..ccdcf5fe4b4f3cd81d765754d00c132960a916a9 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -1159,6 +1159,11 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu)
/* Set the GPU to the current freq */
a6xx_gmu_set_initial_freq(gpu, gmu);
+ if (refcount_read(&gpu->sysprof_active) > 1) {
+ ret = a6xx_gmu_set_oob(gmu, GMU_OOB_PERFCOUNTER_SET);
+ if (!ret)
+ set_bit(GMU_STATUS_OOB_PERF_SET, &gmu->status);
+ }
out:
/* On failure, shut down the GMU to leave it in a good state */
if (ret) {
@@ -1206,6 +1211,9 @@ static void a6xx_gmu_shutdown(struct a6xx_gmu *gmu)
a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET);
}
+ if (test_and_clear_bit(GMU_STATUS_OOB_PERF_SET, &gmu->status))
+ a6xx_gmu_clear_oob(gmu, GMU_OOB_PERFCOUNTER_SET);
+
ret = a6xx_gmu_wait_for_idle(gmu);
/* If the GMU isn't responding assume it is hung */
@@ -1819,6 +1827,35 @@ static int a6xx_gmu_get_irq(struct a6xx_gmu *gmu, struct platform_device *pdev,
return irq;
}
+void a6xx_gmu_sysprof_setup(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;
+ unsigned int sysprof_active;
+
+ /* Nothing to do if GPU is suspended. We will handle this during GMU resume */
+ if (!pm_runtime_get_if_active(&gpu->pdev->dev))
+ return;
+
+ mutex_lock(&gmu->lock);
+
+ sysprof_active = refcount_read(&gpu->sysprof_active);
+
+ /*
+ * 'Perfcounter select' register values are lost during IFPC collapse. To avoid that,
+ * use the currently unused perfcounter oob vote to block IFPC when sysprof is active
+ */
+ if ((sysprof_active > 1) && !test_and_set_bit(GMU_STATUS_OOB_PERF_SET, &gmu->status))
+ a6xx_gmu_set_oob(gmu, GMU_OOB_PERFCOUNTER_SET);
+ else if ((sysprof_active == 1) && test_and_clear_bit(GMU_STATUS_OOB_PERF_SET, &gmu->status))
+ a6xx_gmu_clear_oob(gmu, GMU_OOB_PERFCOUNTER_SET);
+
+ mutex_unlock(&gmu->lock);
+
+ pm_runtime_put(&gpu->pdev->dev);
+}
+
void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu)
{
struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
index 62c98b198551f26b99bd6e094f8fa35e16ec550d..65c2eb8bb757fd45cd9808a44013ed9453bee558 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
@@ -122,6 +122,8 @@ struct a6xx_gmu {
#define GMU_STATUS_FW_START 0
/* To track if PDC sleep seq was done */
#define GMU_STATUS_PDC_SLEEP 1
+/* To track Perfcounter OOB set status */
+#define GMU_STATUS_OOB_PERF_SET 2
unsigned long status;
};
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index b3becb230a94163cccff4eaffb8eed44f1c29ad0..b46fdd222913a46e01b984b90c4e63ae82f54e9f 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -2514,6 +2514,7 @@ static const struct adreno_gpu_funcs funcs = {
.create_private_address_space = a6xx_create_private_address_space,
.get_rptr = a6xx_get_rptr,
.progress = a6xx_progress,
+ .sysprof_setup = a6xx_gmu_sysprof_setup,
},
.get_timestamp = a6xx_gmu_get_timestamp,
};
@@ -2574,6 +2575,7 @@ static const struct adreno_gpu_funcs funcs_a7xx = {
.create_private_address_space = a6xx_create_private_address_space,
.get_rptr = a6xx_get_rptr,
.progress = a6xx_progress,
+ .sysprof_setup = a6xx_gmu_sysprof_setup,
},
.get_timestamp = a6xx_gmu_get_timestamp,
};
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
index 2be036a3faca58b4b559c30881e4b31d5929592a..bd1194bd15bf013489140c5f9f6b9f8582532a13 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
@@ -250,6 +250,7 @@ void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state);
int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node);
int a6xx_gmu_wrapper_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node);
void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu);
+void a6xx_gmu_sysprof_setup(struct msm_gpu *gpu);
void a6xx_preempt_init(struct msm_gpu *gpu);
void a6xx_preempt_hw_init(struct msm_gpu *gpu);
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index a0a0cf9efb3a8035a80cbbbf30ad294a72ccbd48..76be7f2d7e3e6f890f02d6f38a55329189639a2b 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -93,6 +93,7 @@ struct msm_gpu_funcs {
* for cmdstream that is buffered in this FIFO upstream of the CP fw.
*/
bool (*progress)(struct msm_gpu *gpu, struct msm_ringbuffer *ring);
+ void (*sysprof_setup)(struct msm_gpu *gpu);
};
/* Additional state for iommu faults: */
diff --git a/drivers/gpu/drm/msm/msm_submitqueue.c b/drivers/gpu/drm/msm/msm_submitqueue.c
index 7fed1de63b5d9e20df88db8d9ca6ea45ec1a2846..3332d23ce29943da55beb6704f2f5e8cb1589285 100644
--- a/drivers/gpu/drm/msm/msm_submitqueue.c
+++ b/drivers/gpu/drm/msm/msm_submitqueue.c
@@ -41,6 +41,10 @@ int msm_file_private_set_sysprof(struct msm_file_private *ctx,
break;
}
+ /* Some gpu families require additional setup for sysprof */
+ if (gpu->funcs->sysprof_setup)
+ gpu->funcs->sysprof_setup(gpu);
+
ctx->sysprof = sysprof;
return 0;
--
2.50.1
^ permalink raw reply related [flat|nested] 85+ messages in thread
* [PATCH 15/17] drm/msm/a6xx: Make crashstate capture IFPC safe
2025-07-20 12:16 [PATCH 00/17] drm/msm: Support for Inter Frame Power Collapse (IFPC) feature Akhil P Oommen
` (13 preceding siblings ...)
2025-07-20 12:16 ` [PATCH 14/17] drm/msm/adreno: Disable IFPC when sysprof is active Akhil P Oommen
@ 2025-07-20 12:16 ` Akhil P Oommen
2025-07-23 10:32 ` Konrad Dybcio
2025-07-20 12:16 ` [PATCH 16/17] drm/msm/a6xx: Enable IFPC on Adreno X1-85 Akhil P Oommen
2025-07-20 12:16 ` [PATCH 17/17] drm/msm/adreno: Relax devfreq tunings Akhil P Oommen
16 siblings, 1 reply; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-20 12:16 UTC (permalink / raw)
To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Akhil P Oommen
Now with IFPC, GX domain can collapse as soon as GPU becomes IDLE. So
add gx_is_on check before accessing any GX registers during crashstate
capture and recovery.
Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
---
drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 4 ++++
drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 27 +++++++++++++++++++--------
drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c | 10 +++++++---
3 files changed, 30 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index ccdcf5fe4b4f3cd81d765754d00c132960a916a9..c17837013b613b53793db0e34bbc7e65f0eb06e7 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -101,6 +101,10 @@ bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu)
if (!gmu->initialized)
return false;
+ /* If GMU is absent, then GX power domain is ON as long as GPU is in active state */
+ if (adreno_has_gmu_wrapper(adreno_gpu))
+ return true;
+
val = gmu_read(gmu, REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS);
if (adreno_is_a7xx(adreno_gpu))
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index b46fdd222913a46e01b984b90c4e63ae82f54e9f..54decb9908fe526ac7f150465034b03ba688aa6d 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -1518,21 +1518,25 @@ static void a6xx_recover(struct msm_gpu *gpu)
adreno_dump_info(gpu);
- for (i = 0; i < 8; i++)
- DRM_DEV_INFO(&gpu->pdev->dev, "CP_SCRATCH_REG%d: %u\n", i,
- gpu_read(gpu, REG_A6XX_CP_SCRATCH_REG(i)));
+ if (a6xx_gmu_gx_is_on(&a6xx_gpu->gmu)) {
+ /* Sometimes crashstate capture is skipped, so SQE should be halted here again */
+ gpu_write(gpu, REG_A6XX_CP_SQE_CNTL, 3);
- if (hang_debug)
- a6xx_dump(gpu);
+ for (i = 0; i < 8; i++)
+ DRM_DEV_INFO(&gpu->pdev->dev, "CP_SCRATCH_REG%d: %u\n", i,
+ gpu_read(gpu, REG_A6XX_CP_SCRATCH_REG(i)));
+
+ if (hang_debug)
+ a6xx_dump(gpu);
+
+ }
/*
* To handle recovery specific sequences during the rpm suspend we are
* about to trigger
*/
- a6xx_gpu->hung = true;
- /* Halt SQE first */
- gpu_write(gpu, REG_A6XX_CP_SQE_CNTL, 3);
+ a6xx_gpu->hung = true;
pm_runtime_dont_use_autosuspend(&gpu->pdev->dev);
@@ -2394,6 +2398,13 @@ static uint32_t a6xx_get_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
if (adreno_gpu->base.hw_apriv || a6xx_gpu->has_whereami)
return a6xx_gpu->shadow[ring->id];
+ /*
+ * This is true only on an A6XX_GEN1 with GMU, has IFPC enabled and a super old SQE firmware
+ * without 'whereami' support
+ */
+ WARN_ONCE((to_adreno_gpu(gpu)->info->quirks & ADRENO_QUIRK_IFPC),
+ "Can't read CP_RB_RPTR register reliably\n");
+
return ring->memptrs->rptr = gpu_read(gpu, REG_A6XX_CP_RB_RPTR);
}
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
index 341a72a674018258597aadefc9a45269b977e00e..cb846c1548ba4ea31a0ff0f23e98820388cb5ce0 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
@@ -1569,8 +1569,7 @@ struct msm_gpu_state *a6xx_gpu_state_get(struct msm_gpu *gpu)
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
struct a6xx_gpu_state *a6xx_state = kzalloc(sizeof(*a6xx_state),
GFP_KERNEL);
- bool stalled = !!(gpu_read(gpu, REG_A6XX_RBBM_STATUS3) &
- A6XX_RBBM_STATUS3_SMMU_STALLED_ON_FAULT);
+ bool stalled;
if (!a6xx_state)
return ERR_PTR(-ENOMEM);
@@ -1591,15 +1590,20 @@ struct msm_gpu_state *a6xx_gpu_state_get(struct msm_gpu *gpu)
}
/* If GX isn't on the rest of the data isn't going to be accessible */
- if (!adreno_has_gmu_wrapper(adreno_gpu) && !a6xx_gmu_gx_is_on(&a6xx_gpu->gmu))
+ if (!a6xx_gmu_gx_is_on(&a6xx_gpu->gmu))
return &a6xx_state->base;
+ /* Halt SQE first */
+ gpu_write(gpu, REG_A6XX_CP_SQE_CNTL, 3);
+
/* Get the banks of indexed registers */
if (adreno_is_a7xx(adreno_gpu))
a7xx_get_indexed_registers(gpu, a6xx_state);
else
a6xx_get_indexed_registers(gpu, a6xx_state);
+ stalled = !!(gpu_read(gpu, REG_A6XX_RBBM_STATUS3) &
+ A6XX_RBBM_STATUS3_SMMU_STALLED_ON_FAULT);
/*
* Try to initialize the crashdumper, if we are not dumping state
* with the SMMU stalled. The crashdumper needs memory access to
--
2.50.1
^ permalink raw reply related [flat|nested] 85+ messages in thread
* [PATCH 16/17] drm/msm/a6xx: Enable IFPC on Adreno X1-85
2025-07-20 12:16 [PATCH 00/17] drm/msm: Support for Inter Frame Power Collapse (IFPC) feature Akhil P Oommen
` (14 preceding siblings ...)
2025-07-20 12:16 ` [PATCH 15/17] drm/msm/a6xx: Make crashstate capture IFPC safe Akhil P Oommen
@ 2025-07-20 12:16 ` Akhil P Oommen
2025-07-22 13:55 ` Dmitry Baryshkov
` (2 more replies)
2025-07-20 12:16 ` [PATCH 17/17] drm/msm/adreno: Relax devfreq tunings Akhil P Oommen
16 siblings, 3 replies; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-20 12:16 UTC (permalink / raw)
To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Akhil P Oommen
Add the IFPC restore register list and enable IFPC support on Adreno
X1-85 gpu.
Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
---
drivers/gpu/drm/msm/adreno/a6xx_catalog.c | 67 ++++++++++++++++++++++++++++++-
drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 15 +++++--
drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 1 +
3 files changed, 78 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
index 70f7ad806c34076352d84f32d62c2833422b6e5e..07fcabed472c3b9ca47faf1a8b3f7cf580801981 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
@@ -1343,6 +1343,69 @@ static const uint32_t a7xx_pwrup_reglist_regs[] = {
DECLARE_ADRENO_REGLIST_LIST(a7xx_pwrup_reglist);
+/* Applicable for X185, A750 */
+static const u32 a750_ifpc_reglist_regs[] = {
+ REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_0,
+ REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_1,
+ REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_2,
+ REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_3,
+ REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_4,
+ REG_A6XX_TPL1_NC_MODE_CNTL,
+ REG_A6XX_SP_NC_MODE_CNTL,
+ REG_A6XX_CP_DBG_ECO_CNTL,
+ REG_A6XX_CP_PROTECT_CNTL,
+ REG_A6XX_CP_PROTECT(0),
+ REG_A6XX_CP_PROTECT(1),
+ REG_A6XX_CP_PROTECT(2),
+ REG_A6XX_CP_PROTECT(3),
+ REG_A6XX_CP_PROTECT(4),
+ REG_A6XX_CP_PROTECT(5),
+ REG_A6XX_CP_PROTECT(6),
+ REG_A6XX_CP_PROTECT(7),
+ REG_A6XX_CP_PROTECT(8),
+ REG_A6XX_CP_PROTECT(9),
+ REG_A6XX_CP_PROTECT(10),
+ REG_A6XX_CP_PROTECT(11),
+ REG_A6XX_CP_PROTECT(12),
+ REG_A6XX_CP_PROTECT(13),
+ REG_A6XX_CP_PROTECT(14),
+ REG_A6XX_CP_PROTECT(15),
+ REG_A6XX_CP_PROTECT(16),
+ REG_A6XX_CP_PROTECT(17),
+ REG_A6XX_CP_PROTECT(18),
+ REG_A6XX_CP_PROTECT(19),
+ REG_A6XX_CP_PROTECT(20),
+ REG_A6XX_CP_PROTECT(21),
+ REG_A6XX_CP_PROTECT(22),
+ REG_A6XX_CP_PROTECT(23),
+ REG_A6XX_CP_PROTECT(24),
+ REG_A6XX_CP_PROTECT(25),
+ REG_A6XX_CP_PROTECT(26),
+ REG_A6XX_CP_PROTECT(27),
+ REG_A6XX_CP_PROTECT(28),
+ REG_A6XX_CP_PROTECT(29),
+ REG_A6XX_CP_PROTECT(30),
+ REG_A6XX_CP_PROTECT(31),
+ REG_A6XX_CP_PROTECT(32),
+ REG_A6XX_CP_PROTECT(33),
+ REG_A6XX_CP_PROTECT(34),
+ REG_A6XX_CP_PROTECT(35),
+ REG_A6XX_CP_PROTECT(36),
+ REG_A6XX_CP_PROTECT(37),
+ REG_A6XX_CP_PROTECT(38),
+ REG_A6XX_CP_PROTECT(39),
+ REG_A6XX_CP_PROTECT(40),
+ REG_A6XX_CP_PROTECT(41),
+ REG_A6XX_CP_PROTECT(42),
+ REG_A6XX_CP_PROTECT(43),
+ REG_A6XX_CP_PROTECT(44),
+ REG_A6XX_CP_PROTECT(45),
+ REG_A6XX_CP_PROTECT(46),
+ REG_A6XX_CP_PROTECT(47),
+};
+
+DECLARE_ADRENO_REGLIST_LIST(a750_ifpc_reglist);
+
static const struct adreno_info a7xx_gpus[] = {
{
.chip_ids = ADRENO_CHIP_IDS(0x07000200),
@@ -1432,12 +1495,13 @@ static const struct adreno_info a7xx_gpus[] = {
.inactive_period = DRM_MSM_INACTIVE_PERIOD,
.quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
ADRENO_QUIRK_HAS_HW_APRIV |
- ADRENO_QUIRK_PREEMPTION,
+ ADRENO_QUIRK_PREEMPTION | ADRENO_QUIRK_IFPC,
.init = a6xx_gpu_init,
.a6xx = &(const struct a6xx_info) {
.hwcg = a740_hwcg,
.protect = &a730_protect,
.pwrup_reglist = &a7xx_pwrup_reglist,
+ .ifpc_reglist = &a750_ifpc_reglist,
.gmu_chipid = 0x7050001,
.gmu_cgc_mode = 0x00020202,
},
@@ -1459,6 +1523,7 @@ static const struct adreno_info a7xx_gpus[] = {
.a6xx = &(const struct a6xx_info) {
.protect = &a730_protect,
.pwrup_reglist = &a7xx_pwrup_reglist,
+ .ifpc_reglist = &a750_ifpc_reglist,
.gmu_chipid = 0x7090100,
.gmu_cgc_mode = 0x00020202,
.bcms = (const struct a6xx_bcm[]) {
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index 54decb9908fe526ac7f150465034b03ba688aa6d..bc9463840c02c3c3ee3ae0431eff147ae97edc88 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -809,11 +809,10 @@ static void a7xx_patch_pwrup_reglist(struct msm_gpu *gpu)
u32 *dest = (u32 *)&lock->regs[0];
int i;
- reglist = adreno_gpu->info->a6xx->pwrup_reglist;
-
lock->gpu_req = lock->cpu_req = lock->turn = 0;
- lock->ifpc_list_len = 0;
- lock->preemption_list_len = reglist->count;
+
+ reglist = adreno_gpu->info->a6xx->ifpc_reglist;
+ lock->ifpc_list_len = reglist->count;
/*
* For each entry in each of the lists, write the offset and the current
@@ -824,6 +823,14 @@ static void a7xx_patch_pwrup_reglist(struct msm_gpu *gpu)
*dest++ = gpu_read(gpu, reglist->regs[i]);
}
+ reglist = adreno_gpu->info->a6xx->pwrup_reglist;
+ lock->preemption_list_len = reglist->count;
+
+ for (i = 0; i < reglist->count; i++) {
+ *dest++ = reglist->regs[i];
+ *dest++ = gpu_read(gpu, reglist->regs[i]);
+ }
+
/*
* The overall register list is composed of
* 1. Static IFPC-only registers
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
index bd1194bd15bf013489140c5f9f6b9f8582532a13..ed98dd1bd887bd160f73f320366a7b8b2c9f874e 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
@@ -41,6 +41,7 @@ struct a6xx_info {
const struct adreno_reglist *hwcg;
const struct adreno_protect *protect;
const struct adreno_reglist_list *pwrup_reglist;
+ const struct adreno_reglist_list *ifpc_reglist;
u32 gmu_chipid;
u32 gmu_cgc_mode;
u32 prim_fifo_threshold;
--
2.50.1
^ permalink raw reply related [flat|nested] 85+ messages in thread
* [PATCH 17/17] drm/msm/adreno: Relax devfreq tunings
2025-07-20 12:16 [PATCH 00/17] drm/msm: Support for Inter Frame Power Collapse (IFPC) feature Akhil P Oommen
` (15 preceding siblings ...)
2025-07-20 12:16 ` [PATCH 16/17] drm/msm/a6xx: Enable IFPC on Adreno X1-85 Akhil P Oommen
@ 2025-07-20 12:16 ` Akhil P Oommen
2025-07-27 0:49 ` Anthony Ruhier
16 siblings, 1 reply; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-20 12:16 UTC (permalink / raw)
To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Akhil P Oommen
Relax the devfreq tunings when IFPC feature is supported because there
is no wakeup latency that we have to hide with aggressive dcvs. This
helps to eliminate the very frequent gpu frequency spikes to FMAX even
with common lightweight workloads like UI scrolling. Some profiling
data from X1E which shows the improvement:
DUT: X1E CRD, 1.25Ghz GPU FMAX, 2880x1800@120Hz, Debian Trixie Gnome
Testcase: WebGL aquarium with Chromium
Current dcvs config:
+--------+--------------+------------+------+
| Fishes | GPU Load (%) | Freq (Mhz) | FPS |
+--------+--------------+------------+------+
| 1 | 23 | 300 | 120 |
| 100 | 29 | 300 | 120 |
| 500 | 41 | 300 | 120 |
| 1000 | 45 | 390/550 | 120 |
| 5000 | 50 | 1250 | 120 |
| 10000 | 93 | 1250 | 120 |
| 15000 | 100 | 1250 | 87 |
+--------+--------------+------------+------+
New dcvs config:
+--------+--------------+------------+------+
| Fishes | GPU Load (%) | Freq (Mhz) | FPS |
+--------+--------------+------------+------+
| 1 | 23 | 300 | 120 |
| 100 | 28 | 300 | 120 |
| 500 | 42 | 300 | 120 |
| 1000 | 62 | 300 | 120 |
| 5000 | 84 | 744 | 120 |
| 10000 | 93 | 1250 | 120 |
| 15000 | 100 | 1250 | 87 |
+--------+--------------+------------+------+
Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
---
drivers/gpu/drm/msm/msm_gpu_devfreq.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/gpu/drm/msm/msm_gpu_devfreq.c b/drivers/gpu/drm/msm/msm_gpu_devfreq.c
index 53ef2add5047e7d6b6371af949cab36ce8409372..212963a5b8b57597bf5b01ab90893b01fd9c6e76 100644
--- a/drivers/gpu/drm/msm/msm_gpu_devfreq.c
+++ b/drivers/gpu/drm/msm/msm_gpu_devfreq.c
@@ -156,6 +156,13 @@ void msm_devfreq_init(struct msm_gpu *gpu)
priv->gpu_devfreq_config.upthreshold = 50;
priv->gpu_devfreq_config.downdifferential = 10;
+ /*
+ * Relax the tunings when IFPC is supported because there is negligible latency in
+ * switching power state
+ */
+ if (to_adreno_gpu(gpu)->info->quirks & ADRENO_QUIRK_IFPC)
+ priv->gpu_devfreq_config.upthreshold = 90;
+
mutex_init(&df->lock);
df->suspended = true;
--
2.50.1
^ permalink raw reply related [flat|nested] 85+ messages in thread
* Re: [PATCH 03/17] drm/msm: a6xx: Fix gx_is_on check for a7x family
2025-07-20 12:16 ` [PATCH 03/17] drm/msm: a6xx: Fix gx_is_on check for a7x family Akhil P Oommen
@ 2025-07-20 18:46 ` Dmitry Baryshkov
2025-07-22 14:33 ` Konrad Dybcio
1 sibling, 0 replies; 85+ messages in thread
From: Dmitry Baryshkov @ 2025-07-20 18:46 UTC (permalink / raw)
To: Akhil P Oommen
Cc: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, linux-arm-msm, dri-devel, freedreno, linux-kernel
On Sun, Jul 20, 2025 at 05:46:04PM +0530, Akhil P Oommen wrote:
> Bitfield definition for REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS register is
> different in A7XX family. Check the correct bits to see if GX is
> collapsed on A7XX series.
>
> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
Missing Fixes tag
> ---
> drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 7 +++++++
> 1 file changed, 7 insertions(+)
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 12/17] drm/msm: Skip devfreq IDLE when possible
2025-07-20 12:16 ` [PATCH 12/17] drm/msm: Skip devfreq IDLE when possible Akhil P Oommen
@ 2025-07-21 4:00 ` kernel test robot
2025-07-22 13:50 ` Dmitry Baryshkov
2025-07-23 10:28 ` Konrad Dybcio
2 siblings, 0 replies; 85+ messages in thread
From: kernel test robot @ 2025-07-21 4:00 UTC (permalink / raw)
To: Akhil P Oommen, Rob Clark, Sean Paul, Konrad Dybcio,
Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Marijn Suijten,
David Airlie, Simona Vetter
Cc: oe-kbuild-all, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Akhil P Oommen
Hi Akhil,
kernel test robot noticed the following build errors:
[auto build test ERROR on 88bf743cabe5793d24f831ef8240a0bf90e5fd44]
url: https://github.com/intel-lab-lkp/linux/commits/Akhil-P-Oommen/drm-msm-Update-GMU-register-xml/20250720-201844
base: 88bf743cabe5793d24f831ef8240a0bf90e5fd44
patch link: https://lore.kernel.org/r/20250720-ifpc-support-v1-12-9347aa5bcbd6%40oss.qualcomm.com
patch subject: [PATCH 12/17] drm/msm: Skip devfreq IDLE when possible
config: sparc-allmodconfig (https://download.01.org/0day-ci/archive/20250721/202507211133.d0ChrtTQ-lkp@intel.com/config)
compiler: sparc64-linux-gcc (GCC) 15.1.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250721/202507211133.d0ChrtTQ-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202507211133.d0ChrtTQ-lkp@intel.com/
All errors (new ones prefixed by >>):
In file included from drivers/gpu/drm/msm/msm_gpu_devfreq.c:7:
>> drivers/gpu/drm/msm/adreno/adreno_gpu.h:17:10: fatal error: adreno_common.xml.h: No such file or directory
17 | #include "adreno_common.xml.h"
| ^~~~~~~~~~~~~~~~~~~~~
compilation terminated.
vim +17 drivers/gpu/drm/msm/adreno/adreno_gpu.h
7198e6b03155f6 Rob Clark 2013-07-19 16
7198e6b03155f6 Rob Clark 2013-07-19 @17 #include "adreno_common.xml.h"
7198e6b03155f6 Rob Clark 2013-07-19 18 #include "adreno_pm4.xml.h"
7198e6b03155f6 Rob Clark 2013-07-19 19
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 04/17] drm/msm/a6xx: Poll additional DRV status
2025-07-20 12:16 ` [PATCH 04/17] drm/msm/a6xx: Poll additional DRV status Akhil P Oommen
@ 2025-07-22 13:31 ` Dmitry Baryshkov
2025-07-22 19:55 ` Akhil P Oommen
2025-07-23 10:01 ` Konrad Dybcio
1 sibling, 1 reply; 85+ messages in thread
From: Dmitry Baryshkov @ 2025-07-22 13:31 UTC (permalink / raw)
To: Akhil P Oommen
Cc: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, linux-arm-msm, dri-devel, freedreno, linux-kernel
On Sun, Jul 20, 2025 at 05:46:05PM +0530, Akhil P Oommen wrote:
> A7XX_GEN2 generation has additional TCS slots. Poll the respective
> DRV status registers before pm suspend.
>
Fixes?
> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
> ---
> drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 16 ++++++++++++++++
> 1 file changed, 16 insertions(+)
>
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> index 790ef2f94a0b0cd40433d7edb6a89e4f04408bf5..3bebb6dd7059782ceca29f2efd2acee24d3fc930 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> @@ -987,6 +987,22 @@ static void a6xx_gmu_rpmh_off(struct a6xx_gmu *gmu)
> val, (val & 1), 100, 10000);
> gmu_poll_timeout_rscc(gmu, REG_A6XX_RSCC_TCS3_DRV0_STATUS + seqmem_off,
> val, (val & 1), 100, 1000);
> +
> + if (!adreno_is_a740_family(adreno_gpu))
> + return;
> +
> + gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS4_DRV0_STATUS + seqmem_off,
> + val, (val & 1), 100, 10000);
> + gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS5_DRV0_STATUS + seqmem_off,
> + val, (val & 1), 100, 10000);
> + gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS6_DRV0_STATUS + seqmem_off,
> + val, (val & 1), 100, 10000);
> + gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS7_DRV0_STATUS + seqmem_off,
> + val, (val & 1), 100, 1000);
> + gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS8_DRV0_STATUS + seqmem_off,
> + val, (val & 1), 100, 10000);
> + gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS9_DRV0_STATUS + seqmem_off,
> + val, (val & 1), 100, 1000);
> }
>
> /* Force the GMU off in case it isn't responsive */
>
> --
> 2.50.1
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 05/17] drm/msm/a6xx: Fix PDC sleep sequence
2025-07-20 12:16 ` [PATCH 05/17] drm/msm/a6xx: Fix PDC sleep sequence Akhil P Oommen
@ 2025-07-22 13:33 ` Dmitry Baryshkov
2025-07-22 17:26 ` Rob Clark
2025-08-07 13:51 ` Konrad Dybcio
1 sibling, 1 reply; 85+ messages in thread
From: Dmitry Baryshkov @ 2025-07-22 13:33 UTC (permalink / raw)
To: Akhil P Oommen
Cc: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, linux-arm-msm, dri-devel, freedreno, linux-kernel
On Sun, Jul 20, 2025 at 05:46:06PM +0530, Akhil P Oommen wrote:
> 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
s/KMD/the driver/
> GMU firmware has not initialized. Track these dependencies using a new
> status variable and trigger PDC sleep/wake sequences appropriately.
Again, it looks like there should be a Fixes tag here.
>
> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
> ---
> drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 30 +++++++++++++++++++-----------
> drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 6 ++++++
> 2 files changed, 25 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> index 3bebb6dd7059782ceca29f2efd2acee24d3fc930..4d6c70735e0892ed87d6a68d64f24bda844e5e16 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> @@ -279,6 +279,8 @@ static int a6xx_gmu_start(struct a6xx_gmu *gmu)
> if (ret)
> DRM_DEV_ERROR(gmu->dev, "GMU firmware initialization timed out\n");
>
> + set_bit(GMU_STATUS_FW_START, &gmu->status);
> +
> return ret;
> }
>
> @@ -528,6 +530,9 @@ static int a6xx_rpmh_start(struct a6xx_gmu *gmu)
> int ret;
> u32 val;
>
> + if (!test_and_clear_bit(GMU_STATUS_PDC_SLEEP, &gmu->status))
> + return 0;
> +
> gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, BIT(1));
>
> ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_RSCC_CONTROL_ACK, val,
> @@ -555,6 +560,11 @@ static void a6xx_rpmh_stop(struct a6xx_gmu *gmu)
> int ret;
> u32 val;
>
> + if (test_and_clear_bit(GMU_STATUS_FW_START, &gmu->status))
> + return;
> +
> + /* TODO: should we skip if IFPC is not enabled */
Is this a question or a statement?
> +
> gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, 1);
>
> ret = gmu_poll_timeout_rscc(gmu, REG_A6XX_GPU_RSCC_RSC_STATUS0_DRV0,
> @@ -563,6 +573,8 @@ static void a6xx_rpmh_stop(struct a6xx_gmu *gmu)
> DRM_DEV_ERROR(gmu->dev, "Unable to power off the GPU RSC\n");
>
> gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, 0);
> +
> + set_bit(GMU_STATUS_PDC_SLEEP, &gmu->status);
> }
>
> static inline void pdc_write(void __iomem *ptr, u32 offset, u32 value)
> @@ -691,8 +703,6 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu)
> /* ensure no writes happen before the uCode is fully written */
> wmb();
>
> - a6xx_rpmh_stop(gmu);
> -
> err:
> if (!IS_ERR_OR_NULL(pdcptr))
> iounmap(pdcptr);
> @@ -852,19 +862,15 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state)
> else
> gmu_write(gmu, REG_A6XX_GMU_GENERAL_7, 1);
>
> - if (state == GMU_WARM_BOOT) {
> - ret = a6xx_rpmh_start(gmu);
> - if (ret)
> - return ret;
> - } else {
> + ret = a6xx_rpmh_start(gmu);
> + if (ret)
> + return ret;
> +
> + if (state == GMU_COLD_BOOT) {
> if (WARN(!adreno_gpu->fw[ADRENO_FW_GMU],
> "GMU firmware is not loaded\n"))
> return -ENOENT;
>
> - ret = a6xx_rpmh_start(gmu);
> - if (ret)
> - return ret;
> -
> ret = a6xx_gmu_fw_load(gmu);
> if (ret)
> return ret;
> @@ -1046,6 +1052,8 @@ static void a6xx_gmu_force_off(struct a6xx_gmu *gmu)
>
> /* Reset GPU core blocks */
> a6xx_gpu_sw_reset(gpu, true);
> +
> + a6xx_rpmh_stop(gmu);
> }
>
> static void a6xx_gmu_set_initial_freq(struct msm_gpu *gpu, struct a6xx_gmu *gmu)
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
> index b2d4489b40249b1916ab4a42c89e3f4bdc5c4af9..034f1b4e5a3fb9cd601bfbe6d06d64e5ace3b6e7 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
> @@ -117,6 +117,12 @@ struct a6xx_gmu {
>
> struct qmp *qmp;
> struct a6xx_hfi_msg_bw_table *bw_table;
> +
> +/* To check if we can trigger sleep seq at PDC. Cleared in a6xx_rpmh_stop() */
> +#define GMU_STATUS_FW_START 0
> +/* To track if PDC sleep seq was done */
> +#define GMU_STATUS_PDC_SLEEP 1
> + unsigned long status;
> };
>
> static inline u32 gmu_read(struct a6xx_gmu *gmu, u32 offset)
>
> --
> 2.50.1
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 07/17] drm/msm/adreno: Add fenced regwrite support
2025-07-20 12:16 ` [PATCH 07/17] drm/msm/adreno: Add fenced regwrite support Akhil P Oommen
@ 2025-07-22 13:39 ` Dmitry Baryshkov
2025-07-22 14:52 ` Konrad Dybcio
2025-07-23 21:04 ` Akhil P Oommen
0 siblings, 2 replies; 85+ messages in thread
From: Dmitry Baryshkov @ 2025-07-22 13:39 UTC (permalink / raw)
To: Akhil P Oommen
Cc: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, linux-arm-msm, dri-devel, freedreno, linux-kernel
On Sun, Jul 20, 2025 at 05:46:08PM +0530, Akhil P Oommen wrote:
> There are some special registers which are accessible even when GX power
> domain is collapsed during an IFPC sleep. Accessing these registers
> wakes up GPU from power collapse and allow programming these registers
> without additional handshake with GMU. This patch adds support for this
> special register write sequence.
>
> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
> ---
> drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 63 ++++++++++++++++++++++++++++++-
> drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 1 +
> drivers/gpu/drm/msm/adreno/a6xx_preempt.c | 20 +++++-----
> 3 files changed, 73 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> index 491fde0083a202bec7c6b3bca88d0e5a717a6560..8c004fc3abd2896d467a9728b34e99e4ed944dc4 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> @@ -16,6 +16,67 @@
>
> #define GPU_PAS_ID 13
>
> +static bool fence_status_check(struct msm_gpu *gpu, u32 offset, u32 value, u32 status, u32 mask)
> +{
> + /* Success if !writedropped0/1 */
> + if (!(status & mask))
> + return true;
> +
> + udelay(10);
Why do we need udelay() here? Why can't we use interval setting inside
gmu_poll_timeout()?
> +
> + /* Try to update fenced register again */
> + gpu_write(gpu, offset, value);
> + return false;
> +}
> +
> +static int fenced_write(struct a6xx_gpu *a6xx_gpu, u32 offset, u32 value, u32 mask)
> +{
> + struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
> + struct msm_gpu *gpu = &adreno_gpu->base;
> + struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
> + u32 status;
> +
> + gpu_write(gpu, offset, value);
> +
> + /* Nothing else to be done in the case of no-GMU */
> + if (adreno_has_gmu_wrapper(adreno_gpu))
> + return 0;
> +
> + if (!gmu_poll_timeout(gmu, REG_A6XX_GMU_AHB_FENCE_STATUS, status,
> + fence_status_check(gpu, offset, value, status, mask), 0, 1000))
> + return 0;
> +
> + dev_err_ratelimited(gmu->dev, "delay in fenced register write (0x%x)\n",
> + offset);
> +
> + /* Try again for another 1ms before failing */
> + gpu_write(gpu, offset, value);
> + if (!gmu_poll_timeout(gmu, REG_A6XX_GMU_AHB_FENCE_STATUS, status,
> + fence_status_check(gpu, offset, value, status, mask), 0, 1000))
> + return 0;
> +
> + dev_err_ratelimited(gmu->dev, "fenced register write (0x%x) fail\n",
> + offset);
> +
> + return -ETIMEDOUT;
> +}
> +
> +int a6xx_fenced_write(struct a6xx_gpu *a6xx_gpu, u32 offset, u64 value, u32 mask, bool is_64b)
> +{
> + int ret;
> +
> + ret = fenced_write(a6xx_gpu, offset, lower_32_bits(value), mask);
> + if (ret)
> + return ret;
> +
> + if (!is_64b)
> + return 0;
> +
> + ret = fenced_write(a6xx_gpu, offset + 1, upper_32_bits(value), mask);
no need for a separate ret assignment.
> +
> + return ret;
> +}
> +
> static inline bool _a6xx_check_idle(struct msm_gpu *gpu)
> {
> struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
> @@ -86,7 +147,7 @@ static void a6xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
> /* Update HW if this is the current ring and we are not in preempt*/
> if (!a6xx_in_preempt(a6xx_gpu)) {
> if (a6xx_gpu->cur_ring == ring)
> - gpu_write(gpu, REG_A6XX_CP_RB_WPTR, wptr);
> + a6xx_fenced_write(a6xx_gpu, REG_A6XX_CP_RB_WPTR, wptr, BIT(0), false);
I can't stop but notice that we don't handle a6xx_fenced_write() errors.
Is it fine? Or will it result in some sort of crash / reset?
> else
> ring->restore_wptr = true;
> } else {
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
> index 9201a53dd341bf432923ffb44947e015208a3d02..2be036a3faca58b4b559c30881e4b31d5929592a 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
> @@ -291,5 +291,6 @@ int a6xx_gpu_state_put(struct msm_gpu_state *state);
>
> void a6xx_bus_clear_pending_transactions(struct adreno_gpu *adreno_gpu, bool gx_off);
> void a6xx_gpu_sw_reset(struct msm_gpu *gpu, bool assert);
> +int a6xx_fenced_write(struct a6xx_gpu *gpu, u32 offset, u64 value, u32 mask, bool is_64b);
>
> #endif /* __A6XX_GPU_H__ */
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_preempt.c b/drivers/gpu/drm/msm/adreno/a6xx_preempt.c
> index 3b17fd2dba89115a8e48ba9469e52e4305b0cdbb..5b0fd510ff58d989ab285f1a2497f6f522a6b187 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_preempt.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_preempt.c
> @@ -41,7 +41,7 @@ static inline void set_preempt_state(struct a6xx_gpu *gpu,
> }
>
> /* Write the most recent wptr for the given ring into the hardware */
> -static inline void update_wptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
> +static inline void update_wptr(struct a6xx_gpu *a6xx_gpu, struct msm_ringbuffer *ring)
> {
> unsigned long flags;
> uint32_t wptr;
> @@ -51,7 +51,7 @@ static inline void update_wptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
> if (ring->restore_wptr) {
> wptr = get_wptr(ring);
>
> - gpu_write(gpu, REG_A6XX_CP_RB_WPTR, wptr);
> + a6xx_fenced_write(a6xx_gpu, REG_A6XX_CP_RB_WPTR, wptr, BIT(0), false);
>
> ring->restore_wptr = false;
> }
> @@ -172,7 +172,7 @@ void a6xx_preempt_irq(struct msm_gpu *gpu)
>
> set_preempt_state(a6xx_gpu, PREEMPT_FINISH);
>
> - update_wptr(gpu, a6xx_gpu->cur_ring);
> + update_wptr(a6xx_gpu, a6xx_gpu->cur_ring);
>
> set_preempt_state(a6xx_gpu, PREEMPT_NONE);
>
> @@ -268,7 +268,7 @@ void a6xx_preempt_trigger(struct msm_gpu *gpu)
> */
> if (!ring || (a6xx_gpu->cur_ring == ring)) {
> set_preempt_state(a6xx_gpu, PREEMPT_FINISH);
> - update_wptr(gpu, a6xx_gpu->cur_ring);
> + update_wptr(a6xx_gpu, a6xx_gpu->cur_ring);
> set_preempt_state(a6xx_gpu, PREEMPT_NONE);
> spin_unlock_irqrestore(&a6xx_gpu->eval_lock, flags);
> return;
> @@ -302,13 +302,13 @@ void a6xx_preempt_trigger(struct msm_gpu *gpu)
>
> spin_unlock_irqrestore(&ring->preempt_lock, flags);
>
> - gpu_write64(gpu,
> - REG_A6XX_CP_CONTEXT_SWITCH_SMMU_INFO,
> - a6xx_gpu->preempt_smmu_iova[ring->id]);
> + a6xx_fenced_write(a6xx_gpu,
> + REG_A6XX_CP_CONTEXT_SWITCH_SMMU_INFO, a6xx_gpu->preempt_smmu_iova[ring->id],
> + BIT(1), true);
>
> - gpu_write64(gpu,
> + a6xx_fenced_write(a6xx_gpu,
> REG_A6XX_CP_CONTEXT_SWITCH_PRIV_NON_SECURE_RESTORE_ADDR,
> - a6xx_gpu->preempt_iova[ring->id]);
> + a6xx_gpu->preempt_iova[ring->id], BIT(1), true);
>
> a6xx_gpu->next_ring = ring;
>
> @@ -328,7 +328,7 @@ void a6xx_preempt_trigger(struct msm_gpu *gpu)
> set_preempt_state(a6xx_gpu, PREEMPT_TRIGGERED);
>
> /* Trigger the preemption */
> - gpu_write(gpu, REG_A6XX_CP_CONTEXT_SWITCH_CNTL, cntl);
> + a6xx_fenced_write(a6xx_gpu, REG_A6XX_CP_CONTEXT_SWITCH_CNTL, cntl, BIT(1), false);
> }
>
> static int preempt_init_ring(struct a6xx_gpu *a6xx_gpu,
>
> --
> 2.50.1
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 08/17] drm/msm/a6xx: Set Keep-alive votes to block IFPC
2025-07-20 12:16 ` [PATCH 08/17] drm/msm/a6xx: Set Keep-alive votes to block IFPC Akhil P Oommen
@ 2025-07-22 13:44 ` Dmitry Baryshkov
2025-07-22 21:24 ` Akhil P Oommen
0 siblings, 1 reply; 85+ messages in thread
From: Dmitry Baryshkov @ 2025-07-22 13:44 UTC (permalink / raw)
To: Akhil P Oommen
Cc: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, linux-arm-msm, dri-devel, freedreno, linux-kernel
On Sun, Jul 20, 2025 at 05:46:09PM +0530, Akhil P Oommen wrote:
> 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>
> ---
> 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 8c004fc3abd2896d467a9728b34e99e4ed944dc4..6770f0363e7284e4596b1188637a4615d2c0779b 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> @@ -1752,8 +1752,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);
>
> /*
> @@ -1765,13 +1763,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,
> @@ -1810,9 +1801,24 @@ static void a7xx_sw_fuse_violation_irq(struct msm_gpu *gpu)
> }
> }
>
> +static void set_keepalive_vote(struct msm_gpu *gpu, bool on)
a6xx_set_keepalive_vote()
> +{
> + 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 */
> + set_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);
> @@ -1849,6 +1855,8 @@ static irqreturn_t a6xx_irq(struct msm_gpu *gpu)
> if (status & A6XX_RBBM_INT_0_MASK_CP_SW)
> a6xx_preempt_irq(gpu);
>
> + set_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 5b0fd510ff58d989ab285f1a2497f6f522a6b187..1c8ec1911010c00a000d195116fc950c4d947cac 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 set_keepalive_vote(struct msm_gpu *gpu, bool on)
a6xx_set_preempt_keepalive_vote();
> +{
> + 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);
>
> + set_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 */
> + set_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
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 11/17] drm/msm: Add support for IFPC
2025-07-20 12:16 ` [PATCH 11/17] drm/msm: Add support for IFPC Akhil P Oommen
@ 2025-07-22 13:49 ` Dmitry Baryshkov
2025-07-22 21:27 ` Akhil P Oommen
2025-07-23 10:22 ` Konrad Dybcio
1 sibling, 1 reply; 85+ messages in thread
From: Dmitry Baryshkov @ 2025-07-22 13:49 UTC (permalink / raw)
To: Akhil P Oommen
Cc: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, linux-arm-msm, dri-devel, freedreno, linux-kernel
On Sun, Jul 20, 2025 at 05:46:12PM +0530, Akhil P Oommen wrote:
> Add a new quirk to denote IFPC (Inter-Frame Power Collapse) support
> for a gpu. Based on this flag send the feature ctrl hfi message to
> GMU to enable IFPC support.
>
> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
> ---
> drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 5 +++--
> drivers/gpu/drm/msm/adreno/a6xx_hfi.c | 33 +++++++++++++++++++++++++++------
> drivers/gpu/drm/msm/adreno/adreno_gpu.h | 1 +
> 3 files changed, 31 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> index 4d6c70735e0892ed87d6a68d64f24bda844e5e16..3bbcc78179c1cf1bfa21ff097e9350eb2f554011 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> @@ -1961,8 +1961,9 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
> if (ret)
> return ret;
>
> - /* Fow now, don't do anything fancy until we get our feet under us */
> - gmu->idle_level = GMU_IDLE_STATE_ACTIVE;
> + /* Set GMU idle level */
> + gmu->idle_level = (adreno_gpu->info->quirks & ADRENO_QUIRK_IFPC) ?
> + GMU_IDLE_STATE_IFPC : GMU_IDLE_STATE_ACTIVE;
>
> pm_runtime_enable(gmu->dev);
>
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
> index 8e69b1e8465711837151725c8f70e7b4b16a368e..20ade6b0558b016b581078f5cf7377e7e7c57f8e 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
> @@ -21,6 +21,7 @@ static const char * const a6xx_hfi_msg_id[] = {
> HFI_MSG_ID(HFI_H2F_MSG_PERF_TABLE),
> HFI_MSG_ID(HFI_H2F_MSG_TEST),
> HFI_MSG_ID(HFI_H2F_MSG_START),
> + HFI_MSG_ID(HFI_H2F_FEATURE_CTRL),
> HFI_MSG_ID(HFI_H2F_MSG_CORE_FW_START),
> HFI_MSG_ID(HFI_H2F_MSG_GX_BW_PERF_VOTE),
> HFI_MSG_ID(HFI_H2F_MSG_PREPARE_SLUMBER),
> @@ -765,23 +766,39 @@ static int a6xx_hfi_send_bw_table(struct a6xx_gmu *gmu)
> NULL, 0);
> }
>
> +static int a6xx_hfi_feature_ctrl_msg(struct a6xx_gmu *gmu, u32 feature, u32 enable, u32 data)
> +{
> + struct a6xx_hfi_msg_feature_ctrl msg = {
> + .feature = feature,
> + .enable = enable,
> + .data = data,
> + };
> +
> + return a6xx_hfi_send_msg(gmu, HFI_H2F_FEATURE_CTRL, &msg, sizeof(msg), NULL, 0);
> +}
> +
> +#define HFI_FEATURE_IFPC 9
Can we please have an enum or at least a set of defines rather than
havign them scattered through the code?
> +
> +static int a6xx_hfi_enable_ifpc(struct a6xx_gmu *gmu)
> +{
> + if (gmu->idle_level != GMU_IDLE_STATE_IFPC)
> + return 0;
> +
> + return a6xx_hfi_feature_ctrl_msg(gmu, HFI_FEATURE_IFPC, 1, 0x1680);
magic number?
> +}
> +
> #define HFI_FEATURE_ACD 12
>
> static int a6xx_hfi_enable_acd(struct a6xx_gmu *gmu)
> {
> struct a6xx_hfi_acd_table *acd_table = &gmu->acd_table;
> - struct a6xx_hfi_msg_feature_ctrl msg = {
> - .feature = HFI_FEATURE_ACD,
> - .enable = 1,
> - .data = 0,
> - };
> int ret;
>
> if (!acd_table->enable_by_level)
> return 0;
>
> /* Enable ACD feature at GMU */
> - ret = a6xx_hfi_send_msg(gmu, HFI_H2F_FEATURE_CTRL, &msg, sizeof(msg), NULL, 0);
> + ret = a6xx_hfi_feature_ctrl_msg(gmu, HFI_FEATURE_ACD, 1, 0);
> if (ret) {
> DRM_DEV_ERROR(gmu->dev, "Unable to enable ACD (%d)\n", ret);
> return ret;
> @@ -898,6 +915,10 @@ int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state)
> if (ret)
> return ret;
>
> + ret = a6xx_hfi_enable_ifpc(gmu);
> + if (ret)
> + return ret;
> +
> ret = a6xx_hfi_send_core_fw_start(gmu);
> if (ret)
> return ret;
> diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
> index bc063594a359ee6b796381c5fd2c30e2aa12a26d..1135beafac464f3162a3a61938a7de0c7920455a 100644
> --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
> +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
> @@ -58,6 +58,7 @@ enum adreno_family {
> #define ADRENO_QUIRK_HAS_CACHED_COHERENT BIT(4)
> #define ADRENO_QUIRK_PREEMPTION BIT(5)
> #define ADRENO_QUIRK_4GB_VA BIT(6)
> +#define ADRENO_QUIRK_IFPC BIT(7)
>
> /* Helper for formating the chip_id in the way that userspace tools like
> * crashdec expect.
>
> --
> 2.50.1
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 12/17] drm/msm: Skip devfreq IDLE when possible
2025-07-20 12:16 ` [PATCH 12/17] drm/msm: Skip devfreq IDLE when possible Akhil P Oommen
2025-07-21 4:00 ` kernel test robot
@ 2025-07-22 13:50 ` Dmitry Baryshkov
2025-07-22 15:38 ` Rob Clark
2025-07-23 10:28 ` Konrad Dybcio
2 siblings, 1 reply; 85+ messages in thread
From: Dmitry Baryshkov @ 2025-07-22 13:50 UTC (permalink / raw)
To: Akhil P Oommen
Cc: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, linux-arm-msm, dri-devel, freedreno, linux-kernel
On Sun, Jul 20, 2025 at 05:46:13PM +0530, Akhil P Oommen wrote:
> When IFPC is supported, devfreq idling is redundant and adds
> unnecessary pm suspend/wake latency. So skip it when IFPC is
> supported.
With this in place we have a dummy devfreq instance which does nothing.
Wouldn't it be better to skip registering devfreq if IFPC is supported
on the platform?
>
> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
> ---
> drivers/gpu/drm/msm/msm_gpu_devfreq.c | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/drivers/gpu/drm/msm/msm_gpu_devfreq.c b/drivers/gpu/drm/msm/msm_gpu_devfreq.c
> index 2e1d5c3432728cde15d91f69da22bb915588fe86..53ef2add5047e7d6b6371af949cab36ce8409372 100644
> --- a/drivers/gpu/drm/msm/msm_gpu_devfreq.c
> +++ b/drivers/gpu/drm/msm/msm_gpu_devfreq.c
> @@ -4,6 +4,7 @@
> * Author: Rob Clark <robdclark@gmail.com>
> */
>
> +#include "adreno/adreno_gpu.h"
> #include "msm_gpu.h"
> #include "msm_gpu_trace.h"
>
> @@ -300,6 +301,8 @@ void msm_devfreq_active(struct msm_gpu *gpu)
> if (!has_devfreq(gpu))
> return;
>
> + if (to_adreno_gpu(gpu)->info->quirks & ADRENO_QUIRK_IFPC)
> + return;
> /*
> * Cancel any pending transition to idle frequency:
> */
> @@ -370,6 +373,9 @@ void msm_devfreq_idle(struct msm_gpu *gpu)
> if (!has_devfreq(gpu))
> return;
>
> + if (to_adreno_gpu(gpu)->info->quirks & ADRENO_QUIRK_IFPC)
> + return;
> +
> msm_hrtimer_queue_work(&df->idle_work, ms_to_ktime(1),
> HRTIMER_MODE_REL);
> }
>
> --
> 2.50.1
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 13/17] drm/msm/a6xx: Fix hangcheck for IFPC
2025-07-20 12:16 ` [PATCH 13/17] drm/msm/a6xx: Fix hangcheck for IFPC Akhil P Oommen
@ 2025-07-22 13:52 ` Dmitry Baryshkov
2025-07-22 21:33 ` Akhil P Oommen
0 siblings, 1 reply; 85+ messages in thread
From: Dmitry Baryshkov @ 2025-07-22 13:52 UTC (permalink / raw)
To: Akhil P Oommen
Cc: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, linux-arm-msm, dri-devel, freedreno, linux-kernel
On Sun, Jul 20, 2025 at 05:46:14PM +0530, Akhil P Oommen wrote:
> From the hangcheck handler, KMD checks a few registers in GX
> domain to see if the GPU made any progress. But it cannot access
> those registers when IFPC is enabled. Since HW based hang detection
> is pretty decent, lets rely on it instead of these registers when
> IFPC is enabled.
>
> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
> ---
> drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 14 ++++++++++++--
> 1 file changed, 12 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> index e331cbdb117df6cfa8ae0e4c44a5aa91ba93f8eb..b3becb230a94163cccff4eaffb8eed44f1c29ad0 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> @@ -2399,13 +2399,23 @@ static uint32_t a6xx_get_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
>
> static bool a6xx_progress(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
> {
> - struct msm_cp_state cp_state = {
> + struct msm_cp_state cp_state;
> + bool progress;
> +
> + /*
> + * With IFPC, KMD doesn't know whether GX power domain is collapsed or not. So, we can't
> + * blindly read the below registers in GX domain. Lets trust the hang detection in HW and
> + * lie to the caller that there was progress.
I know that we've relaxed code line width to 100 chars. Would it be
possible to reformat the comment to 72-75 chars?
> + */
> + if (to_adreno_gpu(gpu)->info->quirks & ADRENO_QUIRK_IFPC)
> + return true;
> +
> + cp_state = (struct msm_cp_state) {
> .ib1_base = gpu_read64(gpu, REG_A6XX_CP_IB1_BASE),
> .ib2_base = gpu_read64(gpu, REG_A6XX_CP_IB2_BASE),
> .ib1_rem = gpu_read(gpu, REG_A6XX_CP_IB1_REM_SIZE),
> .ib2_rem = gpu_read(gpu, REG_A6XX_CP_IB2_REM_SIZE),
> };
> - bool progress;
>
> /*
> * Adjust the remaining data to account for what has already been
>
> --
> 2.50.1
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 16/17] drm/msm/a6xx: Enable IFPC on Adreno X1-85
2025-07-20 12:16 ` [PATCH 16/17] drm/msm/a6xx: Enable IFPC on Adreno X1-85 Akhil P Oommen
@ 2025-07-22 13:55 ` Dmitry Baryshkov
2025-07-22 21:37 ` Akhil P Oommen
2025-07-22 14:55 ` Konrad Dybcio
2025-07-29 14:06 ` neil.armstrong
2 siblings, 1 reply; 85+ messages in thread
From: Dmitry Baryshkov @ 2025-07-22 13:55 UTC (permalink / raw)
To: Akhil P Oommen
Cc: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, linux-arm-msm, dri-devel, freedreno, linux-kernel
On Sun, Jul 20, 2025 at 05:46:17PM +0530, Akhil P Oommen wrote:
> Add the IFPC restore register list and enable IFPC support on Adreno
> X1-85 gpu.
Nit: GPU
I can't stop but notice that KGSL enables IFPC for a bigger set of
SKUs, starting from a630v2 and a615. Is there a plan to get IFPC
supported on those platforms?
>
> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
> ---
> drivers/gpu/drm/msm/adreno/a6xx_catalog.c | 67 ++++++++++++++++++++++++++++++-
> drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 15 +++++--
> drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 1 +
> 3 files changed, 78 insertions(+), 5 deletions(-)
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 02/17] drm/msm: a6xx: Refactor a6xx_sptprac_enable()
2025-07-20 12:16 ` [PATCH 02/17] drm/msm: a6xx: Refactor a6xx_sptprac_enable() Akhil P Oommen
@ 2025-07-22 14:30 ` Konrad Dybcio
2025-07-22 19:47 ` Akhil P Oommen
0 siblings, 1 reply; 85+ messages in thread
From: Konrad Dybcio @ 2025-07-22 14:30 UTC (permalink / raw)
To: Akhil P Oommen, Rob Clark, Sean Paul, Konrad Dybcio,
Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Marijn Suijten,
David Airlie, Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/20/25 2:16 PM, Akhil P Oommen wrote:
> A minor refactor to combine the subroutines for legacy a6xx GMUs under
> a single check. This helps to avoid an unnecessary check and return
> early from the subroutine for majority of a6xx gpus.
>
> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
> ---
> drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 8 ++++----
> 1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> index 38c0f8ef85c3d260864541d83abe43e49c772c52..41129692d127b70e9293b82bea5ccb6b911b0bfb 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> @@ -403,7 +403,10 @@ int a6xx_sptprac_enable(struct a6xx_gmu *gmu)
> int ret;
> u32 val;
>
> - if (!gmu->legacy)
> + WARN_ON(!gmu->legacy);
> +
> + /* Nothing to do if GMU does the power management */
> + if (gmu->idle_level > GMU_IDLE_STATE_ACTIVE)
This isn't quite a no-op, but I can't seem to find what the '1' value
would map to, even in 845 kernel sources. Do we have to worry about it?
Konrad
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 03/17] drm/msm: a6xx: Fix gx_is_on check for a7x family
2025-07-20 12:16 ` [PATCH 03/17] drm/msm: a6xx: Fix gx_is_on check for a7x family Akhil P Oommen
2025-07-20 18:46 ` Dmitry Baryshkov
@ 2025-07-22 14:33 ` Konrad Dybcio
2025-07-22 19:52 ` Akhil P Oommen
1 sibling, 1 reply; 85+ messages in thread
From: Konrad Dybcio @ 2025-07-22 14:33 UTC (permalink / raw)
To: Akhil P Oommen, Rob Clark, Sean Paul, Konrad Dybcio,
Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Marijn Suijten,
David Airlie, Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/20/25 2:16 PM, Akhil P Oommen wrote:
> Bitfield definition for REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS register is
> different in A7XX family. Check the correct bits to see if GX is
> collapsed on A7XX series.
>
> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
> ---
This seems to have been introduced all the way back in the initial
a7xx submission downstream, so I'll assume this concerns all SKUs
and this is a relevant fixes tag:
Fixes: af66706accdf ("drm/msm/a6xx: Add skeleton A7xx support")
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Konrad
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 07/17] drm/msm/adreno: Add fenced regwrite support
2025-07-22 13:39 ` Dmitry Baryshkov
@ 2025-07-22 14:52 ` Konrad Dybcio
2025-07-23 21:06 ` Akhil P Oommen
2025-07-23 21:04 ` Akhil P Oommen
1 sibling, 1 reply; 85+ messages in thread
From: Konrad Dybcio @ 2025-07-22 14:52 UTC (permalink / raw)
To: Dmitry Baryshkov, Akhil P Oommen
Cc: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/22/25 3:39 PM, Dmitry Baryshkov wrote:
> On Sun, Jul 20, 2025 at 05:46:08PM +0530, Akhil P Oommen wrote:
>> There are some special registers which are accessible even when GX power
>> domain is collapsed during an IFPC sleep. Accessing these registers
>> wakes up GPU from power collapse and allow programming these registers
>> without additional handshake with GMU. This patch adds support for this
>> special register write sequence.
>>
>> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
>> ---
>> drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 63 ++++++++++++++++++++++++++++++-
>> drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 1 +
>> drivers/gpu/drm/msm/adreno/a6xx_preempt.c | 20 +++++-----
>> 3 files changed, 73 insertions(+), 11 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>> index 491fde0083a202bec7c6b3bca88d0e5a717a6560..8c004fc3abd2896d467a9728b34e99e4ed944dc4 100644
>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>> @@ -16,6 +16,67 @@
>>
>> #define GPU_PAS_ID 13
>>
>> +static bool fence_status_check(struct msm_gpu *gpu, u32 offset, u32 value, u32 status, u32 mask)
>> +{
>> + /* Success if !writedropped0/1 */
>> + if (!(status & mask))
>> + return true;
>> +
>> + udelay(10);
>
> Why do we need udelay() here? Why can't we use interval setting inside
> gmu_poll_timeout()?
Similarly here:
[...]
>> + if (!gmu_poll_timeout(gmu, REG_A6XX_GMU_AHB_FENCE_STATUS, status,
>> + fence_status_check(gpu, offset, value, status, mask), 0, 1000))
>> + return 0;
>> +
>> + dev_err_ratelimited(gmu->dev, "delay in fenced register write (0x%x)\n",
>> + offset);
>> +
>> + /* Try again for another 1ms before failing */
>> + gpu_write(gpu, offset, value);
>> + if (!gmu_poll_timeout(gmu, REG_A6XX_GMU_AHB_FENCE_STATUS, status,
>> + fence_status_check(gpu, offset, value, status, mask), 0, 1000))
>> + return 0;
>> +
>> + dev_err_ratelimited(gmu->dev, "fenced register write (0x%x) fail\n",
>> + offset);
We may want to combine the two, so as not to worry the user too much..
If it's going to fail, I would assume it's going to fail both checks
(unless e.g. the bus is so congested a single write can't go through
to a sleepy GPU across 2 miliseconds, but that's another issue)
Konrad
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 16/17] drm/msm/a6xx: Enable IFPC on Adreno X1-85
2025-07-20 12:16 ` [PATCH 16/17] drm/msm/a6xx: Enable IFPC on Adreno X1-85 Akhil P Oommen
2025-07-22 13:55 ` Dmitry Baryshkov
@ 2025-07-22 14:55 ` Konrad Dybcio
2025-07-22 21:41 ` Akhil P Oommen
2025-07-29 14:06 ` neil.armstrong
2 siblings, 1 reply; 85+ messages in thread
From: Konrad Dybcio @ 2025-07-22 14:55 UTC (permalink / raw)
To: Akhil P Oommen, Rob Clark, Sean Paul, Konrad Dybcio,
Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Marijn Suijten,
David Airlie, Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/20/25 2:16 PM, Akhil P Oommen wrote:
> Add the IFPC restore register list and enable IFPC support on Adreno
> X1-85 gpu.
>
> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
> ---
> drivers/gpu/drm/msm/adreno/a6xx_catalog.c | 67 ++++++++++++++++++++++++++++++-
> drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 15 +++++--
> drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 1 +
> 3 files changed, 78 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
> index 70f7ad806c34076352d84f32d62c2833422b6e5e..07fcabed472c3b9ca47faf1a8b3f7cf580801981 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
> @@ -1343,6 +1343,69 @@ static const uint32_t a7xx_pwrup_reglist_regs[] = {
>
> DECLARE_ADRENO_REGLIST_LIST(a7xx_pwrup_reglist);
>
> +/* Applicable for X185, A750 */
> +static const u32 a750_ifpc_reglist_regs[] = {
> + REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_0,
> + REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_1,
> + REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_2,
> + REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_3,
> + REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_4,
> + REG_A6XX_TPL1_NC_MODE_CNTL,
> + REG_A6XX_SP_NC_MODE_CNTL,
> + REG_A6XX_CP_DBG_ECO_CNTL,
> + REG_A6XX_CP_PROTECT_CNTL,
> + REG_A6XX_CP_PROTECT(0),
> + REG_A6XX_CP_PROTECT(1),
Is it fair to assume that we'd like to saverestore all CP_PROT
registers on all SKUs, always? We can save some space in .rodata
this way..
Konrad
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 12/17] drm/msm: Skip devfreq IDLE when possible
2025-07-22 13:50 ` Dmitry Baryshkov
@ 2025-07-22 15:38 ` Rob Clark
2025-07-22 19:23 ` Akhil P Oommen
0 siblings, 1 reply; 85+ messages in thread
From: Rob Clark @ 2025-07-22 15:38 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Akhil P Oommen, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, linux-arm-msm, dri-devel, freedreno, linux-kernel
On Tue, Jul 22, 2025 at 6:50 AM Dmitry Baryshkov
<dmitry.baryshkov@oss.qualcomm.com> wrote:
>
> On Sun, Jul 20, 2025 at 05:46:13PM +0530, Akhil P Oommen wrote:
> > When IFPC is supported, devfreq idling is redundant and adds
> > unnecessary pm suspend/wake latency. So skip it when IFPC is
> > supported.
>
> With this in place we have a dummy devfreq instance which does nothing.
> Wouldn't it be better to skip registering devfreq if IFPC is supported
> on the platform?
devfreq is still scaling the freq. What is being bypassed is
essentially a CPU based version of IFPC (because on sc7180 we didn't
have IFPC
Currently only a618 and 7c3 enable gpu_clamp_to_idle.. if at some
point those grew IFPC support we could remove the trickery to drop GPU
to min freq when it is idle altogether.
BR,
-R
> >
> > Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
> > ---
> > drivers/gpu/drm/msm/msm_gpu_devfreq.c | 6 ++++++
> > 1 file changed, 6 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/msm/msm_gpu_devfreq.c b/drivers/gpu/drm/msm/msm_gpu_devfreq.c
> > index 2e1d5c3432728cde15d91f69da22bb915588fe86..53ef2add5047e7d6b6371af949cab36ce8409372 100644
> > --- a/drivers/gpu/drm/msm/msm_gpu_devfreq.c
> > +++ b/drivers/gpu/drm/msm/msm_gpu_devfreq.c
> > @@ -4,6 +4,7 @@
> > * Author: Rob Clark <robdclark@gmail.com>
> > */
> >
> > +#include "adreno/adreno_gpu.h"
> > #include "msm_gpu.h"
> > #include "msm_gpu_trace.h"
> >
> > @@ -300,6 +301,8 @@ void msm_devfreq_active(struct msm_gpu *gpu)
> > if (!has_devfreq(gpu))
> > return;
> >
> > + if (to_adreno_gpu(gpu)->info->quirks & ADRENO_QUIRK_IFPC)
> > + return;
> > /*
> > * Cancel any pending transition to idle frequency:
> > */
> > @@ -370,6 +373,9 @@ void msm_devfreq_idle(struct msm_gpu *gpu)
> > if (!has_devfreq(gpu))
> > return;
> >
> > + if (to_adreno_gpu(gpu)->info->quirks & ADRENO_QUIRK_IFPC)
> > + return;
> > +
> > msm_hrtimer_queue_work(&df->idle_work, ms_to_ktime(1),
> > HRTIMER_MODE_REL);
> > }
> >
> > --
> > 2.50.1
> >
>
> --
> With best wishes
> Dmitry
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 05/17] drm/msm/a6xx: Fix PDC sleep sequence
2025-07-22 13:33 ` Dmitry Baryshkov
@ 2025-07-22 17:26 ` Rob Clark
2025-07-22 21:05 ` Akhil P Oommen
0 siblings, 1 reply; 85+ messages in thread
From: Rob Clark @ 2025-07-22 17:26 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Akhil P Oommen, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, linux-arm-msm, dri-devel, freedreno, linux-kernel
On Tue, Jul 22, 2025 at 6:33 AM Dmitry Baryshkov
<dmitry.baryshkov@oss.qualcomm.com> wrote:
>
> On Sun, Jul 20, 2025 at 05:46:06PM +0530, Akhil P Oommen wrote:
> > 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
>
> s/KMD/the driver/
IMHO for gpu things "KMD" makes sense, to differentiate between kernel
and user mode (UMD).. this is perhaps different from other areas where
there isn't a userspace component to the driver stack
BR,
-R
> > GMU firmware has not initialized. Track these dependencies using a new
> > status variable and trigger PDC sleep/wake sequences appropriately.
>
> Again, it looks like there should be a Fixes tag here.
>
> >
> > Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
> > ---
> > drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 30 +++++++++++++++++++-----------
> > drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 6 ++++++
> > 2 files changed, 25 insertions(+), 11 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> > index 3bebb6dd7059782ceca29f2efd2acee24d3fc930..4d6c70735e0892ed87d6a68d64f24bda844e5e16 100644
> > --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> > +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> > @@ -279,6 +279,8 @@ static int a6xx_gmu_start(struct a6xx_gmu *gmu)
> > if (ret)
> > DRM_DEV_ERROR(gmu->dev, "GMU firmware initialization timed out\n");
> >
> > + set_bit(GMU_STATUS_FW_START, &gmu->status);
> > +
> > return ret;
> > }
> >
> > @@ -528,6 +530,9 @@ static int a6xx_rpmh_start(struct a6xx_gmu *gmu)
> > int ret;
> > u32 val;
> >
> > + if (!test_and_clear_bit(GMU_STATUS_PDC_SLEEP, &gmu->status))
> > + return 0;
> > +
> > gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, BIT(1));
> >
> > ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_RSCC_CONTROL_ACK, val,
> > @@ -555,6 +560,11 @@ static void a6xx_rpmh_stop(struct a6xx_gmu *gmu)
> > int ret;
> > u32 val;
> >
> > + if (test_and_clear_bit(GMU_STATUS_FW_START, &gmu->status))
> > + return;
> > +
> > + /* TODO: should we skip if IFPC is not enabled */
>
> Is this a question or a statement?
>
> > +
> > gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, 1);
> >
> > ret = gmu_poll_timeout_rscc(gmu, REG_A6XX_GPU_RSCC_RSC_STATUS0_DRV0,
> > @@ -563,6 +573,8 @@ static void a6xx_rpmh_stop(struct a6xx_gmu *gmu)
> > DRM_DEV_ERROR(gmu->dev, "Unable to power off the GPU RSC\n");
> >
> > gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, 0);
> > +
> > + set_bit(GMU_STATUS_PDC_SLEEP, &gmu->status);
> > }
> >
> > static inline void pdc_write(void __iomem *ptr, u32 offset, u32 value)
> > @@ -691,8 +703,6 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu)
> > /* ensure no writes happen before the uCode is fully written */
> > wmb();
> >
> > - a6xx_rpmh_stop(gmu);
> > -
> > err:
> > if (!IS_ERR_OR_NULL(pdcptr))
> > iounmap(pdcptr);
> > @@ -852,19 +862,15 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state)
> > else
> > gmu_write(gmu, REG_A6XX_GMU_GENERAL_7, 1);
> >
> > - if (state == GMU_WARM_BOOT) {
> > - ret = a6xx_rpmh_start(gmu);
> > - if (ret)
> > - return ret;
> > - } else {
> > + ret = a6xx_rpmh_start(gmu);
> > + if (ret)
> > + return ret;
> > +
> > + if (state == GMU_COLD_BOOT) {
> > if (WARN(!adreno_gpu->fw[ADRENO_FW_GMU],
> > "GMU firmware is not loaded\n"))
> > return -ENOENT;
> >
> > - ret = a6xx_rpmh_start(gmu);
> > - if (ret)
> > - return ret;
> > -
> > ret = a6xx_gmu_fw_load(gmu);
> > if (ret)
> > return ret;
> > @@ -1046,6 +1052,8 @@ static void a6xx_gmu_force_off(struct a6xx_gmu *gmu)
> >
> > /* Reset GPU core blocks */
> > a6xx_gpu_sw_reset(gpu, true);
> > +
> > + a6xx_rpmh_stop(gmu);
> > }
> >
> > static void a6xx_gmu_set_initial_freq(struct msm_gpu *gpu, struct a6xx_gmu *gmu)
> > diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
> > index b2d4489b40249b1916ab4a42c89e3f4bdc5c4af9..034f1b4e5a3fb9cd601bfbe6d06d64e5ace3b6e7 100644
> > --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
> > +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
> > @@ -117,6 +117,12 @@ struct a6xx_gmu {
> >
> > struct qmp *qmp;
> > struct a6xx_hfi_msg_bw_table *bw_table;
> > +
> > +/* To check if we can trigger sleep seq at PDC. Cleared in a6xx_rpmh_stop() */
> > +#define GMU_STATUS_FW_START 0
> > +/* To track if PDC sleep seq was done */
> > +#define GMU_STATUS_PDC_SLEEP 1
> > + unsigned long status;
> > };
> >
> > static inline u32 gmu_read(struct a6xx_gmu *gmu, u32 offset)
> >
> > --
> > 2.50.1
> >
>
> --
> With best wishes
> Dmitry
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 12/17] drm/msm: Skip devfreq IDLE when possible
2025-07-22 15:38 ` Rob Clark
@ 2025-07-22 19:23 ` Akhil P Oommen
2025-07-22 20:13 ` Rob Clark
0 siblings, 1 reply; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-22 19:23 UTC (permalink / raw)
To: rob.clark, Dmitry Baryshkov
Cc: Sean Paul, Konrad Dybcio, Dmitry Baryshkov, Abhinav Kumar,
Jessica Zhang, Marijn Suijten, David Airlie, Simona Vetter,
linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/22/2025 9:08 PM, Rob Clark wrote:
> On Tue, Jul 22, 2025 at 6:50 AM Dmitry Baryshkov
> <dmitry.baryshkov@oss.qualcomm.com> wrote:
>>
>> On Sun, Jul 20, 2025 at 05:46:13PM +0530, Akhil P Oommen wrote:
>>> When IFPC is supported, devfreq idling is redundant and adds
>>> unnecessary pm suspend/wake latency. So skip it when IFPC is
>>> supported.
>>
>> With this in place we have a dummy devfreq instance which does nothing.
>> Wouldn't it be better to skip registering devfreq if IFPC is supported
>> on the platform?
>
> devfreq is still scaling the freq. What is being bypassed is
> essentially a CPU based version of IFPC (because on sc7180 we didn't
> have IFPC
>
> Currently only a618 and 7c3 enable gpu_clamp_to_idle.. if at some
> point those grew IFPC support we could remove the trickery to drop GPU
> to min freq when it is idle altogether.
There are 2 functionalities here:
1. Clamp-to-idle: enabled only on a618/7c3
2. boost-after-idle: Enabled for all GPUs.
With this patch, we are skipping both when IFPC is supported. In the
absence of latency due to clamp-to-idle, do you think a618 (relatively
weaker GPU) would require boost-after-idle to keep with the
UI/composition workload for its typical configuration (1080p@60hz)? If
yes, I should probably create a quirk to disable boost-after-idle for
premium tier GPUs, instead of tying it to IFPC feature.
-Akhil.
>
> BR,
> -R
>
>>>
>>> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
>>> ---
>>> drivers/gpu/drm/msm/msm_gpu_devfreq.c | 6 ++++++
>>> 1 file changed, 6 insertions(+)
>>>
>>> diff --git a/drivers/gpu/drm/msm/msm_gpu_devfreq.c b/drivers/gpu/drm/msm/msm_gpu_devfreq.c
>>> index 2e1d5c3432728cde15d91f69da22bb915588fe86..53ef2add5047e7d6b6371af949cab36ce8409372 100644
>>> --- a/drivers/gpu/drm/msm/msm_gpu_devfreq.c
>>> +++ b/drivers/gpu/drm/msm/msm_gpu_devfreq.c
>>> @@ -4,6 +4,7 @@
>>> * Author: Rob Clark <robdclark@gmail.com>
>>> */
>>>
>>> +#include "adreno/adreno_gpu.h"
>>> #include "msm_gpu.h"
>>> #include "msm_gpu_trace.h"
>>>
>>> @@ -300,6 +301,8 @@ void msm_devfreq_active(struct msm_gpu *gpu)
>>> if (!has_devfreq(gpu))
>>> return;
>>>
>>> + if (to_adreno_gpu(gpu)->info->quirks & ADRENO_QUIRK_IFPC)
>>> + return;
>>> /*
>>> * Cancel any pending transition to idle frequency:
>>> */
>>> @@ -370,6 +373,9 @@ void msm_devfreq_idle(struct msm_gpu *gpu)
>>> if (!has_devfreq(gpu))
>>> return;
>>>
>>> + if (to_adreno_gpu(gpu)->info->quirks & ADRENO_QUIRK_IFPC)
>>> + return;
>>> +
>>> msm_hrtimer_queue_work(&df->idle_work, ms_to_ktime(1),
>>> HRTIMER_MODE_REL);
>>> }
>>>
>>> --
>>> 2.50.1
>>>
>>
>> --
>> With best wishes
>> Dmitry
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 02/17] drm/msm: a6xx: Refactor a6xx_sptprac_enable()
2025-07-22 14:30 ` Konrad Dybcio
@ 2025-07-22 19:47 ` Akhil P Oommen
2025-07-23 10:13 ` Konrad Dybcio
0 siblings, 1 reply; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-22 19:47 UTC (permalink / raw)
To: Konrad Dybcio, Rob Clark, Sean Paul, Konrad Dybcio,
Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Marijn Suijten,
David Airlie, Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/22/2025 8:00 PM, Konrad Dybcio wrote:
> On 7/20/25 2:16 PM, Akhil P Oommen wrote:
>> A minor refactor to combine the subroutines for legacy a6xx GMUs under
>> a single check. This helps to avoid an unnecessary check and return
>> early from the subroutine for majority of a6xx gpus.
>>
>> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
>> ---
>> drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 8 ++++----
>> 1 file changed, 4 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
>> index 38c0f8ef85c3d260864541d83abe43e49c772c52..41129692d127b70e9293b82bea5ccb6b911b0bfb 100644
>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
>> @@ -403,7 +403,10 @@ int a6xx_sptprac_enable(struct a6xx_gmu *gmu)
>> int ret;
>> u32 val;
>>
>> - if (!gmu->legacy)
>> + WARN_ON(!gmu->legacy);
>> +
>> + /* Nothing to do if GMU does the power management */
>> + if (gmu->idle_level > GMU_IDLE_STATE_ACTIVE)
>
> This isn't quite a no-op, but I can't seem to find what the '1' value
> would map to, even in 845 kernel sources. Do we have to worry about it?
This is fine. '1' seems to be a low power state that was removed very
early in the gmu firmware development stage. We can ignore that.
-Akhil.
>
> Konrad
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 03/17] drm/msm: a6xx: Fix gx_is_on check for a7x family
2025-07-22 14:33 ` Konrad Dybcio
@ 2025-07-22 19:52 ` Akhil P Oommen
2025-07-23 11:10 ` Dmitry Baryshkov
0 siblings, 1 reply; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-22 19:52 UTC (permalink / raw)
To: Konrad Dybcio, Rob Clark, Sean Paul, Konrad Dybcio,
Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Marijn Suijten,
David Airlie, Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/22/2025 8:03 PM, Konrad Dybcio wrote:
> On 7/20/25 2:16 PM, Akhil P Oommen wrote:
>> Bitfield definition for REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS register is
>> different in A7XX family. Check the correct bits to see if GX is
>> collapsed on A7XX series.
>>
>> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
>> ---
>
> This seems to have been introduced all the way back in the initial
> a7xx submission downstream, so I'll assume this concerns all SKUs
> and this is a relevant fixes tag:
>
> Fixes: af66706accdf ("drm/msm/a6xx: Add skeleton A7xx support")
>
> Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Dmitry/Konrad,
We don't have to backport this change because the existing code reads a
couple of unused bits which are '0's and that is okay when IFPC is not
supported. So there is no practical benefit in cherry-picking this
change to older kernel versions.
-Akhil.
>
> Konrad
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 04/17] drm/msm/a6xx: Poll additional DRV status
2025-07-22 13:31 ` Dmitry Baryshkov
@ 2025-07-22 19:55 ` Akhil P Oommen
0 siblings, 0 replies; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-22 19:55 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/22/2025 7:01 PM, Dmitry Baryshkov wrote:
> On Sun, Jul 20, 2025 at 05:46:05PM +0530, Akhil P Oommen wrote:
>> A7XX_GEN2 generation has additional TCS slots. Poll the respective
>> DRV status registers before pm suspend.
>>
>
> Fixes?
Ack. Will add the tag. It is good to ensure there are no outstanding votes.
-Akhil
>
>> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
>> ---
>> drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 16 ++++++++++++++++
>> 1 file changed, 16 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
>> index 790ef2f94a0b0cd40433d7edb6a89e4f04408bf5..3bebb6dd7059782ceca29f2efd2acee24d3fc930 100644
>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
>> @@ -987,6 +987,22 @@ static void a6xx_gmu_rpmh_off(struct a6xx_gmu *gmu)
>> val, (val & 1), 100, 10000);
>> gmu_poll_timeout_rscc(gmu, REG_A6XX_RSCC_TCS3_DRV0_STATUS + seqmem_off,
>> val, (val & 1), 100, 1000);
>> +
>> + if (!adreno_is_a740_family(adreno_gpu))
>> + return;
>> +
>> + gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS4_DRV0_STATUS + seqmem_off,
>> + val, (val & 1), 100, 10000);
>> + gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS5_DRV0_STATUS + seqmem_off,
>> + val, (val & 1), 100, 10000);
>> + gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS6_DRV0_STATUS + seqmem_off,
>> + val, (val & 1), 100, 10000);
>> + gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS7_DRV0_STATUS + seqmem_off,
>> + val, (val & 1), 100, 1000);
>> + gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS8_DRV0_STATUS + seqmem_off,
>> + val, (val & 1), 100, 10000);
>> + gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS9_DRV0_STATUS + seqmem_off,
>> + val, (val & 1), 100, 1000);
>> }
>>
>> /* Force the GMU off in case it isn't responsive */
>>
>> --
>> 2.50.1
>>
>
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 12/17] drm/msm: Skip devfreq IDLE when possible
2025-07-22 19:23 ` Akhil P Oommen
@ 2025-07-22 20:13 ` Rob Clark
2025-07-23 21:46 ` Akhil P Oommen
0 siblings, 1 reply; 85+ messages in thread
From: Rob Clark @ 2025-07-22 20:13 UTC (permalink / raw)
To: Akhil P Oommen
Cc: Dmitry Baryshkov, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, linux-arm-msm, dri-devel, freedreno, linux-kernel
On Tue, Jul 22, 2025 at 12:23 PM Akhil P Oommen
<akhilpo@oss.qualcomm.com> wrote:
>
> On 7/22/2025 9:08 PM, Rob Clark wrote:
> > On Tue, Jul 22, 2025 at 6:50 AM Dmitry Baryshkov
> > <dmitry.baryshkov@oss.qualcomm.com> wrote:
> >>
> >> On Sun, Jul 20, 2025 at 05:46:13PM +0530, Akhil P Oommen wrote:
> >>> When IFPC is supported, devfreq idling is redundant and adds
> >>> unnecessary pm suspend/wake latency. So skip it when IFPC is
> >>> supported.
> >>
> >> With this in place we have a dummy devfreq instance which does nothing.
> >> Wouldn't it be better to skip registering devfreq if IFPC is supported
> >> on the platform?
> >
> > devfreq is still scaling the freq. What is being bypassed is
> > essentially a CPU based version of IFPC (because on sc7180 we didn't
> > have IFPC
> >
> > Currently only a618 and 7c3 enable gpu_clamp_to_idle.. if at some
> > point those grew IFPC support we could remove the trickery to drop GPU
> > to min freq when it is idle altogether.
>
> There are 2 functionalities here:
> 1. Clamp-to-idle: enabled only on a618/7c3
> 2. boost-after-idle: Enabled for all GPUs.
>
> With this patch, we are skipping both when IFPC is supported. In the
> absence of latency due to clamp-to-idle, do you think a618 (relatively
> weaker GPU) would require boost-after-idle to keep with the
> UI/composition workload for its typical configuration (1080p@60hz)? If
> yes, I should probably create a quirk to disable boost-after-idle for
> premium tier GPUs, instead of tying it to IFPC feature.
Hmm, yeah.. I suppose _this_ patch should only skip clamp-to-idle. It
is a different topic, boost-after-idle.
BR,
-R
> -Akhil.
>
> >
> > BR,
> > -R
> >
> >>>
> >>> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
> >>> ---
> >>> drivers/gpu/drm/msm/msm_gpu_devfreq.c | 6 ++++++
> >>> 1 file changed, 6 insertions(+)
> >>>
> >>> diff --git a/drivers/gpu/drm/msm/msm_gpu_devfreq.c b/drivers/gpu/drm/msm/msm_gpu_devfreq.c
> >>> index 2e1d5c3432728cde15d91f69da22bb915588fe86..53ef2add5047e7d6b6371af949cab36ce8409372 100644
> >>> --- a/drivers/gpu/drm/msm/msm_gpu_devfreq.c
> >>> +++ b/drivers/gpu/drm/msm/msm_gpu_devfreq.c
> >>> @@ -4,6 +4,7 @@
> >>> * Author: Rob Clark <robdclark@gmail.com>
> >>> */
> >>>
> >>> +#include "adreno/adreno_gpu.h"
> >>> #include "msm_gpu.h"
> >>> #include "msm_gpu_trace.h"
> >>>
> >>> @@ -300,6 +301,8 @@ void msm_devfreq_active(struct msm_gpu *gpu)
> >>> if (!has_devfreq(gpu))
> >>> return;
> >>>
> >>> + if (to_adreno_gpu(gpu)->info->quirks & ADRENO_QUIRK_IFPC)
> >>> + return;
> >>> /*
> >>> * Cancel any pending transition to idle frequency:
> >>> */
> >>> @@ -370,6 +373,9 @@ void msm_devfreq_idle(struct msm_gpu *gpu)
> >>> if (!has_devfreq(gpu))
> >>> return;
> >>>
> >>> + if (to_adreno_gpu(gpu)->info->quirks & ADRENO_QUIRK_IFPC)
> >>> + return;
> >>> +
> >>> msm_hrtimer_queue_work(&df->idle_work, ms_to_ktime(1),
> >>> HRTIMER_MODE_REL);
> >>> }
> >>>
> >>> --
> >>> 2.50.1
> >>>
> >>
> >> --
> >> With best wishes
> >> Dmitry
>
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 05/17] drm/msm/a6xx: Fix PDC sleep sequence
2025-07-22 17:26 ` Rob Clark
@ 2025-07-22 21:05 ` Akhil P Oommen
2025-07-23 11:11 ` Dmitry Baryshkov
0 siblings, 1 reply; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-22 21:05 UTC (permalink / raw)
To: rob.clark, Dmitry Baryshkov
Cc: Sean Paul, Konrad Dybcio, Dmitry Baryshkov, Abhinav Kumar,
Jessica Zhang, Marijn Suijten, David Airlie, Simona Vetter,
linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/22/2025 10:56 PM, Rob Clark wrote:
> On Tue, Jul 22, 2025 at 6:33 AM Dmitry Baryshkov
> <dmitry.baryshkov@oss.qualcomm.com> wrote:
>>
>> On Sun, Jul 20, 2025 at 05:46:06PM +0530, Akhil P Oommen wrote:
>>> 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
>>
>> s/KMD/the driver/
>
> IMHO for gpu things "KMD" makes sense, to differentiate between kernel
> and user mode (UMD).. this is perhaps different from other areas where
> there isn't a userspace component to the driver stack
Ack
>
> BR,
> -R
>
>>> GMU firmware has not initialized. Track these dependencies using a new
>>> status variable and trigger PDC sleep/wake sequences appropriately.
>>
>> Again, it looks like there should be a Fixes tag here.
Ack. I guess it is not a bad idea to backport this one too.
>>
>>>
>>> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
>>> ---
>>> drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 30 +++++++++++++++++++-----------
>>> drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 6 ++++++
>>> 2 files changed, 25 insertions(+), 11 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
>>> index 3bebb6dd7059782ceca29f2efd2acee24d3fc930..4d6c70735e0892ed87d6a68d64f24bda844e5e16 100644
>>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
>>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
>>> @@ -279,6 +279,8 @@ static int a6xx_gmu_start(struct a6xx_gmu *gmu)
>>> if (ret)
>>> DRM_DEV_ERROR(gmu->dev, "GMU firmware initialization timed out\n");
>>>
>>> + set_bit(GMU_STATUS_FW_START, &gmu->status);
>>> +
>>> return ret;
>>> }
>>>
>>> @@ -528,6 +530,9 @@ static int a6xx_rpmh_start(struct a6xx_gmu *gmu)
>>> int ret;
>>> u32 val;
>>>
>>> + if (!test_and_clear_bit(GMU_STATUS_PDC_SLEEP, &gmu->status))
>>> + return 0;
>>> +
>>> gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, BIT(1));
>>>
>>> ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_RSCC_CONTROL_ACK, val,
>>> @@ -555,6 +560,11 @@ static void a6xx_rpmh_stop(struct a6xx_gmu *gmu)
>>> int ret;
>>> u32 val;
>>>
>>> + if (test_and_clear_bit(GMU_STATUS_FW_START, &gmu->status))
>>> + return;
>>> +
>>> + /* TODO: should we skip if IFPC is not enabled */
>>
>> Is this a question or a statement?
It was a reminder to myself which I forgot to revisit later. Will
addresss this in the next revision.
-Akhil.
>>
>>> +
>>> gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, 1);
>>>
>>> ret = gmu_poll_timeout_rscc(gmu, REG_A6XX_GPU_RSCC_RSC_STATUS0_DRV0,
>>> @@ -563,6 +573,8 @@ static void a6xx_rpmh_stop(struct a6xx_gmu *gmu)
>>> DRM_DEV_ERROR(gmu->dev, "Unable to power off the GPU RSC\n");
>>>
>>> gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, 0);
>>> +
>>> + set_bit(GMU_STATUS_PDC_SLEEP, &gmu->status);
>>> }
>>>
>>> static inline void pdc_write(void __iomem *ptr, u32 offset, u32 value)
>>> @@ -691,8 +703,6 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu)
>>> /* ensure no writes happen before the uCode is fully written */
>>> wmb();
>>>
>>> - a6xx_rpmh_stop(gmu);
>>> -
>>> err:
>>> if (!IS_ERR_OR_NULL(pdcptr))
>>> iounmap(pdcptr);
>>> @@ -852,19 +862,15 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state)
>>> else
>>> gmu_write(gmu, REG_A6XX_GMU_GENERAL_7, 1);
>>>
>>> - if (state == GMU_WARM_BOOT) {
>>> - ret = a6xx_rpmh_start(gmu);
>>> - if (ret)
>>> - return ret;
>>> - } else {
>>> + ret = a6xx_rpmh_start(gmu);
>>> + if (ret)
>>> + return ret;
>>> +
>>> + if (state == GMU_COLD_BOOT) {
>>> if (WARN(!adreno_gpu->fw[ADRENO_FW_GMU],
>>> "GMU firmware is not loaded\n"))
>>> return -ENOENT;
>>>
>>> - ret = a6xx_rpmh_start(gmu);
>>> - if (ret)
>>> - return ret;
>>> -
>>> ret = a6xx_gmu_fw_load(gmu);
>>> if (ret)
>>> return ret;
>>> @@ -1046,6 +1052,8 @@ static void a6xx_gmu_force_off(struct a6xx_gmu *gmu)
>>>
>>> /* Reset GPU core blocks */
>>> a6xx_gpu_sw_reset(gpu, true);
>>> +
>>> + a6xx_rpmh_stop(gmu);
>>> }
>>>
>>> static void a6xx_gmu_set_initial_freq(struct msm_gpu *gpu, struct a6xx_gmu *gmu)
>>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
>>> index b2d4489b40249b1916ab4a42c89e3f4bdc5c4af9..034f1b4e5a3fb9cd601bfbe6d06d64e5ace3b6e7 100644
>>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
>>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
>>> @@ -117,6 +117,12 @@ struct a6xx_gmu {
>>>
>>> struct qmp *qmp;
>>> struct a6xx_hfi_msg_bw_table *bw_table;
>>> +
>>> +/* To check if we can trigger sleep seq at PDC. Cleared in a6xx_rpmh_stop() */
>>> +#define GMU_STATUS_FW_START 0
>>> +/* To track if PDC sleep seq was done */
>>> +#define GMU_STATUS_PDC_SLEEP 1
>>> + unsigned long status;
>>> };
>>>
>>> static inline u32 gmu_read(struct a6xx_gmu *gmu, u32 offset)
>>>
>>> --
>>> 2.50.1
>>>
>>
>> --
>> With best wishes
>> Dmitry
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 08/17] drm/msm/a6xx: Set Keep-alive votes to block IFPC
2025-07-22 13:44 ` Dmitry Baryshkov
@ 2025-07-22 21:24 ` Akhil P Oommen
2025-07-23 10:05 ` Konrad Dybcio
2025-07-23 11:13 ` Dmitry Baryshkov
0 siblings, 2 replies; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-22 21:24 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/22/2025 7:14 PM, Dmitry Baryshkov wrote:
> On Sun, Jul 20, 2025 at 05:46:09PM +0530, Akhil P Oommen wrote:
>> 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>
>> ---
>> 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 8c004fc3abd2896d467a9728b34e99e4ed944dc4..6770f0363e7284e4596b1188637a4615d2c0779b 100644
>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>> @@ -1752,8 +1752,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);
>>
>> /*
>> @@ -1765,13 +1763,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,
>> @@ -1810,9 +1801,24 @@ static void a7xx_sw_fuse_violation_irq(struct msm_gpu *gpu)
>> }
>> }
>>
>> +static void set_keepalive_vote(struct msm_gpu *gpu, bool on)
>
> a6xx_set_keepalive_vote()
static fn! Why do we need prefix here?
-Akhil
>
>> +{
>> + 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 */
>> + set_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);
>> @@ -1849,6 +1855,8 @@ static irqreturn_t a6xx_irq(struct msm_gpu *gpu)
>> if (status & A6XX_RBBM_INT_0_MASK_CP_SW)
>> a6xx_preempt_irq(gpu);
>>
>> + set_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 5b0fd510ff58d989ab285f1a2497f6f522a6b187..1c8ec1911010c00a000d195116fc950c4d947cac 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 set_keepalive_vote(struct msm_gpu *gpu, bool on)
>
> a6xx_set_preempt_keepalive_vote();
>
>> +{
>> + 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);
>>
>> + set_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 */
>> + set_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
>>
>
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 11/17] drm/msm: Add support for IFPC
2025-07-22 13:49 ` Dmitry Baryshkov
@ 2025-07-22 21:27 ` Akhil P Oommen
2025-07-23 10:27 ` Konrad Dybcio
0 siblings, 1 reply; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-22 21:27 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/22/2025 7:19 PM, Dmitry Baryshkov wrote:
> On Sun, Jul 20, 2025 at 05:46:12PM +0530, Akhil P Oommen wrote:
>> Add a new quirk to denote IFPC (Inter-Frame Power Collapse) support
>> for a gpu. Based on this flag send the feature ctrl hfi message to
>> GMU to enable IFPC support.
>>
>> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
>> ---
>> drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 5 +++--
>> drivers/gpu/drm/msm/adreno/a6xx_hfi.c | 33 +++++++++++++++++++++++++++------
>> drivers/gpu/drm/msm/adreno/adreno_gpu.h | 1 +
>> 3 files changed, 31 insertions(+), 8 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
>> index 4d6c70735e0892ed87d6a68d64f24bda844e5e16..3bbcc78179c1cf1bfa21ff097e9350eb2f554011 100644
>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
>> @@ -1961,8 +1961,9 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
>> if (ret)
>> return ret;
>>
>> - /* Fow now, don't do anything fancy until we get our feet under us */
>> - gmu->idle_level = GMU_IDLE_STATE_ACTIVE;
>> + /* Set GMU idle level */
>> + gmu->idle_level = (adreno_gpu->info->quirks & ADRENO_QUIRK_IFPC) ?
>> + GMU_IDLE_STATE_IFPC : GMU_IDLE_STATE_ACTIVE;
>>
>> pm_runtime_enable(gmu->dev);
>>
>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
>> index 8e69b1e8465711837151725c8f70e7b4b16a368e..20ade6b0558b016b581078f5cf7377e7e7c57f8e 100644
>> --- a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
>> @@ -21,6 +21,7 @@ static const char * const a6xx_hfi_msg_id[] = {
>> HFI_MSG_ID(HFI_H2F_MSG_PERF_TABLE),
>> HFI_MSG_ID(HFI_H2F_MSG_TEST),
>> HFI_MSG_ID(HFI_H2F_MSG_START),
>> + HFI_MSG_ID(HFI_H2F_FEATURE_CTRL),
>> HFI_MSG_ID(HFI_H2F_MSG_CORE_FW_START),
>> HFI_MSG_ID(HFI_H2F_MSG_GX_BW_PERF_VOTE),
>> HFI_MSG_ID(HFI_H2F_MSG_PREPARE_SLUMBER),
>> @@ -765,23 +766,39 @@ static int a6xx_hfi_send_bw_table(struct a6xx_gmu *gmu)
>> NULL, 0);
>> }
>>
>> +static int a6xx_hfi_feature_ctrl_msg(struct a6xx_gmu *gmu, u32 feature, u32 enable, u32 data)
>> +{
>> + struct a6xx_hfi_msg_feature_ctrl msg = {
>> + .feature = feature,
>> + .enable = enable,
>> + .data = data,
>> + };
>> +
>> + return a6xx_hfi_send_msg(gmu, HFI_H2F_FEATURE_CTRL, &msg, sizeof(msg), NULL, 0);
>> +}
>> +
>> +#define HFI_FEATURE_IFPC 9
>
> Can we please have an enum or at least a set of defines rather than
> havign them scattered through the code?
Ack
>
>> +
>> +static int a6xx_hfi_enable_ifpc(struct a6xx_gmu *gmu)
>> +{
>> + if (gmu->idle_level != GMU_IDLE_STATE_IFPC)
>> + return 0;
>> +
>> + return a6xx_hfi_feature_ctrl_msg(gmu, HFI_FEATURE_IFPC, 1, 0x1680);
>
> magic number?
>
Let me check.
-Akhil
>> +}
>> +
>> #define HFI_FEATURE_ACD 12
>>
>> static int a6xx_hfi_enable_acd(struct a6xx_gmu *gmu)
>> {
>> struct a6xx_hfi_acd_table *acd_table = &gmu->acd_table;
>> - struct a6xx_hfi_msg_feature_ctrl msg = {
>> - .feature = HFI_FEATURE_ACD,
>> - .enable = 1,
>> - .data = 0,
>> - };
>> int ret;
>>
>> if (!acd_table->enable_by_level)
>> return 0;
>>
>> /* Enable ACD feature at GMU */
>> - ret = a6xx_hfi_send_msg(gmu, HFI_H2F_FEATURE_CTRL, &msg, sizeof(msg), NULL, 0);
>> + ret = a6xx_hfi_feature_ctrl_msg(gmu, HFI_FEATURE_ACD, 1, 0);
>> if (ret) {
>> DRM_DEV_ERROR(gmu->dev, "Unable to enable ACD (%d)\n", ret);
>> return ret;
>> @@ -898,6 +915,10 @@ int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state)
>> if (ret)
>> return ret;
>>
>> + ret = a6xx_hfi_enable_ifpc(gmu);
>> + if (ret)
>> + return ret;
>> +
>> ret = a6xx_hfi_send_core_fw_start(gmu);
>> if (ret)
>> return ret;
>> diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
>> index bc063594a359ee6b796381c5fd2c30e2aa12a26d..1135beafac464f3162a3a61938a7de0c7920455a 100644
>> --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
>> +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
>> @@ -58,6 +58,7 @@ enum adreno_family {
>> #define ADRENO_QUIRK_HAS_CACHED_COHERENT BIT(4)
>> #define ADRENO_QUIRK_PREEMPTION BIT(5)
>> #define ADRENO_QUIRK_4GB_VA BIT(6)
>> +#define ADRENO_QUIRK_IFPC BIT(7)
>>
>> /* Helper for formating the chip_id in the way that userspace tools like
>> * crashdec expect.
>>
>> --
>> 2.50.1
>>
>
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 13/17] drm/msm/a6xx: Fix hangcheck for IFPC
2025-07-22 13:52 ` Dmitry Baryshkov
@ 2025-07-22 21:33 ` Akhil P Oommen
0 siblings, 0 replies; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-22 21:33 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/22/2025 7:22 PM, Dmitry Baryshkov wrote:
> On Sun, Jul 20, 2025 at 05:46:14PM +0530, Akhil P Oommen wrote:
>> From the hangcheck handler, KMD checks a few registers in GX
>> domain to see if the GPU made any progress. But it cannot access
>> those registers when IFPC is enabled. Since HW based hang detection
>> is pretty decent, lets rely on it instead of these registers when
>> IFPC is enabled.
>>
>> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
>> ---
>> drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 14 ++++++++++++--
>> 1 file changed, 12 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>> index e331cbdb117df6cfa8ae0e4c44a5aa91ba93f8eb..b3becb230a94163cccff4eaffb8eed44f1c29ad0 100644
>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>> @@ -2399,13 +2399,23 @@ static uint32_t a6xx_get_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
>>
>> static bool a6xx_progress(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
>> {
>> - struct msm_cp_state cp_state = {
>> + struct msm_cp_state cp_state;
>> + bool progress;
>> +
>> + /*
>> + * With IFPC, KMD doesn't know whether GX power domain is collapsed or not. So, we can't
>> + * blindly read the below registers in GX domain. Lets trust the hang detection in HW and
>> + * lie to the caller that there was progress.
>
> I know that we've relaxed code line width to 100 chars. Would it be
> possible to reformat the comment to 72-75 chars?
Yeah, makes sense for multi-line comments. Shouldn't the limit be 80?
-Akhil
>
>> + */
>> + if (to_adreno_gpu(gpu)->info->quirks & ADRENO_QUIRK_IFPC)
>> + return true;
>> +
>> + cp_state = (struct msm_cp_state) {
>> .ib1_base = gpu_read64(gpu, REG_A6XX_CP_IB1_BASE),
>> .ib2_base = gpu_read64(gpu, REG_A6XX_CP_IB2_BASE),
>> .ib1_rem = gpu_read(gpu, REG_A6XX_CP_IB1_REM_SIZE),
>> .ib2_rem = gpu_read(gpu, REG_A6XX_CP_IB2_REM_SIZE),
>> };
>> - bool progress;
>>
>> /*
>> * Adjust the remaining data to account for what has already been
>>
>> --
>> 2.50.1
>>
>
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 16/17] drm/msm/a6xx: Enable IFPC on Adreno X1-85
2025-07-22 13:55 ` Dmitry Baryshkov
@ 2025-07-22 21:37 ` Akhil P Oommen
2025-07-23 10:33 ` Konrad Dybcio
0 siblings, 1 reply; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-22 21:37 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/22/2025 7:25 PM, Dmitry Baryshkov wrote:
> On Sun, Jul 20, 2025 at 05:46:17PM +0530, Akhil P Oommen wrote:
>> Add the IFPC restore register list and enable IFPC support on Adreno
>> X1-85 gpu.
>
> Nit: GPU
>
> I can't stop but notice that KGSL enables IFPC for a bigger set of
> SKUs, starting from a630v2 and a615. Is there a plan to get IFPC
> supported on those platforms?
Sorry, no access to those hardwares. But I can certainly help if someone
wants to do that. :)
-Akhil.
>
>>
>> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
>> ---
>> drivers/gpu/drm/msm/adreno/a6xx_catalog.c | 67 ++++++++++++++++++++++++++++++-
>> drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 15 +++++--
>> drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 1 +
>> 3 files changed, 78 insertions(+), 5 deletions(-)
>>
>
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 16/17] drm/msm/a6xx: Enable IFPC on Adreno X1-85
2025-07-22 14:55 ` Konrad Dybcio
@ 2025-07-22 21:41 ` Akhil P Oommen
0 siblings, 0 replies; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-22 21:41 UTC (permalink / raw)
To: Konrad Dybcio, Rob Clark, Sean Paul, Konrad Dybcio,
Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Marijn Suijten,
David Airlie, Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/22/2025 8:25 PM, Konrad Dybcio wrote:
> On 7/20/25 2:16 PM, Akhil P Oommen wrote:
>> Add the IFPC restore register list and enable IFPC support on Adreno
>> X1-85 gpu.
>>
>> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
>> ---
>> drivers/gpu/drm/msm/adreno/a6xx_catalog.c | 67 ++++++++++++++++++++++++++++++-
>> drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 15 +++++--
>> drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 1 +
>> 3 files changed, 78 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
>> index 70f7ad806c34076352d84f32d62c2833422b6e5e..07fcabed472c3b9ca47faf1a8b3f7cf580801981 100644
>> --- a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
>> @@ -1343,6 +1343,69 @@ static const uint32_t a7xx_pwrup_reglist_regs[] = {
>>
>> DECLARE_ADRENO_REGLIST_LIST(a7xx_pwrup_reglist);
>>
>> +/* Applicable for X185, A750 */
>> +static const u32 a750_ifpc_reglist_regs[] = {
>> + REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_0,
>> + REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_1,
>> + REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_2,
>> + REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_3,
>> + REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_4,
>> + REG_A6XX_TPL1_NC_MODE_CNTL,
>> + REG_A6XX_SP_NC_MODE_CNTL,
>> + REG_A6XX_CP_DBG_ECO_CNTL,
>> + REG_A6XX_CP_PROTECT_CNTL,
>> + REG_A6XX_CP_PROTECT(0),
>> + REG_A6XX_CP_PROTECT(1),
>
> Is it fair to assume that we'd like to saverestore all CP_PROT
> registers on all SKUs, always? We can save some space in .rodata
> this way..
Yeah. Makes sense, but lets do that when we duplicate it in future.
-Akhil
>
> Konrad
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 04/17] drm/msm/a6xx: Poll additional DRV status
2025-07-20 12:16 ` [PATCH 04/17] drm/msm/a6xx: Poll additional DRV status Akhil P Oommen
2025-07-22 13:31 ` Dmitry Baryshkov
@ 2025-07-23 10:01 ` Konrad Dybcio
2025-07-23 19:28 ` Akhil P Oommen
1 sibling, 1 reply; 85+ messages in thread
From: Konrad Dybcio @ 2025-07-23 10:01 UTC (permalink / raw)
To: Akhil P Oommen, Rob Clark, Sean Paul, Konrad Dybcio,
Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Marijn Suijten,
David Airlie, Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/20/25 2:16 PM, Akhil P Oommen wrote:
> A7XX_GEN2 generation has additional TCS slots. Poll the respective
> DRV status registers before pm suspend.
>
> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
> ---
> drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 16 ++++++++++++++++
> 1 file changed, 16 insertions(+)
>
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> index 790ef2f94a0b0cd40433d7edb6a89e4f04408bf5..3bebb6dd7059782ceca29f2efd2acee24d3fc930 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> @@ -987,6 +987,22 @@ static void a6xx_gmu_rpmh_off(struct a6xx_gmu *gmu)
> val, (val & 1), 100, 10000);
> gmu_poll_timeout_rscc(gmu, REG_A6XX_RSCC_TCS3_DRV0_STATUS + seqmem_off,
> val, (val & 1), 100, 1000);
> +
> + if (!adreno_is_a740_family(adreno_gpu))
> + return;
> +
> + gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS4_DRV0_STATUS + seqmem_off,
> + val, (val & 1), 100, 10000);
> + gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS5_DRV0_STATUS + seqmem_off,
> + val, (val & 1), 100, 10000);
> + gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS6_DRV0_STATUS + seqmem_off,
> + val, (val & 1), 100, 10000);
> + gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS7_DRV0_STATUS + seqmem_off,
> + val, (val & 1), 100, 1000);
> + gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS8_DRV0_STATUS + seqmem_off,
> + val, (val & 1), 100, 10000);
> + gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS9_DRV0_STATUS + seqmem_off,
> + val, (val & 1), 100, 1000);
FWIW there are places downstream where it polls for 1 ms
(gen7_gmu_pwrctrl_suspend) / 2 ms (gen7_gmu_power_off) ms (as opposed
to 1 or 10 ms here), but the timeouts are all the same across registers
(unlike TCS3 and TCS9 above)
Ultimately it's a timeout, so a value too big shouldn't matter, but
let's make sure the other threshold is ok
Konrad
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 08/17] drm/msm/a6xx: Set Keep-alive votes to block IFPC
2025-07-22 21:24 ` Akhil P Oommen
@ 2025-07-23 10:05 ` Konrad Dybcio
2025-07-23 21:22 ` Akhil P Oommen
2025-07-23 11:13 ` Dmitry Baryshkov
1 sibling, 1 reply; 85+ messages in thread
From: Konrad Dybcio @ 2025-07-23 10:05 UTC (permalink / raw)
To: Akhil P Oommen, Dmitry Baryshkov
Cc: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/22/25 11:24 PM, Akhil P Oommen wrote:
> On 7/22/2025 7:14 PM, Dmitry Baryshkov wrote:
>> On Sun, Jul 20, 2025 at 05:46:09PM +0530, Akhil P Oommen wrote:
>>> 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>
>>> ---
[...]
>>> +static void set_keepalive_vote(struct msm_gpu *gpu, bool on)
>>
>> a6xx_set_keepalive_vote()
>
> static fn! Why do we need prefix here?
It's good practice to namespace-prefix your functions, so that you
can more easily find them, e.g. in a backtrace.
For a prefix, adreno_gmu_ would be even better, as the register doesn't
seem to have changed across generations
Konrad
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 10/17] drm/msm/a6xx: Poll AHB fence status in GPU IRQ handler
2025-07-20 12:16 ` [PATCH 10/17] drm/msm/a6xx: Poll AHB fence status in GPU IRQ handler Akhil P Oommen
@ 2025-07-23 10:10 ` Konrad Dybcio
0 siblings, 0 replies; 85+ messages in thread
From: Konrad Dybcio @ 2025-07-23 10:10 UTC (permalink / raw)
To: Akhil P Oommen, Rob Clark, Sean Paul, Konrad Dybcio,
Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Marijn Suijten,
David Airlie, Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/20/25 2:16 PM, Akhil P Oommen wrote:
> Even though 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. 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>
> ---
There's some more context in this commit message, please include some
of it:
commit 5e1b78bde04ca08ebc27031aba509565f7df348a
Author: Kyle Piefer <kpiefer@codeaurora.org>
Date: Thu Oct 19 13:22:10 2017 -0700
msm: kgsl: Prevent repeated FENCE stuck errors
If the AHB fence is in DROP mode when we enter the RBBM
interrupt handler, it is usually harmless. The GMU will
see the pending interrupt and abort power collapse, causing
the fence to be set back to ALLOW. Until this happens though,
we cannot proceed to read the IRQ status and write the clear
register because they are inaccessible.
Poll the fence status until it is ALLOW and we can proceed.
If we poll for too long and the fence is still stuck,
the GMU is probably hung. In this case print an error
message and give up.
<cut off tags so as not to confuse b4>
Konrad
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 02/17] drm/msm: a6xx: Refactor a6xx_sptprac_enable()
2025-07-22 19:47 ` Akhil P Oommen
@ 2025-07-23 10:13 ` Konrad Dybcio
2025-07-23 19:10 ` Akhil P Oommen
0 siblings, 1 reply; 85+ messages in thread
From: Konrad Dybcio @ 2025-07-23 10:13 UTC (permalink / raw)
To: Akhil P Oommen, Rob Clark, Sean Paul, Konrad Dybcio,
Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Marijn Suijten,
David Airlie, Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/22/25 9:47 PM, Akhil P Oommen wrote:
> On 7/22/2025 8:00 PM, Konrad Dybcio wrote:
>> On 7/20/25 2:16 PM, Akhil P Oommen wrote:
>>> A minor refactor to combine the subroutines for legacy a6xx GMUs under
>>> a single check. This helps to avoid an unnecessary check and return
>>> early from the subroutine for majority of a6xx gpus.
>>>
>>> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
>>> ---
>>> drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 8 ++++----
>>> 1 file changed, 4 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
>>> index 38c0f8ef85c3d260864541d83abe43e49c772c52..41129692d127b70e9293b82bea5ccb6b911b0bfb 100644
>>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
>>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
>>> @@ -403,7 +403,10 @@ int a6xx_sptprac_enable(struct a6xx_gmu *gmu)
>>> int ret;
>>> u32 val;
>>>
>>> - if (!gmu->legacy)
>>> + WARN_ON(!gmu->legacy);
>>> +
>>> + /* Nothing to do if GMU does the power management */
>>> + if (gmu->idle_level > GMU_IDLE_STATE_ACTIVE)
>>
>> This isn't quite a no-op, but I can't seem to find what the '1' value
>> would map to, even in 845 kernel sources. Do we have to worry about it?
>
> This is fine. '1' seems to be a low power state that was removed very
> early in the gmu firmware development stage. We can ignore that.
Ok, good - could you also add a define for it, perhaps something like:
#define GMU_IDLE_STATE_RESERVED 1 /* Cancelled feature, never exposed by fw */
Konrad
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 09/17] drm/msm/a6xx: Switch to GMU AO counter
2025-07-20 12:16 ` [PATCH 09/17] drm/msm/a6xx: Switch to GMU AO counter Akhil P Oommen
@ 2025-07-23 10:19 ` Konrad Dybcio
2025-07-23 12:15 ` Rob Clark
0 siblings, 1 reply; 85+ messages in thread
From: Konrad Dybcio @ 2025-07-23 10:19 UTC (permalink / raw)
To: Akhil P Oommen, Rob Clark, Sean Paul, Konrad Dybcio,
Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Marijn Suijten,
David Airlie, Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/20/25 2:16 PM, Akhil P Oommen wrote:
> CP_ALWAYS_ON counter falls under GX domain which is collapsed during
> IFPC. So switch to GMU_ALWAYS_ON counter for any CPU reads since it is
> not impacted by IFPC. Both counters are clocked by same xo clock source.
>
> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
> ---
> drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 30 ++++++++++++++++--------------
> 1 file changed, 16 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> index 6770f0363e7284e4596b1188637a4615d2c0779b..f000915a4c2698a85b45bd3c92e590f14999d10d 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> @@ -16,6 +16,19 @@
>
> #define GPU_PAS_ID 13
>
> +static u64 read_gmu_ao_counter(struct a6xx_gpu *a6xx_gpu)
> +{
> + u64 count_hi, count_lo, temp;
> +
> + do {
> + count_hi = gmu_read(&a6xx_gpu->gmu, REG_A6XX_GMU_ALWAYS_ON_COUNTER_H);
> + count_lo = gmu_read(&a6xx_gpu->gmu, REG_A6XX_GMU_ALWAYS_ON_COUNTER_L);
> + temp = gmu_read(&a6xx_gpu->gmu, REG_A6XX_GMU_ALWAYS_ON_COUNTER_H);
> + } while (count_hi != temp);
The original logic is as follows:
static u64 gen7_read_alwayson(struct adreno_device *adreno_dev)
{
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
u32 lo = 0, hi = 0, tmp = 0;
/* Always use the GMU AO counter when doing a AHB read */
gmu_core_regread(device, GEN7_GMU_ALWAYS_ON_COUNTER_H, &hi);
gmu_core_regread(device, GEN7_GMU_ALWAYS_ON_COUNTER_L, &lo);
/* Check for overflow */
gmu_core_regread(device, GEN7_GMU_ALWAYS_ON_COUNTER_H, &tmp);
if (hi != tmp) {
gmu_core_regread(device, GEN7_GMU_ALWAYS_ON_COUNTER_L,
&lo);
hi = tmp;
}
return (((u64) hi) << 32) | lo;
}
Doing this in a while-loop almost looks like you want a lot of time to
pass - REG_WIDTH(u32?)/19.2 MHz
Konrad
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 11/17] drm/msm: Add support for IFPC
2025-07-20 12:16 ` [PATCH 11/17] drm/msm: Add support for IFPC Akhil P Oommen
2025-07-22 13:49 ` Dmitry Baryshkov
@ 2025-07-23 10:22 ` Konrad Dybcio
1 sibling, 0 replies; 85+ messages in thread
From: Konrad Dybcio @ 2025-07-23 10:22 UTC (permalink / raw)
To: Akhil P Oommen, Rob Clark, Sean Paul, Konrad Dybcio,
Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Marijn Suijten,
David Airlie, Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/20/25 2:16 PM, Akhil P Oommen wrote:
> Add a new quirk to denote IFPC (Inter-Frame Power Collapse) support
> for a gpu. Based on this flag send the feature ctrl hfi message to
> GMU to enable IFPC support.
>
> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
> ---
[...]
> +static int a6xx_hfi_enable_ifpc(struct a6xx_gmu *gmu)
> +{
> + if (gmu->idle_level != GMU_IDLE_STATE_IFPC)
> + return 0;
> +
> + return a6xx_hfi_feature_ctrl_msg(gmu, HFI_FEATURE_IFPC, 1, 0x1680);
> +}
If this function is not used anywhere else, you may want to inline it,
checking for the opposite condition
Konrad
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 11/17] drm/msm: Add support for IFPC
2025-07-22 21:27 ` Akhil P Oommen
@ 2025-07-23 10:27 ` Konrad Dybcio
2025-07-23 21:43 ` Akhil P Oommen
0 siblings, 1 reply; 85+ messages in thread
From: Konrad Dybcio @ 2025-07-23 10:27 UTC (permalink / raw)
To: Akhil P Oommen, Dmitry Baryshkov
Cc: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/22/25 11:27 PM, Akhil P Oommen wrote:
> On 7/22/2025 7:19 PM, Dmitry Baryshkov wrote:
>> On Sun, Jul 20, 2025 at 05:46:12PM +0530, Akhil P Oommen wrote:
>>> Add a new quirk to denote IFPC (Inter-Frame Power Collapse) support
>>> for a gpu. Based on this flag send the feature ctrl hfi message to
>>> GMU to enable IFPC support.
>>>
>>> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
>>> ---
[...]
>>> +static int a6xx_hfi_enable_ifpc(struct a6xx_gmu *gmu)
>>> +{
>>> + if (gmu->idle_level != GMU_IDLE_STATE_IFPC)
>>> + return 0;
>>> +
>>> + return a6xx_hfi_feature_ctrl_msg(gmu, HFI_FEATURE_IFPC, 1, 0x1680);
>>
>> magic number?
>>
>
> Let me check.
techpack-graphics/adreno_a6xx_gmu.c:
537:#define A6X_GMU_LONG_IFPC_HYST FIELD_PREP(GENMASK(15, 0), 0x1680)
541:#define A6X_GMU_LONG_IFPC_HYST_FLOOR FIELD_PREP(GENMASK(15, 0), 0x0F00)
(same value for a7/a8)
0x0f00 is 3840, which smells oddly like the XO clock rate (possibly mul/div2)
(38.4 MHz or 19.2) / 3840 is (1000 or 500) (ms? us? cycles?) and the other one is
(333 or 667) - without any further information I'd estimate this is some sort of
scheduler tuning
Konrad
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 12/17] drm/msm: Skip devfreq IDLE when possible
2025-07-20 12:16 ` [PATCH 12/17] drm/msm: Skip devfreq IDLE when possible Akhil P Oommen
2025-07-21 4:00 ` kernel test robot
2025-07-22 13:50 ` Dmitry Baryshkov
@ 2025-07-23 10:28 ` Konrad Dybcio
2 siblings, 0 replies; 85+ messages in thread
From: Konrad Dybcio @ 2025-07-23 10:28 UTC (permalink / raw)
To: Akhil P Oommen, Rob Clark, Sean Paul, Konrad Dybcio,
Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Marijn Suijten,
David Airlie, Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/20/25 2:16 PM, Akhil P Oommen wrote:
> When IFPC is supported, devfreq idling is redundant and adds
> unnecessary pm suspend/wake latency. So skip it when IFPC is
> supported.
>
> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
> ---
> drivers/gpu/drm/msm/msm_gpu_devfreq.c | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/drivers/gpu/drm/msm/msm_gpu_devfreq.c b/drivers/gpu/drm/msm/msm_gpu_devfreq.c
> index 2e1d5c3432728cde15d91f69da22bb915588fe86..53ef2add5047e7d6b6371af949cab36ce8409372 100644
> --- a/drivers/gpu/drm/msm/msm_gpu_devfreq.c
> +++ b/drivers/gpu/drm/msm/msm_gpu_devfreq.c
> @@ -4,6 +4,7 @@
> * Author: Rob Clark <robdclark@gmail.com>
> */
>
> +#include "adreno/adreno_gpu.h"
> #include "msm_gpu.h"
> #include "msm_gpu_trace.h"
>
> @@ -300,6 +301,8 @@ void msm_devfreq_active(struct msm_gpu *gpu)
> if (!has_devfreq(gpu))
> return;
>
> + if (to_adreno_gpu(gpu)->info->quirks & ADRENO_QUIRK_IFPC)
> + return;
Do we want a static_branch here instead?
Konrad
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 15/17] drm/msm/a6xx: Make crashstate capture IFPC safe
2025-07-20 12:16 ` [PATCH 15/17] drm/msm/a6xx: Make crashstate capture IFPC safe Akhil P Oommen
@ 2025-07-23 10:32 ` Konrad Dybcio
2025-07-23 21:53 ` Akhil P Oommen
0 siblings, 1 reply; 85+ messages in thread
From: Konrad Dybcio @ 2025-07-23 10:32 UTC (permalink / raw)
To: Akhil P Oommen, Rob Clark, Sean Paul, Konrad Dybcio,
Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Marijn Suijten,
David Airlie, Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/20/25 2:16 PM, Akhil P Oommen wrote:
> Now with IFPC, GX domain can collapse as soon as GPU becomes IDLE. So
> add gx_is_on check before accessing any GX registers during crashstate
> capture and recovery.
>
> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
> ---
[...]
> + /*
> + * This is true only on an A6XX_GEN1 with GMU, has IFPC enabled and a super old SQE firmware
> + * without 'whereami' support
> + */
Firmware that old won't even be accepted by the driver, see the slightly
confusing logic in a6xx_ucode_check_version()
Konrad
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 16/17] drm/msm/a6xx: Enable IFPC on Adreno X1-85
2025-07-22 21:37 ` Akhil P Oommen
@ 2025-07-23 10:33 ` Konrad Dybcio
2025-07-23 21:57 ` Akhil P Oommen
0 siblings, 1 reply; 85+ messages in thread
From: Konrad Dybcio @ 2025-07-23 10:33 UTC (permalink / raw)
To: Akhil P Oommen, Dmitry Baryshkov
Cc: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/22/25 11:37 PM, Akhil P Oommen wrote:
> On 7/22/2025 7:25 PM, Dmitry Baryshkov wrote:
>> On Sun, Jul 20, 2025 at 05:46:17PM +0530, Akhil P Oommen wrote:
>>> Add the IFPC restore register list and enable IFPC support on Adreno
>>> X1-85 gpu.
>>
>> Nit: GPU
>>
>> I can't stop but notice that KGSL enables IFPC for a bigger set of
>> SKUs, starting from a630v2 and a615. Is there a plan to get IFPC
>> supported on those platforms?
>
> Sorry, no access to those hardwares. But I can certainly help if someone
> wants to do that. :)
Let's get the groundwork merged first ;)
Nowadays you can reasonably assume we have access to at least one board,
no matter which SoC
Konrad
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 03/17] drm/msm: a6xx: Fix gx_is_on check for a7x family
2025-07-22 19:52 ` Akhil P Oommen
@ 2025-07-23 11:10 ` Dmitry Baryshkov
2025-07-23 19:11 ` Akhil P Oommen
0 siblings, 1 reply; 85+ messages in thread
From: Dmitry Baryshkov @ 2025-07-23 11:10 UTC (permalink / raw)
To: Akhil P Oommen
Cc: Konrad Dybcio, Rob Clark, Sean Paul, Konrad Dybcio,
Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Marijn Suijten,
David Airlie, Simona Vetter, linux-arm-msm, dri-devel, freedreno,
linux-kernel
On Wed, Jul 23, 2025 at 01:22:20AM +0530, Akhil P Oommen wrote:
> On 7/22/2025 8:03 PM, Konrad Dybcio wrote:
> > On 7/20/25 2:16 PM, Akhil P Oommen wrote:
> >> Bitfield definition for REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS register is
> >> different in A7XX family. Check the correct bits to see if GX is
> >> collapsed on A7XX series.
> >>
> >> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
> >> ---
> >
> > This seems to have been introduced all the way back in the initial
> > a7xx submission downstream, so I'll assume this concerns all SKUs
> > and this is a relevant fixes tag:
> >
> > Fixes: af66706accdf ("drm/msm/a6xx: Add skeleton A7xx support")
> >
> > Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
>
> Dmitry/Konrad,
>
> We don't have to backport this change because the existing code reads a
> couple of unused bits which are '0's and that is okay when IFPC is not
> supported. So there is no practical benefit in cherry-picking this
> change to older kernel versions.
Fixes tag is not about backporting. It is to point out that there was an
issue in the original commit which is fixed by a new one.
>
> -Akhil.
>
> >
> > Konrad
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 05/17] drm/msm/a6xx: Fix PDC sleep sequence
2025-07-22 21:05 ` Akhil P Oommen
@ 2025-07-23 11:11 ` Dmitry Baryshkov
0 siblings, 0 replies; 85+ messages in thread
From: Dmitry Baryshkov @ 2025-07-23 11:11 UTC (permalink / raw)
To: Akhil P Oommen
Cc: rob.clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, linux-arm-msm, dri-devel, freedreno, linux-kernel
On Wed, Jul 23, 2025 at 02:35:31AM +0530, Akhil P Oommen wrote:
> On 7/22/2025 10:56 PM, Rob Clark wrote:
> > On Tue, Jul 22, 2025 at 6:33 AM Dmitry Baryshkov
> > <dmitry.baryshkov@oss.qualcomm.com> wrote:
> >>
> >> On Sun, Jul 20, 2025 at 05:46:06PM +0530, Akhil P Oommen wrote:
> >>> 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
> >>
> >> s/KMD/the driver/
> >
> > IMHO for gpu things "KMD" makes sense, to differentiate between kernel
> > and user mode (UMD).. this is perhaps different from other areas where
> > there isn't a userspace component to the driver stack
>
> Ack
>
> >
> > BR,
> > -R
> >
> >>> GMU firmware has not initialized. Track these dependencies using a new
> >>> status variable and trigger PDC sleep/wake sequences appropriately.
> >>
> >> Again, it looks like there should be a Fixes tag here.
>
> Ack. I guess it is not a bad idea to backport this one too.
Please add cc:stable to the patches that need to be backported and make
sure that all Fixes are at the start of the series.
>
> >>
> >>>
> >>> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
> >>> ---
> >>> drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 30 +++++++++++++++++++-----------
> >>> drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 6 ++++++
> >>> 2 files changed, 25 insertions(+), 11 deletions(-)
> >>>
> >>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> >>> index 3bebb6dd7059782ceca29f2efd2acee24d3fc930..4d6c70735e0892ed87d6a68d64f24bda844e5e16 100644
> >>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> >>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> >>> @@ -279,6 +279,8 @@ static int a6xx_gmu_start(struct a6xx_gmu *gmu)
> >>> if (ret)
> >>> DRM_DEV_ERROR(gmu->dev, "GMU firmware initialization timed out\n");
> >>>
> >>> + set_bit(GMU_STATUS_FW_START, &gmu->status);
> >>> +
> >>> return ret;
> >>> }
> >>>
> >>> @@ -528,6 +530,9 @@ static int a6xx_rpmh_start(struct a6xx_gmu *gmu)
> >>> int ret;
> >>> u32 val;
> >>>
> >>> + if (!test_and_clear_bit(GMU_STATUS_PDC_SLEEP, &gmu->status))
> >>> + return 0;
> >>> +
> >>> gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, BIT(1));
> >>>
> >>> ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_RSCC_CONTROL_ACK, val,
> >>> @@ -555,6 +560,11 @@ static void a6xx_rpmh_stop(struct a6xx_gmu *gmu)
> >>> int ret;
> >>> u32 val;
> >>>
> >>> + if (test_and_clear_bit(GMU_STATUS_FW_START, &gmu->status))
> >>> + return;
> >>> +
> >>> + /* TODO: should we skip if IFPC is not enabled */
> >>
> >> Is this a question or a statement?
>
> It was a reminder to myself which I forgot to revisit later. Will
> addresss this in the next revision.
>
> -Akhil.
>
> >>
> >>> +
> >>> gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, 1);
> >>>
> >>> ret = gmu_poll_timeout_rscc(gmu, REG_A6XX_GPU_RSCC_RSC_STATUS0_DRV0,
> >>> @@ -563,6 +573,8 @@ static void a6xx_rpmh_stop(struct a6xx_gmu *gmu)
> >>> DRM_DEV_ERROR(gmu->dev, "Unable to power off the GPU RSC\n");
> >>>
> >>> gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, 0);
> >>> +
> >>> + set_bit(GMU_STATUS_PDC_SLEEP, &gmu->status);
> >>> }
> >>>
> >>> static inline void pdc_write(void __iomem *ptr, u32 offset, u32 value)
> >>> @@ -691,8 +703,6 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu)
> >>> /* ensure no writes happen before the uCode is fully written */
> >>> wmb();
> >>>
> >>> - a6xx_rpmh_stop(gmu);
> >>> -
> >>> err:
> >>> if (!IS_ERR_OR_NULL(pdcptr))
> >>> iounmap(pdcptr);
> >>> @@ -852,19 +862,15 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state)
> >>> else
> >>> gmu_write(gmu, REG_A6XX_GMU_GENERAL_7, 1);
> >>>
> >>> - if (state == GMU_WARM_BOOT) {
> >>> - ret = a6xx_rpmh_start(gmu);
> >>> - if (ret)
> >>> - return ret;
> >>> - } else {
> >>> + ret = a6xx_rpmh_start(gmu);
> >>> + if (ret)
> >>> + return ret;
> >>> +
> >>> + if (state == GMU_COLD_BOOT) {
> >>> if (WARN(!adreno_gpu->fw[ADRENO_FW_GMU],
> >>> "GMU firmware is not loaded\n"))
> >>> return -ENOENT;
> >>>
> >>> - ret = a6xx_rpmh_start(gmu);
> >>> - if (ret)
> >>> - return ret;
> >>> -
> >>> ret = a6xx_gmu_fw_load(gmu);
> >>> if (ret)
> >>> return ret;
> >>> @@ -1046,6 +1052,8 @@ static void a6xx_gmu_force_off(struct a6xx_gmu *gmu)
> >>>
> >>> /* Reset GPU core blocks */
> >>> a6xx_gpu_sw_reset(gpu, true);
> >>> +
> >>> + a6xx_rpmh_stop(gmu);
> >>> }
> >>>
> >>> static void a6xx_gmu_set_initial_freq(struct msm_gpu *gpu, struct a6xx_gmu *gmu)
> >>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
> >>> index b2d4489b40249b1916ab4a42c89e3f4bdc5c4af9..034f1b4e5a3fb9cd601bfbe6d06d64e5ace3b6e7 100644
> >>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
> >>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
> >>> @@ -117,6 +117,12 @@ struct a6xx_gmu {
> >>>
> >>> struct qmp *qmp;
> >>> struct a6xx_hfi_msg_bw_table *bw_table;
> >>> +
> >>> +/* To check if we can trigger sleep seq at PDC. Cleared in a6xx_rpmh_stop() */
> >>> +#define GMU_STATUS_FW_START 0
> >>> +/* To track if PDC sleep seq was done */
> >>> +#define GMU_STATUS_PDC_SLEEP 1
> >>> + unsigned long status;
> >>> };
> >>>
> >>> static inline u32 gmu_read(struct a6xx_gmu *gmu, u32 offset)
> >>>
> >>> --
> >>> 2.50.1
> >>>
> >>
> >> --
> >> With best wishes
> >> Dmitry
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 08/17] drm/msm/a6xx: Set Keep-alive votes to block IFPC
2025-07-22 21:24 ` Akhil P Oommen
2025-07-23 10:05 ` Konrad Dybcio
@ 2025-07-23 11:13 ` Dmitry Baryshkov
1 sibling, 0 replies; 85+ messages in thread
From: Dmitry Baryshkov @ 2025-07-23 11:13 UTC (permalink / raw)
To: Akhil P Oommen
Cc: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, linux-arm-msm, dri-devel, freedreno, linux-kernel
On Wed, Jul 23, 2025 at 02:54:59AM +0530, Akhil P Oommen wrote:
> On 7/22/2025 7:14 PM, Dmitry Baryshkov wrote:
> > On Sun, Jul 20, 2025 at 05:46:09PM +0530, Akhil P Oommen wrote:
> >> 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>
> >> ---
> >> 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 8c004fc3abd2896d467a9728b34e99e4ed944dc4..6770f0363e7284e4596b1188637a4615d2c0779b 100644
> >> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> >> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> >> @@ -1752,8 +1752,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);
> >>
> >> /*
> >> @@ -1765,13 +1763,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,
> >> @@ -1810,9 +1801,24 @@ static void a7xx_sw_fuse_violation_irq(struct msm_gpu *gpu)
> >> }
> >> }
> >>
> >> +static void set_keepalive_vote(struct msm_gpu *gpu, bool on)
> >
> > a6xx_set_keepalive_vote()
>
> static fn! Why do we need prefix here?
It's really a good custom. Also, note that I suggested two different
names to your functions (otherwise it's too easy to get confused).
> >> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_preempt.c b/drivers/gpu/drm/msm/adreno/a6xx_preempt.c
> >> index 5b0fd510ff58d989ab285f1a2497f6f522a6b187..1c8ec1911010c00a000d195116fc950c4d947cac 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 set_keepalive_vote(struct msm_gpu *gpu, bool on)
> >
> > a6xx_set_preempt_keepalive_vote();
> >
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 09/17] drm/msm/a6xx: Switch to GMU AO counter
2025-07-23 10:19 ` Konrad Dybcio
@ 2025-07-23 12:15 ` Rob Clark
2025-07-29 13:30 ` Konrad Dybcio
0 siblings, 1 reply; 85+ messages in thread
From: Rob Clark @ 2025-07-23 12:15 UTC (permalink / raw)
To: Konrad Dybcio
Cc: Akhil P Oommen, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, linux-arm-msm, dri-devel, freedreno, linux-kernel
On Wed, Jul 23, 2025 at 3:19 AM Konrad Dybcio
<konrad.dybcio@oss.qualcomm.com> wrote:
>
> On 7/20/25 2:16 PM, Akhil P Oommen wrote:
> > CP_ALWAYS_ON counter falls under GX domain which is collapsed during
> > IFPC. So switch to GMU_ALWAYS_ON counter for any CPU reads since it is
> > not impacted by IFPC. Both counters are clocked by same xo clock source.
> >
> > Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
> > ---
> > drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 30 ++++++++++++++++--------------
> > 1 file changed, 16 insertions(+), 14 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> > index 6770f0363e7284e4596b1188637a4615d2c0779b..f000915a4c2698a85b45bd3c92e590f14999d10d 100644
> > --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> > +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> > @@ -16,6 +16,19 @@
> >
> > #define GPU_PAS_ID 13
> >
> > +static u64 read_gmu_ao_counter(struct a6xx_gpu *a6xx_gpu)
> > +{
> > + u64 count_hi, count_lo, temp;
> > +
> > + do {
> > + count_hi = gmu_read(&a6xx_gpu->gmu, REG_A6XX_GMU_ALWAYS_ON_COUNTER_H);
> > + count_lo = gmu_read(&a6xx_gpu->gmu, REG_A6XX_GMU_ALWAYS_ON_COUNTER_L);
> > + temp = gmu_read(&a6xx_gpu->gmu, REG_A6XX_GMU_ALWAYS_ON_COUNTER_H);
> > + } while (count_hi != temp);
>
> The original logic is as follows:
>
> static u64 gen7_read_alwayson(struct adreno_device *adreno_dev)
> {
> struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
> u32 lo = 0, hi = 0, tmp = 0;
>
> /* Always use the GMU AO counter when doing a AHB read */
> gmu_core_regread(device, GEN7_GMU_ALWAYS_ON_COUNTER_H, &hi);
> gmu_core_regread(device, GEN7_GMU_ALWAYS_ON_COUNTER_L, &lo);
>
> /* Check for overflow */
> gmu_core_regread(device, GEN7_GMU_ALWAYS_ON_COUNTER_H, &tmp);
>
> if (hi != tmp) {
> gmu_core_regread(device, GEN7_GMU_ALWAYS_ON_COUNTER_L,
> &lo);
> hi = tmp;
> }
>
> return (((u64) hi) << 32) | lo;
> }
>
> Doing this in a while-loop almost looks like you want a lot of time to
> pass - REG_WIDTH(u32?)/19.2 MHz
would:
} while (unlikely(count_hi != temp));
make it more clear?
> Konrad
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 02/17] drm/msm: a6xx: Refactor a6xx_sptprac_enable()
2025-07-23 10:13 ` Konrad Dybcio
@ 2025-07-23 19:10 ` Akhil P Oommen
0 siblings, 0 replies; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-23 19:10 UTC (permalink / raw)
To: Konrad Dybcio, Rob Clark, Sean Paul, Konrad Dybcio,
Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Marijn Suijten,
David Airlie, Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/23/2025 3:43 PM, Konrad Dybcio wrote:
> On 7/22/25 9:47 PM, Akhil P Oommen wrote:
>> On 7/22/2025 8:00 PM, Konrad Dybcio wrote:
>>> On 7/20/25 2:16 PM, Akhil P Oommen wrote:
>>>> A minor refactor to combine the subroutines for legacy a6xx GMUs under
>>>> a single check. This helps to avoid an unnecessary check and return
>>>> early from the subroutine for majority of a6xx gpus.
>>>>
>>>> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
>>>> ---
>>>> drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 8 ++++----
>>>> 1 file changed, 4 insertions(+), 4 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
>>>> index 38c0f8ef85c3d260864541d83abe43e49c772c52..41129692d127b70e9293b82bea5ccb6b911b0bfb 100644
>>>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
>>>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
>>>> @@ -403,7 +403,10 @@ int a6xx_sptprac_enable(struct a6xx_gmu *gmu)
>>>> int ret;
>>>> u32 val;
>>>>
>>>> - if (!gmu->legacy)
>>>> + WARN_ON(!gmu->legacy);
>>>> +
>>>> + /* Nothing to do if GMU does the power management */
>>>> + if (gmu->idle_level > GMU_IDLE_STATE_ACTIVE)
>>>
>>> This isn't quite a no-op, but I can't seem to find what the '1' value
>>> would map to, even in 845 kernel sources. Do we have to worry about it?
>>
>> This is fine. '1' seems to be a low power state that was removed very
>> early in the gmu firmware development stage. We can ignore that.
>
> Ok, good - could you also add a define for it, perhaps something like:
>
> #define GMU_IDLE_STATE_RESERVED 1 /* Cancelled feature, never exposed by fw */
Ack.
-Akhil
>
> Konrad
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 03/17] drm/msm: a6xx: Fix gx_is_on check for a7x family
2025-07-23 11:10 ` Dmitry Baryshkov
@ 2025-07-23 19:11 ` Akhil P Oommen
0 siblings, 0 replies; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-23 19:11 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Konrad Dybcio, Rob Clark, Sean Paul, Konrad Dybcio,
Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Marijn Suijten,
David Airlie, Simona Vetter, linux-arm-msm, dri-devel, freedreno,
linux-kernel
On 7/23/2025 4:40 PM, Dmitry Baryshkov wrote:
> On Wed, Jul 23, 2025 at 01:22:20AM +0530, Akhil P Oommen wrote:
>> On 7/22/2025 8:03 PM, Konrad Dybcio wrote:
>>> On 7/20/25 2:16 PM, Akhil P Oommen wrote:
>>>> Bitfield definition for REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS register is
>>>> different in A7XX family. Check the correct bits to see if GX is
>>>> collapsed on A7XX series.
>>>>
>>>> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
>>>> ---
>>>
>>> This seems to have been introduced all the way back in the initial
>>> a7xx submission downstream, so I'll assume this concerns all SKUs
>>> and this is a relevant fixes tag:
>>>
>>> Fixes: af66706accdf ("drm/msm/a6xx: Add skeleton A7xx support")
>>>
>>> Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
>>
>> Dmitry/Konrad,
>>
>> We don't have to backport this change because the existing code reads a
>> couple of unused bits which are '0's and that is okay when IFPC is not
>> supported. So there is no practical benefit in cherry-picking this
>> change to older kernel versions.
>
> Fixes tag is not about backporting. It is to point out that there was an
> issue in the original commit which is fixed by a new one.
Ack. Will add the tag. Thanks.
-Akhil
>
>>
>> -Akhil.
>>
>>>
>>> Konrad
>>
>
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 04/17] drm/msm/a6xx: Poll additional DRV status
2025-07-23 10:01 ` Konrad Dybcio
@ 2025-07-23 19:28 ` Akhil P Oommen
2025-07-24 11:39 ` Konrad Dybcio
0 siblings, 1 reply; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-23 19:28 UTC (permalink / raw)
To: Konrad Dybcio, Rob Clark, Sean Paul, Konrad Dybcio,
Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Marijn Suijten,
David Airlie, Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/23/2025 3:31 PM, Konrad Dybcio wrote:
> On 7/20/25 2:16 PM, Akhil P Oommen wrote:
>> A7XX_GEN2 generation has additional TCS slots. Poll the respective
>> DRV status registers before pm suspend.
>>
>> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
>> ---
>> drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 16 ++++++++++++++++
>> 1 file changed, 16 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
>> index 790ef2f94a0b0cd40433d7edb6a89e4f04408bf5..3bebb6dd7059782ceca29f2efd2acee24d3fc930 100644
>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
>> @@ -987,6 +987,22 @@ static void a6xx_gmu_rpmh_off(struct a6xx_gmu *gmu)
>> val, (val & 1), 100, 10000);
>> gmu_poll_timeout_rscc(gmu, REG_A6XX_RSCC_TCS3_DRV0_STATUS + seqmem_off,
>> val, (val & 1), 100, 1000);
1000us here is a typo and I copied the same mistake below. I will update
all of these timeout values to a common 10000us in the next revision.
>> +
>> + if (!adreno_is_a740_family(adreno_gpu))
>> + return;
>> +
>> + gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS4_DRV0_STATUS + seqmem_off,
>> + val, (val & 1), 100, 10000);
>> + gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS5_DRV0_STATUS + seqmem_off,
>> + val, (val & 1), 100, 10000);
>> + gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS6_DRV0_STATUS + seqmem_off,
>> + val, (val & 1), 100, 10000);
>> + gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS7_DRV0_STATUS + seqmem_off,
>> + val, (val & 1), 100, 1000);
>> + gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS8_DRV0_STATUS + seqmem_off,
>> + val, (val & 1), 100, 10000);
>> + gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS9_DRV0_STATUS + seqmem_off,
>> + val, (val & 1), 100, 1000);
>
> FWIW there are places downstream where it polls for 1 ms
> (gen7_gmu_pwrctrl_suspend) / 2 ms (gen7_gmu_power_off) ms (as opposed
> to 1 or 10 ms here), but the timeouts are all the same across registers
> (unlike TCS3 and TCS9 above)
>
> Ultimately it's a timeout, so a value too big shouldn't matter, but
> let's make sure the other threshold is ok
They are fine. We can try to reduce the timeout 2ms in a separate patch
outside of this series.
-Akhil.
>
> Konrad
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 07/17] drm/msm/adreno: Add fenced regwrite support
2025-07-22 13:39 ` Dmitry Baryshkov
2025-07-22 14:52 ` Konrad Dybcio
@ 2025-07-23 21:04 ` Akhil P Oommen
1 sibling, 0 replies; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-23 21:04 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/22/2025 7:09 PM, Dmitry Baryshkov wrote:
> On Sun, Jul 20, 2025 at 05:46:08PM +0530, Akhil P Oommen wrote:
>> There are some special registers which are accessible even when GX power
>> domain is collapsed during an IFPC sleep. Accessing these registers
>> wakes up GPU from power collapse and allow programming these registers
>> without additional handshake with GMU. This patch adds support for this
>> special register write sequence.
>>
>> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
>> ---
>> drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 63 ++++++++++++++++++++++++++++++-
>> drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 1 +
>> drivers/gpu/drm/msm/adreno/a6xx_preempt.c | 20 +++++-----
>> 3 files changed, 73 insertions(+), 11 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>> index 491fde0083a202bec7c6b3bca88d0e5a717a6560..8c004fc3abd2896d467a9728b34e99e4ed944dc4 100644
>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>> @@ -16,6 +16,67 @@
>>
>> #define GPU_PAS_ID 13
>>
>> +static bool fence_status_check(struct msm_gpu *gpu, u32 offset, u32 value, u32 status, u32 mask)
>> +{
>> + /* Success if !writedropped0/1 */>> + if (!(status & mask))
>> + return true;
>> +
>> + udelay(10);
>
> Why do we need udelay() here? Why can't we use interval setting inside
> gmu_poll_timeout()?
Then the delay won't be at the right place when we use gmu_poll_timeout.
We need the below sequence:
1. reg write
2. check for status
2.1 Done if success
3. wait
4. reg write again
5. goto 2
Another option is to avoid gmu_poll_timeout and just open code the loop
here.
>
>> +
>> + /* Try to update fenced register again */
>> + gpu_write(gpu, offset, value);
>> + return false;
>> +}
>> +
>> +static int fenced_write(struct a6xx_gpu *a6xx_gpu, u32 offset, u32 value, u32 mask)
>> +{
>> + struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
>> + struct msm_gpu *gpu = &adreno_gpu->base;
>> + struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
>> + u32 status;
>> +
>> + gpu_write(gpu, offset, value);
>> +
>> + /* Nothing else to be done in the case of no-GMU */
>> + if (adreno_has_gmu_wrapper(adreno_gpu))
>> + return 0;
>> +
I think we should add an mb() here like downstream just to be cautious.
>> + if (!gmu_poll_timeout(gmu, REG_A6XX_GMU_AHB_FENCE_STATUS, status,
>> + fence_status_check(gpu, offset, value, status, mask), 0, 1000))
>> + return 0;
>> +
>> + dev_err_ratelimited(gmu->dev, "delay in fenced register write (0x%x)\n",
>> + offset);
>> +
>> + /* Try again for another 1ms before failing */
>> + gpu_write(gpu, offset, value);
>> + if (!gmu_poll_timeout(gmu, REG_A6XX_GMU_AHB_FENCE_STATUS, status,
>> + fence_status_check(gpu, offset, value, status, mask), 0, 1000))
>> + return 0;
>> +
>> + dev_err_ratelimited(gmu->dev, "fenced register write (0x%x) fail\n",
>> + offset);
>> +
>> + return -ETIMEDOUT;
>> +}
>> +
>> +int a6xx_fenced_write(struct a6xx_gpu *a6xx_gpu, u32 offset, u64 value, u32 mask, bool is_64b)
>> +{
>> + int ret;
>> +
>> + ret = fenced_write(a6xx_gpu, offset, lower_32_bits(value), mask);
>> + if (ret)
>> + return ret;
>> +
>> + if (!is_64b)
>> + return 0;
>> +
>> + ret = fenced_write(a6xx_gpu, offset + 1, upper_32_bits(value), mask);
>
> no need for a separate ret assignment.
Ack
>
>> +
>> + return ret;
>> +}
>> +
>> static inline bool _a6xx_check_idle(struct msm_gpu *gpu)
>> {
>> struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
>> @@ -86,7 +147,7 @@ static void a6xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
>> /* Update HW if this is the current ring and we are not in preempt*/
>> if (!a6xx_in_preempt(a6xx_gpu)) {
>> if (a6xx_gpu->cur_ring == ring)
>> - gpu_write(gpu, REG_A6XX_CP_RB_WPTR, wptr);
>> + a6xx_fenced_write(a6xx_gpu, REG_A6XX_CP_RB_WPTR, wptr, BIT(0), false);
>
> I can't stop but notice that we don't handle a6xx_fenced_write() errors.
> Is it fine? Or will it result in some sort of crash / reset?
Recover_worker will kick in indirectly, for eg: due to hangcheck timeout
here. Chances of failure here production devices are low though.
-Akhil
>
>> else
>> ring->restore_wptr = true;
>> } else {
>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
>> index 9201a53dd341bf432923ffb44947e015208a3d02..2be036a3faca58b4b559c30881e4b31d5929592a 100644
>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
>> @@ -291,5 +291,6 @@ int a6xx_gpu_state_put(struct msm_gpu_state *state);
>>
>> void a6xx_bus_clear_pending_transactions(struct adreno_gpu *adreno_gpu, bool gx_off);
>> void a6xx_gpu_sw_reset(struct msm_gpu *gpu, bool assert);
>> +int a6xx_fenced_write(struct a6xx_gpu *gpu, u32 offset, u64 value, u32 mask, bool is_64b);
>>
>> #endif /* __A6XX_GPU_H__ */
>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_preempt.c b/drivers/gpu/drm/msm/adreno/a6xx_preempt.c
>> index 3b17fd2dba89115a8e48ba9469e52e4305b0cdbb..5b0fd510ff58d989ab285f1a2497f6f522a6b187 100644
>> --- a/drivers/gpu/drm/msm/adreno/a6xx_preempt.c
>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_preempt.c
>> @@ -41,7 +41,7 @@ static inline void set_preempt_state(struct a6xx_gpu *gpu,
>> }
>>
>> /* Write the most recent wptr for the given ring into the hardware */
>> -static inline void update_wptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
>> +static inline void update_wptr(struct a6xx_gpu *a6xx_gpu, struct msm_ringbuffer *ring)
>> {
>> unsigned long flags;
>> uint32_t wptr;
>> @@ -51,7 +51,7 @@ static inline void update_wptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
>> if (ring->restore_wptr) {
>> wptr = get_wptr(ring);
>>
>> - gpu_write(gpu, REG_A6XX_CP_RB_WPTR, wptr);
>> + a6xx_fenced_write(a6xx_gpu, REG_A6XX_CP_RB_WPTR, wptr, BIT(0), false);
>>
>> ring->restore_wptr = false;
>> }
>> @@ -172,7 +172,7 @@ void a6xx_preempt_irq(struct msm_gpu *gpu)
>>
>> set_preempt_state(a6xx_gpu, PREEMPT_FINISH);
>>
>> - update_wptr(gpu, a6xx_gpu->cur_ring);
>> + update_wptr(a6xx_gpu, a6xx_gpu->cur_ring);
>>
>> set_preempt_state(a6xx_gpu, PREEMPT_NONE);
>>
>> @@ -268,7 +268,7 @@ void a6xx_preempt_trigger(struct msm_gpu *gpu)
>> */
>> if (!ring || (a6xx_gpu->cur_ring == ring)) {
>> set_preempt_state(a6xx_gpu, PREEMPT_FINISH);
>> - update_wptr(gpu, a6xx_gpu->cur_ring);
>> + update_wptr(a6xx_gpu, a6xx_gpu->cur_ring);
>> set_preempt_state(a6xx_gpu, PREEMPT_NONE);
>> spin_unlock_irqrestore(&a6xx_gpu->eval_lock, flags);
>> return;
>> @@ -302,13 +302,13 @@ void a6xx_preempt_trigger(struct msm_gpu *gpu)
>>
>> spin_unlock_irqrestore(&ring->preempt_lock, flags);
>>
>> - gpu_write64(gpu,
>> - REG_A6XX_CP_CONTEXT_SWITCH_SMMU_INFO,
>> - a6xx_gpu->preempt_smmu_iova[ring->id]);
>> + a6xx_fenced_write(a6xx_gpu,
>> + REG_A6XX_CP_CONTEXT_SWITCH_SMMU_INFO, a6xx_gpu->preempt_smmu_iova[ring->id],
>> + BIT(1), true);
>>
>> - gpu_write64(gpu,
>> + a6xx_fenced_write(a6xx_gpu,
>> REG_A6XX_CP_CONTEXT_SWITCH_PRIV_NON_SECURE_RESTORE_ADDR,
>> - a6xx_gpu->preempt_iova[ring->id]);
>> + a6xx_gpu->preempt_iova[ring->id], BIT(1), true);
>>
>> a6xx_gpu->next_ring = ring;
>>
>> @@ -328,7 +328,7 @@ void a6xx_preempt_trigger(struct msm_gpu *gpu)
>> set_preempt_state(a6xx_gpu, PREEMPT_TRIGGERED);
>>
>> /* Trigger the preemption */
>> - gpu_write(gpu, REG_A6XX_CP_CONTEXT_SWITCH_CNTL, cntl);
>> + a6xx_fenced_write(a6xx_gpu, REG_A6XX_CP_CONTEXT_SWITCH_CNTL, cntl, BIT(1), false);
>> }
>>
>> static int preempt_init_ring(struct a6xx_gpu *a6xx_gpu,
>>
>> --
>> 2.50.1
>>
>
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 07/17] drm/msm/adreno: Add fenced regwrite support
2025-07-22 14:52 ` Konrad Dybcio
@ 2025-07-23 21:06 ` Akhil P Oommen
2025-07-24 11:46 ` Konrad Dybcio
0 siblings, 1 reply; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-23 21:06 UTC (permalink / raw)
To: Konrad Dybcio, Dmitry Baryshkov
Cc: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/22/2025 8:22 PM, Konrad Dybcio wrote:
> On 7/22/25 3:39 PM, Dmitry Baryshkov wrote:
>> On Sun, Jul 20, 2025 at 05:46:08PM +0530, Akhil P Oommen wrote:
>>> There are some special registers which are accessible even when GX power
>>> domain is collapsed during an IFPC sleep. Accessing these registers
>>> wakes up GPU from power collapse and allow programming these registers
>>> without additional handshake with GMU. This patch adds support for this
>>> special register write sequence.
>>>
>>> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
>>> ---
>>> drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 63 ++++++++++++++++++++++++++++++-
>>> drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 1 +
>>> drivers/gpu/drm/msm/adreno/a6xx_preempt.c | 20 +++++-----
>>> 3 files changed, 73 insertions(+), 11 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>>> index 491fde0083a202bec7c6b3bca88d0e5a717a6560..8c004fc3abd2896d467a9728b34e99e4ed944dc4 100644
>>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>>> @@ -16,6 +16,67 @@
>>>
>>> #define GPU_PAS_ID 13
>>>
>>> +static bool fence_status_check(struct msm_gpu *gpu, u32 offset, u32 value, u32 status, u32 mask)
>>> +{
>>> + /* Success if !writedropped0/1 */
>>> + if (!(status & mask))
>>> + return true;
>>> +
>>> + udelay(10);
>>
>> Why do we need udelay() here? Why can't we use interval setting inside
>> gmu_poll_timeout()?
>
> Similarly here:
>
> [...]
>
>>> + if (!gmu_poll_timeout(gmu, REG_A6XX_GMU_AHB_FENCE_STATUS, status,
>>> + fence_status_check(gpu, offset, value, status, mask), 0, 1000))
>>> + return 0;
>>> +
>>> + dev_err_ratelimited(gmu->dev, "delay in fenced register write (0x%x)\n",
>>> + offset);
>>> +
>>> + /* Try again for another 1ms before failing */
>>> + gpu_write(gpu, offset, value);
>>> + if (!gmu_poll_timeout(gmu, REG_A6XX_GMU_AHB_FENCE_STATUS, status,
>>> + fence_status_check(gpu, offset, value, status, mask), 0, 1000))
>>> + return 0;
>>> +
>>> + dev_err_ratelimited(gmu->dev, "fenced register write (0x%x) fail\n",
>>> + offset);
>
> We may want to combine the two, so as not to worry the user too much..
>
> If it's going to fail, I would assume it's going to fail both checks
> (unless e.g. the bus is so congested a single write can't go through
> to a sleepy GPU across 2 miliseconds, but that's another issue)
In case of success, we cannot be sure if the first write went through.
So we should poll separately.
-Akhil.
>
> Konrad
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 08/17] drm/msm/a6xx: Set Keep-alive votes to block IFPC
2025-07-23 10:05 ` Konrad Dybcio
@ 2025-07-23 21:22 ` Akhil P Oommen
2025-07-23 21:53 ` Dmitry Baryshkov
0 siblings, 1 reply; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-23 21:22 UTC (permalink / raw)
To: Konrad Dybcio, Dmitry Baryshkov
Cc: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/23/2025 3:35 PM, Konrad Dybcio wrote:
> On 7/22/25 11:24 PM, Akhil P Oommen wrote:
>> On 7/22/2025 7:14 PM, Dmitry Baryshkov wrote:
>>> On Sun, Jul 20, 2025 at 05:46:09PM +0530, Akhil P Oommen wrote:
>>>> 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>
>>>> ---
>
> [...]
>
>>>> +static void set_keepalive_vote(struct msm_gpu *gpu, bool on)
>>>
>>> a6xx_set_keepalive_vote()
>>
>> static fn! Why do we need prefix here?
>
> It's good practice to namespace-prefix your functions, so that you
> can more easily find them, e.g. in a backtrace.
It would be obvious from the parent functions in the backtrace, right?
A bit subjective! I feel that the prefixes are unnecessary for small
local helper fns. Prefix for *every* single routine in a source file
makes the code look a little bit bloated.
-Akhil.
>
> For a prefix, adreno_gmu_ would be even better, as the register doesn't
> seem to have changed across generations
>
> Konrad
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 11/17] drm/msm: Add support for IFPC
2025-07-23 10:27 ` Konrad Dybcio
@ 2025-07-23 21:43 ` Akhil P Oommen
0 siblings, 0 replies; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-23 21:43 UTC (permalink / raw)
To: Konrad Dybcio, Dmitry Baryshkov
Cc: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/23/2025 3:57 PM, Konrad Dybcio wrote:
> On 7/22/25 11:27 PM, Akhil P Oommen wrote:
>> On 7/22/2025 7:19 PM, Dmitry Baryshkov wrote:
>>> On Sun, Jul 20, 2025 at 05:46:12PM +0530, Akhil P Oommen wrote:
>>>> Add a new quirk to denote IFPC (Inter-Frame Power Collapse) support
>>>> for a gpu. Based on this flag send the feature ctrl hfi message to
>>>> GMU to enable IFPC support.
>>>>
>>>> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
>>>> ---
>
> [...]
>
>>>> +static int a6xx_hfi_enable_ifpc(struct a6xx_gmu *gmu)
>>>> +{
>>>> + if (gmu->idle_level != GMU_IDLE_STATE_IFPC)
>>>> + return 0;
>>>> +
>>>> + return a6xx_hfi_feature_ctrl_msg(gmu, HFI_FEATURE_IFPC, 1, 0x1680);
>>>
>>> magic number?
>>>
>>
>> Let me check.
>
> techpack-graphics/adreno_a6xx_gmu.c:
> 537:#define A6X_GMU_LONG_IFPC_HYST FIELD_PREP(GENMASK(15, 0), 0x1680)
> 541:#define A6X_GMU_LONG_IFPC_HYST_FLOOR FIELD_PREP(GENMASK(15, 0), 0x0F00)
>
> (same value for a7/a8)
>
> 0x0f00 is 3840, which smells oddly like the XO clock rate (possibly mul/div2)
>
> (38.4 MHz or 19.2) / 3840 is (1000 or 500) (ms? us? cycles?) and the other one is
> (333 or 667) - without any further information I'd estimate this is some sort of
> scheduler tuning
Thats right. It is around 300us. Will add the same macro in the next rev.
-Akhil
>
> Konrad
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 12/17] drm/msm: Skip devfreq IDLE when possible
2025-07-22 20:13 ` Rob Clark
@ 2025-07-23 21:46 ` Akhil P Oommen
0 siblings, 0 replies; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-23 21:46 UTC (permalink / raw)
To: rob.clark
Cc: Dmitry Baryshkov, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/23/2025 1:43 AM, Rob Clark wrote:
> On Tue, Jul 22, 2025 at 12:23 PM Akhil P Oommen
> <akhilpo@oss.qualcomm.com> wrote:
>>
>> On 7/22/2025 9:08 PM, Rob Clark wrote:
>>> On Tue, Jul 22, 2025 at 6:50 AM Dmitry Baryshkov
>>> <dmitry.baryshkov@oss.qualcomm.com> wrote:
>>>>
>>>> On Sun, Jul 20, 2025 at 05:46:13PM +0530, Akhil P Oommen wrote:
>>>>> When IFPC is supported, devfreq idling is redundant and adds
>>>>> unnecessary pm suspend/wake latency. So skip it when IFPC is
>>>>> supported.
>>>>
>>>> With this in place we have a dummy devfreq instance which does nothing.
>>>> Wouldn't it be better to skip registering devfreq if IFPC is supported
>>>> on the platform?
>>>
>>> devfreq is still scaling the freq. What is being bypassed is
>>> essentially a CPU based version of IFPC (because on sc7180 we didn't
>>> have IFPC
>>>
>>> Currently only a618 and 7c3 enable gpu_clamp_to_idle.. if at some
>>> point those grew IFPC support we could remove the trickery to drop GPU
>>> to min freq when it is idle altogether.
>>
>> There are 2 functionalities here:
>> 1. Clamp-to-idle: enabled only on a618/7c3
>> 2. boost-after-idle: Enabled for all GPUs.
>>
>> With this patch, we are skipping both when IFPC is supported. In the
>> absence of latency due to clamp-to-idle, do you think a618 (relatively
>> weaker GPU) would require boost-after-idle to keep with the
>> UI/composition workload for its typical configuration (1080p@60hz)? If
>> yes, I should probably create a quirk to disable boost-after-idle for
>> premium tier GPUs, instead of tying it to IFPC feature.
>
> Hmm, yeah.. I suppose _this_ patch should only skip clamp-to-idle. It
> is a different topic, boost-after-idle.
I think we can just drop this patch. Also, Boost-after-idle is not super
bad as it is only doubling the gpu freq. We can try to optimize it
separately.
-Akhil.
>
> BR,
> -R
>
>> -Akhil.
>>
>>>
>>> BR,
>>> -R
>>>
>>>>>
>>>>> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
>>>>> ---
>>>>> drivers/gpu/drm/msm/msm_gpu_devfreq.c | 6 ++++++
>>>>> 1 file changed, 6 insertions(+)
>>>>>
>>>>> diff --git a/drivers/gpu/drm/msm/msm_gpu_devfreq.c b/drivers/gpu/drm/msm/msm_gpu_devfreq.c
>>>>> index 2e1d5c3432728cde15d91f69da22bb915588fe86..53ef2add5047e7d6b6371af949cab36ce8409372 100644
>>>>> --- a/drivers/gpu/drm/msm/msm_gpu_devfreq.c
>>>>> +++ b/drivers/gpu/drm/msm/msm_gpu_devfreq.c
>>>>> @@ -4,6 +4,7 @@
>>>>> * Author: Rob Clark <robdclark@gmail.com>
>>>>> */
>>>>>
>>>>> +#include "adreno/adreno_gpu.h"
>>>>> #include "msm_gpu.h"
>>>>> #include "msm_gpu_trace.h"
>>>>>
>>>>> @@ -300,6 +301,8 @@ void msm_devfreq_active(struct msm_gpu *gpu)
>>>>> if (!has_devfreq(gpu))
>>>>> return;
>>>>>
>>>>> + if (to_adreno_gpu(gpu)->info->quirks & ADRENO_QUIRK_IFPC)
>>>>> + return;
>>>>> /*
>>>>> * Cancel any pending transition to idle frequency:
>>>>> */
>>>>> @@ -370,6 +373,9 @@ void msm_devfreq_idle(struct msm_gpu *gpu)
>>>>> if (!has_devfreq(gpu))
>>>>> return;
>>>>>
>>>>> + if (to_adreno_gpu(gpu)->info->quirks & ADRENO_QUIRK_IFPC)
>>>>> + return;
>>>>> +
>>>>> msm_hrtimer_queue_work(&df->idle_work, ms_to_ktime(1),
>>>>> HRTIMER_MODE_REL);
>>>>> }
>>>>>
>>>>> --
>>>>> 2.50.1
>>>>>
>>>>
>>>> --
>>>> With best wishes
>>>> Dmitry
>>
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 08/17] drm/msm/a6xx: Set Keep-alive votes to block IFPC
2025-07-23 21:22 ` Akhil P Oommen
@ 2025-07-23 21:53 ` Dmitry Baryshkov
0 siblings, 0 replies; 85+ messages in thread
From: Dmitry Baryshkov @ 2025-07-23 21:53 UTC (permalink / raw)
To: Akhil P Oommen
Cc: Konrad Dybcio, Rob Clark, Sean Paul, Konrad Dybcio,
Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Marijn Suijten,
David Airlie, Simona Vetter, linux-arm-msm, dri-devel, freedreno,
linux-kernel
On Thu, Jul 24, 2025 at 02:52:52AM +0530, Akhil P Oommen wrote:
> On 7/23/2025 3:35 PM, Konrad Dybcio wrote:
> > On 7/22/25 11:24 PM, Akhil P Oommen wrote:
> >> On 7/22/2025 7:14 PM, Dmitry Baryshkov wrote:
> >>> On Sun, Jul 20, 2025 at 05:46:09PM +0530, Akhil P Oommen wrote:
> >>>> 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>
> >>>> ---
> >
> > [...]
> >
> >>>> +static void set_keepalive_vote(struct msm_gpu *gpu, bool on)
> >>>
> >>> a6xx_set_keepalive_vote()
> >>
> >> static fn! Why do we need prefix here?
> >
> > It's good practice to namespace-prefix your functions, so that you
> > can more easily find them, e.g. in a backtrace.
>
> It would be obvious from the parent functions in the backtrace, right?
Think about jumping to a tag, etc.
>
> A bit subjective! I feel that the prefixes are unnecessary for small
> local helper fns. Prefix for *every* single routine in a source file
> makes the code look a little bit bloated.
>
> -Akhil.
>
> >
> > For a prefix, adreno_gmu_ would be even better, as the register doesn't
> > seem to have changed across generations
> >
> > Konrad
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 15/17] drm/msm/a6xx: Make crashstate capture IFPC safe
2025-07-23 10:32 ` Konrad Dybcio
@ 2025-07-23 21:53 ` Akhil P Oommen
0 siblings, 0 replies; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-23 21:53 UTC (permalink / raw)
To: Konrad Dybcio, Rob Clark, Sean Paul, Konrad Dybcio,
Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Marijn Suijten,
David Airlie, Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/23/2025 4:02 PM, Konrad Dybcio wrote:
> On 7/20/25 2:16 PM, Akhil P Oommen wrote:
>> Now with IFPC, GX domain can collapse as soon as GPU becomes IDLE. So
>> add gx_is_on check before accessing any GX registers during crashstate
>> capture and recovery.
>>
>> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
>> ---
>
> [...]
>
>> + /*
>> + * This is true only on an A6XX_GEN1 with GMU, has IFPC enabled and a super old SQE firmware
>> + * without 'whereami' support
>> + */
>
> Firmware that old won't even be accepted by the driver, see the slightly
> confusing logic in a6xx_ucode_check_version()
hmm. you are right. In that case, I don't know why we still have the
below bit here:
ring->memptrs->rptr = gpu_read(gpu, REG_A6XX_CP_RB_RPTR);
-Akhil
>
> Konrad
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 16/17] drm/msm/a6xx: Enable IFPC on Adreno X1-85
2025-07-23 10:33 ` Konrad Dybcio
@ 2025-07-23 21:57 ` Akhil P Oommen
0 siblings, 0 replies; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-23 21:57 UTC (permalink / raw)
To: Konrad Dybcio, Dmitry Baryshkov
Cc: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/23/2025 4:03 PM, Konrad Dybcio wrote:
> On 7/22/25 11:37 PM, Akhil P Oommen wrote:
>> On 7/22/2025 7:25 PM, Dmitry Baryshkov wrote:
>>> On Sun, Jul 20, 2025 at 05:46:17PM +0530, Akhil P Oommen wrote:
>>>> Add the IFPC restore register list and enable IFPC support on Adreno
>>>> X1-85 gpu.
>>>
>>> Nit: GPU
>>>
>>> I can't stop but notice that KGSL enables IFPC for a bigger set of
>>> SKUs, starting from a630v2 and a615. Is there a plan to get IFPC
>>> supported on those platforms?
>>
>> Sorry, no access to those hardwares. But I can certainly help if someone
>> wants to do that. :)
>
> Let's get the groundwork merged first ;)
>
> Nowadays you can reasonably assume we have access to at least one board,
> no matter which SoC
We just need to add a proper ifpc restore register list for most
chipsets. But the legacy gmu firmware (a630 derivatives) might have some
quirks.
-Akhil.
>
> Konrad
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 04/17] drm/msm/a6xx: Poll additional DRV status
2025-07-23 19:28 ` Akhil P Oommen
@ 2025-07-24 11:39 ` Konrad Dybcio
0 siblings, 0 replies; 85+ messages in thread
From: Konrad Dybcio @ 2025-07-24 11:39 UTC (permalink / raw)
To: Akhil P Oommen, Rob Clark, Sean Paul, Konrad Dybcio,
Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Marijn Suijten,
David Airlie, Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/23/25 9:28 PM, Akhil P Oommen wrote:
> On 7/23/2025 3:31 PM, Konrad Dybcio wrote:
>> On 7/20/25 2:16 PM, Akhil P Oommen wrote:
>>> A7XX_GEN2 generation has additional TCS slots. Poll the respective
>>> DRV status registers before pm suspend.
>>>
>>> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
>>> ---
>>> drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 16 ++++++++++++++++
>>> 1 file changed, 16 insertions(+)
>>>
>>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
>>> index 790ef2f94a0b0cd40433d7edb6a89e4f04408bf5..3bebb6dd7059782ceca29f2efd2acee24d3fc930 100644
>>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
>>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
>>> @@ -987,6 +987,22 @@ static void a6xx_gmu_rpmh_off(struct a6xx_gmu *gmu)
>>> val, (val & 1), 100, 10000);
>>> gmu_poll_timeout_rscc(gmu, REG_A6XX_RSCC_TCS3_DRV0_STATUS + seqmem_off,
>>> val, (val & 1), 100, 1000);
>
> 1000us here is a typo and I copied the same mistake below. I will update
> all of these timeout values to a common 10000us in the next revision.
>
>>> +
>>> + if (!adreno_is_a740_family(adreno_gpu))
>>> + return;
>>> +
>>> + gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS4_DRV0_STATUS + seqmem_off,
>>> + val, (val & 1), 100, 10000);
>>> + gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS5_DRV0_STATUS + seqmem_off,
>>> + val, (val & 1), 100, 10000);
>>> + gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS6_DRV0_STATUS + seqmem_off,
>>> + val, (val & 1), 100, 10000);
>>> + gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS7_DRV0_STATUS + seqmem_off,
>>> + val, (val & 1), 100, 1000);
>>> + gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS8_DRV0_STATUS + seqmem_off,
>>> + val, (val & 1), 100, 10000);
>>> + gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS9_DRV0_STATUS + seqmem_off,
>>> + val, (val & 1), 100, 1000);
>>
>> FWIW there are places downstream where it polls for 1 ms
>> (gen7_gmu_pwrctrl_suspend) / 2 ms (gen7_gmu_power_off) ms (as opposed
>> to 1 or 10 ms here), but the timeouts are all the same across registers
>> (unlike TCS3 and TCS9 above)
>>
>> Ultimately it's a timeout, so a value too big shouldn't matter, but
>> let's make sure the other threshold is ok
>
> They are fine. We can try to reduce the timeout 2ms in a separate patch
> outside of this series.
Great, thanks for confirming!
Konrad
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 07/17] drm/msm/adreno: Add fenced regwrite support
2025-07-23 21:06 ` Akhil P Oommen
@ 2025-07-24 11:46 ` Konrad Dybcio
2025-07-24 16:54 ` Akhil P Oommen
0 siblings, 1 reply; 85+ messages in thread
From: Konrad Dybcio @ 2025-07-24 11:46 UTC (permalink / raw)
To: Akhil P Oommen, Dmitry Baryshkov
Cc: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/23/25 11:06 PM, Akhil P Oommen wrote:
> On 7/22/2025 8:22 PM, Konrad Dybcio wrote:
>> On 7/22/25 3:39 PM, Dmitry Baryshkov wrote:
>>> On Sun, Jul 20, 2025 at 05:46:08PM +0530, Akhil P Oommen wrote:
>>>> There are some special registers which are accessible even when GX power
>>>> domain is collapsed during an IFPC sleep. Accessing these registers
>>>> wakes up GPU from power collapse and allow programming these registers
>>>> without additional handshake with GMU. This patch adds support for this
>>>> special register write sequence.
>>>>
>>>> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
>>>> ---
>>>> drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 63 ++++++++++++++++++++++++++++++-
>>>> drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 1 +
>>>> drivers/gpu/drm/msm/adreno/a6xx_preempt.c | 20 +++++-----
>>>> 3 files changed, 73 insertions(+), 11 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>>>> index 491fde0083a202bec7c6b3bca88d0e5a717a6560..8c004fc3abd2896d467a9728b34e99e4ed944dc4 100644
>>>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>>>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>>>> @@ -16,6 +16,67 @@
>>>>
>>>> #define GPU_PAS_ID 13
>>>>
>>>> +static bool fence_status_check(struct msm_gpu *gpu, u32 offset, u32 value, u32 status, u32 mask)
>>>> +{
>>>> + /* Success if !writedropped0/1 */
>>>> + if (!(status & mask))
>>>> + return true;
>>>> +
>>>> + udelay(10);
>>>
>>> Why do we need udelay() here? Why can't we use interval setting inside
>>> gmu_poll_timeout()?
>>
>> Similarly here:
>>
>> [...]
>>
>>>> + if (!gmu_poll_timeout(gmu, REG_A6XX_GMU_AHB_FENCE_STATUS, status,
>>>> + fence_status_check(gpu, offset, value, status, mask), 0, 1000))
>>>> + return 0;
>>>> +
>>>> + dev_err_ratelimited(gmu->dev, "delay in fenced register write (0x%x)\n",
>>>> + offset);
>>>> +
>>>> + /* Try again for another 1ms before failing */
>>>> + gpu_write(gpu, offset, value);
>>>> + if (!gmu_poll_timeout(gmu, REG_A6XX_GMU_AHB_FENCE_STATUS, status,
>>>> + fence_status_check(gpu, offset, value, status, mask), 0, 1000))
>>>> + return 0;
>>>> +
>>>> + dev_err_ratelimited(gmu->dev, "fenced register write (0x%x) fail\n",
>>>> + offset);
>>
>> We may want to combine the two, so as not to worry the user too much..
>>
>> If it's going to fail, I would assume it's going to fail both checks
>> (unless e.g. the bus is so congested a single write can't go through
>> to a sleepy GPU across 2 miliseconds, but that's another issue)
>
> In case of success, we cannot be sure if the first write went through.
> So we should poll separately.
You're writing to it 2 (outside fence_status_check) + 2*1000/10 (inside)
== 202 times, it really better go through..
If it's just about the write reaching the GPU, you can write it once and
read back the register you've written to, this way you're sure that the
GPU can observe the write
Konrad
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 07/17] drm/msm/adreno: Add fenced regwrite support
2025-07-24 11:46 ` Konrad Dybcio
@ 2025-07-24 16:54 ` Akhil P Oommen
2025-07-29 13:01 ` Konrad Dybcio
0 siblings, 1 reply; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-24 16:54 UTC (permalink / raw)
To: Konrad Dybcio, Dmitry Baryshkov
Cc: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/24/2025 5:16 PM, Konrad Dybcio wrote:
> On 7/23/25 11:06 PM, Akhil P Oommen wrote:
>> On 7/22/2025 8:22 PM, Konrad Dybcio wrote:
>>> On 7/22/25 3:39 PM, Dmitry Baryshkov wrote:
>>>> On Sun, Jul 20, 2025 at 05:46:08PM +0530, Akhil P Oommen wrote:
>>>>> There are some special registers which are accessible even when GX power
>>>>> domain is collapsed during an IFPC sleep. Accessing these registers
>>>>> wakes up GPU from power collapse and allow programming these registers
>>>>> without additional handshake with GMU. This patch adds support for this
>>>>> special register write sequence.
>>>>>
>>>>> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
>>>>> ---
>>>>> drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 63 ++++++++++++++++++++++++++++++-
>>>>> drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 1 +
>>>>> drivers/gpu/drm/msm/adreno/a6xx_preempt.c | 20 +++++-----
>>>>> 3 files changed, 73 insertions(+), 11 deletions(-)
>>>>>
>>>>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>>>>> index 491fde0083a202bec7c6b3bca88d0e5a717a6560..8c004fc3abd2896d467a9728b34e99e4ed944dc4 100644
>>>>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>>>>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>>>>> @@ -16,6 +16,67 @@
>>>>>
>>>>> #define GPU_PAS_ID 13
>>>>>
>>>>> +static bool fence_status_check(struct msm_gpu *gpu, u32 offset, u32 value, u32 status, u32 mask)
>>>>> +{
>>>>> + /* Success if !writedropped0/1 */
>>>>> + if (!(status & mask))
>>>>> + return true;
>>>>> +
>>>>> + udelay(10);
>>>>
>>>> Why do we need udelay() here? Why can't we use interval setting inside
>>>> gmu_poll_timeout()?
>>>
>>> Similarly here:
>>>
>>> [...]
>>>
>>>>> + if (!gmu_poll_timeout(gmu, REG_A6XX_GMU_AHB_FENCE_STATUS, status,
>>>>> + fence_status_check(gpu, offset, value, status, mask), 0, 1000))
>>>>> + return 0;
>>>>> +
>>>>> + dev_err_ratelimited(gmu->dev, "delay in fenced register write (0x%x)\n",
>>>>> + offset);
>>>>> +
>>>>> + /* Try again for another 1ms before failing */
>>>>> + gpu_write(gpu, offset, value);
>>>>> + if (!gmu_poll_timeout(gmu, REG_A6XX_GMU_AHB_FENCE_STATUS, status,
>>>>> + fence_status_check(gpu, offset, value, status, mask), 0, 1000))
>>>>> + return 0;
>>>>> +
>>>>> + dev_err_ratelimited(gmu->dev, "fenced register write (0x%x) fail\n",
>>>>> + offset);
>>>
>>> We may want to combine the two, so as not to worry the user too much..
>>>
>>> If it's going to fail, I would assume it's going to fail both checks
>>> (unless e.g. the bus is so congested a single write can't go through
>>> to a sleepy GPU across 2 miliseconds, but that's another issue)
>>
>> In case of success, we cannot be sure if the first write went through.
>> So we should poll separately.
>
> You're writing to it 2 (outside fence_status_check) + 2*1000/10 (inside)
> == 202 times, it really better go through..
For the following sequence:
1. write reg1 <- suppose this is dropped
2. write reg2 <- and this went through
3. Check fence status <- This will show success
>
> If it's just about the write reaching the GPU, you can write it once and
> read back the register you've written to, this way you're sure that the
> GPU can observe the write
This is a very unique hw behavior. We can't do posted write.
-Akhil
>
> Konrad
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 17/17] drm/msm/adreno: Relax devfreq tunings
2025-07-20 12:16 ` [PATCH 17/17] drm/msm/adreno: Relax devfreq tunings Akhil P Oommen
@ 2025-07-27 0:49 ` Anthony Ruhier
0 siblings, 0 replies; 85+ messages in thread
From: Anthony Ruhier @ 2025-07-27 0:49 UTC (permalink / raw)
To: Akhil P Oommen
Cc: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, linux-arm-msm, dri-devel, freedreno, linux-kernel
Tested-by: Anthony Ruhier <aruhier@mailbox.org>
Thanks for this patch series! I tested in on the Yoga Slim 7x, it works well on
my setup beside this specific patch. On Hyprland, it makes the animations
stuttery (in particular workspace changes, which are by default similar to
Gnome's).
Dropping this patch fixes this problem.
Thanks,
--
Anthony Ruhier
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 07/17] drm/msm/adreno: Add fenced regwrite support
2025-07-24 16:54 ` Akhil P Oommen
@ 2025-07-29 13:01 ` Konrad Dybcio
2025-07-29 21:40 ` Akhil P Oommen
0 siblings, 1 reply; 85+ messages in thread
From: Konrad Dybcio @ 2025-07-29 13:01 UTC (permalink / raw)
To: Akhil P Oommen, Dmitry Baryshkov
Cc: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/24/25 6:54 PM, Akhil P Oommen wrote:
> On 7/24/2025 5:16 PM, Konrad Dybcio wrote:
>> On 7/23/25 11:06 PM, Akhil P Oommen wrote:
>>> On 7/22/2025 8:22 PM, Konrad Dybcio wrote:
>>>> On 7/22/25 3:39 PM, Dmitry Baryshkov wrote:
>>>>> On Sun, Jul 20, 2025 at 05:46:08PM +0530, Akhil P Oommen wrote:
>>>>>> There are some special registers which are accessible even when GX power
>>>>>> domain is collapsed during an IFPC sleep. Accessing these registers
>>>>>> wakes up GPU from power collapse and allow programming these registers
>>>>>> without additional handshake with GMU. This patch adds support for this
>>>>>> special register write sequence.
>>>>>>
>>>>>> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
>>>>>> ---
>>>>>> drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 63 ++++++++++++++++++++++++++++++-
>>>>>> drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 1 +
>>>>>> drivers/gpu/drm/msm/adreno/a6xx_preempt.c | 20 +++++-----
>>>>>> 3 files changed, 73 insertions(+), 11 deletions(-)
>>>>>>
>>>>>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>>>>>> index 491fde0083a202bec7c6b3bca88d0e5a717a6560..8c004fc3abd2896d467a9728b34e99e4ed944dc4 100644
>>>>>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>>>>>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>>>>>> @@ -16,6 +16,67 @@
>>>>>>
>>>>>> #define GPU_PAS_ID 13
>>>>>>
>>>>>> +static bool fence_status_check(struct msm_gpu *gpu, u32 offset, u32 value, u32 status, u32 mask)
>>>>>> +{
>>>>>> + /* Success if !writedropped0/1 */
>>>>>> + if (!(status & mask))
>>>>>> + return true;
>>>>>> +
>>>>>> + udelay(10);
>>>>>
>>>>> Why do we need udelay() here? Why can't we use interval setting inside
>>>>> gmu_poll_timeout()?
>>>>
>>>> Similarly here:
>>>>
>>>> [...]
>>>>
>>>>>> + if (!gmu_poll_timeout(gmu, REG_A6XX_GMU_AHB_FENCE_STATUS, status,
>>>>>> + fence_status_check(gpu, offset, value, status, mask), 0, 1000))
>>>>>> + return 0;
>>>>>> +
>>>>>> + dev_err_ratelimited(gmu->dev, "delay in fenced register write (0x%x)\n",
>>>>>> + offset);
>>>>>> +
>>>>>> + /* Try again for another 1ms before failing */
>>>>>> + gpu_write(gpu, offset, value);
>>>>>> + if (!gmu_poll_timeout(gmu, REG_A6XX_GMU_AHB_FENCE_STATUS, status,
>>>>>> + fence_status_check(gpu, offset, value, status, mask), 0, 1000))
>>>>>> + return 0;
>>>>>> +
>>>>>> + dev_err_ratelimited(gmu->dev, "fenced register write (0x%x) fail\n",
>>>>>> + offset);
>>>>
>>>> We may want to combine the two, so as not to worry the user too much..
>>>>
>>>> If it's going to fail, I would assume it's going to fail both checks
>>>> (unless e.g. the bus is so congested a single write can't go through
>>>> to a sleepy GPU across 2 miliseconds, but that's another issue)
>>>
>>> In case of success, we cannot be sure if the first write went through.
>>> So we should poll separately.
>>
>> You're writing to it 2 (outside fence_status_check) + 2*1000/10 (inside)
>> == 202 times, it really better go through..
>
> For the following sequence:
> 1. write reg1 <- suppose this is dropped
> 2. write reg2 <- and this went through
> 3. Check fence status <- This will show success
What I'm saying is that fence_status_check() does the same write you
execute inbetween the polling calls
Konrad
>
>>
>> If it's just about the write reaching the GPU, you can write it once and
>> read back the register you've written to, this way you're sure that the
>> GPU can observe the write
>
> This is a very unique hw behavior. We can't do posted write.
>
> -Akhil
>
>>
>> Konrad
>
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 09/17] drm/msm/a6xx: Switch to GMU AO counter
2025-07-23 12:15 ` Rob Clark
@ 2025-07-29 13:30 ` Konrad Dybcio
0 siblings, 0 replies; 85+ messages in thread
From: Konrad Dybcio @ 2025-07-29 13:30 UTC (permalink / raw)
To: rob.clark
Cc: Akhil P Oommen, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/23/25 2:15 PM, Rob Clark wrote:
> On Wed, Jul 23, 2025 at 3:19 AM Konrad Dybcio
> <konrad.dybcio@oss.qualcomm.com> wrote:
>>
>> On 7/20/25 2:16 PM, Akhil P Oommen wrote:
>>> CP_ALWAYS_ON counter falls under GX domain which is collapsed during
>>> IFPC. So switch to GMU_ALWAYS_ON counter for any CPU reads since it is
>>> not impacted by IFPC. Both counters are clocked by same xo clock source.
>>>
>>> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
>>> ---
>>> drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 30 ++++++++++++++++--------------
>>> 1 file changed, 16 insertions(+), 14 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>>> index 6770f0363e7284e4596b1188637a4615d2c0779b..f000915a4c2698a85b45bd3c92e590f14999d10d 100644
>>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>>> @@ -16,6 +16,19 @@
>>>
>>> #define GPU_PAS_ID 13
>>>
>>> +static u64 read_gmu_ao_counter(struct a6xx_gpu *a6xx_gpu)
>>> +{
>>> + u64 count_hi, count_lo, temp;
>>> +
>>> + do {
>>> + count_hi = gmu_read(&a6xx_gpu->gmu, REG_A6XX_GMU_ALWAYS_ON_COUNTER_H);
>>> + count_lo = gmu_read(&a6xx_gpu->gmu, REG_A6XX_GMU_ALWAYS_ON_COUNTER_L);
>>> + temp = gmu_read(&a6xx_gpu->gmu, REG_A6XX_GMU_ALWAYS_ON_COUNTER_H);
>>> + } while (count_hi != temp);
>>
>> The original logic is as follows:
>>
>> static u64 gen7_read_alwayson(struct adreno_device *adreno_dev)
>> {
>> struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
>> u32 lo = 0, hi = 0, tmp = 0;
>>
>> /* Always use the GMU AO counter when doing a AHB read */
>> gmu_core_regread(device, GEN7_GMU_ALWAYS_ON_COUNTER_H, &hi);
>> gmu_core_regread(device, GEN7_GMU_ALWAYS_ON_COUNTER_L, &lo);
>>
>> /* Check for overflow */
>> gmu_core_regread(device, GEN7_GMU_ALWAYS_ON_COUNTER_H, &tmp);
>>
>> if (hi != tmp) {
>> gmu_core_regread(device, GEN7_GMU_ALWAYS_ON_COUNTER_L,
>> &lo);
>> hi = tmp;
>> }
>>
>> return (((u64) hi) << 32) | lo;
>> }
>>
>> Doing this in a while-loop almost looks like you want a lot of time to
>> pass - REG_WIDTH(u32?)/19.2 MHz
>
> would:
>
> } while (unlikely(count_hi != temp));
>
> make it more clear?
I guess so
Konrad
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 16/17] drm/msm/a6xx: Enable IFPC on Adreno X1-85
2025-07-20 12:16 ` [PATCH 16/17] drm/msm/a6xx: Enable IFPC on Adreno X1-85 Akhil P Oommen
2025-07-22 13:55 ` Dmitry Baryshkov
2025-07-22 14:55 ` Konrad Dybcio
@ 2025-07-29 14:06 ` neil.armstrong
2025-07-29 18:19 ` Akhil P Oommen
2 siblings, 1 reply; 85+ messages in thread
From: neil.armstrong @ 2025-07-29 14:06 UTC (permalink / raw)
To: Akhil P Oommen, Rob Clark, Sean Paul, Konrad Dybcio,
Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Marijn Suijten,
David Airlie, Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel
On 20/07/2025 14:16, Akhil P Oommen wrote:
> Add the IFPC restore register list and enable IFPC support on Adreno
> X1-85 gpu.
>
> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
> ---
> drivers/gpu/drm/msm/adreno/a6xx_catalog.c | 67 ++++++++++++++++++++++++++++++-
> drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 15 +++++--
> drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 1 +
> 3 files changed, 78 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
> index 70f7ad806c34076352d84f32d62c2833422b6e5e..07fcabed472c3b9ca47faf1a8b3f7cf580801981 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
> @@ -1343,6 +1343,69 @@ static const uint32_t a7xx_pwrup_reglist_regs[] = {
>
<snip>
> +
> static const struct adreno_info a7xx_gpus[] = {
> {
> .chip_ids = ADRENO_CHIP_IDS(0x07000200),
> @@ -1432,12 +1495,13 @@ static const struct adreno_info a7xx_gpus[] = {
> .inactive_period = DRM_MSM_INACTIVE_PERIOD,
> .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
> ADRENO_QUIRK_HAS_HW_APRIV |
> - ADRENO_QUIRK_PREEMPTION,
> + ADRENO_QUIRK_PREEMPTION | ADRENO_QUIRK_IFPC,
> .init = a6xx_gpu_init,
> .a6xx = &(const struct a6xx_info) {
> .hwcg = a740_hwcg,
> .protect = &a730_protect,
> .pwrup_reglist = &a7xx_pwrup_reglist,
> + .ifpc_reglist = &a750_ifpc_reglist,
> .gmu_chipid = 0x7050001,
> .gmu_cgc_mode = 0x00020202,
> },
> @@ -1459,6 +1523,7 @@ static const struct adreno_info a7xx_gpus[] = {
> .a6xx = &(const struct a6xx_info) {
> .protect = &a730_protect,
> .pwrup_reglist = &a7xx_pwrup_reglist,
> + .ifpc_reglist = &a750_ifpc_reglist,
So far it's stable on a750 so I think can safely add ADRENO_QUIRK_IFPC here aswell.
Neil
<snip>
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 16/17] drm/msm/a6xx: Enable IFPC on Adreno X1-85
2025-07-29 14:06 ` neil.armstrong
@ 2025-07-29 18:19 ` Akhil P Oommen
0 siblings, 0 replies; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-29 18:19 UTC (permalink / raw)
To: Neil Armstrong, Rob Clark, Sean Paul, Konrad Dybcio,
Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Marijn Suijten,
David Airlie, Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/29/2025 7:36 PM, neil.armstrong@linaro.org wrote:
> On 20/07/2025 14:16, Akhil P Oommen wrote:
>> Add the IFPC restore register list and enable IFPC support on Adreno
>> X1-85 gpu.
>>
>> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
>> ---
>> drivers/gpu/drm/msm/adreno/a6xx_catalog.c | 67 +++++++++++++++++++++
>> +++++++++-
>> drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 15 +++++--
>> drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 1 +
>> 3 files changed, 78 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c b/drivers/gpu/
>> drm/msm/adreno/a6xx_catalog.c
>> index
>> 70f7ad806c34076352d84f32d62c2833422b6e5e..07fcabed472c3b9ca47faf1a8b3f7cf580801981 100644
>> --- a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
>> @@ -1343,6 +1343,69 @@ static const uint32_t a7xx_pwrup_reglist_regs[]
>> = {
>>
>
> <snip>
>
>> +
>> static const struct adreno_info a7xx_gpus[] = {
>> {
>> .chip_ids = ADRENO_CHIP_IDS(0x07000200),
>> @@ -1432,12 +1495,13 @@ static const struct adreno_info a7xx_gpus[] = {
>> .inactive_period = DRM_MSM_INACTIVE_PERIOD,
>> .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
>> ADRENO_QUIRK_HAS_HW_APRIV |
>> - ADRENO_QUIRK_PREEMPTION,
>> + ADRENO_QUIRK_PREEMPTION | ADRENO_QUIRK_IFPC,
>> .init = a6xx_gpu_init,
>> .a6xx = &(const struct a6xx_info) {
>> .hwcg = a740_hwcg,
>> .protect = &a730_protect,
>> .pwrup_reglist = &a7xx_pwrup_reglist,
>> + .ifpc_reglist = &a750_ifpc_reglist,
>> .gmu_chipid = 0x7050001,
>> .gmu_cgc_mode = 0x00020202,
>> },
>> @@ -1459,6 +1523,7 @@ static const struct adreno_info a7xx_gpus[] = {
>> .a6xx = &(const struct a6xx_info) {
>> .protect = &a730_protect,
>> .pwrup_reglist = &a7xx_pwrup_reglist,
>> + .ifpc_reglist = &a750_ifpc_reglist,
>
> So far it's stable on a750 so I think can safely add ADRENO_QUIRK_IFPC
> here aswell.
Thanks for testing. I will enable it for a750 in the next revision.
-Akhil
>
> Neil
>
> <snip>
>
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 07/17] drm/msm/adreno: Add fenced regwrite support
2025-07-29 13:01 ` Konrad Dybcio
@ 2025-07-29 21:40 ` Akhil P Oommen
2025-07-29 21:49 ` Akhil P Oommen
0 siblings, 1 reply; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-29 21:40 UTC (permalink / raw)
To: Konrad Dybcio, Dmitry Baryshkov
Cc: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/29/2025 6:31 PM, Konrad Dybcio wrote:
> On 7/24/25 6:54 PM, Akhil P Oommen wrote:
>> On 7/24/2025 5:16 PM, Konrad Dybcio wrote:
>>> On 7/23/25 11:06 PM, Akhil P Oommen wrote:
>>>> On 7/22/2025 8:22 PM, Konrad Dybcio wrote:
>>>>> On 7/22/25 3:39 PM, Dmitry Baryshkov wrote:
>>>>>> On Sun, Jul 20, 2025 at 05:46:08PM +0530, Akhil P Oommen wrote:
>>>>>>> There are some special registers which are accessible even when GX power
>>>>>>> domain is collapsed during an IFPC sleep. Accessing these registers
>>>>>>> wakes up GPU from power collapse and allow programming these registers
>>>>>>> without additional handshake with GMU. This patch adds support for this
>>>>>>> special register write sequence.
>>>>>>>
>>>>>>> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
>>>>>>> ---
>>>>>>> drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 63 ++++++++++++++++++++++++++++++-
>>>>>>> drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 1 +
>>>>>>> drivers/gpu/drm/msm/adreno/a6xx_preempt.c | 20 +++++-----
>>>>>>> 3 files changed, 73 insertions(+), 11 deletions(-)
>>>>>>>
>>>>>>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>>>>>>> index 491fde0083a202bec7c6b3bca88d0e5a717a6560..8c004fc3abd2896d467a9728b34e99e4ed944dc4 100644
>>>>>>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>>>>>>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>>>>>>> @@ -16,6 +16,67 @@
>>>>>>>
>>>>>>> #define GPU_PAS_ID 13
>>>>>>>
>>>>>>> +static bool fence_status_check(struct msm_gpu *gpu, u32 offset, u32 value, u32 status, u32 mask)
>>>>>>> +{
>>>>>>> + /* Success if !writedropped0/1 */
>>>>>>> + if (!(status & mask))
>>>>>>> + return true;
>>>>>>> +
>>>>>>> + udelay(10);
>>>>>>
>>>>>> Why do we need udelay() here? Why can't we use interval setting inside
>>>>>> gmu_poll_timeout()?
>>>>>
>>>>> Similarly here:
>>>>>
>>>>> [...]
>>>>>
>>>>>>> + if (!gmu_poll_timeout(gmu, REG_A6XX_GMU_AHB_FENCE_STATUS, status,
>>>>>>> + fence_status_check(gpu, offset, value, status, mask), 0, 1000))
>>>>>>> + return 0;
>>>>>>> +
>>>>>>> + dev_err_ratelimited(gmu->dev, "delay in fenced register write (0x%x)\n",
>>>>>>> + offset);
This print should be after the 2nd polling. Otherwise the delay due to
this may allow GPU to go back to IFPC.
>>>>>>> +
>>>>>>> + /* Try again for another 1ms before failing */
>>>>>>> + gpu_write(gpu, offset, value);
>>>>>>> + if (!gmu_poll_timeout(gmu, REG_A6XX_GMU_AHB_FENCE_STATUS, status,
>>>>>>> + fence_status_check(gpu, offset, value, status, mask), 0, 1000))
>>>>>>> + return 0;
>>>>>>> +
>>>>>>> + dev_err_ratelimited(gmu->dev, "fenced register write (0x%x) fail\n",
>>>>>>> + offset);
>>>>>
>>>>> We may want to combine the two, so as not to worry the user too much..
>>>>>
>>>>> If it's going to fail, I would assume it's going to fail both checks
>>>>> (unless e.g. the bus is so congested a single write can't go through
>>>>> to a sleepy GPU across 2 miliseconds, but that's another issue)
>>>>
>>>> In case of success, we cannot be sure if the first write went through.
>>>> So we should poll separately.
>>>
>>> You're writing to it 2 (outside fence_status_check) + 2*1000/10 (inside)
>>> == 202 times, it really better go through..
>>
>> For the following sequence:
>> 1. write reg1 <- suppose this is dropped
>> 2. write reg2 <- and this went through
>> 3. Check fence status <- This will show success
>
> What I'm saying is that fence_status_check() does the same write you
> execute inbetween the polling calls
On a second thought I think it is simpler to just use a single polling
of 2ms and measure the time taken using ktime to print a warning if it
took more that 1ms.
-Akhil.
>
> Konrad
>>
>>>
>>> If it's just about the write reaching the GPU, you can write it once and
>>> read back the register you've written to, this way you're sure that the
>>> GPU can observe the write
>>
>> This is a very unique hw behavior. We can't do posted write.
>>
>> -Akhil
>>
>>>
>>> Konrad
>>
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 07/17] drm/msm/adreno: Add fenced regwrite support
2025-07-29 21:40 ` Akhil P Oommen
@ 2025-07-29 21:49 ` Akhil P Oommen
2025-07-30 7:49 ` Konrad Dybcio
0 siblings, 1 reply; 85+ messages in thread
From: Akhil P Oommen @ 2025-07-29 21:49 UTC (permalink / raw)
To: Konrad Dybcio, Dmitry Baryshkov
Cc: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/30/2025 3:10 AM, Akhil P Oommen wrote:
> On 7/29/2025 6:31 PM, Konrad Dybcio wrote:
>> On 7/24/25 6:54 PM, Akhil P Oommen wrote:
>>> On 7/24/2025 5:16 PM, Konrad Dybcio wrote:
>>>> On 7/23/25 11:06 PM, Akhil P Oommen wrote:
>>>>> On 7/22/2025 8:22 PM, Konrad Dybcio wrote:
>>>>>> On 7/22/25 3:39 PM, Dmitry Baryshkov wrote:
>>>>>>> On Sun, Jul 20, 2025 at 05:46:08PM +0530, Akhil P Oommen wrote:
>>>>>>>> There are some special registers which are accessible even when GX power
>>>>>>>> domain is collapsed during an IFPC sleep. Accessing these registers
>>>>>>>> wakes up GPU from power collapse and allow programming these registers
>>>>>>>> without additional handshake with GMU. This patch adds support for this
>>>>>>>> special register write sequence.
>>>>>>>>
>>>>>>>> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
>>>>>>>> ---
>>>>>>>> drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 63 ++++++++++++++++++++++++++++++-
>>>>>>>> drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 1 +
>>>>>>>> drivers/gpu/drm/msm/adreno/a6xx_preempt.c | 20 +++++-----
>>>>>>>> 3 files changed, 73 insertions(+), 11 deletions(-)
>>>>>>>>
>>>>>>>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>>>>>>>> index 491fde0083a202bec7c6b3bca88d0e5a717a6560..8c004fc3abd2896d467a9728b34e99e4ed944dc4 100644
>>>>>>>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>>>>>>>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>>>>>>>> @@ -16,6 +16,67 @@
>>>>>>>>
>>>>>>>> #define GPU_PAS_ID 13
>>>>>>>>
>>>>>>>> +static bool fence_status_check(struct msm_gpu *gpu, u32 offset, u32 value, u32 status, u32 mask)
>>>>>>>> +{
>>>>>>>> + /* Success if !writedropped0/1 */
>>>>>>>> + if (!(status & mask))
>>>>>>>> + return true;
>>>>>>>> +
>>>>>>>> + udelay(10);
>>>>>>>
>>>>>>> Why do we need udelay() here? Why can't we use interval setting inside
>>>>>>> gmu_poll_timeout()?
>>>>>>
>>>>>> Similarly here:
>>>>>>
>>>>>> [...]
>>>>>>
>>>>>>>> + if (!gmu_poll_timeout(gmu, REG_A6XX_GMU_AHB_FENCE_STATUS, status,
>>>>>>>> + fence_status_check(gpu, offset, value, status, mask), 0, 1000))
>>>>>>>> + return 0;
>>>>>>>> +
>>>>>>>> + dev_err_ratelimited(gmu->dev, "delay in fenced register write (0x%x)\n",
>>>>>>>> + offset);
>
> This print should be after the 2nd polling. Otherwise the delay due to
> this may allow GPU to go back to IFPC.
>
>>>>>>>> +
>>>>>>>> + /* Try again for another 1ms before failing */
>>>>>>>> + gpu_write(gpu, offset, value);
>>>>>>>> + if (!gmu_poll_timeout(gmu, REG_A6XX_GMU_AHB_FENCE_STATUS, status,
>>>>>>>> + fence_status_check(gpu, offset, value, status, mask), 0, 1000))
>>>>>>>> + return 0;
>>>>>>>> +
>>>>>>>> + dev_err_ratelimited(gmu->dev, "fenced register write (0x%x) fail\n",
>>>>>>>> + offset);
>>>>>>
>>>>>> We may want to combine the two, so as not to worry the user too much..
>>>>>>
>>>>>> If it's going to fail, I would assume it's going to fail both checks
>>>>>> (unless e.g. the bus is so congested a single write can't go through
>>>>>> to a sleepy GPU across 2 miliseconds, but that's another issue)
>>>>>
>>>>> In case of success, we cannot be sure if the first write went through.
>>>>> So we should poll separately.
>>>>
>>>> You're writing to it 2 (outside fence_status_check) + 2*1000/10 (inside)
>>>> == 202 times, it really better go through..
>>>
>>> For the following sequence:
>>> 1. write reg1 <- suppose this is dropped
>>> 2. write reg2 <- and this went through
>>> 3. Check fence status <- This will show success
>>
>> What I'm saying is that fence_status_check() does the same write you
>> execute inbetween the polling calls
>
> On a second thought I think it is simpler to just use a single polling
> of 2ms and measure the time taken using ktime to print a warning if it
> took more that 1ms.
But then we can't know if the higher latency measured is because this
thread got scheduled out just before we measure with ktime 2nd time. So
we should rely on gmu_poll_timeout() for accuracy.
We need a warn after 1ms because there is a 1ms timeout in VRM. We
should know if it occurs frequently enough to cause a performance issue.
I will move the the prints towards fn exit.
-Akhil.
>
> -Akhil.
>
>>
>> Konrad
>>>
>>>>
>>>> If it's just about the write reaching the GPU, you can write it once and
>>>> read back the register you've written to, this way you're sure that the
>>>> GPU can observe the write
>>>
>>> This is a very unique hw behavior. We can't do posted write.
>>>
>>> -Akhil
>>>
>>>>
>>>> Konrad
>>>
>
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 07/17] drm/msm/adreno: Add fenced regwrite support
2025-07-29 21:49 ` Akhil P Oommen
@ 2025-07-30 7:49 ` Konrad Dybcio
0 siblings, 0 replies; 85+ messages in thread
From: Konrad Dybcio @ 2025-07-30 7:49 UTC (permalink / raw)
To: Akhil P Oommen, Dmitry Baryshkov
Cc: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/29/25 11:49 PM, Akhil P Oommen wrote:
> On 7/30/2025 3:10 AM, Akhil P Oommen wrote:
>> On 7/29/2025 6:31 PM, Konrad Dybcio wrote:
>>> On 7/24/25 6:54 PM, Akhil P Oommen wrote:
>>>> On 7/24/2025 5:16 PM, Konrad Dybcio wrote:
>>>>> On 7/23/25 11:06 PM, Akhil P Oommen wrote:
>>>>>> On 7/22/2025 8:22 PM, Konrad Dybcio wrote:
>>>>>>> On 7/22/25 3:39 PM, Dmitry Baryshkov wrote:
>>>>>>>> On Sun, Jul 20, 2025 at 05:46:08PM +0530, Akhil P Oommen wrote:
>>>>>>>>> There are some special registers which are accessible even when GX power
>>>>>>>>> domain is collapsed during an IFPC sleep. Accessing these registers
>>>>>>>>> wakes up GPU from power collapse and allow programming these registers
>>>>>>>>> without additional handshake with GMU. This patch adds support for this
>>>>>>>>> special register write sequence.
>>>>>>>>>
>>>>>>>>> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
>>>>>>>>> ---
>>>>>>>>> drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 63 ++++++++++++++++++++++++++++++-
>>>>>>>>> drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 1 +
>>>>>>>>> drivers/gpu/drm/msm/adreno/a6xx_preempt.c | 20 +++++-----
>>>>>>>>> 3 files changed, 73 insertions(+), 11 deletions(-)
>>>>>>>>>
>>>>>>>>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>>>>>>>>> index 491fde0083a202bec7c6b3bca88d0e5a717a6560..8c004fc3abd2896d467a9728b34e99e4ed944dc4 100644
>>>>>>>>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>>>>>>>>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>>>>>>>>> @@ -16,6 +16,67 @@
>>>>>>>>>
>>>>>>>>> #define GPU_PAS_ID 13
>>>>>>>>>
>>>>>>>>> +static bool fence_status_check(struct msm_gpu *gpu, u32 offset, u32 value, u32 status, u32 mask)
>>>>>>>>> +{
>>>>>>>>> + /* Success if !writedropped0/1 */
>>>>>>>>> + if (!(status & mask))
>>>>>>>>> + return true;
>>>>>>>>> +
>>>>>>>>> + udelay(10);
>>>>>>>>
>>>>>>>> Why do we need udelay() here? Why can't we use interval setting inside
>>>>>>>> gmu_poll_timeout()?
>>>>>>>
>>>>>>> Similarly here:
>>>>>>>
>>>>>>> [...]
>>>>>>>
>>>>>>>>> + if (!gmu_poll_timeout(gmu, REG_A6XX_GMU_AHB_FENCE_STATUS, status,
>>>>>>>>> + fence_status_check(gpu, offset, value, status, mask), 0, 1000))
>>>>>>>>> + return 0;
>>>>>>>>> +
>>>>>>>>> + dev_err_ratelimited(gmu->dev, "delay in fenced register write (0x%x)\n",
>>>>>>>>> + offset);
>>
>> This print should be after the 2nd polling. Otherwise the delay due to
>> this may allow GPU to go back to IFPC.
>>
>>>>>>>>> +
>>>>>>>>> + /* Try again for another 1ms before failing */
>>>>>>>>> + gpu_write(gpu, offset, value);
>>>>>>>>> + if (!gmu_poll_timeout(gmu, REG_A6XX_GMU_AHB_FENCE_STATUS, status,
>>>>>>>>> + fence_status_check(gpu, offset, value, status, mask), 0, 1000))
>>>>>>>>> + return 0;
>>>>>>>>> +
>>>>>>>>> + dev_err_ratelimited(gmu->dev, "fenced register write (0x%x) fail\n",
>>>>>>>>> + offset);
>>>>>>>
>>>>>>> We may want to combine the two, so as not to worry the user too much..
>>>>>>>
>>>>>>> If it's going to fail, I would assume it's going to fail both checks
>>>>>>> (unless e.g. the bus is so congested a single write can't go through
>>>>>>> to a sleepy GPU across 2 miliseconds, but that's another issue)
>>>>>>
>>>>>> In case of success, we cannot be sure if the first write went through.
>>>>>> So we should poll separately.
>>>>>
>>>>> You're writing to it 2 (outside fence_status_check) + 2*1000/10 (inside)
>>>>> == 202 times, it really better go through..
>>>>
>>>> For the following sequence:
>>>> 1. write reg1 <- suppose this is dropped
>>>> 2. write reg2 <- and this went through
>>>> 3. Check fence status <- This will show success
>>>
>>> What I'm saying is that fence_status_check() does the same write you
>>> execute inbetween the polling calls
>>
>> On a second thought I think it is simpler to just use a single polling
>> of 2ms and measure the time taken using ktime to print a warning if it
>> took more that 1ms.
>
> But then we can't know if the higher latency measured is because this
> thread got scheduled out just before we measure with ktime 2nd time. So
> we should rely on gmu_poll_timeout() for accuracy.
>
> We need a warn after 1ms because there is a 1ms timeout in VRM. We
> should know if it occurs frequently enough to cause a performance issue.
VRM, as in the RPMh component?
Please provide more context on how it's tied together in the commit
message, it'll be useful for people down the line (I'd assume accessing
these special registers invokes some handler that brings GX back up
momentarily, which is why we're polling in the first place?)
Konrad
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 05/17] drm/msm/a6xx: Fix PDC sleep sequence
2025-07-20 12:16 ` [PATCH 05/17] drm/msm/a6xx: Fix PDC sleep sequence Akhil P Oommen
2025-07-22 13:33 ` Dmitry Baryshkov
@ 2025-08-07 13:51 ` Konrad Dybcio
2025-08-08 17:22 ` Akhil P Oommen
1 sibling, 1 reply; 85+ messages in thread
From: Konrad Dybcio @ 2025-08-07 13:51 UTC (permalink / raw)
To: Akhil P Oommen, Rob Clark, Sean Paul, Konrad Dybcio,
Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Marijn Suijten,
David Airlie, Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/20/25 2:16 PM, Akhil P Oommen wrote:
> 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.
>
> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
> ---
FWIW some time ago I made this patch, which tackles a similar issue,
perhaps it's a good idea to merge both:
From 7d6441fc6ec5ee7fe723e1ad86d11fdd17bee922 Mon Sep 17 00:00:00 2001
From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Date: Thu, 20 Feb 2025 10:28:51 +0100
Subject: [PATCH] drm/msm/adreno: Delay the Adreno RPMh startup to HFI init
There's no use in trying to power up the GX logic before we're almost
ready to fire up the GPU. In fact, with A8xx the PDC and RSC uCode are
loaded by the GMU firmware, so we *must* wait for the GMU to fully
initialize before trying to do so.
Move it to right before HFI init.
Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
---
drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 12 ++----------
drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 1 +
drivers/gpu/drm/msm/adreno/a6xx_hfi.c | 2 +-
3 files changed, 4 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index 28e6705c6da6..3335583ada45 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -513,7 +513,7 @@ static int a6xx_gmu_notify_slumber(struct a6xx_gmu *gmu)
return ret;
}
-static int a6xx_rpmh_start(struct a6xx_gmu *gmu)
+int a6xx_rpmh_start(struct a6xx_gmu *gmu)
{
int ret;
u32 val;
@@ -842,19 +842,11 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state)
else
gmu_write(gmu, REG_A6XX_GMU_GENERAL_7, 1);
- if (state == GMU_WARM_BOOT) {
- ret = a6xx_rpmh_start(gmu);
- if (ret)
- return ret;
- } else {
+ if (state == GMU_COLD_BOOT) {
if (WARN(!adreno_gpu->fw[ADRENO_FW_GMU],
"GMU firmware is not loaded\n"))
return -ENOENT;
- ret = a6xx_rpmh_start(gmu);
- if (ret)
- return ret;
-
ret = a6xx_gmu_fw_load(gmu);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
index d1ce11131ba6..309305298a45 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
@@ -216,5 +216,6 @@ bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu);
bool a6xx_gmu_sptprac_is_on(struct a6xx_gmu *gmu);
void a6xx_sptprac_disable(struct a6xx_gmu *gmu);
int a6xx_sptprac_enable(struct a6xx_gmu *gmu);
+int a6xx_rpmh_start(struct a6xx_gmu *gmu);
#endif
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
index 8e69b1e84657..9ea01daf2995 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
@@ -910,7 +910,7 @@ int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state)
if (ret)
return ret;
- return 0;
+ return a6xx_rpmh_start(gmu);
}
void a6xx_hfi_stop(struct a6xx_gmu *gmu)
--
2.50.1
Konrad
^ permalink raw reply related [flat|nested] 85+ messages in thread
* Re: [PATCH 05/17] drm/msm/a6xx: Fix PDC sleep sequence
2025-08-07 13:51 ` Konrad Dybcio
@ 2025-08-08 17:22 ` Akhil P Oommen
2025-08-11 8:40 ` Konrad Dybcio
0 siblings, 1 reply; 85+ messages in thread
From: Akhil P Oommen @ 2025-08-08 17:22 UTC (permalink / raw)
To: Konrad Dybcio, Rob Clark, Sean Paul, Konrad Dybcio,
Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Marijn Suijten,
David Airlie, Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel
On 8/7/2025 7:21 PM, Konrad Dybcio wrote:
> On 7/20/25 2:16 PM, Akhil P Oommen wrote:
>> 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.
>>
>> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
>> ---
>
> FWIW some time ago I made this patch, which tackles a similar issue,
> perhaps it's a good idea to merge both:
>
> From 7d6441fc6ec5ee7fe723e1ad86d11fdd17bee922 Mon Sep 17 00:00:00 2001
> From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> Date: Thu, 20 Feb 2025 10:28:51 +0100
> Subject: [PATCH] drm/msm/adreno: Delay the Adreno RPMh startup to HFI init
>
> There's no use in trying to power up the GX logic before we're almost
> ready to fire up the GPU. In fact, with A8xx the PDC and RSC uCode are
> loaded by the GMU firmware, so we *must* wait for the GMU to fully
> initialize before trying to do so.
>
iirc, this wake up sequence should be done before fw start. That aligns
with downstream sequence order too.
-Akhil
> Move it to right before HFI init.
>
> Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> ---
> drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 12 ++----------
> drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 1 +
> drivers/gpu/drm/msm/adreno/a6xx_hfi.c | 2 +-
> 3 files changed, 4 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> index 28e6705c6da6..3335583ada45 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> @@ -513,7 +513,7 @@ static int a6xx_gmu_notify_slumber(struct a6xx_gmu *gmu)
> return ret;
> }
>
> -static int a6xx_rpmh_start(struct a6xx_gmu *gmu)
> +int a6xx_rpmh_start(struct a6xx_gmu *gmu)
> {
> int ret;
> u32 val;
> @@ -842,19 +842,11 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state)
> else
> gmu_write(gmu, REG_A6XX_GMU_GENERAL_7, 1);
>
> - if (state == GMU_WARM_BOOT) {
> - ret = a6xx_rpmh_start(gmu);
> - if (ret)
> - return ret;
> - } else {
> + if (state == GMU_COLD_BOOT) {
> if (WARN(!adreno_gpu->fw[ADRENO_FW_GMU],
> "GMU firmware is not loaded\n"))
> return -ENOENT;
>
> - ret = a6xx_rpmh_start(gmu);
> - if (ret)
> - return ret;
> -
> ret = a6xx_gmu_fw_load(gmu);
> if (ret)
> return ret;
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
> index d1ce11131ba6..309305298a45 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
> @@ -216,5 +216,6 @@ bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu);
> bool a6xx_gmu_sptprac_is_on(struct a6xx_gmu *gmu);
> void a6xx_sptprac_disable(struct a6xx_gmu *gmu);
> int a6xx_sptprac_enable(struct a6xx_gmu *gmu);
> +int a6xx_rpmh_start(struct a6xx_gmu *gmu);
>
> #endif
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
> index 8e69b1e84657..9ea01daf2995 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
> @@ -910,7 +910,7 @@ int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state)
> if (ret)
> return ret;
>
> - return 0;
> + return a6xx_rpmh_start(gmu);
> }
>
> void a6xx_hfi_stop(struct a6xx_gmu *gmu)
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 05/17] drm/msm/a6xx: Fix PDC sleep sequence
2025-08-08 17:22 ` Akhil P Oommen
@ 2025-08-11 8:40 ` Konrad Dybcio
2025-08-13 21:15 ` Akhil P Oommen
0 siblings, 1 reply; 85+ messages in thread
From: Konrad Dybcio @ 2025-08-11 8:40 UTC (permalink / raw)
To: Akhil P Oommen, Rob Clark, Sean Paul, Konrad Dybcio,
Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Marijn Suijten,
David Airlie, Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel
On 8/8/25 7:22 PM, Akhil P Oommen wrote:
> On 8/7/2025 7:21 PM, Konrad Dybcio wrote:
>> On 7/20/25 2:16 PM, Akhil P Oommen wrote:
>>> 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.
>>>
>>> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
>>> ---
>>
>> FWIW some time ago I made this patch, which tackles a similar issue,
>> perhaps it's a good idea to merge both:
>>
>> From 7d6441fc6ec5ee7fe723e1ad86d11fdd17bee922 Mon Sep 17 00:00:00 2001
>> From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
>> Date: Thu, 20 Feb 2025 10:28:51 +0100
>> Subject: [PATCH] drm/msm/adreno: Delay the Adreno RPMh startup to HFI init
>>
>> There's no use in trying to power up the GX logic before we're almost
>> ready to fire up the GPU. In fact, with A8xx the PDC and RSC uCode are
>> loaded by the GMU firmware, so we *must* wait for the GMU to fully
>> initialize before trying to do so.
>>
>
> iirc, this wake up sequence should be done before fw start. That aligns
> with downstream sequence order too.
FWIW techpack/graphics adreno_gen7_gmu.c @ gfx-kernel.lnx.15.0.r3-rel
adb0a9da173e ("kgsl: rgmu: corrected pm suspend flag check on resume")
// load gmu fw, enable clocks, irq, set up chipid etc.
[...]
// unmask CM3_SYSRESET
ret = gen7_gmu_device_start(adreno_dev);
if (ret)
goto err;
if (!test_bit(GMU_PRIV_PDC_RSC_LOADED, &gmu->flags)) {
// set PDC_GPU_ENABLE_PDC & seq_start_addr
ret = gen7_load_pdc_ucode(adreno_dev);
if (ret)
goto err;
// disable hwcg, sleep/wake handshake setup, pdc ucode
gen7_load_rsc_ucode(adreno_dev);
set_bit(GMU_PRIV_PDC_RSC_LOADED, &gmu->flags);
}
// set HFI_CTRL_INIT
ret = gen7_gmu_hfi_start(adreno_dev);
if (ret)
goto err;
// continue booting the gpus, send out feature messages
on a830, the patch is observably necessary (gmu doesn't start otherwise)
Konrad
^ permalink raw reply [flat|nested] 85+ messages in thread
* Re: [PATCH 05/17] drm/msm/a6xx: Fix PDC sleep sequence
2025-08-11 8:40 ` Konrad Dybcio
@ 2025-08-13 21:15 ` Akhil P Oommen
0 siblings, 0 replies; 85+ messages in thread
From: Akhil P Oommen @ 2025-08-13 21:15 UTC (permalink / raw)
To: Konrad Dybcio, Rob Clark, Sean Paul, Konrad Dybcio,
Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Marijn Suijten,
David Airlie, Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel
On 8/11/2025 2:10 PM, Konrad Dybcio wrote:
> On 8/8/25 7:22 PM, Akhil P Oommen wrote:
>> On 8/7/2025 7:21 PM, Konrad Dybcio wrote:
>>> On 7/20/25 2:16 PM, Akhil P Oommen wrote:
>>>> 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.
>>>>
>>>> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
>>>> ---
>>>
>>> FWIW some time ago I made this patch, which tackles a similar issue,
>>> perhaps it's a good idea to merge both:
>>>
>>> From 7d6441fc6ec5ee7fe723e1ad86d11fdd17bee922 Mon Sep 17 00:00:00 2001
>>> From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
>>> Date: Thu, 20 Feb 2025 10:28:51 +0100
>>> Subject: [PATCH] drm/msm/adreno: Delay the Adreno RPMh startup to HFI init
>>>
>>> There's no use in trying to power up the GX logic before we're almost
>>> ready to fire up the GPU. In fact, with A8xx the PDC and RSC uCode are
>>> loaded by the GMU firmware, so we *must* wait for the GMU to fully
>>> initialize before trying to do so.
>>>
>>
>> iirc, this wake up sequence should be done before fw start. That aligns
>> with downstream sequence order too.
>
> FWIW techpack/graphics adreno_gen7_gmu.c @ gfx-kernel.lnx.15.0.r3-rel
> adb0a9da173e ("kgsl: rgmu: corrected pm suspend flag check on resume")
>
> // load gmu fw, enable clocks, irq, set up chipid etc.
> [...]
>
> // unmask CM3_SYSRESET
> ret = gen7_gmu_device_start(adreno_dev);
> if (ret)
> goto err;
>
> if (!test_bit(GMU_PRIV_PDC_RSC_LOADED, &gmu->flags)) {
> // set PDC_GPU_ENABLE_PDC & seq_start_addr
> ret = gen7_load_pdc_ucode(adreno_dev);
> if (ret)
> goto err;
>
> // disable hwcg, sleep/wake handshake setup, pdc ucode
> gen7_load_rsc_ucode(adreno_dev);
> set_bit(GMU_PRIV_PDC_RSC_LOADED, &gmu->flags);
> }
>
> // set HFI_CTRL_INIT
> ret = gen7_gmu_hfi_start(adreno_dev);
> if (ret)
> goto err;
>
> // continue booting the gpus, send out feature messages
>
> on a830, the patch is observably necessary (gmu doesn't start otherwise)
I am confused actually, why are we mixing ucode load and PDC trigger
sequence?
-Akhil.
>
> Konrad
^ permalink raw reply [flat|nested] 85+ messages in thread
end of thread, other threads:[~2025-08-13 21:15 UTC | newest]
Thread overview: 85+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-20 12:16 [PATCH 00/17] drm/msm: Support for Inter Frame Power Collapse (IFPC) feature Akhil P Oommen
2025-07-20 12:16 ` [PATCH 01/17] drm/msm: Update GMU register xml Akhil P Oommen
2025-07-20 12:16 ` [PATCH 02/17] drm/msm: a6xx: Refactor a6xx_sptprac_enable() Akhil P Oommen
2025-07-22 14:30 ` Konrad Dybcio
2025-07-22 19:47 ` Akhil P Oommen
2025-07-23 10:13 ` Konrad Dybcio
2025-07-23 19:10 ` Akhil P Oommen
2025-07-20 12:16 ` [PATCH 03/17] drm/msm: a6xx: Fix gx_is_on check for a7x family Akhil P Oommen
2025-07-20 18:46 ` Dmitry Baryshkov
2025-07-22 14:33 ` Konrad Dybcio
2025-07-22 19:52 ` Akhil P Oommen
2025-07-23 11:10 ` Dmitry Baryshkov
2025-07-23 19:11 ` Akhil P Oommen
2025-07-20 12:16 ` [PATCH 04/17] drm/msm/a6xx: Poll additional DRV status Akhil P Oommen
2025-07-22 13:31 ` Dmitry Baryshkov
2025-07-22 19:55 ` Akhil P Oommen
2025-07-23 10:01 ` Konrad Dybcio
2025-07-23 19:28 ` Akhil P Oommen
2025-07-24 11:39 ` Konrad Dybcio
2025-07-20 12:16 ` [PATCH 05/17] drm/msm/a6xx: Fix PDC sleep sequence Akhil P Oommen
2025-07-22 13:33 ` Dmitry Baryshkov
2025-07-22 17:26 ` Rob Clark
2025-07-22 21:05 ` Akhil P Oommen
2025-07-23 11:11 ` Dmitry Baryshkov
2025-08-07 13:51 ` Konrad Dybcio
2025-08-08 17:22 ` Akhil P Oommen
2025-08-11 8:40 ` Konrad Dybcio
2025-08-13 21:15 ` Akhil P Oommen
2025-07-20 12:16 ` [PATCH 06/17] drm/msm: Add an ftrace for gpu register access Akhil P Oommen
2025-07-20 12:16 ` [PATCH 07/17] drm/msm/adreno: Add fenced regwrite support Akhil P Oommen
2025-07-22 13:39 ` Dmitry Baryshkov
2025-07-22 14:52 ` Konrad Dybcio
2025-07-23 21:06 ` Akhil P Oommen
2025-07-24 11:46 ` Konrad Dybcio
2025-07-24 16:54 ` Akhil P Oommen
2025-07-29 13:01 ` Konrad Dybcio
2025-07-29 21:40 ` Akhil P Oommen
2025-07-29 21:49 ` Akhil P Oommen
2025-07-30 7:49 ` Konrad Dybcio
2025-07-23 21:04 ` Akhil P Oommen
2025-07-20 12:16 ` [PATCH 08/17] drm/msm/a6xx: Set Keep-alive votes to block IFPC Akhil P Oommen
2025-07-22 13:44 ` Dmitry Baryshkov
2025-07-22 21:24 ` Akhil P Oommen
2025-07-23 10:05 ` Konrad Dybcio
2025-07-23 21:22 ` Akhil P Oommen
2025-07-23 21:53 ` Dmitry Baryshkov
2025-07-23 11:13 ` Dmitry Baryshkov
2025-07-20 12:16 ` [PATCH 09/17] drm/msm/a6xx: Switch to GMU AO counter Akhil P Oommen
2025-07-23 10:19 ` Konrad Dybcio
2025-07-23 12:15 ` Rob Clark
2025-07-29 13:30 ` Konrad Dybcio
2025-07-20 12:16 ` [PATCH 10/17] drm/msm/a6xx: Poll AHB fence status in GPU IRQ handler Akhil P Oommen
2025-07-23 10:10 ` Konrad Dybcio
2025-07-20 12:16 ` [PATCH 11/17] drm/msm: Add support for IFPC Akhil P Oommen
2025-07-22 13:49 ` Dmitry Baryshkov
2025-07-22 21:27 ` Akhil P Oommen
2025-07-23 10:27 ` Konrad Dybcio
2025-07-23 21:43 ` Akhil P Oommen
2025-07-23 10:22 ` Konrad Dybcio
2025-07-20 12:16 ` [PATCH 12/17] drm/msm: Skip devfreq IDLE when possible Akhil P Oommen
2025-07-21 4:00 ` kernel test robot
2025-07-22 13:50 ` Dmitry Baryshkov
2025-07-22 15:38 ` Rob Clark
2025-07-22 19:23 ` Akhil P Oommen
2025-07-22 20:13 ` Rob Clark
2025-07-23 21:46 ` Akhil P Oommen
2025-07-23 10:28 ` Konrad Dybcio
2025-07-20 12:16 ` [PATCH 13/17] drm/msm/a6xx: Fix hangcheck for IFPC Akhil P Oommen
2025-07-22 13:52 ` Dmitry Baryshkov
2025-07-22 21:33 ` Akhil P Oommen
2025-07-20 12:16 ` [PATCH 14/17] drm/msm/adreno: Disable IFPC when sysprof is active Akhil P Oommen
2025-07-20 12:16 ` [PATCH 15/17] drm/msm/a6xx: Make crashstate capture IFPC safe Akhil P Oommen
2025-07-23 10:32 ` Konrad Dybcio
2025-07-23 21:53 ` Akhil P Oommen
2025-07-20 12:16 ` [PATCH 16/17] drm/msm/a6xx: Enable IFPC on Adreno X1-85 Akhil P Oommen
2025-07-22 13:55 ` Dmitry Baryshkov
2025-07-22 21:37 ` Akhil P Oommen
2025-07-23 10:33 ` Konrad Dybcio
2025-07-23 21:57 ` Akhil P Oommen
2025-07-22 14:55 ` Konrad Dybcio
2025-07-22 21:41 ` Akhil P Oommen
2025-07-29 14:06 ` neil.armstrong
2025-07-29 18:19 ` Akhil P Oommen
2025-07-20 12:16 ` [PATCH 17/17] drm/msm/adreno: Relax devfreq tunings Akhil P Oommen
2025-07-27 0:49 ` Anthony Ruhier
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).