cpufreq: Prevent memory leak in cpufreq_stats on hotplug
authorColin Cross <ccross@android.com>
Sat, 29 Jan 2011 03:32:31 +0000 (19:32 -0800)
committerColin Cross <ccross@android.com>
Sun, 30 Jan 2011 07:51:46 +0000 (23:51 -0800)
Ensures that cpufreq_stats_free_table is called before
__cpufreq_remove_dev on cpu hotplug (which also occurs during
suspend on SMP systems) to make sure that sysfs_remove_group
can get called before the cpufreq kobj is freed.  Otherwise,
the sysfs file structures are leaked.

Change-Id: I87e55277272f5cfad47e9e7c92630e990bb90069
Signed-off-by: Colin Cross <ccross@android.com>
drivers/cpufreq/cpufreq_stats.c

index 00d73fc8e4e2853d26d217761a2d2e40a2b22ead..ca3f24c296a033c07417ef6d2acce1eef514d33d 100644 (file)
@@ -305,6 +305,27 @@ static int cpufreq_stat_notifier_trans(struct notifier_block *nb,
        return 0;
 }
 
+static int cpufreq_stats_create_table_cpu(unsigned int cpu)
+{
+       struct cpufreq_policy *policy;
+       struct cpufreq_frequency_table *table;
+       int ret = -ENODEV;
+
+       policy = cpufreq_cpu_get(cpu);
+       if (!policy)
+               return -ENODEV;
+
+       table = cpufreq_frequency_get_table(cpu);
+       if (!table)
+               goto out;
+
+       ret = cpufreq_stats_create_table(policy, table);
+
+out:
+       cpufreq_cpu_put(policy);
+       return ret;
+}
+
 static int __cpuinit cpufreq_stat_cpu_callback(struct notifier_block *nfb,
                                               unsigned long action,
                                               void *hcpu)
@@ -316,10 +337,14 @@ static int __cpuinit cpufreq_stat_cpu_callback(struct notifier_block *nfb,
        case CPU_ONLINE_FROZEN:
                cpufreq_update_policy(cpu);
                break;
-       case CPU_DEAD:
-       case CPU_DEAD_FROZEN:
+       case CPU_DOWN_PREPARE:
+       case CPU_DOWN_PREPARE_FROZEN:
                cpufreq_stats_free_table(cpu);
                break;
+       case CPU_DOWN_FAILED:
+       case CPU_DOWN_FAILED_FROZEN:
+               cpufreq_stats_create_table_cpu(cpu);
+               break;
        }
        return NOTIFY_OK;
 }
@@ -327,6 +352,7 @@ static int __cpuinit cpufreq_stat_cpu_callback(struct notifier_block *nfb,
 static struct notifier_block cpufreq_stat_cpu_notifier __refdata =
 {
        .notifier_call = cpufreq_stat_cpu_callback,
+       .priority = 1,
 };
 
 static struct notifier_block notifier_policy_block = {