Commit 2cc6ced132f472b2bdb619960a650b9a85cdd34f

Authored by Rafael J. Wysocki

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

Showing 5 changed files Side-by-side Diff

Documentation/ABI/testing/sysfs-devices-system-cpu
... ... @@ -144,6 +144,21 @@
144 144 to learn how to control the knobs.
145 145  
146 146  
  147 +What: /sys/devices/system/cpu/cpu#/cpufreq/freqdomain_cpus
  148 +Date: June 2013
  149 +Contact: cpufreq@vger.kernel.org
  150 +Description: Discover CPUs in the same CPU frequency coordination domain
  151 +
  152 + freqdomain_cpus is the list of CPUs (online+offline) that share
  153 + the same clock/freq domain (possibly at the hardware level).
  154 + That information may be hidden from the cpufreq core and the
  155 + value of related_cpus may be different from freqdomain_cpus. This
  156 + attribute is useful for user space DVFS controllers to get better
  157 + power/performance results for platforms using acpi-cpufreq.
  158 +
  159 + This file is only present if the acpi-cpufreq driver is in use.
  160 +
  161 +
147 162 What: /sys/devices/system/cpu/cpu*/cache/index3/cache_disable_{0,1}
148 163 Date: August 2008
149 164 KernelVersion: 2.6.27
drivers/cpufreq/acpi-cpufreq.c
... ... @@ -70,6 +70,7 @@
70 70 struct cpufreq_frequency_table *freq_table;
71 71 unsigned int resume;
72 72 unsigned int cpu_feature;
  73 + cpumask_var_t freqdomain_cpus;
73 74 };
74 75  
75 76 static DEFINE_PER_CPU(struct acpi_cpufreq_data *, acfreq_data);
... ... @@ -176,6 +177,15 @@
176 177 show_global_boost,
177 178 store_global_boost);
178 179  
  180 +static 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 +
  187 +cpufreq_freq_attr_ro(freqdomain_cpus);
  188 +
179 189 #ifdef CONFIG_X86_ACPI_CPUFREQ_CPB
180 190 static ssize_t store_cpb(struct cpufreq_policy *policy, const char *buf,
181 191 size_t count)
... ... @@ -704,6 +714,11 @@
704 714 if (!data)
705 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 722 data->acpi_data = per_cpu_ptr(acpi_perf_data, cpu);
708 723 per_cpu(acfreq_data, cpu) = data;
709 724  
... ... @@ -712,7 +727,7 @@
712 727  
713 728 result = acpi_processor_register_performance(data->acpi_data, cpu);
714 729 if (result)
715   - goto err_free;
  730 + goto err_free_mask;
716 731  
717 732 perf = data->acpi_data;
718 733 policy->shared_type = perf->shared_type;
... ... @@ -725,6 +740,7 @@
725 740 policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) {
726 741 cpumask_copy(policy->cpus, perf->shared_cpu_map);
727 742 }
  743 + cpumask_copy(data->freqdomain_cpus, perf->shared_cpu_map);
728 744  
729 745 #ifdef CONFIG_SMP
730 746 dmi_check_system(sw_any_bug_dmi_table);
... ... @@ -736,6 +752,7 @@
736 752 if (check_amd_hwpstate_cpu(cpu) && !acpi_pstate_strict) {
737 753 cpumask_clear(policy->cpus);
738 754 cpumask_set_cpu(cpu, policy->cpus);
  755 + cpumask_copy(data->freqdomain_cpus, cpu_sibling_mask(cpu));
739 756 policy->shared_type = CPUFREQ_SHARED_TYPE_HW;
740 757 pr_info_once(PFX "overriding BIOS provided _PSD data\n");
741 758 }
... ... @@ -870,6 +887,8 @@
870 887 kfree(data->freq_table);
871 888 err_unreg:
872 889 acpi_processor_unregister_performance(perf, cpu);
  890 +err_free_mask:
  891 + free_cpumask_var(data->freqdomain_cpus);
873 892 err_free:
874 893 kfree(data);
875 894 per_cpu(acfreq_data, cpu) = NULL;
... ... @@ -888,6 +907,7 @@
888 907 per_cpu(acfreq_data, policy->cpu) = NULL;
889 908 acpi_processor_unregister_performance(data->acpi_data,
890 909 policy->cpu);
  910 + free_cpumask_var(data->freqdomain_cpus);
891 911 kfree(data->freq_table);
892 912 kfree(data);
893 913 }
... ... @@ -908,6 +928,7 @@
908 928  
909 929 static struct freq_attr *acpi_cpufreq_attr[] = {
910 930 &cpufreq_freq_attr_scaling_available_freqs,
  931 + &freqdomain_cpus,
911 932 NULL, /* this is a placeholder for cpb, do not remove */
912 933 NULL,
913 934 };
drivers/cpufreq/cpufreq.c
... ... @@ -312,6 +312,12 @@
312 312 switch (state) {
313 313  
314 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 321 /* detect if the driver reported a value as "old frequency"
316 322 * which is not equal to what the cpufreq core thinks is
317 323 * "old frequency".
... ... @@ -331,6 +337,12 @@
331 337 break;
332 338  
333 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 346 adjust_jiffies(CPUFREQ_POSTCHANGE, freqs);
335 347 pr_debug("FREQ: %lu - CPU: %lu", (unsigned long)freqs->new,
336 348 (unsigned long)freqs->cpu);
... ... @@ -573,7 +585,7 @@
573 585 return i;
574 586 }
575 587  
576   -static ssize_t show_cpus(const struct cpumask *mask, char *buf)
  588 +ssize_t cpufreq_show_cpus(const struct cpumask *mask, char *buf)
577 589 {
578 590 ssize_t i = 0;
579 591 unsigned int cpu;
... ... @@ -588,6 +600,7 @@
588 600 i += sprintf(&buf[i], "\n");
589 601 return i;
590 602 }
  603 +EXPORT_SYMBOL_GPL(cpufreq_show_cpus);
591 604  
592 605 /**
593 606 * show_related_cpus - show the CPUs affected by each transition even if
... ... @@ -595,7 +608,7 @@
595 608 */
596 609 static 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 @@
603 616 */
604 617 static 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  
609 622 static ssize_t store_scaling_setspeed(struct cpufreq_policy *policy,
... ... @@ -1539,6 +1552,8 @@
1539 1552  
1540 1553 if (cpufreq_disabled())
1541 1554 return -ENODEV;
  1555 + if (policy->transition_ongoing)
  1556 + return -EBUSY;
1542 1557  
1543 1558 /* Make sure that target_freq is within supported range */
1544 1559 if (target_freq > policy->max)
drivers/cpufreq/cpufreq_governor.c
... ... @@ -366,6 +366,7 @@
366 366  
367 367 mutex_lock(&dbs_data->mutex);
368 368 mutex_destroy(&cpu_cdbs->timer_mutex);
  369 + cpu_cdbs->cur_policy = NULL;
369 370  
370 371 mutex_unlock(&dbs_data->mutex);
371 372  
include/linux/cpufreq.h
... ... @@ -119,6 +119,7 @@
119 119  
120 120 struct kobject kobj;
121 121 struct completion kobj_unregister;
  122 + bool transition_ongoing; /* Tracks transition status */
122 123 };
123 124  
124 125 #define CPUFREQ_ADJUST (0)
... ... @@ -438,5 +439,8 @@
438 439 void cpufreq_frequency_table_update_policy_cpu(struct cpufreq_policy *policy);
439 440  
440 441 void cpufreq_frequency_table_put_attr(unsigned int cpu);
  442 +
  443 +ssize_t cpufreq_show_cpus(const struct cpumask *mask, char *buf);
  444 +
441 445 #endif /* _LINUX_CPUFREQ_H */