aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq/cpufreq_stats.c
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.org>2013-01-14 08:23:03 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-02-01 18:01:14 -0500
commitb8eed8af94f9203e0cc39245ea335f4b8dc1ed31 (patch)
tree39c9e57baa6daf91295c331c6b995c9d6286b2bc /drivers/cpufreq/cpufreq_stats.c
parentf85178048c083520bd920921744dd2c4a797fbc5 (diff)
cpufreq: Simplify __cpufreq_remove_dev()
__cpufreq_remove_dev() is called on multiple occasions: cpufreq_driver unregister and cpu removals. Current implementation of this routine is overly complex without much need. If the cpu to be removed is the policy->cpu, we remove the policy first and add all other cpus again from policy->cpus and then finally call __cpufreq_remove_dev() again to remove the cpu to be deleted. Haahhhh.. There exist a simple solution to removal of a cpu: - Simply use the old policy structure - update its fields like: policy->cpu, etc. - notify any users of cpufreq, which depend on changing policy->cpu Hence this patch, which tries to implement the above theory. It is tested well by myself on ARM big.LITTLE TC2 SoC, which has 5 cores (2 A15 and 3 A7). Both A15's share same struct policy and all A7's share same policy structure. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Tested-by: Shawn Guo <shawn.guo@linaro.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/cpufreq/cpufreq_stats.c')
-rw-r--r--drivers/cpufreq/cpufreq_stats.c27
1 files changed, 25 insertions, 2 deletions
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c
index 9d7732b81044..beef6b54382b 100644
--- a/drivers/cpufreq/cpufreq_stats.c
+++ b/drivers/cpufreq/cpufreq_stats.c
@@ -170,11 +170,13 @@ static int freq_table_get_index(struct cpufreq_stats *stat, unsigned int freq)
170static void cpufreq_stats_free_table(unsigned int cpu) 170static void cpufreq_stats_free_table(unsigned int cpu)
171{ 171{
172 struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, cpu); 172 struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, cpu);
173
173 if (stat) { 174 if (stat) {
175 pr_debug("%s: Free stat table\n", __func__);
174 kfree(stat->time_in_state); 176 kfree(stat->time_in_state);
175 kfree(stat); 177 kfree(stat);
178 per_cpu(cpufreq_stats_table, cpu) = NULL;
176 } 179 }
177 per_cpu(cpufreq_stats_table, cpu) = NULL;
178} 180}
179 181
180/* must be called early in the CPU removal sequence (before 182/* must be called early in the CPU removal sequence (before
@@ -183,8 +185,10 @@ static void cpufreq_stats_free_table(unsigned int cpu)
183static void cpufreq_stats_free_sysfs(unsigned int cpu) 185static void cpufreq_stats_free_sysfs(unsigned int cpu)
184{ 186{
185 struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); 187 struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
186 if (policy && policy->cpu == cpu) 188 if (policy && (cpumask_weight(policy->cpus) == 1)) {
189 pr_debug("%s: Free sysfs stat\n", __func__);
187 sysfs_remove_group(&policy->kobj, &stats_attr_group); 190 sysfs_remove_group(&policy->kobj, &stats_attr_group);
191 }
188 if (policy) 192 if (policy)
189 cpufreq_cpu_put(policy); 193 cpufreq_cpu_put(policy);
190} 194}
@@ -262,6 +266,19 @@ error_get_fail:
262 return ret; 266 return ret;
263} 267}
264 268
269static void cpufreq_stats_update_policy_cpu(struct cpufreq_policy *policy)
270{
271 struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table,
272 policy->last_cpu);
273
274 pr_debug("Updating stats_table for new_cpu %u from last_cpu %u\n",
275 policy->cpu, policy->last_cpu);
276 per_cpu(cpufreq_stats_table, policy->cpu) = per_cpu(cpufreq_stats_table,
277 policy->last_cpu);
278 per_cpu(cpufreq_stats_table, policy->last_cpu) = NULL;
279 stat->cpu = policy->cpu;
280}
281
265static int cpufreq_stat_notifier_policy(struct notifier_block *nb, 282static int cpufreq_stat_notifier_policy(struct notifier_block *nb,
266 unsigned long val, void *data) 283 unsigned long val, void *data)
267{ 284{
@@ -269,6 +286,12 @@ static int cpufreq_stat_notifier_policy(struct notifier_block *nb,
269 struct cpufreq_policy *policy = data; 286 struct cpufreq_policy *policy = data;
270 struct cpufreq_frequency_table *table; 287 struct cpufreq_frequency_table *table;
271 unsigned int cpu = policy->cpu; 288 unsigned int cpu = policy->cpu;
289
290 if (val == CPUFREQ_UPDATE_POLICY_CPU) {
291 cpufreq_stats_update_policy_cpu(policy);
292 return 0;
293 }
294
272 if (val != CPUFREQ_NOTIFY) 295 if (val != CPUFREQ_NOTIFY)
273 return 0; 296 return 0;
274 table = cpufreq_frequency_get_table(cpu); 297 table = cpufreq_frequency_get_table(cpu);