rockchip: fix panic when probe rockchip-cpufreq driver

Signed-off-by: Tianling Shen <cnsztl@immortalwrt.org>
This commit is contained in:
Tianling Shen 2023-05-29 17:20:20 +08:00
parent 81d0182d18
commit e6a0be1ac5

View File

@ -0,0 +1,178 @@
--- a/drivers/cpufreq/rockchip-cpufreq.c
+++ b/drivers/cpufreq/rockchip-cpufreq.c
@@ -332,13 +332,13 @@ static int rockchip_cpufreq_cluster_init
reg_table_token = dev_pm_opp_set_regulators(dev, reg_names);
if (reg_table_token < 0) {
ret = reg_table_token;
- dev_err_probe(dev, ret, "Failed to set opp regulators\n");
+ dev_err(dev, "Failed to set opp regulators\n");
goto np_err;
}
ret = dev_pm_opp_of_get_sharing_cpus(dev, &cluster->cpus);
if (ret) {
- dev_err_probe(dev, ret, "Failed to get sharing cpus\n");
+ dev_err(dev, "Failed to get sharing cpus\n");
goto np_err;
}
@@ -519,67 +519,10 @@ static int rockchip_cpufreq_init(struct
return 0;
}
-static void rockchip_cpufreq_free_list(void *data)
-{
- struct cluster_info *cluster, *pos;
-
- list_for_each_entry_safe(cluster, pos, &cluster_info_list, list_head) {
- list_del(&cluster->list_head);
- }
-}
-
-static int rockchip_cpufreq_init_list(struct device *dev)
-{
- struct cluster_info *cluster;
- int cpu, ret;
-
- for_each_possible_cpu(cpu) {
- cluster = rockchip_cluster_info_lookup(cpu);
- if (cluster)
- continue;
-
- cluster = devm_kzalloc(dev, sizeof(*cluster), GFP_KERNEL);
- if (!cluster) {
- ret = -ENOMEM;
- goto release_cluster_info;
- }
-
- ret = rockchip_cpufreq_cluster_init(cpu, cluster);
- if (ret) {
- dev_err_probe(dev, ret, "Failed to initialize dvfs info cpu%d\n", cpu);
- goto release_cluster_info;
- }
- list_add(&cluster->list_head, &cluster_info_list);
- }
-
- return 0;
-
-release_cluster_info:
- rockchip_cpufreq_free_list(NULL);
- return ret;
-}
-
-static void rockchip_cpufreq_unregister(void *data)
-{
- cpufreq_unregister_driver(&rockchip_cpufreq_driver);
-}
-
static int rockchip_cpufreq_probe(struct platform_device *pdev)
{
int ret, cpu;
- ret = rockchip_cpufreq_init_list(&pdev->dev);
- if (ret)
- return ret;
-
- ret = devm_add_action_or_reset(&pdev->dev, rockchip_cpufreq_free_list, NULL);
- if (ret)
- return ret;
-
- ret = devm_register_reboot_notifier(&pdev->dev, &rockchip_cpufreq_reboot_notifier);
- if (ret)
- return dev_err_probe(&pdev->dev, ret, "Failed to register reboot handler\n");
-
for_each_possible_cpu(cpu) {
ret = rockchip_cpufreq_init(&pdev->dev, cpu);
if (ret)
@@ -590,10 +533,12 @@ static int rockchip_cpufreq_probe(struct
if (ret)
return dev_err_probe(&pdev->dev, ret, "failed register driver\n");
- ret = devm_add_action_or_reset(&pdev->dev, rockchip_cpufreq_unregister, NULL);
- if (ret)
- return ret;
+ return 0;
+}
+static int rockchip_cpufreq_remove(struct platform_device *pdev)
+{
+ cpufreq_unregister_driver(&rockchip_cpufreq_driver);
return 0;
}
@@ -602,15 +547,42 @@ static struct platform_driver rockchip_c
.name = "rockchip-cpufreq",
},
.probe = rockchip_cpufreq_probe,
+ .remove = rockchip_cpufreq_remove,
};
static int __init rockchip_cpufreq_driver_init(void)
{
- int ret;
+ struct cluster_info *cluster, *pos;
+ int cpu, ret;
+
+ for_each_possible_cpu(cpu) {
+ cluster = rockchip_cluster_info_lookup(cpu);
+ if (cluster)
+ continue;
+
+ cluster = kzalloc(sizeof(*cluster), GFP_KERNEL);
+ if (!cluster) {
+ ret = -ENOMEM;
+ goto release_cluster_info;
+ }
+
+ ret = rockchip_cpufreq_cluster_init(cpu, cluster);
+ if (ret) {
+ pr_err("Failed to initialize dvfs info cpu%d\n", cpu);
+ goto release_cluster_info;
+ }
+ list_add(&cluster->list_head, &cluster_info_list);
+ }
+
+ ret = register_reboot_notifier(&rockchip_cpufreq_reboot_notifier);
+ if (ret) {
+ pr_err("Failed to register reboot handler\n");
+ goto release_cluster_info;
+ }
ret = platform_driver_register(&rockchip_cpufreq_platdrv);
if (ret)
- return ret;
+ goto remove_reboot_notifier;
cpufreq_pdev = platform_device_register_data(NULL, "rockchip-cpufreq", -1,
NULL, 0);
@@ -624,14 +596,30 @@ static int __init rockchip_cpufreq_drive
unregister_platform_driver:
platform_driver_unregister(&rockchip_cpufreq_platdrv);
+
+remove_reboot_notifier:
+ unregister_reboot_notifier(&rockchip_cpufreq_reboot_notifier);
+
+release_cluster_info:
+ list_for_each_entry_safe(cluster, pos, &cluster_info_list, list_head) {
+ list_del(&cluster->list_head);
+ kfree(cluster);
+ }
return ret;
}
module_init(rockchip_cpufreq_driver_init);
static void __exit rockchip_cpufreq_driver_exit(void)
{
+ struct cluster_info *cluster, *pos;
+
platform_device_unregister(cpufreq_pdev);
platform_driver_unregister(&rockchip_cpufreq_platdrv);
+ unregister_reboot_notifier(&rockchip_cpufreq_reboot_notifier);
+ list_for_each_entry_safe(cluster, pos, &cluster_info_list, list_head) {
+ list_del(&cluster->list_head);
+ kfree(cluster);
+ }
}
module_exit(rockchip_cpufreq_driver_exit)