Message ID | 20241021-gpu-acd-v2-0-9c25a62803bc@quicinc.com |
---|---|
Headers | show |
Series | Support for GPU ACD feature on Adreno X1-85 | expand |
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_akhilpo@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); ? > + } > + > + 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 ? --- bod