aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-06-29 09:04:07 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-06-29 09:04:07 -0400
commit2cc6ced132f472b2bdb619960a650b9a85cdd34f (patch)
tree171d6613cd7117dcd750efdd665ec2eab6e24a8e /drivers/cpufreq
parent867a420b222b25e9608f4430bea3af50835b56b5 (diff)
parent419e172145cf6c51d436a8bf4afcd17511f0ff79 (diff)
Merge branch 'pm-cpufreq'
* pm-cpufreq: cpufreq: don't leave stale policy pointer in cdbs->cur_policy acpi-cpufreq: Add new sysfs attribute freqdomain_cpus cpufreq: make sure frequency transitions are serialized
Diffstat (limited to 'drivers/cpufreq')
-rw-r--r--drivers/cpufreq/acpi-cpufreq.c23
-rw-r--r--drivers/cpufreq/cpufreq.c21
-rw-r--r--drivers/cpufreq/cpufreq_governor.c1
3 files changed, 41 insertions, 4 deletions
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
index f4fef0acc183..39264020b88a 100644
--- a/drivers/cpufreq/acpi-cpufreq.c
+++ b/drivers/cpufreq/acpi-cpufreq.c
@@ -70,6 +70,7 @@ struct acpi_cpufreq_data {
70 struct cpufreq_frequency_table *freq_table; 70 struct cpufreq_frequency_table *freq_table;
71 unsigned int resume; 71 unsigned int resume;
72 unsigned int cpu_feature; 72 unsigned int cpu_feature;
73 cpumask_var_t freqdomain_cpus;
73}; 74};
74 75
75static DEFINE_PER_CPU(struct acpi_cpufreq_data *, acfreq_data); 76static DEFINE_PER_CPU(struct acpi_cpufreq_data *, acfreq_data);
@@ -176,6 +177,15 @@ static struct global_attr global_boost = __ATTR(boost, 0644,
176 show_global_boost, 177 show_global_boost,
177 store_global_boost); 178 store_global_boost);
178 179
180static ssize_t show_freqdomain_cpus(struct cpufreq_policy *policy, char *buf)
181{
182 struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
183
184 return cpufreq_show_cpus(data->freqdomain_cpus, buf);
185}
186
187cpufreq_freq_attr_ro(freqdomain_cpus);
188
179#ifdef CONFIG_X86_ACPI_CPUFREQ_CPB 189#ifdef CONFIG_X86_ACPI_CPUFREQ_CPB
180static ssize_t store_cpb(struct cpufreq_policy *policy, const char *buf, 190static ssize_t store_cpb(struct cpufreq_policy *policy, const char *buf,
181 size_t count) 191 size_t count)
@@ -704,6 +714,11 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
704 if (!data) 714 if (!data)
705 return -ENOMEM; 715 return -ENOMEM;
706 716
717 if (!zalloc_cpumask_var(&data->freqdomain_cpus, GFP_KERNEL)) {
718 result = -ENOMEM;
719 goto err_free;
720 }
721
707 data->acpi_data = per_cpu_ptr(acpi_perf_data, cpu); 722 data->acpi_data = per_cpu_ptr(acpi_perf_data, cpu);
708 per_cpu(acfreq_data, cpu) = data; 723 per_cpu(acfreq_data, cpu) = data;
709 724
@@ -712,7 +727,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
712 727
713 result = acpi_processor_register_performance(data->acpi_data, cpu); 728 result = acpi_processor_register_performance(data->acpi_data, cpu);
714 if (result) 729 if (result)
715 goto err_free; 730 goto err_free_mask;
716 731
717 perf = data->acpi_data; 732 perf = data->acpi_data;
718 policy->shared_type = perf->shared_type; 733 policy->shared_type = perf->shared_type;
@@ -725,6 +740,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
725 policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) { 740 policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) {
726 cpumask_copy(policy->cpus, perf->shared_cpu_map); 741 cpumask_copy(policy->cpus, perf->shared_cpu_map);
727 } 742 }
743 cpumask_copy(data->freqdomain_cpus, perf->shared_cpu_map);
728 744
729#ifdef CONFIG_SMP 745#ifdef CONFIG_SMP
730 dmi_check_system(sw_any_bug_dmi_table); 746 dmi_check_system(sw_any_bug_dmi_table);
@@ -736,6 +752,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
736 if (check_amd_hwpstate_cpu(cpu) && !acpi_pstate_strict) { 752 if (check_amd_hwpstate_cpu(cpu) && !acpi_pstate_strict) {
737 cpumask_clear(policy->cpus); 753 cpumask_clear(policy->cpus);
738 cpumask_set_cpu(cpu, policy->cpus); 754 cpumask_set_cpu(cpu, policy->cpus);
755 cpumask_copy(data->freqdomain_cpus, cpu_sibling_mask(cpu));
739 policy->shared_type = CPUFREQ_SHARED_TYPE_HW; 756 policy->shared_type = CPUFREQ_SHARED_TYPE_HW;
740 pr_info_once(PFX "overriding BIOS provided _PSD data\n"); 757 pr_info_once(PFX "overriding BIOS provided _PSD data\n");
741 } 758 }
@@ -870,6 +887,8 @@ err_freqfree:
870 kfree(data->freq_table); 887 kfree(data->freq_table);
871err_unreg: 888err_unreg:
872 acpi_processor_unregister_performance(perf, cpu); 889 acpi_processor_unregister_performance(perf, cpu);
890err_free_mask:
891 free_cpumask_var(data->freqdomain_cpus);
873err_free: 892err_free:
874 kfree(data); 893 kfree(data);
875 per_cpu(acfreq_data, cpu) = NULL; 894 per_cpu(acfreq_data, cpu) = NULL;
@@ -888,6 +907,7 @@ static int acpi_cpufreq_cpu_exit(struct cpufreq_policy *policy)
888 per_cpu(acfreq_data, policy->cpu) = NULL; 907 per_cpu(acfreq_data, policy->cpu) = NULL;
889 acpi_processor_unregister_performance(data->acpi_data, 908 acpi_processor_unregister_performance(data->acpi_data,
890 policy->cpu); 909 policy->cpu);
910 free_cpumask_var(data->freqdomain_cpus);
891 kfree(data->freq_table); 911 kfree(data->freq_table);
892 kfree(data); 912 kfree(data);
893 } 913 }
@@ -908,6 +928,7 @@ static int acpi_cpufreq_resume(struct cpufreq_policy *policy)
908 928
909static struct freq_attr *acpi_cpufreq_attr[] = { 929static struct freq_attr *acpi_cpufreq_attr[] = {
910 &cpufreq_freq_attr_scaling_available_freqs, 930 &cpufreq_freq_attr_scaling_available_freqs,
931 &freqdomain_cpus,
911 NULL, /* this is a placeholder for cpb, do not remove */ 932 NULL, /* this is a placeholder for cpb, do not remove */
912 NULL, 933 NULL,
913}; 934};
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index d976e222f10f..6a015ada5285 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -312,6 +312,12 @@ static void __cpufreq_notify_transition(struct cpufreq_policy *policy,
312 switch (state) { 312 switch (state) {
313 313
314 case CPUFREQ_PRECHANGE: 314 case CPUFREQ_PRECHANGE:
315 if (WARN(policy->transition_ongoing,
316 "In middle of another frequency transition\n"))
317 return;
318
319 policy->transition_ongoing = true;
320
315 /* detect if the driver reported a value as "old frequency" 321 /* detect if the driver reported a value as "old frequency"
316 * which is not equal to what the cpufreq core thinks is 322 * which is not equal to what the cpufreq core thinks is
317 * "old frequency". 323 * "old frequency".
@@ -331,6 +337,12 @@ static void __cpufreq_notify_transition(struct cpufreq_policy *policy,
331 break; 337 break;
332 338
333 case CPUFREQ_POSTCHANGE: 339 case CPUFREQ_POSTCHANGE:
340 if (WARN(!policy->transition_ongoing,
341 "No frequency transition in progress\n"))
342 return;
343
344 policy->transition_ongoing = false;
345
334 adjust_jiffies(CPUFREQ_POSTCHANGE, freqs); 346 adjust_jiffies(CPUFREQ_POSTCHANGE, freqs);
335 pr_debug("FREQ: %lu - CPU: %lu", (unsigned long)freqs->new, 347 pr_debug("FREQ: %lu - CPU: %lu", (unsigned long)freqs->new,
336 (unsigned long)freqs->cpu); 348 (unsigned long)freqs->cpu);
@@ -573,7 +585,7 @@ out:
573 return i; 585 return i;
574} 586}
575 587
576static ssize_t show_cpus(const struct cpumask *mask, char *buf) 588ssize_t cpufreq_show_cpus(const struct cpumask *mask, char *buf)
577{ 589{
578 ssize_t i = 0; 590 ssize_t i = 0;
579 unsigned int cpu; 591 unsigned int cpu;
@@ -588,6 +600,7 @@ static ssize_t show_cpus(const struct cpumask *mask, char *buf)
588 i += sprintf(&buf[i], "\n"); 600 i += sprintf(&buf[i], "\n");
589 return i; 601 return i;
590} 602}
603EXPORT_SYMBOL_GPL(cpufreq_show_cpus);
591 604
592/** 605/**
593 * show_related_cpus - show the CPUs affected by each transition even if 606 * show_related_cpus - show the CPUs affected by each transition even if
@@ -595,7 +608,7 @@ static ssize_t show_cpus(const struct cpumask *mask, char *buf)
595 */ 608 */
596static ssize_t show_related_cpus(struct cpufreq_policy *policy, char *buf) 609static ssize_t show_related_cpus(struct cpufreq_policy *policy, char *buf)
597{ 610{
598 return show_cpus(policy->related_cpus, buf); 611 return cpufreq_show_cpus(policy->related_cpus, buf);
599} 612}
600 613
601/** 614/**
@@ -603,7 +616,7 @@ static ssize_t show_related_cpus(struct cpufreq_policy *policy, char *buf)
603 */ 616 */
604static ssize_t show_affected_cpus(struct cpufreq_policy *policy, char *buf) 617static ssize_t show_affected_cpus(struct cpufreq_policy *policy, char *buf)
605{ 618{
606 return show_cpus(policy->cpus, buf); 619 return cpufreq_show_cpus(policy->cpus, buf);
607} 620}
608 621
609static ssize_t store_scaling_setspeed(struct cpufreq_policy *policy, 622static ssize_t store_scaling_setspeed(struct cpufreq_policy *policy,
@@ -1539,6 +1552,8 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
1539 1552
1540 if (cpufreq_disabled()) 1553 if (cpufreq_disabled())
1541 return -ENODEV; 1554 return -ENODEV;
1555 if (policy->transition_ongoing)
1556 return -EBUSY;
1542 1557
1543 /* Make sure that target_freq is within supported range */ 1558 /* Make sure that target_freq is within supported range */
1544 if (target_freq > policy->max) 1559 if (target_freq > policy->max)
diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c
index a849b2d499fa..464587697561 100644
--- a/drivers/cpufreq/cpufreq_governor.c
+++ b/drivers/cpufreq/cpufreq_governor.c
@@ -366,6 +366,7 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy,
366 366
367 mutex_lock(&dbs_data->mutex); 367 mutex_lock(&dbs_data->mutex);
368 mutex_destroy(&cpu_cdbs->timer_mutex); 368 mutex_destroy(&cpu_cdbs->timer_mutex);
369 cpu_cdbs->cur_policy = NULL;
369 370
370 mutex_unlock(&dbs_data->mutex); 371 mutex_unlock(&dbs_data->mutex);
371 372