* [PATCH v2 01/16] drm/msm: Update GMU register xml
2025-09-08 8:26 [PATCH v2 00/16] drm/msm: Support for Inter Frame Power Collapse (IFPC) feature Akhil P Oommen
@ 2025-09-08 8:26 ` Akhil P Oommen
2025-09-08 8:26 ` [PATCH v2 02/16] drm/msm: a6xx: Fix gx_is_on check for a7x family Akhil P Oommen
` (15 subsequent siblings)
16 siblings, 0 replies; 31+ messages in thread
From: Akhil P Oommen @ 2025-09-08 8:26 UTC (permalink / raw)
To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, Antonino Maniscalco, Neil Armstrong
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 [flat|nested] 31+ messages in thread* [PATCH v2 02/16] drm/msm: a6xx: Fix gx_is_on check for a7x family
2025-09-08 8:26 [PATCH v2 00/16] drm/msm: Support for Inter Frame Power Collapse (IFPC) feature Akhil P Oommen
2025-09-08 8:26 ` [PATCH v2 01/16] drm/msm: Update GMU register xml Akhil P Oommen
@ 2025-09-08 8:26 ` Akhil P Oommen
2025-09-08 8:26 ` [PATCH v2 03/16] drm/msm/a6xx: Poll additional DRV status Akhil P Oommen
` (14 subsequent siblings)
16 siblings, 0 replies; 31+ messages in thread
From: Akhil P Oommen @ 2025-09-08 8:26 UTC (permalink / raw)
To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, Antonino Maniscalco, Neil Armstrong
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel,
Akhil P Oommen, Konrad Dybcio
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.
Fixes: af66706accdf ("drm/msm/a6xx: Add skeleton A7xx support")
Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
Reviewed-by: Konrad Dybcio <konrad.dybcio@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 28e6705c6da682c7b41c748e375dda59a6551898..bb30b11175737e04d4bfd6bfa5470d6365c520fa 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 [flat|nested] 31+ messages in thread* [PATCH v2 03/16] drm/msm/a6xx: Poll additional DRV status
2025-09-08 8:26 [PATCH v2 00/16] drm/msm: Support for Inter Frame Power Collapse (IFPC) feature Akhil P Oommen
2025-09-08 8:26 ` [PATCH v2 01/16] drm/msm: Update GMU register xml Akhil P Oommen
2025-09-08 8:26 ` [PATCH v2 02/16] drm/msm: a6xx: Fix gx_is_on check for a7x family Akhil P Oommen
@ 2025-09-08 8:26 ` Akhil P Oommen
2025-09-08 15:18 ` Konrad Dybcio
2025-09-08 8:26 ` [PATCH v2 04/16] drm/msm/a6xx: Fix PDC sleep sequence Akhil P Oommen
` (13 subsequent siblings)
16 siblings, 1 reply; 31+ messages in thread
From: Akhil P Oommen @ 2025-09-08 8:26 UTC (permalink / raw)
To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, Antonino Maniscalco, Neil Armstrong
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.
Fixes: 1f8c29e80066 ("drm/msm/a6xx: Add A740 support")
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 bb30b11175737e04d4bfd6bfa5470d6365c520fa..06870f6596a7cb045deecaff3c95fba32ee84d52 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] 31+ messages in thread* Re: [PATCH v2 03/16] drm/msm/a6xx: Poll additional DRV status
2025-09-08 8:26 ` [PATCH v2 03/16] drm/msm/a6xx: Poll additional DRV status Akhil P Oommen
@ 2025-09-08 15:18 ` Konrad Dybcio
2025-09-08 16:49 ` Akhil P Oommen
0 siblings, 1 reply; 31+ messages in thread
From: Konrad Dybcio @ 2025-09-08 15:18 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, Antonino Maniscalco, Neil Armstrong
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel
On 9/8/25 10:26 AM, Akhil P Oommen wrote:
> A7XX_GEN2 generation has additional TCS slots. Poll the respective
> DRV status registers before pm suspend.
>
> Fixes: 1f8c29e80066 ("drm/msm/a6xx: Add A740 support")
> 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 bb30b11175737e04d4bfd6bfa5470d6365c520fa..06870f6596a7cb045deecaff3c95fba32ee84d52 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);
https://lore.kernel.org/linux-arm-msm/002eb889-87cb-4b8c-98fb-6826c6977868@oss.qualcomm.com/
Konrad
^ permalink raw reply [flat|nested] 31+ messages in thread* Re: [PATCH v2 03/16] drm/msm/a6xx: Poll additional DRV status
2025-09-08 15:18 ` Konrad Dybcio
@ 2025-09-08 16:49 ` Akhil P Oommen
0 siblings, 0 replies; 31+ messages in thread
From: Akhil P Oommen @ 2025-09-08 16:49 UTC (permalink / raw)
To: Konrad Dybcio
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Rob Clark,
Sean Paul, Konrad Dybcio, Dmitry Baryshkov, Abhinav Kumar,
Jessica Zhang, Marijn Suijten, David Airlie, Simona Vetter,
Antonino Maniscalco, Neil Armstrong
On 9/8/2025 8:48 PM, Konrad Dybcio wrote:
> On 9/8/25 10:26 AM, Akhil P Oommen wrote:
>> A7XX_GEN2 generation has additional TCS slots. Poll the respective
>> DRV status registers before pm suspend.
>>
>> Fixes: 1f8c29e80066 ("drm/msm/a6xx: Add A740 support")
>> 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 bb30b11175737e04d4bfd6bfa5470d6365c520fa..06870f6596a7cb045deecaff3c95fba32ee84d52 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);
>
> https://lore.kernel.org/linux-arm-msm/002eb889-87cb-4b8c-98fb-6826c6977868@oss.qualcomm.com/
I missed the timeout value update. It is not bad since we already have
the same value for TCS3 above. Will fix them all separately.
-Akhil.
>
> Konrad
^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH v2 04/16] drm/msm/a6xx: Fix PDC sleep sequence
2025-09-08 8:26 [PATCH v2 00/16] drm/msm: Support for Inter Frame Power Collapse (IFPC) feature Akhil P Oommen
` (2 preceding siblings ...)
2025-09-08 8:26 ` [PATCH v2 03/16] drm/msm/a6xx: Poll additional DRV status Akhil P Oommen
@ 2025-09-08 8:26 ` Akhil P Oommen
2025-09-08 8:26 ` [PATCH v2 05/16] drm/msm: a6xx: Refactor a6xx_sptprac_enable() Akhil P Oommen
` (12 subsequent siblings)
16 siblings, 0 replies; 31+ messages in thread
From: Akhil P Oommen @ 2025-09-08 8:26 UTC (permalink / raw)
To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, Antonino Maniscalco, Neil Armstrong
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel,
Akhil P Oommen, stable
Since the PDC resides out of the GPU subsystem and cannot be reset in
case it enters bad state, utmost care must be taken to trigger the PDC
wake/sleep routines in the correct order.
The PDC wake sequence can be exercised only after a PDC sleep sequence.
Additionally, GMU firmware should initialize a few registers before the
KMD can trigger a PDC sleep sequence. So PDC sleep can't be done if the
GMU firmware has not initialized. Track these dependencies using a new
status variable and trigger PDC sleep/wake sequences appropriately.
Cc: stable@vger.kernel.org
Fixes: 4b565ca5a2cb ("drm/msm: Add A6XX device support")
Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
---
drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 28 +++++++++++++++++-----------
drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 6 ++++++
2 files changed, 23 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index 06870f6596a7cb045deecaff3c95fba32ee84d52..ba593ccfe3c6a2f3a2ea0db3a1435d0668ed7bf2 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;
}
@@ -525,6 +527,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,
@@ -552,6 +557,9 @@ 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;
+
gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, 1);
ret = gmu_poll_timeout_rscc(gmu, REG_A6XX_GPU_RSCC_RSC_STATUS0_DRV0,
@@ -560,6 +568,8 @@ static void a6xx_rpmh_stop(struct a6xx_gmu *gmu)
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)
@@ -688,8 +698,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);
@@ -849,19 +857,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 +1050,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 d1ce11131ba6746056b3314dccdc3612cf982306..069a8c9474e8beb4ebe84d1609a8d38b44314125 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 [flat|nested] 31+ messages in thread* [PATCH v2 05/16] drm/msm: a6xx: Refactor a6xx_sptprac_enable()
2025-09-08 8:26 [PATCH v2 00/16] drm/msm: Support for Inter Frame Power Collapse (IFPC) feature Akhil P Oommen
` (3 preceding siblings ...)
2025-09-08 8:26 ` [PATCH v2 04/16] drm/msm/a6xx: Fix PDC sleep sequence Akhil P Oommen
@ 2025-09-08 8:26 ` Akhil P Oommen
2025-09-08 15:21 ` Konrad Dybcio
2025-09-08 8:26 ` [PATCH v2 06/16] drm/msm: Add an ftrace for gpu register access Akhil P Oommen
` (11 subsequent siblings)
16 siblings, 1 reply; 31+ messages in thread
From: Akhil P Oommen @ 2025-09-08 8:26 UTC (permalink / raw)
To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, Antonino Maniscalco, Neil Armstrong
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.
Also, document an intermediate unknown low power state which is not
exposed by the GMU firmware.
Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
---
drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 8 ++++----
drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 3 +++
2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index ba593ccfe3c6a2f3a2ea0db3a1435d0668ed7bf2..18f5fc2c28e33d81ccc248216cc018300c81eb77 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -412,7 +412,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);
@@ -936,10 +939,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;
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
index 069a8c9474e8beb4ebe84d1609a8d38b44314125..9494bbed9a1ff86b19acec139d7ab27697d7ec8a 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
@@ -50,6 +50,9 @@ struct a6xx_bcm {
/* The GMU does not do any idle state management */
#define GMU_IDLE_STATE_ACTIVE 0
+/* Unknown power state. Not exposed by the firmware. For documentation purpose only */
+#define GMU_IDLE_STATE_RESERVED 1
+
/* The GMU manages SPTP power collapse */
#define GMU_IDLE_STATE_SPTP 2
--
2.50.1
^ permalink raw reply [flat|nested] 31+ messages in thread* Re: [PATCH v2 05/16] drm/msm: a6xx: Refactor a6xx_sptprac_enable()
2025-09-08 8:26 ` [PATCH v2 05/16] drm/msm: a6xx: Refactor a6xx_sptprac_enable() Akhil P Oommen
@ 2025-09-08 15:21 ` Konrad Dybcio
0 siblings, 0 replies; 31+ messages in thread
From: Konrad Dybcio @ 2025-09-08 15:21 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, Antonino Maniscalco, Neil Armstrong
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel
On 9/8/25 10:26 AM, 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.
>
> Also, document an intermediate unknown low power state which is not
> exposed by the GMU firmware.
>
> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
> ---
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Konrad
^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH v2 06/16] drm/msm: Add an ftrace for gpu register access
2025-09-08 8:26 [PATCH v2 00/16] drm/msm: Support for Inter Frame Power Collapse (IFPC) feature Akhil P Oommen
` (4 preceding siblings ...)
2025-09-08 8:26 ` [PATCH v2 05/16] drm/msm: a6xx: Refactor a6xx_sptprac_enable() Akhil P Oommen
@ 2025-09-08 8:26 ` Akhil P Oommen
2025-09-08 8:27 ` [PATCH v2 07/16] drm/msm/adreno: Add fenced regwrite support Akhil P Oommen
` (10 subsequent siblings)
16 siblings, 0 replies; 31+ messages in thread
From: Akhil P Oommen @ 2025-09-08 8:26 UTC (permalink / raw)
To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, Antonino Maniscalco, Neil Armstrong
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 b2a96544f92a55cdb372729498b8f0b0f9ca80bd..866bb090af064666586cea7125254bd375b7a35c 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"
@@ -613,16 +614,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);
}
@@ -644,7 +648,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;
@@ -652,8 +658,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 781bbe5540bde6d9cd6758050229fd0406fad232..5417f8d389a370e8d0b9c7e447050e2965011c0a 100644
--- a/drivers/gpu/drm/msm/msm_gpu_trace.h
+++ b/drivers/gpu/drm/msm/msm_gpu_trace.h
@@ -219,6 +219,18 @@ TRACE_EVENT(msm_mmu_prealloc_cleanup,
TP_printk("count=%u, remaining=%u", __entry->count, __entry->remaining)
);
+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 [flat|nested] 31+ messages in thread* [PATCH v2 07/16] drm/msm/adreno: Add fenced regwrite support
2025-09-08 8:26 [PATCH v2 00/16] drm/msm: Support for Inter Frame Power Collapse (IFPC) feature Akhil P Oommen
` (5 preceding siblings ...)
2025-09-08 8:26 ` [PATCH v2 06/16] drm/msm: Add an ftrace for gpu register access Akhil P Oommen
@ 2025-09-08 8:27 ` Akhil P Oommen
2025-09-08 15:37 ` Konrad Dybcio
2025-09-08 15:54 ` Connor Abbott
2025-09-08 8:27 ` [PATCH v2 08/16] drm/msm/a6xx: Set Keep-alive votes to block IFPC Akhil P Oommen
` (9 subsequent siblings)
16 siblings, 2 replies; 31+ messages in thread
From: Akhil P Oommen @ 2025-09-08 8:27 UTC (permalink / raw)
To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, Antonino Maniscalco, Neil Armstrong
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 | 80 ++++++++++++++++++++++++++++++-
drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 1 +
drivers/gpu/drm/msm/adreno/a6xx_preempt.c | 20 ++++----
3 files changed, 90 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index 45dd5fd1c2bfcb0a01b71a326c7d95b0f9496d99..a63dad80ef461da45d5c41a042ed4f19d8282ef5 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -16,6 +16,84 @@
#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);
+
+ /* We can't do a posted write here because the power domain could be
+ * in collapse state. So use the heaviest barrier instead
+ */
+ mb();
+ 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;
+
+ /* We can't do a posted write here because the power domain could be
+ * in collapse state. So use the heaviest barrier instead
+ */
+ mb();
+
+ if (!gmu_poll_timeout(gmu, REG_A6XX_GMU_AHB_FENCE_STATUS, status,
+ fence_status_check(gpu, offset, value, status, mask), 0, 1000))
+ return 0;
+
+ /* Try again for another 1ms before failing */
+ gpu_write(gpu, offset, value);
+ mb();
+
+ if (!gmu_poll_timeout(gmu, REG_A6XX_GMU_AHB_FENCE_STATUS, status,
+ fence_status_check(gpu, offset, value, status, mask), 0, 1000)) {
+ /*
+ * The 'delay' warning is here because the pause to print this
+ * warning will allow gpu to move to power collapse which
+ * defeats the purpose of continuous polling for 2 ms
+ */
+ dev_err_ratelimited(gmu->dev, "delay in fenced register write (0x%x)\n",
+ offset);
+ 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 +164,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 6e71f617fc3d0d564e51650dfed63a18f31042ac..e736c59d566b3fcf8c62a212494e3b110c09caa9 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
@@ -295,5 +295,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 6a12a35dabff1e64aae8440c2a8c88f5feb4803e..10625ffbc4cfc26edc36efcf11dbb4efd55ab3e0 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] 31+ messages in thread* Re: [PATCH v2 07/16] drm/msm/adreno: Add fenced regwrite support
2025-09-08 8:27 ` [PATCH v2 07/16] drm/msm/adreno: Add fenced regwrite support Akhil P Oommen
@ 2025-09-08 15:37 ` Konrad Dybcio
2025-09-08 16:15 ` Akhil P Oommen
2025-09-08 15:54 ` Connor Abbott
1 sibling, 1 reply; 31+ messages in thread
From: Konrad Dybcio @ 2025-09-08 15:37 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, Antonino Maniscalco, Neil Armstrong
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel
On 9/8/25 10:27 AM, 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 | 80 ++++++++++++++++++++++++++++++-
> drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 1 +
> drivers/gpu/drm/msm/adreno/a6xx_preempt.c | 20 ++++----
> 3 files changed, 90 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> index 45dd5fd1c2bfcb0a01b71a326c7d95b0f9496d99..a63dad80ef461da45d5c41a042ed4f19d8282ef5 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> @@ -16,6 +16,84 @@
>
> #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);
> +
> + /* We can't do a posted write here because the power domain could be
> + * in collapse state. So use the heaviest barrier instead
> + */
> + mb();
> + 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;
> +
> + /* We can't do a posted write here because the power domain could be
> + * in collapse state. So use the heaviest barrier instead
> + */
I'm not sure I follow - what's the relationship between the write being
posted and the power domain being collapsed (i.e. the hw not being
powered on)?
Are you trying to get rid of the delay that could happen between this
write leaving the CPU and arriving at the GPU (which would then be
woken up), so that the 1ms poll below has greater chance to succeed
because of how these "special registers" work?
Konrad
^ permalink raw reply [flat|nested] 31+ messages in thread* Re: [PATCH v2 07/16] drm/msm/adreno: Add fenced regwrite support
2025-09-08 15:37 ` Konrad Dybcio
@ 2025-09-08 16:15 ` Akhil P Oommen
0 siblings, 0 replies; 31+ messages in thread
From: Akhil P Oommen @ 2025-09-08 16:15 UTC (permalink / raw)
To: Konrad Dybcio
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Rob Clark,
Sean Paul, Konrad Dybcio, Dmitry Baryshkov, Abhinav Kumar,
Jessica Zhang, Marijn Suijten, David Airlie, Simona Vetter,
Antonino Maniscalco, Neil Armstrong
On 9/8/2025 9:07 PM, Konrad Dybcio wrote:
> On 9/8/25 10:27 AM, 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 | 80 ++++++++++++++++++++++++++++++-
>> drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 1 +
>> drivers/gpu/drm/msm/adreno/a6xx_preempt.c | 20 ++++----
>> 3 files changed, 90 insertions(+), 11 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>> index 45dd5fd1c2bfcb0a01b71a326c7d95b0f9496d99..a63dad80ef461da45d5c41a042ed4f19d8282ef5 100644
>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>> @@ -16,6 +16,84 @@
>>
>> #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);
>> +
>> + /* We can't do a posted write here because the power domain could be
>> + * in collapse state. So use the heaviest barrier instead
>> + */
>> + mb();
>> + 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;
>> +
>> + /* We can't do a posted write here because the power domain could be
>> + * in collapse state. So use the heaviest barrier instead
>> + */
>
> I'm not sure I follow - what's the relationship between the write being
> posted and the power domain being collapsed (i.e. the hw not being
> powered on)?
>
> Are you trying to get rid of the delay that could happen between this
> write leaving the CPU and arriving at the GPU (which would then be
> woken up), so that the 1ms poll below has greater chance to succeed
> because of how these "special registers" work?
We should strictly ensure that the GX register write is posted first (it
could be posted to the hw or dropped by the fence hw). Otherwise the
fence status register (in CX domain) might incorrectly report that the
register write went through. Ideally, we should do a posted write here,
but we can't do that due to IFPC. A full barrier (DSB SY) will ensure
this ordering requirement.
Another motivation here is to align closely with the downstream sequence
which uses a similar barrier. It will be a super painful debug if this
sequence miss a register write.
-Akhil.
>
> Konrad
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH v2 07/16] drm/msm/adreno: Add fenced regwrite support
2025-09-08 8:27 ` [PATCH v2 07/16] drm/msm/adreno: Add fenced regwrite support Akhil P Oommen
2025-09-08 15:37 ` Konrad Dybcio
@ 2025-09-08 15:54 ` Connor Abbott
2025-09-08 16:46 ` Akhil P Oommen
1 sibling, 1 reply; 31+ messages in thread
From: Connor Abbott @ 2025-09-08 15:54 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, Antonino Maniscalco, Neil Armstrong,
linux-arm-msm, dri-devel, freedreno, linux-kernel
On Mon, Sep 8, 2025 at 4:27 AM Akhil P Oommen <akhilpo@oss.qualcomm.com> 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 | 80 ++++++++++++++++++++++++++++++-
> drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 1 +
> drivers/gpu/drm/msm/adreno/a6xx_preempt.c | 20 ++++----
> 3 files changed, 90 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> index 45dd5fd1c2bfcb0a01b71a326c7d95b0f9496d99..a63dad80ef461da45d5c41a042ed4f19d8282ef5 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> @@ -16,6 +16,84 @@
>
> #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);
> +
> + /* We can't do a posted write here because the power domain could be
> + * in collapse state. So use the heaviest barrier instead
> + */
> + mb();
> + 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;
> +
> + /* We can't do a posted write here because the power domain could be
> + * in collapse state. So use the heaviest barrier instead
> + */
> + mb();
> +
> + if (!gmu_poll_timeout(gmu, REG_A6XX_GMU_AHB_FENCE_STATUS, status,
> + fence_status_check(gpu, offset, value, status, mask), 0, 1000))
> + return 0;
> +
> + /* Try again for another 1ms before failing */
> + gpu_write(gpu, offset, value);
> + mb();
> +
> + if (!gmu_poll_timeout(gmu, REG_A6XX_GMU_AHB_FENCE_STATUS, status,
> + fence_status_check(gpu, offset, value, status, mask), 0, 1000)) {
> + /*
> + * The 'delay' warning is here because the pause to print this
> + * warning will allow gpu to move to power collapse which
> + * defeats the purpose of continuous polling for 2 ms
> + */
> + dev_err_ratelimited(gmu->dev, "delay in fenced register write (0x%x)\n",
> + offset);
> + 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 +164,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 6e71f617fc3d0d564e51650dfed63a18f31042ac..e736c59d566b3fcf8c62a212494e3b110c09caa9 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
> @@ -295,5 +295,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);
"mask" makes it sound like it's the mask for a masked write, which it
isn't. At least in the public API I'd name it something more explicit
like "fence_status_mask". Also it would be nice to add defines like
GMU_FENCE_STATUS_WPTR/CONTEXT_SWITCH to make the parameter values in
callsites less magical. Finally, this might be personal preference,
but it's not immediately obvious what the "true"/"false" in callsites
mean, so it would make users clearer to add a separate
"a6xx_fenced_write64" and make 64-bit reg writes use that instead of
is_64b.
Connor
>
> #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 6a12a35dabff1e64aae8440c2a8c88f5feb4803e..10625ffbc4cfc26edc36efcf11dbb4efd55ab3e0 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] 31+ messages in thread* Re: [PATCH v2 07/16] drm/msm/adreno: Add fenced regwrite support
2025-09-08 15:54 ` Connor Abbott
@ 2025-09-08 16:46 ` Akhil P Oommen
0 siblings, 0 replies; 31+ messages in thread
From: Akhil P Oommen @ 2025-09-08 16:46 UTC (permalink / raw)
To: Connor Abbott
Cc: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, Antonino Maniscalco, Neil Armstrong,
linux-arm-msm, dri-devel, freedreno, linux-kernel
On 9/8/2025 9:24 PM, Connor Abbott wrote:
> On Mon, Sep 8, 2025 at 4:27 AM Akhil P Oommen <akhilpo@oss.qualcomm.com> 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 | 80 ++++++++++++++++++++++++++++++-
>> drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 1 +
>> drivers/gpu/drm/msm/adreno/a6xx_preempt.c | 20 ++++----
>> 3 files changed, 90 insertions(+), 11 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>> index 45dd5fd1c2bfcb0a01b71a326c7d95b0f9496d99..a63dad80ef461da45d5c41a042ed4f19d8282ef5 100644
>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>> @@ -16,6 +16,84 @@
>>
>> #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);
>> +
>> + /* We can't do a posted write here because the power domain could be
>> + * in collapse state. So use the heaviest barrier instead
>> + */
>> + mb();
>> + 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;
>> +
>> + /* We can't do a posted write here because the power domain could be
>> + * in collapse state. So use the heaviest barrier instead
>> + */
>> + mb();
>> +
>> + if (!gmu_poll_timeout(gmu, REG_A6XX_GMU_AHB_FENCE_STATUS, status,
>> + fence_status_check(gpu, offset, value, status, mask), 0, 1000))
>> + return 0;
>> +
>> + /* Try again for another 1ms before failing */
>> + gpu_write(gpu, offset, value);
>> + mb();
>> +
>> + if (!gmu_poll_timeout(gmu, REG_A6XX_GMU_AHB_FENCE_STATUS, status,
>> + fence_status_check(gpu, offset, value, status, mask), 0, 1000)) {
>> + /*
>> + * The 'delay' warning is here because the pause to print this
>> + * warning will allow gpu to move to power collapse which
>> + * defeats the purpose of continuous polling for 2 ms
>> + */
>> + dev_err_ratelimited(gmu->dev, "delay in fenced register write (0x%x)\n",
>> + offset);
>> + 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 +164,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 6e71f617fc3d0d564e51650dfed63a18f31042ac..e736c59d566b3fcf8c62a212494e3b110c09caa9 100644
>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
>> @@ -295,5 +295,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);
>
> "mask" makes it sound like it's the mask for a masked write, which it
> isn't. At least in the public API I'd name it something more explicit
> like "fence_status_mask". Also it would be nice to add defines like
> GMU_FENCE_STATUS_WPTR/CONTEXT_SWITCH to make the parameter values in
> callsites less magical. Finally, this might be personal preference,
> but it's not immediately obvious what the "true"/"false" in callsites
> mean, so it would make users clearer to add a separate
> "a6xx_fenced_write64" and make 64-bit reg writes use that instead of
> is_64b.
I agree about the BIT definition. Will update if I send another
revision. Same for the 'mask'. I can see the confusion due to write and
mask in the same line.
64B fenced write is used only at a single place (in the preempt trigger
call). So I feel it is an overkill to create another function for that.
I did weigh that option earlier though.
-Akhil
>
> Connor
>
>>
^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH v2 08/16] drm/msm/a6xx: Set Keep-alive votes to block IFPC
2025-09-08 8:26 [PATCH v2 00/16] drm/msm: Support for Inter Frame Power Collapse (IFPC) feature Akhil P Oommen
` (6 preceding siblings ...)
2025-09-08 8:27 ` [PATCH v2 07/16] drm/msm/adreno: Add fenced regwrite support Akhil P Oommen
@ 2025-09-08 8:27 ` Akhil P Oommen
2025-09-08 8:27 ` [PATCH v2 09/16] drm/msm/a6xx: Switch to GMU AO counter Akhil P Oommen
` (8 subsequent siblings)
16 siblings, 0 replies; 31+ messages in thread
From: Akhil P Oommen @ 2025-09-08 8:27 UTC (permalink / raw)
To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, Antonino Maniscalco, Neil Armstrong
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 a63dad80ef461da45d5c41a042ed4f19d8282ef5..33a26bbd245ff49784bf1219a584936b4caa62b6 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -1771,8 +1771,6 @@ static void a6xx_cp_hw_err_irq(struct msm_gpu *gpu)
static void a6xx_fault_detect_irq(struct msm_gpu *gpu)
{
- struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
- struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
struct msm_ringbuffer *ring = gpu->funcs->active_ring(gpu);
/*
@@ -1784,13 +1782,6 @@ static void a6xx_fault_detect_irq(struct msm_gpu *gpu)
if (gpu_read(gpu, REG_A6XX_RBBM_STATUS3) & A6XX_RBBM_STATUS3_SMMU_STALLED_ON_FAULT)
return;
- /*
- * Force the GPU to stay on until after we finish
- * collecting information
- */
- if (!adreno_has_gmu_wrapper(adreno_gpu))
- gmu_write(&a6xx_gpu->gmu, REG_A6XX_GMU_GMU_PWR_COL_KEEPALIVE, 1);
-
DRM_DEV_ERROR(&gpu->pdev->dev,
"gpu fault ring %d fence %x status %8.8X rb %4.4x/%4.4x ib1 %16.16llX/%4.4x ib2 %16.16llX/%4.4x\n",
ring ? ring->id : -1, ring ? ring->fctx->last_fence : 0,
@@ -1829,9 +1820,24 @@ static void a7xx_sw_fuse_violation_irq(struct msm_gpu *gpu)
}
}
+static void a6xx_gpu_keepalive_vote(struct msm_gpu *gpu, bool on)
+{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
+
+ if (adreno_has_gmu_wrapper(adreno_gpu))
+ return;
+
+ gmu_write(&a6xx_gpu->gmu, REG_A6XX_GMU_GMU_PWR_COL_KEEPALIVE, on);
+}
+
static irqreturn_t a6xx_irq(struct msm_gpu *gpu)
{
struct msm_drm_private *priv = gpu->dev->dev_private;
+
+ /* Set keepalive vote to avoid power collapse after RBBM_INT_0_STATUS is read */
+ a6xx_gpu_keepalive_vote(gpu, true);
+
u32 status = gpu_read(gpu, REG_A6XX_RBBM_INT_0_STATUS);
gpu_write(gpu, REG_A6XX_RBBM_INT_CLEAR_CMD, status);
@@ -1868,6 +1874,8 @@ static irqreturn_t a6xx_irq(struct msm_gpu *gpu)
if (status & A6XX_RBBM_INT_0_MASK_CP_SW)
a6xx_preempt_irq(gpu);
+ a6xx_gpu_keepalive_vote(gpu, false);
+
return IRQ_HANDLED;
}
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_preempt.c b/drivers/gpu/drm/msm/adreno/a6xx_preempt.c
index 10625ffbc4cfc26edc36efcf11dbb4efd55ab3e0..2ce073d1cf8cfd7c774918851de03d6e367e5625 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_preempt.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_preempt.c
@@ -136,6 +136,21 @@ static void preempt_disable_postamble(struct a6xx_gpu *a6xx_gpu)
a6xx_gpu->postamble_enabled = false;
}
+/*
+ * Set preemption keepalive vote. Please note that this vote is different from the one used in
+ * a6xx_irq()
+ */
+static void a6xx_preempt_keepalive_vote(struct msm_gpu *gpu, bool on)
+{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
+
+ if (adreno_has_gmu_wrapper(adreno_gpu))
+ return;
+
+ gmu_write(&a6xx_gpu->gmu, REG_A6XX_GMU_PWR_COL_PREEMPT_KEEPALIVE, on);
+}
+
void a6xx_preempt_irq(struct msm_gpu *gpu)
{
uint32_t status;
@@ -176,6 +191,8 @@ void a6xx_preempt_irq(struct msm_gpu *gpu)
set_preempt_state(a6xx_gpu, PREEMPT_NONE);
+ a6xx_preempt_keepalive_vote(gpu, false);
+
trace_msm_gpu_preemption_irq(a6xx_gpu->cur_ring->id);
/*
@@ -302,6 +319,9 @@ void a6xx_preempt_trigger(struct msm_gpu *gpu)
spin_unlock_irqrestore(&ring->preempt_lock, flags);
+ /* Set the keepalive bit to keep the GPU ON until preemption is complete */
+ a6xx_preempt_keepalive_vote(gpu, true);
+
a6xx_fenced_write(a6xx_gpu,
REG_A6XX_CP_CONTEXT_SWITCH_SMMU_INFO, a6xx_gpu->preempt_smmu_iova[ring->id],
BIT(1), true);
--
2.50.1
^ permalink raw reply [flat|nested] 31+ messages in thread* [PATCH v2 09/16] drm/msm/a6xx: Switch to GMU AO counter
2025-09-08 8:26 [PATCH v2 00/16] drm/msm: Support for Inter Frame Power Collapse (IFPC) feature Akhil P Oommen
` (7 preceding siblings ...)
2025-09-08 8:27 ` [PATCH v2 08/16] drm/msm/a6xx: Set Keep-alive votes to block IFPC Akhil P Oommen
@ 2025-09-08 8:27 ` Akhil P Oommen
2025-09-08 8:27 ` [PATCH v2 10/16] drm/msm/a6xx: Poll AHB fence status in GPU IRQ handler Akhil P Oommen
` (7 subsequent siblings)
16 siblings, 0 replies; 31+ messages in thread
From: Akhil P Oommen @ 2025-09-08 8:27 UTC (permalink / raw)
To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, Antonino Maniscalco, Neil Armstrong
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 33a26bbd245ff49784bf1219a584936b4caa62b6..c64c84affa6821f79ea74b80b2f2014df38ec918 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 (unlikely(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 */
@@ -376,8 +389,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);
}
@@ -577,8 +589,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);
@@ -2265,16 +2276,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 [flat|nested] 31+ messages in thread* [PATCH v2 10/16] drm/msm/a6xx: Poll AHB fence status in GPU IRQ handler
2025-09-08 8:26 [PATCH v2 00/16] drm/msm: Support for Inter Frame Power Collapse (IFPC) feature Akhil P Oommen
` (8 preceding siblings ...)
2025-09-08 8:27 ` [PATCH v2 09/16] drm/msm/a6xx: Switch to GMU AO counter Akhil P Oommen
@ 2025-09-08 8:27 ` Akhil P Oommen
2025-09-08 8:27 ` [PATCH v2 11/16] drm/msm: Add support for IFPC Akhil P Oommen
` (6 subsequent siblings)
16 siblings, 0 replies; 31+ messages in thread
From: Akhil P Oommen @ 2025-09-08 8:27 UTC (permalink / raw)
To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, Antonino Maniscalco, Neil Armstrong
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Akhil P Oommen
Even though the GX power domain is kept ON when there is a pending GPU
interrupt, there is a small window of potential race with GMU where it
may move the AHB fence to 'Drop' mode. Once the GMU sees the pending IRQ,
it will move back the fence state to ALLOW mode. Close this race window
by polling for AHB fence to ensure that it is in 'Allow' mode.
Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
---
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 9494bbed9a1ff86b19acec139d7ab27697d7ec8a..40c4c0445b8e4349c9111850df9c0b1d355f0b73 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
@@ -167,6 +167,9 @@ static inline u64 gmu_read64(struct a6xx_gmu *gmu, u32 lo, u32 hi)
#define gmu_poll_timeout(gmu, addr, val, cond, interval, timeout) \
readl_poll_timeout((gmu)->mmio + ((addr) << 2), val, cond, \
interval, timeout)
+#define gmu_poll_timeout_atomic(gmu, addr, val, cond, interval, timeout) \
+ readl_poll_timeout_atomic((gmu)->mmio + ((addr) << 2), val, cond, \
+ interval, timeout)
static inline u32 gmu_read_rscc(struct a6xx_gmu *gmu, u32 offset)
{
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index c64c84affa6821f79ea74b80b2f2014df38ec918..bba09c02f9809ed24b4a9c30b1eb993ce01c7ec0 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -1842,6 +1842,28 @@ static void a6xx_gpu_keepalive_vote(struct msm_gpu *gpu, bool on)
gmu_write(&a6xx_gpu->gmu, REG_A6XX_GMU_GMU_PWR_COL_KEEPALIVE, on);
}
+static int irq_poll_fence(struct msm_gpu *gpu)
+{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
+ struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
+ u32 status;
+
+ if (adreno_has_gmu_wrapper(adreno_gpu))
+ return 0;
+
+ if (gmu_poll_timeout_atomic(gmu, REG_A6XX_GMU_AO_AHB_FENCE_CTRL, status, !status, 1, 100)) {
+ u32 rbbm_unmasked = gmu_read(gmu, REG_A6XX_GMU_RBBM_INT_UNMASKED_STATUS);
+
+ dev_err_ratelimited(&gpu->pdev->dev,
+ "irq fence poll timeout, fence_ctrl=0x%x, unmasked_status=0x%x\n",
+ status, rbbm_unmasked);
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
static irqreturn_t a6xx_irq(struct msm_gpu *gpu)
{
struct msm_drm_private *priv = gpu->dev->dev_private;
@@ -1849,6 +1871,9 @@ static irqreturn_t a6xx_irq(struct msm_gpu *gpu)
/* Set keepalive vote to avoid power collapse after RBBM_INT_0_STATUS is read */
a6xx_gpu_keepalive_vote(gpu, true);
+ if (irq_poll_fence(gpu))
+ goto done;
+
u32 status = gpu_read(gpu, REG_A6XX_RBBM_INT_0_STATUS);
gpu_write(gpu, REG_A6XX_RBBM_INT_CLEAR_CMD, status);
@@ -1885,6 +1910,7 @@ static irqreturn_t a6xx_irq(struct msm_gpu *gpu)
if (status & A6XX_RBBM_INT_0_MASK_CP_SW)
a6xx_preempt_irq(gpu);
+done:
a6xx_gpu_keepalive_vote(gpu, false);
return IRQ_HANDLED;
--
2.50.1
^ permalink raw reply [flat|nested] 31+ messages in thread* [PATCH v2 11/16] drm/msm: Add support for IFPC
2025-09-08 8:26 [PATCH v2 00/16] drm/msm: Support for Inter Frame Power Collapse (IFPC) feature Akhil P Oommen
` (9 preceding siblings ...)
2025-09-08 8:27 ` [PATCH v2 10/16] drm/msm/a6xx: Poll AHB fence status in GPU IRQ handler Akhil P Oommen
@ 2025-09-08 8:27 ` Akhil P Oommen
2025-09-08 8:27 ` [PATCH v2 12/16] drm/msm/a6xx: Fix hangcheck " Akhil P Oommen
` (5 subsequent siblings)
16 siblings, 0 replies; 31+ messages in thread
From: Akhil P Oommen @ 2025-09-08 8:27 UTC (permalink / raw)
To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, Antonino Maniscalco, Neil Armstrong
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 | 34 +++++++++++++++++++++++++++------
drivers/gpu/drm/msm/adreno/adreno_gpu.h | 1 +
3 files changed, 32 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index 18f5fc2c28e33d81ccc248216cc018300c81eb77..d6297cc7fe664a74224c441e877050612714a3e4 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..550de6ad68effacaea09751891c2528464bdfcc5 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,40 @@ 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
+#define IFPC_LONG_HYST 0x1680
+
+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, IFPC_LONG_HYST);
+}
+
#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 +916,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 9dc93c247196d5b8b3659157f7aeea81809d4056..390fa6720d9b096f4fa7d1639645d453d43b153a 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
@@ -59,6 +59,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] 31+ messages in thread* [PATCH v2 12/16] drm/msm/a6xx: Fix hangcheck for IFPC
2025-09-08 8:26 [PATCH v2 00/16] drm/msm: Support for Inter Frame Power Collapse (IFPC) feature Akhil P Oommen
` (10 preceding siblings ...)
2025-09-08 8:27 ` [PATCH v2 11/16] drm/msm: Add support for IFPC Akhil P Oommen
@ 2025-09-08 8:27 ` Akhil P Oommen
2025-09-08 8:27 ` [PATCH v2 13/16] drm/msm/adreno: Disable IFPC when sysprof is active Akhil P Oommen
` (4 subsequent siblings)
16 siblings, 0 replies; 31+ messages in thread
From: Akhil P Oommen @ 2025-09-08 8:27 UTC (permalink / raw)
To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, Antonino Maniscalco, Neil Armstrong
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 | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index bba09c02f9809ed24b4a9c30b1eb993ce01c7ec0..61538b6912883a0e7ec7802cf5f5cfc8649ece2b 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -2417,13 +2417,24 @@ 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 [flat|nested] 31+ messages in thread* [PATCH v2 13/16] drm/msm/adreno: Disable IFPC when sysprof is active
2025-09-08 8:26 [PATCH v2 00/16] drm/msm: Support for Inter Frame Power Collapse (IFPC) feature Akhil P Oommen
` (11 preceding siblings ...)
2025-09-08 8:27 ` [PATCH v2 12/16] drm/msm/a6xx: Fix hangcheck " Akhil P Oommen
@ 2025-09-08 8:27 ` Akhil P Oommen
2025-09-08 8:27 ` [PATCH v2 14/16] drm/msm/a6xx: Make crashstate capture IFPC safe Akhil P Oommen
` (3 subsequent siblings)
16 siblings, 0 replies; 31+ messages in thread
From: Akhil P Oommen @ 2025-09-08 8:27 UTC (permalink / raw)
To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, Antonino Maniscalco, Neil Armstrong
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 d6297cc7fe664a74224c441e877050612714a3e4..d76b6b766d4a644d342f62435892d54ebd7192e5 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -1157,6 +1157,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) {
@@ -1204,6 +1209,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 40c4c0445b8e4349c9111850df9c0b1d355f0b73..06cfc294016f513a33eb4004c7892996ac9e0435 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
@@ -125,6 +125,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 61538b6912883a0e7ec7802cf5f5cfc8649ece2b..b54c88fb27d57f81306163e699961803ff765bdb 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -2533,6 +2533,7 @@ static const struct adreno_gpu_funcs funcs = {
.create_private_vm = a6xx_create_private_vm,
.get_rptr = a6xx_get_rptr,
.progress = a6xx_progress,
+ .sysprof_setup = a6xx_gmu_sysprof_setup,
},
.get_timestamp = a6xx_gmu_get_timestamp,
};
@@ -2593,6 +2594,7 @@ static const struct adreno_gpu_funcs funcs_a7xx = {
.create_private_vm = a6xx_create_private_vm,
.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 e736c59d566b3fcf8c62a212494e3b110c09caa9..124c63c4615930b00c64e488a498163ae35afccd 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
@@ -254,6 +254,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 866bb090af064666586cea7125254bd375b7a35c..a597f2bee30b6370ecc3639bfe1072c85993e789 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -92,6 +92,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 8617a82cd6b38a74d996ae6965a253a29a231fa4..d53dfad16bde7d5ae7b1e48f221696d525a10965 100644
--- a/drivers/gpu/drm/msm/msm_submitqueue.c
+++ b/drivers/gpu/drm/msm/msm_submitqueue.c
@@ -40,6 +40,10 @@ int msm_context_set_sysprof(struct msm_context *ctx, struct msm_gpu *gpu, int sy
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 [flat|nested] 31+ messages in thread* [PATCH v2 14/16] drm/msm/a6xx: Make crashstate capture IFPC safe
2025-09-08 8:26 [PATCH v2 00/16] drm/msm: Support for Inter Frame Power Collapse (IFPC) feature Akhil P Oommen
` (12 preceding siblings ...)
2025-09-08 8:27 ` [PATCH v2 13/16] drm/msm/adreno: Disable IFPC when sysprof is active Akhil P Oommen
@ 2025-09-08 8:27 ` Akhil P Oommen
2025-09-08 8:27 ` [PATCH v2 15/16] drm/msm/a6xx: Enable IFPC on Adreno X1-85 Akhil P Oommen
` (2 subsequent siblings)
16 siblings, 0 replies; 31+ messages in thread
From: Akhil P Oommen @ 2025-09-08 8:27 UTC (permalink / raw)
To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, Antonino Maniscalco, Neil Armstrong
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 d76b6b766d4a644d342f62435892d54ebd7192e5..81076349d69c8c13e6c6b4e1c336c2d990ebda6d 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 b54c88fb27d57f81306163e699961803ff765bdb..76dd78f5c48ea818a2aa209e0c0c88bc5e8f4e06 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -1537,21 +1537,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);
@@ -2412,6 +2416,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 d5d1271fce611b60121b36f4b772d6f5e0093d2b..4c7f3c642f6ac0a397ac3b282966d25cd4488d3e 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
@@ -1586,8 +1586,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);
@@ -1608,15 +1607,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 [flat|nested] 31+ messages in thread* [PATCH v2 15/16] drm/msm/a6xx: Enable IFPC on Adreno X1-85
2025-09-08 8:26 [PATCH v2 00/16] drm/msm: Support for Inter Frame Power Collapse (IFPC) feature Akhil P Oommen
` (13 preceding siblings ...)
2025-09-08 8:27 ` [PATCH v2 14/16] drm/msm/a6xx: Make crashstate capture IFPC safe Akhil P Oommen
@ 2025-09-08 8:27 ` Akhil P Oommen
2025-09-08 15:24 ` Konrad Dybcio
2025-10-31 23:43 ` Chia-I Wu
2025-09-08 8:27 ` [PATCH v2 16/16] drm/msm/a6xx: Enable IFPC on A750 GPU Akhil P Oommen
2025-09-08 17:11 ` [PATCH v2 00/16] drm/msm: Support for Inter Frame Power Collapse (IFPC) feature Neil Armstrong
16 siblings, 2 replies; 31+ messages in thread
From: Akhil P Oommen @ 2025-09-08 8:27 UTC (permalink / raw)
To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, Antonino Maniscalco, Neil Armstrong
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 | 68 ++++++++++++++++++++++++++++++-
drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 15 +++++--
drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 1 +
3 files changed, 79 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
index 00e1afd46b81546eec03e22cda9e9a604f6f3b60..547c046730a9b50a82cc9b27f08a5b1eeb08dced 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,14 @@ 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,
},
@@ -1466,6 +1531,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 76dd78f5c48ea818a2aa209e0c0c88bc5e8f4e06..91a2a82c4f388ca6b052172efdd7255165f3c04a 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -828,11 +828,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
@@ -843,6 +842,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 124c63c4615930b00c64e488a498163ae35afccd..0b17d36c36a9567e6afa4269ae7783ed3578e40e 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
@@ -45,6 +45,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 [flat|nested] 31+ messages in thread* Re: [PATCH v2 15/16] drm/msm/a6xx: Enable IFPC on Adreno X1-85
2025-09-08 8:27 ` [PATCH v2 15/16] drm/msm/a6xx: Enable IFPC on Adreno X1-85 Akhil P Oommen
@ 2025-09-08 15:24 ` Konrad Dybcio
2025-10-31 23:43 ` Chia-I Wu
1 sibling, 0 replies; 31+ messages in thread
From: Konrad Dybcio @ 2025-09-08 15:24 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, Antonino Maniscalco, Neil Armstrong
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel
On 9/8/25 10:27 AM, 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>
> ---
[...]
> @@ -1432,12 +1495,14 @@ 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,
> },
> @@ -1466,6 +1531,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,
The latter one should be part of the last patch
Konrad
^ permalink raw reply [flat|nested] 31+ messages in thread* Re: [PATCH v2 15/16] drm/msm/a6xx: Enable IFPC on Adreno X1-85
2025-09-08 8:27 ` [PATCH v2 15/16] drm/msm/a6xx: Enable IFPC on Adreno X1-85 Akhil P Oommen
2025-09-08 15:24 ` Konrad Dybcio
@ 2025-10-31 23:43 ` Chia-I Wu
2025-11-01 12:57 ` Rob Clark
1 sibling, 1 reply; 31+ messages in thread
From: Chia-I Wu @ 2025-10-31 23:43 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, Antonino Maniscalco, Neil Armstrong,
linux-arm-msm, dri-devel, freedreno, linux-kernel
On Mon, Sep 8, 2025 at 1:28 AM Akhil P Oommen <akhilpo@oss.qualcomm.com> 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 | 68 ++++++++++++++++++++++++++++++-
> drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 15 +++++--
> drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 1 +
> 3 files changed, 79 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
> index 00e1afd46b81546eec03e22cda9e9a604f6f3b60..547c046730a9b50a82cc9b27f08a5b1eeb08dced 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,14 @@ 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,
> },
> @@ -1466,6 +1531,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 76dd78f5c48ea818a2aa209e0c0c88bc5e8f4e06..91a2a82c4f388ca6b052172efdd7255165f3c04a 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> @@ -828,11 +828,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;
This is NULL on X1-45 and causes
[ 8.795603] Unable to handle kernel NULL pointer dereference at
virtual address 0000000000000008
> + lock->ifpc_list_len = reglist->count;
>
> /*
> * For each entry in each of the lists, write the offset and the current
> @@ -843,6 +842,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 124c63c4615930b00c64e488a498163ae35afccd..0b17d36c36a9567e6afa4269ae7783ed3578e40e 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
> @@ -45,6 +45,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 [flat|nested] 31+ messages in thread* Re: [PATCH v2 15/16] drm/msm/a6xx: Enable IFPC on Adreno X1-85
2025-10-31 23:43 ` Chia-I Wu
@ 2025-11-01 12:57 ` Rob Clark
2025-11-01 19:52 ` Akhil P Oommen
0 siblings, 1 reply; 31+ messages in thread
From: Rob Clark @ 2025-11-01 12:57 UTC (permalink / raw)
To: Chia-I Wu
Cc: Akhil P Oommen, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, Antonino Maniscalco, Neil Armstrong,
linux-arm-msm, dri-devel, freedreno, linux-kernel
On Fri, Oct 31, 2025 at 4:43 PM Chia-I Wu <olvaffe@gmail.com> wrote:
>
> On Mon, Sep 8, 2025 at 1:28 AM Akhil P Oommen <akhilpo@oss.qualcomm.com> 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 | 68 ++++++++++++++++++++++++++++++-
> > drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 15 +++++--
> > drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 1 +
> > 3 files changed, 79 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
> > index 00e1afd46b81546eec03e22cda9e9a604f6f3b60..547c046730a9b50a82cc9b27f08a5b1eeb08dced 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,14 @@ 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,
> > },
> > @@ -1466,6 +1531,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 76dd78f5c48ea818a2aa209e0c0c88bc5e8f4e06..91a2a82c4f388ca6b052172efdd7255165f3c04a 100644
> > --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> > +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> > @@ -828,11 +828,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;
> This is NULL on X1-45 and causes
>
> [ 8.795603] Unable to handle kernel NULL pointer dereference at
> virtual address 0000000000000008
Hmm, this is probably going to happen on all a7xx which don't have
IFPC from the looks of it.
We should either check for the IFPC quirk.. or maybe just drop the
quirk and decide whether IFPC is supported based on ifpc_reglist !=
NULL?
(That said, we probably do want to have IFPC enabled for x1-45)
BR,
-R
> > + lock->ifpc_list_len = reglist->count;
> >
> > /*
> > * For each entry in each of the lists, write the offset and the current
> > @@ -843,6 +842,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 124c63c4615930b00c64e488a498163ae35afccd..0b17d36c36a9567e6afa4269ae7783ed3578e40e 100644
> > --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
> > +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
> > @@ -45,6 +45,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 [flat|nested] 31+ messages in thread* Re: [PATCH v2 15/16] drm/msm/a6xx: Enable IFPC on Adreno X1-85
2025-11-01 12:57 ` Rob Clark
@ 2025-11-01 19:52 ` Akhil P Oommen
2025-11-02 17:55 ` Chia-I Wu
0 siblings, 1 reply; 31+ messages in thread
From: Akhil P Oommen @ 2025-11-01 19:52 UTC (permalink / raw)
To: rob.clark, Chia-I Wu
Cc: Sean Paul, Konrad Dybcio, Dmitry Baryshkov, Abhinav Kumar,
Jessica Zhang, Marijn Suijten, David Airlie, Simona Vetter,
Antonino Maniscalco, Neil Armstrong, linux-arm-msm, dri-devel,
freedreno, linux-kernel
On 11/1/2025 6:27 PM, Rob Clark wrote:
> On Fri, Oct 31, 2025 at 4:43 PM Chia-I Wu <olvaffe@gmail.com> wrote:
>>
>> On Mon, Sep 8, 2025 at 1:28 AM Akhil P Oommen <akhilpo@oss.qualcomm.com> 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 | 68 ++++++++++++++++++++++++++++++-
>>> drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 15 +++++--
>>> drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 1 +
>>> 3 files changed, 79 insertions(+), 5 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
>>> index 00e1afd46b81546eec03e22cda9e9a604f6f3b60..547c046730a9b50a82cc9b27f08a5b1eeb08dced 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,14 @@ 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,
>>> },
>>> @@ -1466,6 +1531,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 76dd78f5c48ea818a2aa209e0c0c88bc5e8f4e06..91a2a82c4f388ca6b052172efdd7255165f3c04a 100644
>>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>>> @@ -828,11 +828,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;
>> This is NULL on X1-45 and causes
>>
>> [ 8.795603] Unable to handle kernel NULL pointer dereference at
>> virtual address 0000000000000008
>
> Hmm, this is probably going to happen on all a7xx which don't have
> IFPC from the looks of it.
>
> We should either check for the IFPC quirk.. or maybe just drop the
> quirk and decide whether IFPC is supported based on ifpc_reglist !=
> NULL?
>
> (That said, we probably do want to have IFPC enabled for x1-45)
We should add a check for IFPC quirk here. Chia, do you plan to send a fix?
To enable IFPC, we can just add a750_ifpc_reglist_regs[] to
adreno_gpu->info->a6xx->ifpc_reglist and enable the IFPC quirk.
-Akhil.
>
> BR,
> -R
>
>>> + lock->ifpc_list_len = reglist->count;
>>>
>>> /*
>>> * For each entry in each of the lists, write the offset and the current
>>> @@ -843,6 +842,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 124c63c4615930b00c64e488a498163ae35afccd..0b17d36c36a9567e6afa4269ae7783ed3578e40e 100644
>>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
>>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
>>> @@ -45,6 +45,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 [flat|nested] 31+ messages in thread* Re: [PATCH v2 15/16] drm/msm/a6xx: Enable IFPC on Adreno X1-85
2025-11-01 19:52 ` Akhil P Oommen
@ 2025-11-02 17:55 ` Chia-I Wu
2025-11-03 15:11 ` Akhil P Oommen
0 siblings, 1 reply; 31+ messages in thread
From: Chia-I Wu @ 2025-11-02 17: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, Antonino Maniscalco, Neil Armstrong,
linux-arm-msm, dri-devel, freedreno, linux-kernel
On Sat, Nov 1, 2025 at 12:52 PM Akhil P Oommen <akhilpo@oss.qualcomm.com> wrote:
>
> On 11/1/2025 6:27 PM, Rob Clark wrote:
> > On Fri, Oct 31, 2025 at 4:43 PM Chia-I Wu <olvaffe@gmail.com> wrote:
> >>
> >> On Mon, Sep 8, 2025 at 1:28 AM Akhil P Oommen <akhilpo@oss.qualcomm.com> 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 | 68 ++++++++++++++++++++++++++++++-
> >>> drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 15 +++++--
> >>> drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 1 +
> >>> 3 files changed, 79 insertions(+), 5 deletions(-)
> >>>
> >>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
> >>> index 00e1afd46b81546eec03e22cda9e9a604f6f3b60..547c046730a9b50a82cc9b27f08a5b1eeb08dced 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,14 @@ 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,
> >>> },
> >>> @@ -1466,6 +1531,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 76dd78f5c48ea818a2aa209e0c0c88bc5e8f4e06..91a2a82c4f388ca6b052172efdd7255165f3c04a 100644
> >>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> >>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> >>> @@ -828,11 +828,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;
> >> This is NULL on X1-45 and causes
> >>
> >> [ 8.795603] Unable to handle kernel NULL pointer dereference at
> >> virtual address 0000000000000008
> >
> > Hmm, this is probably going to happen on all a7xx which don't have
> > IFPC from the looks of it.
> >
> > We should either check for the IFPC quirk.. or maybe just drop the
> > quirk and decide whether IFPC is supported based on ifpc_reglist !=
> > NULL?
> >
> > (That said, we probably do want to have IFPC enabled for x1-45)
>
> We should add a check for IFPC quirk here. Chia, do you plan to send a fix?
>
> To enable IFPC, we can just add a750_ifpc_reglist_regs[] to
> adreno_gpu->info->a6xx->ifpc_reglist and enable the IFPC quirk.
Maybe it is easier for you to do the fix? Because I would have several
little questions (what happens when the reglist and the quirk flag are
inconsistent? how about preemption reglist?)
I am happy to do the testing.
>
> -Akhil.
>
> >
> > BR,
> > -R
> >
> >>> + lock->ifpc_list_len = reglist->count;
> >>>
> >>> /*
> >>> * For each entry in each of the lists, write the offset and the current
> >>> @@ -843,6 +842,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 124c63c4615930b00c64e488a498163ae35afccd..0b17d36c36a9567e6afa4269ae7783ed3578e40e 100644
> >>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
> >>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
> >>> @@ -45,6 +45,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 [flat|nested] 31+ messages in thread* Re: [PATCH v2 15/16] drm/msm/a6xx: Enable IFPC on Adreno X1-85
2025-11-02 17:55 ` Chia-I Wu
@ 2025-11-03 15:11 ` Akhil P Oommen
0 siblings, 0 replies; 31+ messages in thread
From: Akhil P Oommen @ 2025-11-03 15:11 UTC (permalink / raw)
To: Chia-I Wu
Cc: rob.clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, Antonino Maniscalco, Neil Armstrong,
linux-arm-msm, dri-devel, freedreno, linux-kernel
On 11/2/2025 11:25 PM, Chia-I Wu wrote:
> On Sat, Nov 1, 2025 at 12:52 PM Akhil P Oommen <akhilpo@oss.qualcomm.com> wrote:
>>
>> On 11/1/2025 6:27 PM, Rob Clark wrote:
>>> On Fri, Oct 31, 2025 at 4:43 PM Chia-I Wu <olvaffe@gmail.com> wrote:
>>>>
>>>> On Mon, Sep 8, 2025 at 1:28 AM Akhil P Oommen <akhilpo@oss.qualcomm.com> 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 | 68 ++++++++++++++++++++++++++++++-
>>>>> drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 15 +++++--
>>>>> drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 1 +
>>>>> 3 files changed, 79 insertions(+), 5 deletions(-)
>>>>>
>>>>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
>>>>> index 00e1afd46b81546eec03e22cda9e9a604f6f3b60..547c046730a9b50a82cc9b27f08a5b1eeb08dced 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,14 @@ 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,
>>>>> },
>>>>> @@ -1466,6 +1531,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 76dd78f5c48ea818a2aa209e0c0c88bc5e8f4e06..91a2a82c4f388ca6b052172efdd7255165f3c04a 100644
>>>>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>>>>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>>>>> @@ -828,11 +828,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;
>>>> This is NULL on X1-45 and causes
>>>>
>>>> [ 8.795603] Unable to handle kernel NULL pointer dereference at
>>>> virtual address 0000000000000008
>>>
>>> Hmm, this is probably going to happen on all a7xx which don't have
>>> IFPC from the looks of it.
>>>
>>> We should either check for the IFPC quirk.. or maybe just drop the
>>> quirk and decide whether IFPC is supported based on ifpc_reglist !=
>>> NULL?
>>>
>>> (That said, we probably do want to have IFPC enabled for x1-45)
>>
>> We should add a check for IFPC quirk here. Chia, do you plan to send a fix?
>>
>> To enable IFPC, we can just add a750_ifpc_reglist_regs[] to
>> adreno_gpu->info->a6xx->ifpc_reglist and enable the IFPC quirk.
> Maybe it is easier for you to do the fix? Because I would have several
> little questions (what happens when the reglist and the quirk flag are
> inconsistent? how about preemption reglist?)
>
> I am happy to do the testing.
No problem. I will send a fix.
-Akhil
>
>>
>> -Akhil.
>>
>>>
>>> BR,
>>> -R
>>>
>>>>> + lock->ifpc_list_len = reglist->count;
>>>>>
>>>>> /*
>>>>> * For each entry in each of the lists, write the offset and the current
>>>>> @@ -843,6 +842,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 124c63c4615930b00c64e488a498163ae35afccd..0b17d36c36a9567e6afa4269ae7783ed3578e40e 100644
>>>>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
>>>>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
>>>>> @@ -45,6 +45,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 [flat|nested] 31+ messages in thread
* [PATCH v2 16/16] drm/msm/a6xx: Enable IFPC on A750 GPU
2025-09-08 8:26 [PATCH v2 00/16] drm/msm: Support for Inter Frame Power Collapse (IFPC) feature Akhil P Oommen
` (14 preceding siblings ...)
2025-09-08 8:27 ` [PATCH v2 15/16] drm/msm/a6xx: Enable IFPC on Adreno X1-85 Akhil P Oommen
@ 2025-09-08 8:27 ` Akhil P Oommen
2025-09-08 17:11 ` [PATCH v2 00/16] drm/msm: Support for Inter Frame Power Collapse (IFPC) feature Neil Armstrong
16 siblings, 0 replies; 31+ messages in thread
From: Akhil P Oommen @ 2025-09-08 8:27 UTC (permalink / raw)
To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, Antonino Maniscalco, Neil Armstrong
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Akhil P Oommen
A750 GPU has similar IFPC related configurations like X1-85. Add
the IFPC QUIRK to enable IFPC feature.
Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
---
drivers/gpu/drm/msm/adreno/a6xx_catalog.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
index 547c046730a9b50a82cc9b27f08a5b1eeb08dced..6008f8b0144456c5652dab4c6393b3abb7d709c9 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
@@ -1525,7 +1525,8 @@ 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,
.zapfw = "gen70900_zap.mbn",
.a6xx = &(const struct a6xx_info) {
--
2.50.1
^ permalink raw reply [flat|nested] 31+ messages in thread* Re: [PATCH v2 00/16] drm/msm: Support for Inter Frame Power Collapse (IFPC) feature
2025-09-08 8:26 [PATCH v2 00/16] drm/msm: Support for Inter Frame Power Collapse (IFPC) feature Akhil P Oommen
` (15 preceding siblings ...)
2025-09-08 8:27 ` [PATCH v2 16/16] drm/msm/a6xx: Enable IFPC on A750 GPU Akhil P Oommen
@ 2025-09-08 17:11 ` Neil Armstrong
16 siblings, 0 replies; 31+ messages in thread
From: Neil Armstrong @ 2025-09-08 17:11 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, Antonino Maniscalco
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Konrad Dybcio, stable
On 08/09/2025 10:26, Akhil P Oommen wrote:
> 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. Rest of the patches are additional changes required for
> IFPC. This series adds the necessary restore register list for X1-85/A750
> GPUs and enables IFPC support for them.
>
> 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>
> To: Antonino Maniscalco <antomani103@gmail.com>
> To: Neil Armstrong <neil.armstrong@linaro.org>
> Cc: linux-arm-msm@vger.kernel.org
> Cc: dri-devel@lists.freedesktop.org
> Cc: freedreno@lists.freedesktop.org
> Cc: linux-kernel@vger.kernel.org
> Cc: Antonino Maniscalco <antomani103@gmail.com>
> Cc: Neil Armstrong <neil.armstrong@linaro.org>
>
> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
> ---
> Changes in v2:
> - Elaborate commit text and add Fixes tags (Dmitry/Konrad)
> - Document GMU_IDLE_STATE_RESERVED (Konrad)
> - Add a memory barrier in fenced_write
> - Move an error print in fenced_write to after polling
> - %s/set_keepalive_vote/a6xx[gpu|preempt]_keepalive_vote (Dmitry)
> - Add an "unlikely()" to read_gmu_ao_counter() (Konrad/Rob)
> - Define IFPC_LONG_HYST to document a magic number
> - Add a new patch to enable IFPC on A750 GPU (Neil/Antonino)
> - Drop patch 12 & 17 from v1 revision
> - Link to v1: https://lore.kernel.org/r/20250720-ifpc-support-v1-0-9347aa5bcbd6@oss.qualcomm.com
>
> ---
> Akhil P Oommen (16):
> drm/msm: Update GMU register xml
> 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: a6xx: Refactor a6xx_sptprac_enable()
> 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/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/a6xx: Enable IFPC on A750 GPU
>
> drivers/gpu/drm/msm/adreno/a6xx_catalog.c | 71 ++++++-
> drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 105 ++++++++--
> drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 14 ++
> drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 221 ++++++++++++++++++----
> 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 | 34 +++-
> 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_trace.h | 12 ++
> drivers/gpu/drm/msm/msm_submitqueue.c | 4 +
> drivers/gpu/drm/msm/registers/adreno/a6xx_gmu.xml | 11 ++
> 13 files changed, 459 insertions(+), 76 deletions(-)
> ---
> base-commit: 5cc61f86dff464a63b6a6e4758f26557fda4d494
> change-id: 20241216-ifpc-support-3b80167b3532
>
> Best regards,
Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8650-HDK
Thanks,
Neil
^ permalink raw reply [flat|nested] 31+ messages in thread