Skip to content

Commit 7047e65

Browse files
superna9999robclark
authored andcommitted
drm/msm: adreno: find bandwidth index of OPP and set it along freq index
The Adreno GPU 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. The GMU also takes another vote called AB which is a 16bit quantized value of the floor bandwidth against the maximum supported bandwidth. The AB is calculated with a default 25% of the bandwidth like the downstream implementation too inform the GMU firmware the minimal quantity of bandwidth we require for this OPP. Only pass the AB vote starting from A750 GPUs. 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. Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> Reviewed-by: Akhil P Oommen <quic_akhilpo@quicinc.com> Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org> Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com> Patchwork: https://patchwork.freedesktop.org/patch/629397/ Signed-off-by: Rob Clark <robdclark@chromium.org>
1 parent 8c1b945 commit 7047e65

File tree

5 files changed

+51
-6
lines changed

5 files changed

+51
-6
lines changed

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

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,11 @@ void a6xx_gmu_set_freq(struct msm_gpu *gpu, struct dev_pm_opp *opp,
110110
bool suspended)
111111
{
112112
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
113+
const struct a6xx_info *info = adreno_gpu->info->a6xx;
113114
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
114115
struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
115116
u32 perf_index;
117+
u32 bw_index = 0;
116118
unsigned long gpu_freq;
117119
int ret = 0;
118120

@@ -125,6 +127,37 @@ void a6xx_gmu_set_freq(struct msm_gpu *gpu, struct dev_pm_opp *opp,
125127
if (gpu_freq == gmu->gpu_freqs[perf_index])
126128
break;
127129

130+
/* If enabled, find the corresponding DDR bandwidth index */
131+
if (info->bcms && gmu->nr_gpu_bws > 1) {
132+
unsigned int bw = dev_pm_opp_get_bw(opp, true, 0);
133+
134+
for (bw_index = 0; bw_index < gmu->nr_gpu_bws - 1; bw_index++) {
135+
if (bw == gmu->gpu_bw_table[bw_index])
136+
break;
137+
}
138+
139+
/* Vote AB as a fraction of the max bandwidth, starting from A750 */
140+
if (bw && adreno_is_a750_family(adreno_gpu)) {
141+
u64 tmp;
142+
143+
/* For now, vote for 25% of the bandwidth */
144+
tmp = bw * 25;
145+
do_div(tmp, 100);
146+
147+
/*
148+
* The AB vote consists of a 16 bit wide quantized level
149+
* against the maximum supported bandwidth.
150+
* Quantization can be calculated as below:
151+
* vote = (bandwidth * 2^16) / max bandwidth
152+
*/
153+
tmp *= MAX_AB_VOTE;
154+
do_div(tmp, gmu->gpu_bw_table[gmu->nr_gpu_bws - 1]);
155+
156+
bw_index |= AB_VOTE(clamp(tmp, 1, MAX_AB_VOTE));
157+
bw_index |= AB_VOTE_ENABLE;
158+
}
159+
}
160+
128161
gmu->current_perf_index = perf_index;
129162
gmu->freq = gmu->gpu_freqs[perf_index];
130163

@@ -140,8 +173,10 @@ void a6xx_gmu_set_freq(struct msm_gpu *gpu, struct dev_pm_opp *opp,
140173
return;
141174

142175
if (!gmu->legacy) {
143-
a6xx_hfi_set_freq(gmu, perf_index);
144-
dev_pm_opp_set_opp(&gpu->pdev->dev, opp);
176+
a6xx_hfi_set_freq(gmu, perf_index, bw_index);
177+
/* With Bandwidth voting, we now vote for all resources, so skip OPP set */
178+
if (!bw_index)
179+
dev_pm_opp_set_opp(&gpu->pdev->dev, opp);
145180
return;
146181
}
147182

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ void a6xx_hfi_init(struct a6xx_gmu *gmu);
209209
int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state);
210210
void a6xx_hfi_stop(struct a6xx_gmu *gmu);
211211
int a6xx_hfi_send_prep_slumber(struct a6xx_gmu *gmu);
212-
int a6xx_hfi_set_freq(struct a6xx_gmu *gmu, int index);
212+
int a6xx_hfi_set_freq(struct a6xx_gmu *gmu, u32 perf_index, u32 bw_index);
213213

214214
bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu);
215215
bool a6xx_gmu_sptprac_is_on(struct a6xx_gmu *gmu);

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -772,13 +772,13 @@ static int a6xx_hfi_send_core_fw_start(struct a6xx_gmu *gmu)
772772
sizeof(msg), NULL, 0);
773773
}
774774

775-
int a6xx_hfi_set_freq(struct a6xx_gmu *gmu, int index)
775+
int a6xx_hfi_set_freq(struct a6xx_gmu *gmu, u32 freq_index, u32 bw_index)
776776
{
777777
struct a6xx_hfi_gx_bw_perf_vote_cmd msg = { 0 };
778778

779779
msg.ack_type = 1; /* blocking */
780-
msg.freq = index;
781-
msg.bw = 0; /* TODO: bus scaling */
780+
msg.freq = freq_index;
781+
msg.bw = bw_index;
782782

783783
return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_GX_BW_PERF_VOTE, &msg,
784784
sizeof(msg), NULL, 0);

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,11 @@ struct a6xx_hfi_gx_bw_perf_vote_cmd {
173173
u32 bw;
174174
};
175175

176+
#define AB_VOTE_MASK GENMASK(31, 16)
177+
#define MAX_AB_VOTE (FIELD_MAX(AB_VOTE_MASK) - 1)
178+
#define AB_VOTE(vote) FIELD_PREP(AB_VOTE_MASK, (vote))
179+
#define AB_VOTE_ENABLE BIT(8)
180+
176181
#define HFI_H2F_MSG_PREPARE_SLUMBER 33
177182

178183
struct a6xx_hfi_prep_slumber_cmd {

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,11 @@ static inline int adreno_is_a740_family(struct adreno_gpu *gpu)
559559
gpu->info->family == ADRENO_7XX_GEN3;
560560
}
561561

562+
static inline int adreno_is_a750_family(struct adreno_gpu *gpu)
563+
{
564+
return gpu->info->family == ADRENO_7XX_GEN3;
565+
}
566+
562567
static inline int adreno_is_a7xx(struct adreno_gpu *gpu)
563568
{
564569
/* Update with non-fake (i.e. non-A702) Gen 7 GPUs */

0 commit comments

Comments
 (0)