diff options
author | Lan Tianyu <tianyu.lan@intel.com> | 2013-06-27 03:08:54 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-06-27 15:51:09 -0400 |
commit | f4fd3797848aa04e72e942c855fd279840a47fe4 (patch) | |
tree | 41419a82efe0e11be4f2cf870a58b3356e01ce0b | |
parent | 7c30ed532cf798a8d924562f2f44d03d7652f7a7 (diff) |
acpi-cpufreq: Add new sysfs attribute freqdomain_cpus
Commits fcf8058 (cpufreq: Simplify cpufreq_add_dev()) and aa77a52
(cpufreq: acpi-cpufreq: Don't set policy->related_cpus from .init())
changed the contents of the "related_cpus" sysfs attribute on systems
where acpi-cpufreq is used and user space can't get the list of CPUs
which are in the same hardware coordination CPU domain (provided by
the ACPI AML method _PSD) via "related_cpus" any more.
To make up for that loss add a new sysfs attribute "freqdomian_cpus"
for the acpi-cpufreq driver which exposes the list of CPUs in the
same domain regardless of whether it is coordinated by hardware or
software.
[rjw: Changelog, documentation]
References: https://bugzilla.kernel.org/show_bug.cgi?id=58761
Reported-by: Jean-Philippe Halimi <jean-philippe.halimi@exascale-computing.eu>
Signed-off-by: Lan Tianyu <tianyu.lan@intel.com>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r-- | Documentation/ABI/testing/sysfs-devices-system-cpu | 15 | ||||
-rw-r--r-- | drivers/cpufreq/acpi-cpufreq.c | 23 | ||||
-rw-r--r-- | drivers/cpufreq/cpufreq.c | 7 | ||||
-rw-r--r-- | include/linux/cpufreq.h | 3 |
4 files changed, 44 insertions, 4 deletions
diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu index 2447698aed41..468e4d48f884 100644 --- a/Documentation/ABI/testing/sysfs-devices-system-cpu +++ b/Documentation/ABI/testing/sysfs-devices-system-cpu | |||
@@ -144,6 +144,21 @@ Description: Discover and change clock speed of CPUs | |||
144 | to learn how to control the knobs. | 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 | What: /sys/devices/system/cpu/cpu*/cache/index3/cache_disable_{0,1} | 162 | What: /sys/devices/system/cpu/cpu*/cache/index3/cache_disable_{0,1} |
148 | Date: August 2008 | 163 | Date: August 2008 |
149 | KernelVersion: 2.6.27 | 164 | KernelVersion: 2.6.27 |
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index 2c5906d71397..403dad646abe 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 | ||
75 | static DEFINE_PER_CPU(struct acpi_cpufreq_data *, acfreq_data); | 76 | static 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 | ||
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 | #ifdef CONFIG_X86_ACPI_CPUFREQ_CPB | 189 | #ifdef CONFIG_X86_ACPI_CPUFREQ_CPB |
180 | static ssize_t store_cpb(struct cpufreq_policy *policy, const char *buf, | 190 | static 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); |
871 | err_unreg: | 888 | err_unreg: |
872 | acpi_processor_unregister_performance(perf, cpu); | 889 | acpi_processor_unregister_performance(perf, cpu); |
890 | err_free_mask: | ||
891 | free_cpumask_var(data->freqdomain_cpus); | ||
873 | err_free: | 892 | err_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 | ||
909 | static struct freq_attr *acpi_cpufreq_attr[] = { | 929 | static 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 03b3b69f64a7..6a015ada5285 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
@@ -585,7 +585,7 @@ out: | |||
585 | return i; | 585 | return i; |
586 | } | 586 | } |
587 | 587 | ||
588 | static ssize_t show_cpus(const struct cpumask *mask, char *buf) | 588 | ssize_t cpufreq_show_cpus(const struct cpumask *mask, char *buf) |
589 | { | 589 | { |
590 | ssize_t i = 0; | 590 | ssize_t i = 0; |
591 | unsigned int cpu; | 591 | unsigned int cpu; |
@@ -600,6 +600,7 @@ static ssize_t show_cpus(const struct cpumask *mask, char *buf) | |||
600 | i += sprintf(&buf[i], "\n"); | 600 | i += sprintf(&buf[i], "\n"); |
601 | return i; | 601 | return i; |
602 | } | 602 | } |
603 | EXPORT_SYMBOL_GPL(cpufreq_show_cpus); | ||
603 | 604 | ||
604 | /** | 605 | /** |
605 | * 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 |
@@ -607,7 +608,7 @@ static ssize_t show_cpus(const struct cpumask *mask, char *buf) | |||
607 | */ | 608 | */ |
608 | static ssize_t show_related_cpus(struct cpufreq_policy *policy, char *buf) | 609 | static ssize_t show_related_cpus(struct cpufreq_policy *policy, char *buf) |
609 | { | 610 | { |
610 | return show_cpus(policy->related_cpus, buf); | 611 | return cpufreq_show_cpus(policy->related_cpus, buf); |
611 | } | 612 | } |
612 | 613 | ||
613 | /** | 614 | /** |
@@ -615,7 +616,7 @@ static ssize_t show_related_cpus(struct cpufreq_policy *policy, char *buf) | |||
615 | */ | 616 | */ |
616 | static ssize_t show_affected_cpus(struct cpufreq_policy *policy, char *buf) | 617 | static ssize_t show_affected_cpus(struct cpufreq_policy *policy, char *buf) |
617 | { | 618 | { |
618 | return show_cpus(policy->cpus, buf); | 619 | return cpufreq_show_cpus(policy->cpus, buf); |
619 | } | 620 | } |
620 | 621 | ||
621 | static ssize_t store_scaling_setspeed(struct cpufreq_policy *policy, | 622 | static ssize_t store_scaling_setspeed(struct cpufreq_policy *policy, |
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index c0bc7374445e..4d7390bc1727 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h | |||
@@ -439,4 +439,7 @@ void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table, | |||
439 | void cpufreq_frequency_table_update_policy_cpu(struct cpufreq_policy *policy); | 439 | void cpufreq_frequency_table_update_policy_cpu(struct cpufreq_policy *policy); |
440 | 440 | ||
441 | void cpufreq_frequency_table_put_attr(unsigned int cpu); | 441 | void cpufreq_frequency_table_put_attr(unsigned int cpu); |
442 | |||
443 | ssize_t cpufreq_show_cpus(const struct cpumask *mask, char *buf); | ||
444 | |||
442 | #endif /* _LINUX_CPUFREQ_H */ | 445 | #endif /* _LINUX_CPUFREQ_H */ |