cpufreq / stats: fix race between stats allocation and first usage
[cascardo/linux.git] / drivers / cpufreq / cpufreq_stats.c
index 3998316..9d7732b 100644 (file)
@@ -37,7 +37,7 @@ struct cpufreq_stats {
        unsigned int max_state;
        unsigned int state_num;
        unsigned int last_index;
-       cputime64_t *time_in_state;
+       u64 *time_in_state;
        unsigned int *freq_table;
 #ifdef CONFIG_CPU_FREQ_STAT_DETAILS
        unsigned int *trans_table;
@@ -223,7 +223,7 @@ static int cpufreq_stats_create_table(struct cpufreq_policy *policy,
                count++;
        }
 
-       alloc_size = count * sizeof(int) + count * sizeof(cputime64_t);
+       alloc_size = count * sizeof(int) + count * sizeof(u64);
 
 #ifdef CONFIG_CPU_FREQ_STAT_DETAILS
        alloc_size += count * count * sizeof(int);
@@ -364,18 +364,21 @@ static int __init cpufreq_stats_init(void)
        if (ret)
                return ret;
 
+       register_hotcpu_notifier(&cpufreq_stat_cpu_notifier);
+       for_each_online_cpu(cpu)
+               cpufreq_update_policy(cpu);
+
        ret = cpufreq_register_notifier(&notifier_trans_block,
                                CPUFREQ_TRANSITION_NOTIFIER);
        if (ret) {
                cpufreq_unregister_notifier(&notifier_policy_block,
                                CPUFREQ_POLICY_NOTIFIER);
+               unregister_hotcpu_notifier(&cpufreq_stat_cpu_notifier);
+               for_each_online_cpu(cpu)
+                       cpufreq_stats_free_table(cpu);
                return ret;
        }
 
-       register_hotcpu_notifier(&cpufreq_stat_cpu_notifier);
-       for_each_online_cpu(cpu) {
-               cpufreq_update_policy(cpu);
-       }
        return 0;
 }
 static void __exit cpufreq_stats_exit(void)