On 10/22/2024 2:37 PM, Bryan O'Donoghue wrote: > On 21/10/2024 12:53, Akhil P Oommen wrote: >> ACD a.k.a Adaptive Clock Distribution is a feature which helps to reduce >> the power consumption. In some chipsets, it is also a requirement to >> support higher GPU frequencies. This patch adds support for GPU ACD by >> sending necessary data to GMU and AOSS. The feature support for the >> chipset is detected based on devicetree data. >> >> Signed-off-by: Akhil P Oommen <quic_akhi...@quicinc.com> >> --- >> drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 81 >> ++++++++++++++++++++++++++++------- >> drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 1 + >> drivers/gpu/drm/msm/adreno/a6xx_hfi.c | 36 ++++++++++++++++ >> drivers/gpu/drm/msm/adreno/a6xx_hfi.h | 21 +++++++++ >> 4 files changed, 124 insertions(+), 15 deletions(-) >> >> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c >> b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c >> index 37927bdd6fbe..09fb3f397dbb 100644 >> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c >> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c >> @@ -1021,14 +1021,6 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu) >> gmu->hung = false; >> - /* Notify AOSS about the ACD state (unimplemented for now => disable >> it) */ >> - if (!IS_ERR(gmu->qmp)) { >> - ret = qmp_send(gmu->qmp, "{class: gpu, res: acd, val: %d}", >> - 0 /* Hardcode ACD to be disabled for now */); >> - if (ret) >> - dev_err(gmu->dev, "failed to send GPU ACD state\n"); >> - } >> - >> /* Turn on the resources */ >> pm_runtime_get_sync(gmu->dev); >> @@ -1476,6 +1468,64 @@ static int a6xx_gmu_pwrlevels_probe(struct a6xx_gmu >> *gmu) >> return a6xx_gmu_rpmh_votes_init(gmu); >> } >> +static int a6xx_gmu_acd_probe(struct a6xx_gmu *gmu) >> +{ >> + struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu); >> + struct a6xx_hfi_acd_table *cmd = &gmu->acd_table; >> + struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; >> + struct msm_gpu *gpu = &adreno_gpu->base; >> + int ret, i, cmd_idx = 0; >> + >> + cmd->version = 1; >> + cmd->stride = 1; >> + cmd->enable_by_level = 0; >> + >> + /* Skip freq = 0 and parse acd-level for rest of the OPPs */ >> + for (i = 1; i < gmu->nr_gpu_freqs; i++) { >> + struct dev_pm_opp *opp; >> + struct device_node *np; >> + unsigned long freq; >> + u32 val; >> + >> + freq = gmu->gpu_freqs[i]; >> + opp = dev_pm_opp_find_freq_exact(&gpu->pdev->dev, freq, true); >> + np = dev_pm_opp_get_of_node(opp); >> + >> + ret = of_property_read_u32(np, "qcom,opp-acd-level", &val); >> + of_node_put(np); >> + dev_pm_opp_put(opp); >> + if (ret == -EINVAL) >> + continue; >> + else if (ret) { >> + DRM_DEV_ERROR(gmu->dev, "Unable to read acd level for freq >> %lu\n", freq); >> + return ret; >> + } >> + >> + cmd->enable_by_level |= BIT(i); >> + cmd->data[cmd_idx++] = val; > > How do you know that cmd_idx is always < sizeof(cmd->data); ?
Because "i < nr_gpu_freqs". I can think of some potential improvements here, but that is outside the scope of this patch. > >> + } >> + >> + cmd->num_levels = cmd_idx; >> + >> + /* We are done here if ACD is not required for any of the OPPs */ >> + if (!cmd->enable_by_level) >> + return 0; >> + >> + /* Initialize qmp node to talk to AOSS */ >> + gmu->qmp = qmp_get(gmu->dev); >> + if (IS_ERR(gmu->qmp)) { >> + cmd->enable_by_level = 0; >> + return dev_err_probe(gmu->dev, PTR_ERR(gmu->qmp), "Failed to >> initialize qmp\n"); >> + } >> + >> + /* Notify AOSS about the ACD state */ >> + ret = qmp_send(gmu->qmp, "{class: gpu, res: acd, val: %d}", 1); >> + if (ret) >> + DRM_DEV_ERROR(gmu->dev, "failed to send GPU ACD state\n"); >> + >> + return 0; > > Shouldn't the ret from gmp_send() get propogated in the return of this > function ? > > i.e. how can your probe be successful if the notification failed ? Failure to send this message to AOP is not worth failing the probe. We just loose a little bit of power savings. -Akhil. > > --- > bod