mirror of
https://github.com/nxp-imx/linux-imx.git
synced 2025-07-11 20:05:22 +02:00
cpufreq: qcom-nvmem: Simplify driver data allocation
[ Upstream commit2a5d46c3ad
] Simplify the allocation and cleanup of driver data by using devm together with a flexible array. Prepare for adding additional per-CPU data by defining a struct qcom_cpufreq_drv_cpu instead of storing the opp_tokens directly. Signed-off-by: Stephan Gerhold <stephan.gerhold@kernkonzept.com> Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Stable-dep-of:d01c84b97f
("cpufreq: qcom-nvmem: fix memory leaks in probe error paths") Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
df7363307e
commit
51a45209a8
|
@ -40,10 +40,14 @@ struct qcom_cpufreq_match_data {
|
||||||
const char **genpd_names;
|
const char **genpd_names;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct qcom_cpufreq_drv_cpu {
|
||||||
|
int opp_token;
|
||||||
|
};
|
||||||
|
|
||||||
struct qcom_cpufreq_drv {
|
struct qcom_cpufreq_drv {
|
||||||
int *opp_tokens;
|
|
||||||
u32 versions;
|
u32 versions;
|
||||||
const struct qcom_cpufreq_match_data *data;
|
const struct qcom_cpufreq_match_data *data;
|
||||||
|
struct qcom_cpufreq_drv_cpu cpus[];
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct platform_device *cpufreq_dt_pdev, *cpufreq_pdev;
|
static struct platform_device *cpufreq_dt_pdev, *cpufreq_pdev;
|
||||||
|
@ -243,42 +247,32 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
drv = kzalloc(sizeof(*drv), GFP_KERNEL);
|
drv = devm_kzalloc(&pdev->dev, struct_size(drv, cpus, num_possible_cpus()),
|
||||||
|
GFP_KERNEL);
|
||||||
if (!drv)
|
if (!drv)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
match = pdev->dev.platform_data;
|
match = pdev->dev.platform_data;
|
||||||
drv->data = match->data;
|
drv->data = match->data;
|
||||||
if (!drv->data) {
|
if (!drv->data)
|
||||||
ret = -ENODEV;
|
return -ENODEV;
|
||||||
goto free_drv;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (drv->data->get_version) {
|
if (drv->data->get_version) {
|
||||||
speedbin_nvmem = of_nvmem_cell_get(np, NULL);
|
speedbin_nvmem = of_nvmem_cell_get(np, NULL);
|
||||||
if (IS_ERR(speedbin_nvmem)) {
|
if (IS_ERR(speedbin_nvmem))
|
||||||
ret = dev_err_probe(cpu_dev, PTR_ERR(speedbin_nvmem),
|
return dev_err_probe(cpu_dev, PTR_ERR(speedbin_nvmem),
|
||||||
"Could not get nvmem cell\n");
|
"Could not get nvmem cell\n");
|
||||||
goto free_drv;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = drv->data->get_version(cpu_dev,
|
ret = drv->data->get_version(cpu_dev,
|
||||||
speedbin_nvmem, &pvs_name, drv);
|
speedbin_nvmem, &pvs_name, drv);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
nvmem_cell_put(speedbin_nvmem);
|
nvmem_cell_put(speedbin_nvmem);
|
||||||
goto free_drv;
|
return ret;
|
||||||
}
|
}
|
||||||
nvmem_cell_put(speedbin_nvmem);
|
nvmem_cell_put(speedbin_nvmem);
|
||||||
}
|
}
|
||||||
of_node_put(np);
|
of_node_put(np);
|
||||||
|
|
||||||
drv->opp_tokens = kcalloc(num_possible_cpus(), sizeof(*drv->opp_tokens),
|
|
||||||
GFP_KERNEL);
|
|
||||||
if (!drv->opp_tokens) {
|
|
||||||
ret = -ENOMEM;
|
|
||||||
goto free_drv;
|
|
||||||
}
|
|
||||||
|
|
||||||
for_each_possible_cpu(cpu) {
|
for_each_possible_cpu(cpu) {
|
||||||
struct dev_pm_opp_config config = {
|
struct dev_pm_opp_config config = {
|
||||||
.supported_hw = NULL,
|
.supported_hw = NULL,
|
||||||
|
@ -304,9 +298,9 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.supported_hw || config.genpd_names) {
|
if (config.supported_hw || config.genpd_names) {
|
||||||
drv->opp_tokens[cpu] = dev_pm_opp_set_config(cpu_dev, &config);
|
drv->cpus[cpu].opp_token = dev_pm_opp_set_config(cpu_dev, &config);
|
||||||
if (drv->opp_tokens[cpu] < 0) {
|
if (drv->cpus[cpu].opp_token < 0) {
|
||||||
ret = drv->opp_tokens[cpu];
|
ret = drv->cpus[cpu].opp_token;
|
||||||
dev_err(cpu_dev, "Failed to set OPP config\n");
|
dev_err(cpu_dev, "Failed to set OPP config\n");
|
||||||
goto free_opp;
|
goto free_opp;
|
||||||
}
|
}
|
||||||
|
@ -325,11 +319,7 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
free_opp:
|
free_opp:
|
||||||
for_each_possible_cpu(cpu)
|
for_each_possible_cpu(cpu)
|
||||||
dev_pm_opp_clear_config(drv->opp_tokens[cpu]);
|
dev_pm_opp_clear_config(drv->cpus[cpu].opp_token);
|
||||||
kfree(drv->opp_tokens);
|
|
||||||
free_drv:
|
|
||||||
kfree(drv);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,10 +331,7 @@ static void qcom_cpufreq_remove(struct platform_device *pdev)
|
||||||
platform_device_unregister(cpufreq_dt_pdev);
|
platform_device_unregister(cpufreq_dt_pdev);
|
||||||
|
|
||||||
for_each_possible_cpu(cpu)
|
for_each_possible_cpu(cpu)
|
||||||
dev_pm_opp_clear_config(drv->opp_tokens[cpu]);
|
dev_pm_opp_clear_config(drv->cpus[cpu].opp_token);
|
||||||
|
|
||||||
kfree(drv->opp_tokens);
|
|
||||||
kfree(drv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct platform_driver qcom_cpufreq_driver = {
|
static struct platform_driver qcom_cpufreq_driver = {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user