The Adreno GMU Management Unit (GMU) can also scale the DDR Bandwidth
along the Frequency and Power Domain level, until now we left the OPP
core scale the OPP bandwidth via the interconnect path.
In order to enable bandwidth voting via the GPU Management
Unit (GMU), when an opp is set by devfreq we also look for
the corresponding bandwidth index in the previously generated
bw_table and pass this value along the frequency index to the GMU.
Since we now vote for all resources via the GMU, setting the OPP
is no more needed, so we can completely skip calling
dev_pm_opp_set_opp() in this situation.
Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
---
drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 17 +++++++++++++++--
drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 2 +-
drivers/gpu/drm/msm/adreno/a6xx_hfi.c | 6 +++---
3 files changed, 19 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index 504a7c5d5a9df4c787951f2ae3a69d566d205ad5..1131c3521ebbb0d053aceb162052ed01e197726a 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -113,6 +113,7 @@ void a6xx_gmu_set_freq(struct msm_gpu *gpu, struct dev_pm_opp *opp,
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
u32 perf_index;
+ u32 bw_index = 0;
unsigned long gpu_freq;
int ret = 0;
@@ -125,6 +126,16 @@ void a6xx_gmu_set_freq(struct msm_gpu *gpu, struct dev_pm_opp *opp,
if (gpu_freq == gmu->gpu_freqs[perf_index])
break;
+ /* If enabled, find the corresponding DDR bandwidth index */
+ if ((adreno_gpu->info->quirks & ADRENO_QUIRK_GMU_BW_VOTE) && gmu->nr_gpu_bws) {
+ unsigned int bw = dev_pm_opp_get_bandwidth(opp, true, 0);
+
+ for (bw_index = 0; bw_index < gmu->nr_gpu_bws - 1; bw_index++) {
+ if (bw == gmu->gpu_bw_table[bw_index])
+ break;
+ }
+ }
+
gmu->current_perf_index = perf_index;
gmu->freq = gmu->gpu_freqs[perf_index];
@@ -140,8 +151,10 @@ void a6xx_gmu_set_freq(struct msm_gpu *gpu, struct dev_pm_opp *opp,
return;
if (!gmu->legacy) {
- a6xx_hfi_set_freq(gmu, perf_index);
- dev_pm_opp_set_opp(&gpu->pdev->dev, opp);
+ a6xx_hfi_set_freq(gmu, perf_index, bw_index);
+ /* With Bandwidth voting, we now vote for all resources, so skip OPP set */
+ if (bw_index)
+ dev_pm_opp_set_opp(&gpu->pdev->dev, opp);
return;
}
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
index 95c632d8987a517f067c48c61c6c06b9a4f61fc0..9b4f2b1a0c48a133cd5c48713bc321c74eaffce9 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
@@ -205,7 +205,7 @@ void a6xx_hfi_init(struct a6xx_gmu *gmu);
int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state);
void a6xx_hfi_stop(struct a6xx_gmu *gmu);
int a6xx_hfi_send_prep_slumber(struct a6xx_gmu *gmu);
-int a6xx_hfi_set_freq(struct a6xx_gmu *gmu, int index);
+int a6xx_hfi_set_freq(struct a6xx_gmu *gmu, int perf_index, int bw_index);
bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu);
bool a6xx_gmu_sptprac_is_on(struct a6xx_gmu *gmu);
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
index 9a89ba95843e7805d78f0e5ddbe328677b6431dd..e2325c15677f1a1194a811e6ecbb5931bdfb1ad9 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
@@ -752,13 +752,13 @@ static int a6xx_hfi_send_core_fw_start(struct a6xx_gmu *gmu)
sizeof(msg), NULL, 0);
}
-int a6xx_hfi_set_freq(struct a6xx_gmu *gmu, int index)
+int a6xx_hfi_set_freq(struct a6xx_gmu *gmu, int freq_index, int bw_index)
{
struct a6xx_hfi_gx_bw_perf_vote_cmd msg = { 0 };
msg.ack_type = 1; /* blocking */
- msg.freq = index;
- msg.bw = 0; /* TODO: bus scaling */
+ msg.freq = freq_index;
+ msg.bw = bw_index;
return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_GX_BW_PERF_VOTE, &msg,
sizeof(msg), NULL, 0);
--
2.34.1
On Wed, Nov 13, 2024 at 04:48:31PM +0100, Neil Armstrong wrote: > The Adreno GMU Management Unit (GMU) can also scale the DDR Bandwidth > along the Frequency and Power Domain level, until now we left the OPP > core scale the OPP bandwidth via the interconnect path. > > In order to enable bandwidth voting via the GPU Management > Unit (GMU), when an opp is set by devfreq we also look for > the corresponding bandwidth index in the previously generated > bw_table and pass this value along the frequency index to the GMU. > > Since we now vote for all resources via the GMU, setting the OPP > is no more needed, so we can completely skip calling > dev_pm_opp_set_opp() in this situation. > > Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org> > --- > drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 17 +++++++++++++++-- > drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 2 +- > drivers/gpu/drm/msm/adreno/a6xx_hfi.c | 6 +++--- > 3 files changed, 19 insertions(+), 6 deletions(-) > > diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c > index 504a7c5d5a9df4c787951f2ae3a69d566d205ad5..1131c3521ebbb0d053aceb162052ed01e197726a 100644 > --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c > +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c > @@ -113,6 +113,7 @@ void a6xx_gmu_set_freq(struct msm_gpu *gpu, struct dev_pm_opp *opp, > struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); > struct a6xx_gmu *gmu = &a6xx_gpu->gmu; > u32 perf_index; > + u32 bw_index = 0; > unsigned long gpu_freq; > int ret = 0; > > @@ -125,6 +126,16 @@ void a6xx_gmu_set_freq(struct msm_gpu *gpu, struct dev_pm_opp *opp, > if (gpu_freq == gmu->gpu_freqs[perf_index]) > break; > > + /* If enabled, find the corresponding DDR bandwidth index */ > + if ((adreno_gpu->info->quirks & ADRENO_QUIRK_GMU_BW_VOTE) && gmu->nr_gpu_bws) { > + unsigned int bw = dev_pm_opp_get_bandwidth(opp, true, 0); > + > + for (bw_index = 0; bw_index < gmu->nr_gpu_bws - 1; bw_index++) { > + if (bw == gmu->gpu_bw_table[bw_index]) > + break; > + } > + } > + > gmu->current_perf_index = perf_index; > gmu->freq = gmu->gpu_freqs[perf_index]; > > @@ -140,8 +151,10 @@ void a6xx_gmu_set_freq(struct msm_gpu *gpu, struct dev_pm_opp *opp, > return; > > if (!gmu->legacy) { > - a6xx_hfi_set_freq(gmu, perf_index); > - dev_pm_opp_set_opp(&gpu->pdev->dev, opp); > + a6xx_hfi_set_freq(gmu, perf_index, bw_index); > + /* With Bandwidth voting, we now vote for all resources, so skip OPP set */ > + if (bw_index) if (!bw_index) ??? Also should there be a 0 vote too in case we are shutting down / suspending? > + dev_pm_opp_set_opp(&gpu->pdev->dev, opp); > return; > } > > diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h > index 95c632d8987a517f067c48c61c6c06b9a4f61fc0..9b4f2b1a0c48a133cd5c48713bc321c74eaffce9 100644 > --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h > +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h > @@ -205,7 +205,7 @@ void a6xx_hfi_init(struct a6xx_gmu *gmu); > int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state); > void a6xx_hfi_stop(struct a6xx_gmu *gmu); > int a6xx_hfi_send_prep_slumber(struct a6xx_gmu *gmu); > -int a6xx_hfi_set_freq(struct a6xx_gmu *gmu, int index); > +int a6xx_hfi_set_freq(struct a6xx_gmu *gmu, int perf_index, int bw_index); > > bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu); > bool a6xx_gmu_sptprac_is_on(struct a6xx_gmu *gmu); > diff --git a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c > index 9a89ba95843e7805d78f0e5ddbe328677b6431dd..e2325c15677f1a1194a811e6ecbb5931bdfb1ad9 100644 > --- a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c > +++ b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c > @@ -752,13 +752,13 @@ static int a6xx_hfi_send_core_fw_start(struct a6xx_gmu *gmu) > sizeof(msg), NULL, 0); > } > > -int a6xx_hfi_set_freq(struct a6xx_gmu *gmu, int index) > +int a6xx_hfi_set_freq(struct a6xx_gmu *gmu, int freq_index, int bw_index) > { > struct a6xx_hfi_gx_bw_perf_vote_cmd msg = { 0 }; > > msg.ack_type = 1; /* blocking */ > - msg.freq = index; > - msg.bw = 0; /* TODO: bus scaling */ > + msg.freq = freq_index; > + msg.bw = bw_index; > > return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_GX_BW_PERF_VOTE, &msg, > sizeof(msg), NULL, 0); > > -- > 2.34.1 > -- With best wishes Dmitry
On 15/11/2024 08:28, Dmitry Baryshkov wrote: > On Wed, Nov 13, 2024 at 04:48:31PM +0100, Neil Armstrong wrote: >> The Adreno GMU Management Unit (GMU) can also scale the DDR Bandwidth >> along the Frequency and Power Domain level, until now we left the OPP >> core scale the OPP bandwidth via the interconnect path. >> >> In order to enable bandwidth voting via the GPU Management >> Unit (GMU), when an opp is set by devfreq we also look for >> the corresponding bandwidth index in the previously generated >> bw_table and pass this value along the frequency index to the GMU. >> >> Since we now vote for all resources via the GMU, setting the OPP >> is no more needed, so we can completely skip calling >> dev_pm_opp_set_opp() in this situation. >> >> Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org> >> --- >> drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 17 +++++++++++++++-- >> drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 2 +- >> drivers/gpu/drm/msm/adreno/a6xx_hfi.c | 6 +++--- >> 3 files changed, 19 insertions(+), 6 deletions(-) >> >> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c >> index 504a7c5d5a9df4c787951f2ae3a69d566d205ad5..1131c3521ebbb0d053aceb162052ed01e197726a 100644 >> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c >> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c >> @@ -113,6 +113,7 @@ void a6xx_gmu_set_freq(struct msm_gpu *gpu, struct dev_pm_opp *opp, >> struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); >> struct a6xx_gmu *gmu = &a6xx_gpu->gmu; >> u32 perf_index; >> + u32 bw_index = 0; >> unsigned long gpu_freq; >> int ret = 0; >> >> @@ -125,6 +126,16 @@ void a6xx_gmu_set_freq(struct msm_gpu *gpu, struct dev_pm_opp *opp, >> if (gpu_freq == gmu->gpu_freqs[perf_index]) >> break; >> >> + /* If enabled, find the corresponding DDR bandwidth index */ >> + if ((adreno_gpu->info->quirks & ADRENO_QUIRK_GMU_BW_VOTE) && gmu->nr_gpu_bws) { >> + unsigned int bw = dev_pm_opp_get_bandwidth(opp, true, 0); >> + >> + for (bw_index = 0; bw_index < gmu->nr_gpu_bws - 1; bw_index++) { >> + if (bw == gmu->gpu_bw_table[bw_index]) >> + break; >> + } >> + } >> + >> gmu->current_perf_index = perf_index; >> gmu->freq = gmu->gpu_freqs[perf_index]; >> >> @@ -140,8 +151,10 @@ void a6xx_gmu_set_freq(struct msm_gpu *gpu, struct dev_pm_opp *opp, >> return; >> >> if (!gmu->legacy) { >> - a6xx_hfi_set_freq(gmu, perf_index); >> - dev_pm_opp_set_opp(&gpu->pdev->dev, opp); >> + a6xx_hfi_set_freq(gmu, perf_index, bw_index); >> + /* With Bandwidth voting, we now vote for all resources, so skip OPP set */ >> + if (bw_index) > > if (!bw_index) ??? Good catch, I added it back wrongly when refactoring... > > Also should there be a 0 vote too in case we are shutting down / > suspending? It's already handled in a6xx_gmu_stop() > >> + dev_pm_opp_set_opp(&gpu->pdev->dev, opp); >> return; >> } >> >> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h >> index 95c632d8987a517f067c48c61c6c06b9a4f61fc0..9b4f2b1a0c48a133cd5c48713bc321c74eaffce9 100644 >> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h >> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h >> @@ -205,7 +205,7 @@ void a6xx_hfi_init(struct a6xx_gmu *gmu); >> int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state); >> void a6xx_hfi_stop(struct a6xx_gmu *gmu); >> int a6xx_hfi_send_prep_slumber(struct a6xx_gmu *gmu); >> -int a6xx_hfi_set_freq(struct a6xx_gmu *gmu, int index); >> +int a6xx_hfi_set_freq(struct a6xx_gmu *gmu, int perf_index, int bw_index); >> >> bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu); >> bool a6xx_gmu_sptprac_is_on(struct a6xx_gmu *gmu); >> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c >> index 9a89ba95843e7805d78f0e5ddbe328677b6431dd..e2325c15677f1a1194a811e6ecbb5931bdfb1ad9 100644 >> --- a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c >> +++ b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c >> @@ -752,13 +752,13 @@ static int a6xx_hfi_send_core_fw_start(struct a6xx_gmu *gmu) >> sizeof(msg), NULL, 0); >> } >> >> -int a6xx_hfi_set_freq(struct a6xx_gmu *gmu, int index) >> +int a6xx_hfi_set_freq(struct a6xx_gmu *gmu, int freq_index, int bw_index) >> { >> struct a6xx_hfi_gx_bw_perf_vote_cmd msg = { 0 }; >> >> msg.ack_type = 1; /* blocking */ >> - msg.freq = index; >> - msg.bw = 0; /* TODO: bus scaling */ >> + msg.freq = freq_index; >> + msg.bw = bw_index; >> >> return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_GX_BW_PERF_VOTE, &msg, >> sizeof(msg), NULL, 0); >> >> -- >> 2.34.1 >> >
© 2016 - 2024 Red Hat, Inc.