On 2/27/19 12:04, Viresh Kumar wrote: > Commit 5ad7346b4ae2 ("cpufreq: kryo: Add module remove and exit") made > it possible to build the kyro cpufreq driver as a module, but it failed Nit: s/kyro/kryo/ above and in the subject > to release all the resources, i.e. OPP tables, when the module is > unloaded. > > This patch fixes it by releasing the OPP tables, by calling > dev_pm_opp_put_supported_hw() for them, from the > qcom_cpufreq_kryo_remove() routine. The array of pointers to the OPP > tables is also allocated dynamically now in qcom_cpufreq_kryo_probe(), > as the pointers will be required while releasing the resources. > > Compile tested only. > > Cc: 4.18+ <stable@xxxxxxxxxxxxxxx> # v4.18+ > Fixes: 5ad7346b4ae2 ("cpufreq: kryo: Add module remove and exit") > Signed-off-by: Viresh Kumar <viresh.kumar@xxxxxxxxxx> > --- > V1->V2: > - The previous version targeted a compile time issue of frame size but > this fixes a bug in the driver and needs to get applied to 4.18+ > kernels. > - This may go in 5.0 release. > - Haven't included any Reviewed-by tags as there were many changes in > this version. > > drivers/cpufreq/qcom-cpufreq-kryo.c | 20 ++++++++++++++++++-- > 1 file changed, 18 insertions(+), 2 deletions(-) > > diff --git a/drivers/cpufreq/qcom-cpufreq-kryo.c b/drivers/cpufreq/qcom-cpufreq-kryo.c > index 2a3675c24032..65edbfd4d4a5 100644 > --- a/drivers/cpufreq/qcom-cpufreq-kryo.c > +++ b/drivers/cpufreq/qcom-cpufreq-kryo.c > @@ -75,7 +75,7 @@ static enum _msm8996_version qcom_cpufreq_kryo_get_msm_id(void) > > static int qcom_cpufreq_kryo_probe(struct platform_device *pdev) > { > - struct opp_table *opp_tables[NR_CPUS] = {0}; > + struct opp_table **opp_tables; > enum _msm8996_version msm8996_version; > struct nvmem_cell *speedbin_nvmem; > struct device_node *np; > @@ -133,6 +133,10 @@ static int qcom_cpufreq_kryo_probe(struct platform_device *pdev) > } > kfree(speedbin); > > + opp_tables = kcalloc(num_possible_cpus(), sizeof(*opp_tables), GFP_KERNEL); > + if (!opp_tables) > + return -ENOMEM; > + > for_each_possible_cpu(cpu) { > cpu_dev = get_cpu_device(cpu); > if (NULL == cpu_dev) { > @@ -151,8 +155,10 @@ static int qcom_cpufreq_kryo_probe(struct platform_device *pdev) > > cpufreq_dt_pdev = platform_device_register_simple("cpufreq-dt", -1, > NULL, 0); > - if (!IS_ERR(cpufreq_dt_pdev)) > + if (!IS_ERR(cpufreq_dt_pdev)) { > + platform_set_drvdata(pdev, opp_tables); > return 0; > + } > > ret = PTR_ERR(cpufreq_dt_pdev); > dev_err(cpu_dev, "Failed to register platform device\n"); > @@ -163,13 +169,23 @@ static int qcom_cpufreq_kryo_probe(struct platform_device *pdev) > break; > dev_pm_opp_put_supported_hw(opp_tables[cpu]); > } > + kfree(opp_tables); > > return ret; > } > > static int qcom_cpufreq_kryo_remove(struct platform_device *pdev) > { > + struct opp_table **opp_tables = platform_get_drvdata(pdev); > + unsigned cpu; Nit: unsigned int > + > platform_device_unregister(cpufreq_dt_pdev); > + > + for_each_possible_cpu(cpu) > + dev_pm_opp_put_supported_hw(opp_tables[cpu]); > + > + kfree(opp_tables); > + > return 0; > } > Reviewed-by: Georgi Djakov <georgi.djakov@xxxxxxxxxx> Thanks, Georgi