Message ID | 20240625-topic-smem_speedbin-v4-4-f6f8493ab814@linaro.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Add SMEM-based speedbin matching | expand |
On Tue, Jun 25, 2024 at 08:28:09PM +0200, Konrad Dybcio wrote: > There is no need to reinvent the wheel for simple read-match-set logic. > > Make speedbin discovery and assignment generation independent. > > This implicitly removes the bogus 0x80 / BIT(7) speed bin on A5xx, > which has no representation in hardware whatshowever. > > Signed-off-by: Konrad Dybcio <konrad.dybcio@linaro.org> > --- > drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 34 -------------------- > drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 56 --------------------------------- > drivers/gpu/drm/msm/adreno/adreno_gpu.c | 51 ++++++++++++++++++++++++++---- > drivers/gpu/drm/msm/adreno/adreno_gpu.h | 3 -- > 4 files changed, 45 insertions(+), 99 deletions(-) > > diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c > index c003f970189b..eed6a2eb1731 100644 > --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c > +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c > @@ -1704,38 +1704,6 @@ static const struct adreno_gpu_funcs funcs = { > .get_timestamp = a5xx_get_timestamp, > }; > > -static void check_speed_bin(struct device *dev) > -{ > - struct nvmem_cell *cell; > - u32 val; > - > - /* > - * If the OPP table specifies a opp-supported-hw property then we have > - * to set something with dev_pm_opp_set_supported_hw() or the table > - * doesn't get populated so pick an arbitrary value that should > - * ensure the default frequencies are selected but not conflict with any > - * actual bins > - */ > - val = 0x80; > - > - cell = nvmem_cell_get(dev, "speed_bin"); > - > - if (!IS_ERR(cell)) { > - void *buf = nvmem_cell_read(cell, NULL); > - > - if (!IS_ERR(buf)) { > - u8 bin = *((u8 *) buf); > - > - val = (1 << bin); > - kfree(buf); > - } > - > - nvmem_cell_put(cell); > - } > - > - devm_pm_opp_set_supported_hw(dev, &val, 1); > -} > - > struct msm_gpu *a5xx_gpu_init(struct drm_device *dev) > { > struct msm_drm_private *priv = dev->dev_private; > @@ -1763,8 +1731,6 @@ struct msm_gpu *a5xx_gpu_init(struct drm_device *dev) > > a5xx_gpu->lm_leakage = 0x4E001A; > > - check_speed_bin(&pdev->dev); > - > nr_rings = 4; > > if (config->info->revn == 510) > diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c > index 8ace096bb68c..f038e5f1fe59 100644 > --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c > +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c > @@ -2112,55 +2112,6 @@ static bool a6xx_progress(struct msm_gpu *gpu, struct msm_ringbuffer *ring) > return progress; > } > > -static u32 fuse_to_supp_hw(const struct adreno_info *info, u32 fuse) > -{ > - if (!info->speedbins) > - return UINT_MAX; > - > - for (int i = 0; info->speedbins[i].fuse != SHRT_MAX; i++) > - if (info->speedbins[i].fuse == fuse) > - return BIT(info->speedbins[i].speedbin); > - > - return UINT_MAX; > -} > - > -static int a6xx_set_supported_hw(struct adreno_gpu *adreno_gpu, > - struct device *dev, > - const struct adreno_info *info) > -{ > - u32 supp_hw; > - u32 speedbin; > - int ret; > - > - ret = adreno_read_speedbin(adreno_gpu, dev, &speedbin); > - /* > - * -ENOENT means that the platform doesn't support speedbin which is > - * fine > - */ > - if (ret == -ENOENT) { > - return 0; > - } else if (ret) { > - dev_err_probe(dev, ret, > - "failed to read speed-bin. Some OPPs may not be supported by hardware\n"); > - return ret; > - } > - > - supp_hw = fuse_to_supp_hw(info, speedbin); > - > - if (supp_hw == UINT_MAX) { > - DRM_DEV_ERROR(dev, > - "missing support for speed-bin: %u. Some OPPs may not be supported by hardware\n", > - speedbin); > - supp_hw = BIT(0); /* Default */ > - } > - > - ret = devm_pm_opp_set_supported_hw(dev, &supp_hw, 1); > - if (ret) > - return ret; > - > - return 0; > -} > - > static const struct adreno_gpu_funcs funcs = { > .base = { > .get_param = adreno_get_param, > @@ -2292,13 +2243,6 @@ struct msm_gpu *a6xx_gpu_init(struct drm_device *dev) > > a6xx_llc_slices_init(pdev, a6xx_gpu, is_a7xx); > > - ret = a6xx_set_supported_hw(adreno_gpu, &pdev->dev, config->info); > - if (ret) { > - a6xx_llc_slices_destroy(a6xx_gpu); > - kfree(a6xx_gpu); > - return ERR_PTR(ret); > - } > - > if (is_a7xx) > ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs_a7xx, 1); > else if (adreno_has_gmu_wrapper(adreno_gpu)) > diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c > index 6ffd02f38499..5b4205b76cdf 100644 > --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c > +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c > @@ -1064,8 +1064,8 @@ void adreno_gpu_ocmem_cleanup(struct adreno_ocmem *adreno_ocmem) > adreno_ocmem->hdl); > } > > -int adreno_read_speedbin(struct adreno_gpu *adreno_gpu, > - struct device *dev, u32 *fuse) > +static int adreno_read_speedbin(struct adreno_gpu *adreno_gpu, > + struct device *dev, u32 *fuse) > { > u32 fcode; > int ret; > @@ -1099,6 +1099,46 @@ int adreno_read_speedbin(struct adreno_gpu *adreno_gpu, > return 0; > } > > +#define ADRENO_SPEEDBIN_FUSE_NODATA 0xFFFF /* Made-up large value, expected by mesa */ > +static int adreno_set_speedbin(struct adreno_gpu *adreno_gpu, struct device *dev) > +{ > + const struct adreno_info *info = adreno_gpu->info; > + u32 fuse = ADRENO_SPEEDBIN_FUSE_NODATA; > + u32 supp_hw = UINT_MAX; > + int ret; > + > + /* No speedbins defined for this GPU SKU => allow all defined OPPs */ > + if (!info->speedbins) { > + adreno_gpu->speedbin = ADRENO_SPEEDBIN_FUSE_NODATA; > + return devm_pm_opp_set_supported_hw(dev, &supp_hw, 1); > + } > + > + /* > + * If a real error (not counting older devicetrees having no nvmem references) > + * occurs when trying to get the fuse value, bail out. > + */ > + ret = adreno_read_speedbin(adreno_gpu, dev, &fuse); > + if (ret) { > + return ret; > + } else if (fuse == ADRENO_SPEEDBIN_FUSE_NODATA) { > + /* The info struct has speedbin data, but the DT is too old => allow all OPPs */ > + DRM_DEV_INFO(dev, "No GPU speed bin fuse, please update your device tree\n"); > + return devm_pm_opp_set_supported_hw(dev, &supp_hw, 1); > + } > + > + adreno_gpu->speedbin = fuse; > + > + /* Traverse the known speedbins */ > + for (int i = 0; info->speedbins[i].fuse != SHRT_MAX; i++) { > + if (info->speedbins[i].fuse == fuse) { > + supp_hw = BIT(info->speedbins[i].speedbin); > + return devm_pm_opp_set_supported_hw(dev, &supp_hw, 1); Can we do this if supp_hw property is not present in opp table? -Akhil > + } > + } > + > + return dev_err_probe(dev, -EINVAL, "Unknown speed bin fuse value: 0x%x\n", fuse); > +} > + > int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, > struct adreno_gpu *adreno_gpu, > const struct adreno_gpu_funcs *funcs, int nr_rings) > @@ -1108,7 +1148,6 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, > struct msm_gpu_config adreno_gpu_config = { 0 }; > struct msm_gpu *gpu = &adreno_gpu->base; > const char *gpu_name; > - u32 speedbin; > int ret; > > adreno_gpu->funcs = funcs; > @@ -1135,9 +1174,9 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, > devm_pm_opp_set_clkname(dev, "core"); > } > > - if (adreno_read_speedbin(adreno_gpu, dev, &speedbin) || !speedbin) > - speedbin = 0xffff; > - adreno_gpu->speedbin = speedbin; > + ret = adreno_set_speedbin(adreno_gpu, dev); > + if (ret) > + return ret; > > gpu_name = devm_kasprintf(dev, GFP_KERNEL, "%"ADRENO_CHIPID_FMT, > ADRENO_CHIPID_ARGS(config->chip_id)); > diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h > index 563c08b44624..dc579f7afdc7 100644 > --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h > +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h > @@ -549,9 +549,6 @@ int adreno_fault_handler(struct msm_gpu *gpu, unsigned long iova, int flags, > struct adreno_smmu_fault_info *info, const char *block, > u32 scratch[4]); > > -int adreno_read_speedbin(struct adreno_gpu *adreno_gpu, > - struct device *dev, u32 *speedbin); > - > /* > * For a5xx and a6xx targets load the zap shader that is used to pull the GPU > * out of secure mode > > -- > 2.45.2 >
On 30.06.2024 12:29 PM, Akhil P Oommen wrote: > On Tue, Jun 25, 2024 at 08:28:09PM +0200, Konrad Dybcio wrote: >> There is no need to reinvent the wheel for simple read-match-set logic. >> >> Make speedbin discovery and assignment generation independent. >> >> This implicitly removes the bogus 0x80 / BIT(7) speed bin on A5xx, >> which has no representation in hardware whatshowever. >> >> Signed-off-by: Konrad Dybcio <konrad.dybcio@linaro.org> >> --- [...] >> + >> + /* Traverse the known speedbins */ >> + for (int i = 0; info->speedbins[i].fuse != SHRT_MAX; i++) { >> + if (info->speedbins[i].fuse == fuse) { >> + supp_hw = BIT(info->speedbins[i].speedbin); >> + return devm_pm_opp_set_supported_hw(dev, &supp_hw, 1); > > Can we do this if supp_hw property is not present in opp table? No, but this is also the case without this patchset (a.k.a. no change in behavior). We shouldn't add code complexity to support that case, as having speedbin data in the driver and not the dt means the DT is incomplete, which is not a case we should care about I can however try and add a clearer error path that would perhaps not crash the kernel in this situation.. in a separate patchset Konrad
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c index c003f970189b..eed6a2eb1731 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c @@ -1704,38 +1704,6 @@ static const struct adreno_gpu_funcs funcs = { .get_timestamp = a5xx_get_timestamp, }; -static void check_speed_bin(struct device *dev) -{ - struct nvmem_cell *cell; - u32 val; - - /* - * If the OPP table specifies a opp-supported-hw property then we have - * to set something with dev_pm_opp_set_supported_hw() or the table - * doesn't get populated so pick an arbitrary value that should - * ensure the default frequencies are selected but not conflict with any - * actual bins - */ - val = 0x80; - - cell = nvmem_cell_get(dev, "speed_bin"); - - if (!IS_ERR(cell)) { - void *buf = nvmem_cell_read(cell, NULL); - - if (!IS_ERR(buf)) { - u8 bin = *((u8 *) buf); - - val = (1 << bin); - kfree(buf); - } - - nvmem_cell_put(cell); - } - - devm_pm_opp_set_supported_hw(dev, &val, 1); -} - struct msm_gpu *a5xx_gpu_init(struct drm_device *dev) { struct msm_drm_private *priv = dev->dev_private; @@ -1763,8 +1731,6 @@ struct msm_gpu *a5xx_gpu_init(struct drm_device *dev) a5xx_gpu->lm_leakage = 0x4E001A; - check_speed_bin(&pdev->dev); - nr_rings = 4; if (config->info->revn == 510) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index 8ace096bb68c..f038e5f1fe59 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -2112,55 +2112,6 @@ static bool a6xx_progress(struct msm_gpu *gpu, struct msm_ringbuffer *ring) return progress; } -static u32 fuse_to_supp_hw(const struct adreno_info *info, u32 fuse) -{ - if (!info->speedbins) - return UINT_MAX; - - for (int i = 0; info->speedbins[i].fuse != SHRT_MAX; i++) - if (info->speedbins[i].fuse == fuse) - return BIT(info->speedbins[i].speedbin); - - return UINT_MAX; -} - -static int a6xx_set_supported_hw(struct adreno_gpu *adreno_gpu, - struct device *dev, - const struct adreno_info *info) -{ - u32 supp_hw; - u32 speedbin; - int ret; - - ret = adreno_read_speedbin(adreno_gpu, dev, &speedbin); - /* - * -ENOENT means that the platform doesn't support speedbin which is - * fine - */ - if (ret == -ENOENT) { - return 0; - } else if (ret) { - dev_err_probe(dev, ret, - "failed to read speed-bin. Some OPPs may not be supported by hardware\n"); - return ret; - } - - supp_hw = fuse_to_supp_hw(info, speedbin); - - if (supp_hw == UINT_MAX) { - DRM_DEV_ERROR(dev, - "missing support for speed-bin: %u. Some OPPs may not be supported by hardware\n", - speedbin); - supp_hw = BIT(0); /* Default */ - } - - ret = devm_pm_opp_set_supported_hw(dev, &supp_hw, 1); - if (ret) - return ret; - - return 0; -} - static const struct adreno_gpu_funcs funcs = { .base = { .get_param = adreno_get_param, @@ -2292,13 +2243,6 @@ struct msm_gpu *a6xx_gpu_init(struct drm_device *dev) a6xx_llc_slices_init(pdev, a6xx_gpu, is_a7xx); - ret = a6xx_set_supported_hw(adreno_gpu, &pdev->dev, config->info); - if (ret) { - a6xx_llc_slices_destroy(a6xx_gpu); - kfree(a6xx_gpu); - return ERR_PTR(ret); - } - if (is_a7xx) ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs_a7xx, 1); else if (adreno_has_gmu_wrapper(adreno_gpu)) diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index 6ffd02f38499..5b4205b76cdf 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -1064,8 +1064,8 @@ void adreno_gpu_ocmem_cleanup(struct adreno_ocmem *adreno_ocmem) adreno_ocmem->hdl); } -int adreno_read_speedbin(struct adreno_gpu *adreno_gpu, - struct device *dev, u32 *fuse) +static int adreno_read_speedbin(struct adreno_gpu *adreno_gpu, + struct device *dev, u32 *fuse) { u32 fcode; int ret; @@ -1099,6 +1099,46 @@ int adreno_read_speedbin(struct adreno_gpu *adreno_gpu, return 0; } +#define ADRENO_SPEEDBIN_FUSE_NODATA 0xFFFF /* Made-up large value, expected by mesa */ +static int adreno_set_speedbin(struct adreno_gpu *adreno_gpu, struct device *dev) +{ + const struct adreno_info *info = adreno_gpu->info; + u32 fuse = ADRENO_SPEEDBIN_FUSE_NODATA; + u32 supp_hw = UINT_MAX; + int ret; + + /* No speedbins defined for this GPU SKU => allow all defined OPPs */ + if (!info->speedbins) { + adreno_gpu->speedbin = ADRENO_SPEEDBIN_FUSE_NODATA; + return devm_pm_opp_set_supported_hw(dev, &supp_hw, 1); + } + + /* + * If a real error (not counting older devicetrees having no nvmem references) + * occurs when trying to get the fuse value, bail out. + */ + ret = adreno_read_speedbin(adreno_gpu, dev, &fuse); + if (ret) { + return ret; + } else if (fuse == ADRENO_SPEEDBIN_FUSE_NODATA) { + /* The info struct has speedbin data, but the DT is too old => allow all OPPs */ + DRM_DEV_INFO(dev, "No GPU speed bin fuse, please update your device tree\n"); + return devm_pm_opp_set_supported_hw(dev, &supp_hw, 1); + } + + adreno_gpu->speedbin = fuse; + + /* Traverse the known speedbins */ + for (int i = 0; info->speedbins[i].fuse != SHRT_MAX; i++) { + if (info->speedbins[i].fuse == fuse) { + supp_hw = BIT(info->speedbins[i].speedbin); + return devm_pm_opp_set_supported_hw(dev, &supp_hw, 1); + } + } + + return dev_err_probe(dev, -EINVAL, "Unknown speed bin fuse value: 0x%x\n", fuse); +} + int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, struct adreno_gpu *adreno_gpu, const struct adreno_gpu_funcs *funcs, int nr_rings) @@ -1108,7 +1148,6 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, struct msm_gpu_config adreno_gpu_config = { 0 }; struct msm_gpu *gpu = &adreno_gpu->base; const char *gpu_name; - u32 speedbin; int ret; adreno_gpu->funcs = funcs; @@ -1135,9 +1174,9 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, devm_pm_opp_set_clkname(dev, "core"); } - if (adreno_read_speedbin(adreno_gpu, dev, &speedbin) || !speedbin) - speedbin = 0xffff; - adreno_gpu->speedbin = speedbin; + ret = adreno_set_speedbin(adreno_gpu, dev); + if (ret) + return ret; gpu_name = devm_kasprintf(dev, GFP_KERNEL, "%"ADRENO_CHIPID_FMT, ADRENO_CHIPID_ARGS(config->chip_id)); diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h index 563c08b44624..dc579f7afdc7 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h @@ -549,9 +549,6 @@ int adreno_fault_handler(struct msm_gpu *gpu, unsigned long iova, int flags, struct adreno_smmu_fault_info *info, const char *block, u32 scratch[4]); -int adreno_read_speedbin(struct adreno_gpu *adreno_gpu, - struct device *dev, u32 *speedbin); - /* * For a5xx and a6xx targets load the zap shader that is used to pull the GPU * out of secure mode
There is no need to reinvent the wheel for simple read-match-set logic. Make speedbin discovery and assignment generation independent. This implicitly removes the bogus 0x80 / BIT(7) speed bin on A5xx, which has no representation in hardware whatshowever. Signed-off-by: Konrad Dybcio <konrad.dybcio@linaro.org> --- drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 34 -------------------- drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 56 --------------------------------- drivers/gpu/drm/msm/adreno/adreno_gpu.c | 51 ++++++++++++++++++++++++++---- drivers/gpu/drm/msm/adreno/adreno_gpu.h | 3 -- 4 files changed, 45 insertions(+), 99 deletions(-)