diff options
| author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2015-02-10 10:10:44 -0500 |
|---|---|---|
| committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2015-02-10 10:10:44 -0500 |
| commit | 7bc95d4ef1033af808cb0714081cb45cd4ee5669 (patch) | |
| tree | d43620fa7ff300ec8422c8eddc38014e902312bb | |
| parent | f52386892fb17b4a70a7a73240c0f04a0a6011a6 (diff) | |
| parent | c488ea461359483976ff7d4838cce5c0138c6b3e (diff) | |
Merge branch 'pm-cpufreq'
* pm-cpufreq: (46 commits)
intel_pstate: provide option to only use intel_pstate with HWP
cpufreq-dt: Drop unnecessary check before cpufreq_cooling_unregister() invocation
cpufreq: Create for_each_governor()
cpufreq: Create for_each_policy()
cpufreq: Drop cpufreq_disabled() check from cpufreq_cpu_{get|put}()
cpufreq: Set cpufreq_cpu_data to NULL before putting kobject
intel_pstate: honor user space min_perf_pct override on resume
intel_pstate: respect cpufreq policy request
intel_pstate: Add num_pstates to sysfs
intel_pstate: expose turbo range to sysfs
intel_pstate: Add support for SkyLake
cpufreq: stats: drop unnecessary locking
cpufreq: stats: don't update stats on false notifiers
cpufreq: stats: don't update stats from show_trans_table()
cpufreq: stats: time_in_state can't be NULL in cpufreq_stats_update()
cpufreq: stats: create sysfs group once we are ready
cpufreq: remove CPUFREQ_UPDATE_POLICY_CPU notifications
cpufreq: stats: drop 'cpu' field of struct cpufreq_stats
cpufreq: Remove (now) unused 'last_cpu' from struct cpufreq_policy
cpufreq: stats: rename 'struct cpufreq_stats' objects as 'stats'
...
| -rw-r--r-- | Documentation/cpu-freq/intel-pstate.txt | 8 | ||||
| -rw-r--r-- | Documentation/kernel-parameters.txt | 3 | ||||
| -rw-r--r-- | arch/x86/include/uapi/asm/msr-index.h | 1 | ||||
| -rw-r--r-- | drivers/cpufreq/Kconfig.x86 | 10 | ||||
| -rw-r--r-- | drivers/cpufreq/Makefile | 1 | ||||
| -rw-r--r-- | drivers/cpufreq/cpufreq-dt.c | 3 | ||||
| -rw-r--r-- | drivers/cpufreq/cpufreq.c | 174 | ||||
| -rw-r--r-- | drivers/cpufreq/cpufreq_stats.c | 219 | ||||
| -rw-r--r-- | drivers/cpufreq/intel_pstate.c | 55 | ||||
| -rw-r--r-- | drivers/cpufreq/ls1x-cpufreq.c | 1 | ||||
| -rw-r--r-- | drivers/cpufreq/sfi-cpufreq.c | 136 | ||||
| -rw-r--r-- | drivers/sfi/sfi_core.c | 4 | ||||
| -rw-r--r-- | include/linux/cpufreq.h | 10 |
13 files changed, 386 insertions, 239 deletions
diff --git a/Documentation/cpu-freq/intel-pstate.txt b/Documentation/cpu-freq/intel-pstate.txt index 765d7fc0e692..655750743fb0 100644 --- a/Documentation/cpu-freq/intel-pstate.txt +++ b/Documentation/cpu-freq/intel-pstate.txt | |||
| @@ -37,6 +37,14 @@ controlling P state selection. These files have been added to | |||
| 37 | no_turbo: limits the driver to selecting P states below the turbo | 37 | no_turbo: limits the driver to selecting P states below the turbo |
| 38 | frequency range. | 38 | frequency range. |
| 39 | 39 | ||
| 40 | turbo_pct: displays the percentage of the total performance that | ||
| 41 | is supported by hardware that is in the turbo range. This number | ||
| 42 | is independent of whether turbo has been disabled or not. | ||
| 43 | |||
| 44 | num_pstates: displays the number of pstates that are supported | ||
| 45 | by hardware. This number is independent of whether turbo has | ||
| 46 | been disabled or not. | ||
| 47 | |||
| 40 | For contemporary Intel processors, the frequency is controlled by the | 48 | For contemporary Intel processors, the frequency is controlled by the |
| 41 | processor itself and the P-states exposed to software are related to | 49 | processor itself and the P-states exposed to software are related to |
| 42 | performance levels. The idea that frequency can be set to a single | 50 | performance levels. The idea that frequency can be set to a single |
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 176d4fe4f076..f06f1f609cb7 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
| @@ -1470,6 +1470,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted. | |||
| 1470 | no_hwp | 1470 | no_hwp |
| 1471 | Do not enable hardware P state control (HWP) | 1471 | Do not enable hardware P state control (HWP) |
| 1472 | if available. | 1472 | if available. |
| 1473 | hwp_only | ||
| 1474 | Only load intel_pstate on systems which support | ||
| 1475 | hardware P state control (HWP) if available. | ||
| 1473 | 1476 | ||
| 1474 | intremap= [X86-64, Intel-IOMMU] | 1477 | intremap= [X86-64, Intel-IOMMU] |
| 1475 | on enable Interrupt Remapping (default) | 1478 | on enable Interrupt Remapping (default) |
diff --git a/arch/x86/include/uapi/asm/msr-index.h b/arch/x86/include/uapi/asm/msr-index.h index c8aa65d56027..d11e1c57cfc5 100644 --- a/arch/x86/include/uapi/asm/msr-index.h +++ b/arch/x86/include/uapi/asm/msr-index.h | |||
| @@ -358,6 +358,7 @@ | |||
| 358 | 358 | ||
| 359 | #define MSR_IA32_PERF_STATUS 0x00000198 | 359 | #define MSR_IA32_PERF_STATUS 0x00000198 |
| 360 | #define MSR_IA32_PERF_CTL 0x00000199 | 360 | #define MSR_IA32_PERF_CTL 0x00000199 |
| 361 | #define INTEL_PERF_CTL_MASK 0xffff | ||
| 361 | #define MSR_AMD_PSTATE_DEF_BASE 0xc0010064 | 362 | #define MSR_AMD_PSTATE_DEF_BASE 0xc0010064 |
| 362 | #define MSR_AMD_PERF_STATUS 0xc0010063 | 363 | #define MSR_AMD_PERF_STATUS 0xc0010063 |
| 363 | #define MSR_AMD_PERF_CTL 0xc0010062 | 364 | #define MSR_AMD_PERF_CTL 0xc0010062 |
diff --git a/drivers/cpufreq/Kconfig.x86 b/drivers/cpufreq/Kconfig.x86 index 89ae88f91895..c59bdcb83217 100644 --- a/drivers/cpufreq/Kconfig.x86 +++ b/drivers/cpufreq/Kconfig.x86 | |||
| @@ -57,6 +57,16 @@ config X86_ACPI_CPUFREQ_CPB | |||
| 57 | By enabling this option the acpi_cpufreq driver provides the old | 57 | By enabling this option the acpi_cpufreq driver provides the old |
| 58 | entry in addition to the new boost ones, for compatibility reasons. | 58 | entry in addition to the new boost ones, for compatibility reasons. |
| 59 | 59 | ||
| 60 | config X86_SFI_CPUFREQ | ||
| 61 | tristate "SFI Performance-States driver" | ||
| 62 | depends on X86_INTEL_MID && SFI | ||
| 63 | help | ||
| 64 | This adds a CPUFreq driver for some Silvermont based Intel Atom | ||
| 65 | architectures like Z34xx and Z35xx which enumerate processor | ||
| 66 | performance states through SFI. | ||
| 67 | |||
| 68 | If in doubt, say N. | ||
| 69 | |||
| 60 | config ELAN_CPUFREQ | 70 | config ELAN_CPUFREQ |
| 61 | tristate "AMD Elan SC400 and SC410" | 71 | tristate "AMD Elan SC400 and SC410" |
| 62 | depends on MELAN | 72 | depends on MELAN |
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index b3ca7b0b2c33..8b4220ac888b 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile | |||
| @@ -41,6 +41,7 @@ obj-$(CONFIG_X86_P4_CLOCKMOD) += p4-clockmod.o | |||
| 41 | obj-$(CONFIG_X86_CPUFREQ_NFORCE2) += cpufreq-nforce2.o | 41 | obj-$(CONFIG_X86_CPUFREQ_NFORCE2) += cpufreq-nforce2.o |
| 42 | obj-$(CONFIG_X86_INTEL_PSTATE) += intel_pstate.o | 42 | obj-$(CONFIG_X86_INTEL_PSTATE) += intel_pstate.o |
| 43 | obj-$(CONFIG_X86_AMD_FREQ_SENSITIVITY) += amd_freq_sensitivity.o | 43 | obj-$(CONFIG_X86_AMD_FREQ_SENSITIVITY) += amd_freq_sensitivity.o |
| 44 | obj-$(CONFIG_X86_SFI_CPUFREQ) += sfi-cpufreq.o | ||
| 44 | 45 | ||
| 45 | ################################################################################## | 46 | ################################################################################## |
| 46 | # ARM SoC drivers | 47 | # ARM SoC drivers |
diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c index fde97d6e31d6..bab67db54b7e 100644 --- a/drivers/cpufreq/cpufreq-dt.c +++ b/drivers/cpufreq/cpufreq-dt.c | |||
| @@ -320,8 +320,7 @@ static int cpufreq_exit(struct cpufreq_policy *policy) | |||
| 320 | { | 320 | { |
| 321 | struct private_data *priv = policy->driver_data; | 321 | struct private_data *priv = policy->driver_data; |
| 322 | 322 | ||
| 323 | if (priv->cdev) | 323 | cpufreq_cooling_unregister(priv->cdev); |
| 324 | cpufreq_cooling_unregister(priv->cdev); | ||
| 325 | dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table); | 324 | dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table); |
| 326 | of_free_opp_table(priv->cpu_dev); | 325 | of_free_opp_table(priv->cpu_dev); |
| 327 | clk_put(policy->clk); | 326 | clk_put(policy->clk); |
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 46bed4f81cde..28e59a48b35f 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
| @@ -27,9 +27,21 @@ | |||
| 27 | #include <linux/mutex.h> | 27 | #include <linux/mutex.h> |
| 28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
| 29 | #include <linux/suspend.h> | 29 | #include <linux/suspend.h> |
| 30 | #include <linux/syscore_ops.h> | ||
| 30 | #include <linux/tick.h> | 31 | #include <linux/tick.h> |
| 31 | #include <trace/events/power.h> | 32 | #include <trace/events/power.h> |
| 32 | 33 | ||
| 34 | /* Macros to iterate over lists */ | ||
| 35 | /* Iterate over online CPUs policies */ | ||
| 36 | static LIST_HEAD(cpufreq_policy_list); | ||
| 37 | #define for_each_policy(__policy) \ | ||
| 38 | list_for_each_entry(__policy, &cpufreq_policy_list, policy_list) | ||
| 39 | |||
| 40 | /* Iterate over governors */ | ||
| 41 | static LIST_HEAD(cpufreq_governor_list); | ||
| 42 | #define for_each_governor(__governor) \ | ||
| 43 | list_for_each_entry(__governor, &cpufreq_governor_list, governor_list) | ||
| 44 | |||
| 33 | /** | 45 | /** |
| 34 | * The "cpufreq driver" - the arch- or hardware-dependent low | 46 | * The "cpufreq driver" - the arch- or hardware-dependent low |
| 35 | * level driver of CPUFreq support, and its spinlock. This lock | 47 | * level driver of CPUFreq support, and its spinlock. This lock |
| @@ -40,7 +52,6 @@ static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data); | |||
| 40 | static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data_fallback); | 52 | static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data_fallback); |
| 41 | static DEFINE_RWLOCK(cpufreq_driver_lock); | 53 | static DEFINE_RWLOCK(cpufreq_driver_lock); |
| 42 | DEFINE_MUTEX(cpufreq_governor_lock); | 54 | DEFINE_MUTEX(cpufreq_governor_lock); |
| 43 | static LIST_HEAD(cpufreq_policy_list); | ||
| 44 | 55 | ||
| 45 | /* This one keeps track of the previously set governor of a removed CPU */ | 56 | /* This one keeps track of the previously set governor of a removed CPU */ |
| 46 | static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN], cpufreq_cpu_governor); | 57 | static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN], cpufreq_cpu_governor); |
| @@ -62,7 +73,7 @@ static DECLARE_RWSEM(cpufreq_rwsem); | |||
| 62 | /* internal prototypes */ | 73 | /* internal prototypes */ |
| 63 | static int __cpufreq_governor(struct cpufreq_policy *policy, | 74 | static int __cpufreq_governor(struct cpufreq_policy *policy, |
| 64 | unsigned int event); | 75 | unsigned int event); |
| 65 | static unsigned int __cpufreq_get(unsigned int cpu); | 76 | static unsigned int __cpufreq_get(struct cpufreq_policy *policy); |
| 66 | static void handle_update(struct work_struct *work); | 77 | static void handle_update(struct work_struct *work); |
| 67 | 78 | ||
| 68 | /** | 79 | /** |
| @@ -93,7 +104,6 @@ void disable_cpufreq(void) | |||
| 93 | { | 104 | { |
| 94 | off = 1; | 105 | off = 1; |
| 95 | } | 106 | } |
| 96 | static LIST_HEAD(cpufreq_governor_list); | ||
| 97 | static DEFINE_MUTEX(cpufreq_governor_mutex); | 107 | static DEFINE_MUTEX(cpufreq_governor_mutex); |
| 98 | 108 | ||
| 99 | bool have_governor_per_policy(void) | 109 | bool have_governor_per_policy(void) |
| @@ -202,7 +212,7 @@ struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu) | |||
| 202 | struct cpufreq_policy *policy = NULL; | 212 | struct cpufreq_policy *policy = NULL; |
| 203 | unsigned long flags; | 213 | unsigned long flags; |
| 204 | 214 | ||
| 205 | if (cpufreq_disabled() || (cpu >= nr_cpu_ids)) | 215 | if (cpu >= nr_cpu_ids) |
| 206 | return NULL; | 216 | return NULL; |
| 207 | 217 | ||
| 208 | if (!down_read_trylock(&cpufreq_rwsem)) | 218 | if (!down_read_trylock(&cpufreq_rwsem)) |
| @@ -229,9 +239,6 @@ EXPORT_SYMBOL_GPL(cpufreq_cpu_get); | |||
| 229 | 239 | ||
| 230 | void cpufreq_cpu_put(struct cpufreq_policy *policy) | 240 | void cpufreq_cpu_put(struct cpufreq_policy *policy) |
| 231 | { | 241 | { |
| 232 | if (cpufreq_disabled()) | ||
| 233 | return; | ||
| 234 | |||
| 235 | kobject_put(&policy->kobj); | 242 | kobject_put(&policy->kobj); |
| 236 | up_read(&cpufreq_rwsem); | 243 | up_read(&cpufreq_rwsem); |
| 237 | } | 244 | } |
| @@ -249,12 +256,12 @@ EXPORT_SYMBOL_GPL(cpufreq_cpu_put); | |||
| 249 | * systems as each CPU might be scaled differently. So, use the arch | 256 | * systems as each CPU might be scaled differently. So, use the arch |
| 250 | * per-CPU loops_per_jiffy value wherever possible. | 257 | * per-CPU loops_per_jiffy value wherever possible. |
| 251 | */ | 258 | */ |
| 252 | #ifndef CONFIG_SMP | ||
| 253 | static unsigned long l_p_j_ref; | ||
| 254 | static unsigned int l_p_j_ref_freq; | ||
| 255 | |||
| 256 | static void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) | 259 | static void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) |
| 257 | { | 260 | { |
| 261 | #ifndef CONFIG_SMP | ||
| 262 | static unsigned long l_p_j_ref; | ||
| 263 | static unsigned int l_p_j_ref_freq; | ||
| 264 | |||
| 258 | if (ci->flags & CPUFREQ_CONST_LOOPS) | 265 | if (ci->flags & CPUFREQ_CONST_LOOPS) |
| 259 | return; | 266 | return; |
| 260 | 267 | ||
| @@ -270,13 +277,8 @@ static void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) | |||
| 270 | pr_debug("scaling loops_per_jiffy to %lu for frequency %u kHz\n", | 277 | pr_debug("scaling loops_per_jiffy to %lu for frequency %u kHz\n", |
| 271 | loops_per_jiffy, ci->new); | 278 | loops_per_jiffy, ci->new); |
| 272 | } | 279 | } |
| 273 | } | ||
| 274 | #else | ||
| 275 | static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) | ||
| 276 | { | ||
| 277 | return; | ||
| 278 | } | ||
| 279 | #endif | 280 | #endif |
| 281 | } | ||
| 280 | 282 | ||
| 281 | static void __cpufreq_notify_transition(struct cpufreq_policy *policy, | 283 | static void __cpufreq_notify_transition(struct cpufreq_policy *policy, |
| 282 | struct cpufreq_freqs *freqs, unsigned int state) | 284 | struct cpufreq_freqs *freqs, unsigned int state) |
| @@ -432,11 +434,11 @@ static ssize_t store_boost(struct kobject *kobj, struct attribute *attr, | |||
| 432 | } | 434 | } |
| 433 | define_one_global_rw(boost); | 435 | define_one_global_rw(boost); |
| 434 | 436 | ||
| 435 | static struct cpufreq_governor *__find_governor(const char *str_governor) | 437 | static struct cpufreq_governor *find_governor(const char *str_governor) |
| 436 | { | 438 | { |
| 437 | struct cpufreq_governor *t; | 439 | struct cpufreq_governor *t; |
| 438 | 440 | ||
| 439 | list_for_each_entry(t, &cpufreq_governor_list, governor_list) | 441 | for_each_governor(t) |
| 440 | if (!strncasecmp(str_governor, t->name, CPUFREQ_NAME_LEN)) | 442 | if (!strncasecmp(str_governor, t->name, CPUFREQ_NAME_LEN)) |
| 441 | return t; | 443 | return t; |
| 442 | 444 | ||
| @@ -463,12 +465,12 @@ static int cpufreq_parse_governor(char *str_governor, unsigned int *policy, | |||
| 463 | *policy = CPUFREQ_POLICY_POWERSAVE; | 465 | *policy = CPUFREQ_POLICY_POWERSAVE; |
| 464 | err = 0; | 466 | err = 0; |
| 465 | } | 467 | } |
| 466 | } else if (has_target()) { | 468 | } else { |
| 467 | struct cpufreq_governor *t; | 469 | struct cpufreq_governor *t; |
| 468 | 470 | ||
| 469 | mutex_lock(&cpufreq_governor_mutex); | 471 | mutex_lock(&cpufreq_governor_mutex); |
| 470 | 472 | ||
| 471 | t = __find_governor(str_governor); | 473 | t = find_governor(str_governor); |
| 472 | 474 | ||
| 473 | if (t == NULL) { | 475 | if (t == NULL) { |
| 474 | int ret; | 476 | int ret; |
| @@ -478,7 +480,7 @@ static int cpufreq_parse_governor(char *str_governor, unsigned int *policy, | |||
| 478 | mutex_lock(&cpufreq_governor_mutex); | 480 | mutex_lock(&cpufreq_governor_mutex); |
| 479 | 481 | ||
| 480 | if (ret == 0) | 482 | if (ret == 0) |
| 481 | t = __find_governor(str_governor); | 483 | t = find_governor(str_governor); |
| 482 | } | 484 | } |
| 483 | 485 | ||
| 484 | if (t != NULL) { | 486 | if (t != NULL) { |
| @@ -513,8 +515,7 @@ show_one(cpuinfo_transition_latency, cpuinfo.transition_latency); | |||
| 513 | show_one(scaling_min_freq, min); | 515 | show_one(scaling_min_freq, min); |
| 514 | show_one(scaling_max_freq, max); | 516 | show_one(scaling_max_freq, max); |
| 515 | 517 | ||
| 516 | static ssize_t show_scaling_cur_freq( | 518 | static ssize_t show_scaling_cur_freq(struct cpufreq_policy *policy, char *buf) |
| 517 | struct cpufreq_policy *policy, char *buf) | ||
| 518 | { | 519 | { |
| 519 | ssize_t ret; | 520 | ssize_t ret; |
| 520 | 521 | ||
| @@ -563,7 +564,7 @@ store_one(scaling_max_freq, max); | |||
| 563 | static ssize_t show_cpuinfo_cur_freq(struct cpufreq_policy *policy, | 564 | static ssize_t show_cpuinfo_cur_freq(struct cpufreq_policy *policy, |
| 564 | char *buf) | 565 | char *buf) |
| 565 | { | 566 | { |
| 566 | unsigned int cur_freq = __cpufreq_get(policy->cpu); | 567 | unsigned int cur_freq = __cpufreq_get(policy); |
| 567 | if (!cur_freq) | 568 | if (!cur_freq) |
| 568 | return sprintf(buf, "<unknown>"); | 569 | return sprintf(buf, "<unknown>"); |
| 569 | return sprintf(buf, "%u\n", cur_freq); | 570 | return sprintf(buf, "%u\n", cur_freq); |
| @@ -639,7 +640,7 @@ static ssize_t show_scaling_available_governors(struct cpufreq_policy *policy, | |||
| 639 | goto out; | 640 | goto out; |
| 640 | } | 641 | } |
| 641 | 642 | ||
| 642 | list_for_each_entry(t, &cpufreq_governor_list, governor_list) { | 643 | for_each_governor(t) { |
| 643 | if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char)) | 644 | if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char)) |
| 644 | - (CPUFREQ_NAME_LEN + 2))) | 645 | - (CPUFREQ_NAME_LEN + 2))) |
| 645 | goto out; | 646 | goto out; |
| @@ -902,7 +903,7 @@ static int cpufreq_add_dev_interface(struct cpufreq_policy *policy, | |||
| 902 | 903 | ||
| 903 | /* set up files for this cpu device */ | 904 | /* set up files for this cpu device */ |
| 904 | drv_attr = cpufreq_driver->attr; | 905 | drv_attr = cpufreq_driver->attr; |
| 905 | while ((drv_attr) && (*drv_attr)) { | 906 | while (drv_attr && *drv_attr) { |
| 906 | ret = sysfs_create_file(&policy->kobj, &((*drv_attr)->attr)); | 907 | ret = sysfs_create_file(&policy->kobj, &((*drv_attr)->attr)); |
| 907 | if (ret) | 908 | if (ret) |
| 908 | return ret; | 909 | return ret; |
| @@ -936,7 +937,7 @@ static void cpufreq_init_policy(struct cpufreq_policy *policy) | |||
| 936 | memcpy(&new_policy, policy, sizeof(*policy)); | 937 | memcpy(&new_policy, policy, sizeof(*policy)); |
| 937 | 938 | ||
| 938 | /* Update governor of new_policy to the governor used before hotplug */ | 939 | /* Update governor of new_policy to the governor used before hotplug */ |
| 939 | gov = __find_governor(per_cpu(cpufreq_cpu_governor, policy->cpu)); | 940 | gov = find_governor(per_cpu(cpufreq_cpu_governor, policy->cpu)); |
| 940 | if (gov) | 941 | if (gov) |
| 941 | pr_debug("Restoring governor %s for cpu %d\n", | 942 | pr_debug("Restoring governor %s for cpu %d\n", |
| 942 | policy->governor->name, policy->cpu); | 943 | policy->governor->name, policy->cpu); |
| @@ -958,7 +959,6 @@ static void cpufreq_init_policy(struct cpufreq_policy *policy) | |||
| 958 | } | 959 | } |
| 959 | } | 960 | } |
| 960 | 961 | ||
| 961 | #ifdef CONFIG_HOTPLUG_CPU | ||
| 962 | static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy, | 962 | static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy, |
| 963 | unsigned int cpu, struct device *dev) | 963 | unsigned int cpu, struct device *dev) |
| 964 | { | 964 | { |
| @@ -996,7 +996,6 @@ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy, | |||
| 996 | 996 | ||
| 997 | return sysfs_create_link(&dev->kobj, &policy->kobj, "cpufreq"); | 997 | return sysfs_create_link(&dev->kobj, &policy->kobj, "cpufreq"); |
| 998 | } | 998 | } |
| 999 | #endif | ||
| 1000 | 999 | ||
| 1001 | static struct cpufreq_policy *cpufreq_policy_restore(unsigned int cpu) | 1000 | static struct cpufreq_policy *cpufreq_policy_restore(unsigned int cpu) |
| 1002 | { | 1001 | { |
| @@ -1033,6 +1032,8 @@ static struct cpufreq_policy *cpufreq_policy_alloc(void) | |||
| 1033 | init_rwsem(&policy->rwsem); | 1032 | init_rwsem(&policy->rwsem); |
| 1034 | spin_lock_init(&policy->transition_lock); | 1033 | spin_lock_init(&policy->transition_lock); |
| 1035 | init_waitqueue_head(&policy->transition_wait); | 1034 | init_waitqueue_head(&policy->transition_wait); |
| 1035 | init_completion(&policy->kobj_unregister); | ||
| 1036 | INIT_WORK(&policy->update, handle_update); | ||
| 1036 | 1037 | ||
| 1037 | return policy; | 1038 | return policy; |
| 1038 | 1039 | ||
| @@ -1091,15 +1092,9 @@ static int update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu, | |||
| 1091 | } | 1092 | } |
| 1092 | 1093 | ||
| 1093 | down_write(&policy->rwsem); | 1094 | down_write(&policy->rwsem); |
| 1094 | |||
| 1095 | policy->last_cpu = policy->cpu; | ||
| 1096 | policy->cpu = cpu; | 1095 | policy->cpu = cpu; |
| 1097 | |||
| 1098 | up_write(&policy->rwsem); | 1096 | up_write(&policy->rwsem); |
| 1099 | 1097 | ||
| 1100 | blocking_notifier_call_chain(&cpufreq_policy_notifier_list, | ||
| 1101 | CPUFREQ_UPDATE_POLICY_CPU, policy); | ||
| 1102 | |||
| 1103 | return 0; | 1098 | return 0; |
| 1104 | } | 1099 | } |
| 1105 | 1100 | ||
| @@ -1110,41 +1105,32 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) | |||
| 1110 | struct cpufreq_policy *policy; | 1105 | struct cpufreq_policy *policy; |
| 1111 | unsigned long flags; | 1106 | unsigned long flags; |
| 1112 | bool recover_policy = cpufreq_suspended; | 1107 | bool recover_policy = cpufreq_suspended; |
| 1113 | #ifdef CONFIG_HOTPLUG_CPU | ||
| 1114 | struct cpufreq_policy *tpolicy; | ||
| 1115 | #endif | ||
| 1116 | 1108 | ||
| 1117 | if (cpu_is_offline(cpu)) | 1109 | if (cpu_is_offline(cpu)) |
| 1118 | return 0; | 1110 | return 0; |
| 1119 | 1111 | ||
| 1120 | pr_debug("adding CPU %u\n", cpu); | 1112 | pr_debug("adding CPU %u\n", cpu); |
| 1121 | 1113 | ||
| 1122 | #ifdef CONFIG_SMP | ||
| 1123 | /* check whether a different CPU already registered this | 1114 | /* check whether a different CPU already registered this |
| 1124 | * CPU because it is in the same boat. */ | 1115 | * CPU because it is in the same boat. */ |
| 1125 | policy = cpufreq_cpu_get(cpu); | 1116 | policy = cpufreq_cpu_get_raw(cpu); |
| 1126 | if (unlikely(policy)) { | 1117 | if (unlikely(policy)) |
| 1127 | cpufreq_cpu_put(policy); | ||
| 1128 | return 0; | 1118 | return 0; |
| 1129 | } | ||
| 1130 | #endif | ||
| 1131 | 1119 | ||
| 1132 | if (!down_read_trylock(&cpufreq_rwsem)) | 1120 | if (!down_read_trylock(&cpufreq_rwsem)) |
| 1133 | return 0; | 1121 | return 0; |
| 1134 | 1122 | ||
| 1135 | #ifdef CONFIG_HOTPLUG_CPU | ||
| 1136 | /* Check if this cpu was hot-unplugged earlier and has siblings */ | 1123 | /* Check if this cpu was hot-unplugged earlier and has siblings */ |
| 1137 | read_lock_irqsave(&cpufreq_driver_lock, flags); | 1124 | read_lock_irqsave(&cpufreq_driver_lock, flags); |
| 1138 | list_for_each_entry(tpolicy, &cpufreq_policy_list, policy_list) { | 1125 | for_each_policy(policy) { |
| 1139 | if (cpumask_test_cpu(cpu, tpolicy->related_cpus)) { | 1126 | if (cpumask_test_cpu(cpu, policy->related_cpus)) { |
| 1140 | read_unlock_irqrestore(&cpufreq_driver_lock, flags); | 1127 | read_unlock_irqrestore(&cpufreq_driver_lock, flags); |
| 1141 | ret = cpufreq_add_policy_cpu(tpolicy, cpu, dev); | 1128 | ret = cpufreq_add_policy_cpu(policy, cpu, dev); |
| 1142 | up_read(&cpufreq_rwsem); | 1129 | up_read(&cpufreq_rwsem); |
| 1143 | return ret; | 1130 | return ret; |
| 1144 | } | 1131 | } |
| 1145 | } | 1132 | } |
| 1146 | read_unlock_irqrestore(&cpufreq_driver_lock, flags); | 1133 | read_unlock_irqrestore(&cpufreq_driver_lock, flags); |
| 1147 | #endif | ||
| 1148 | 1134 | ||
| 1149 | /* | 1135 | /* |
| 1150 | * Restore the saved policy when doing light-weight init and fall back | 1136 | * Restore the saved policy when doing light-weight init and fall back |
| @@ -1171,9 +1157,6 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) | |||
| 1171 | 1157 | ||
| 1172 | cpumask_copy(policy->cpus, cpumask_of(cpu)); | 1158 | cpumask_copy(policy->cpus, cpumask_of(cpu)); |
| 1173 | 1159 | ||
| 1174 | init_completion(&policy->kobj_unregister); | ||
| 1175 | INIT_WORK(&policy->update, handle_update); | ||
| 1176 | |||
| 1177 | /* call driver. From then on the cpufreq must be able | 1160 | /* call driver. From then on the cpufreq must be able |
| 1178 | * to accept all calls to ->verify and ->setpolicy for this CPU | 1161 | * to accept all calls to ->verify and ->setpolicy for this CPU |
| 1179 | */ | 1162 | */ |
| @@ -1371,11 +1354,10 @@ static int __cpufreq_remove_dev_prepare(struct device *dev, | |||
| 1371 | pr_err("%s: Failed to stop governor\n", __func__); | 1354 | pr_err("%s: Failed to stop governor\n", __func__); |
| 1372 | return ret; | 1355 | return ret; |
| 1373 | } | 1356 | } |
| 1374 | } | ||
| 1375 | 1357 | ||
| 1376 | if (!cpufreq_driver->setpolicy) | ||
| 1377 | strncpy(per_cpu(cpufreq_cpu_governor, cpu), | 1358 | strncpy(per_cpu(cpufreq_cpu_governor, cpu), |
| 1378 | policy->governor->name, CPUFREQ_NAME_LEN); | 1359 | policy->governor->name, CPUFREQ_NAME_LEN); |
| 1360 | } | ||
| 1379 | 1361 | ||
| 1380 | down_read(&policy->rwsem); | 1362 | down_read(&policy->rwsem); |
| 1381 | cpus = cpumask_weight(policy->cpus); | 1363 | cpus = cpumask_weight(policy->cpus); |
| @@ -1416,9 +1398,10 @@ static int __cpufreq_remove_dev_finish(struct device *dev, | |||
| 1416 | unsigned long flags; | 1398 | unsigned long flags; |
| 1417 | struct cpufreq_policy *policy; | 1399 | struct cpufreq_policy *policy; |
| 1418 | 1400 | ||
| 1419 | read_lock_irqsave(&cpufreq_driver_lock, flags); | 1401 | write_lock_irqsave(&cpufreq_driver_lock, flags); |
| 1420 | policy = per_cpu(cpufreq_cpu_data, cpu); | 1402 | policy = per_cpu(cpufreq_cpu_data, cpu); |
| 1421 | read_unlock_irqrestore(&cpufreq_driver_lock, flags); | 1403 | per_cpu(cpufreq_cpu_data, cpu) = NULL; |
| 1404 | write_unlock_irqrestore(&cpufreq_driver_lock, flags); | ||
| 1422 | 1405 | ||
| 1423 | if (!policy) { | 1406 | if (!policy) { |
| 1424 | pr_debug("%s: No cpu_data found\n", __func__); | 1407 | pr_debug("%s: No cpu_data found\n", __func__); |
| @@ -1473,7 +1456,6 @@ static int __cpufreq_remove_dev_finish(struct device *dev, | |||
| 1473 | } | 1456 | } |
| 1474 | } | 1457 | } |
| 1475 | 1458 | ||
| 1476 | per_cpu(cpufreq_cpu_data, cpu) = NULL; | ||
| 1477 | return 0; | 1459 | return 0; |
| 1478 | } | 1460 | } |
| 1479 | 1461 | ||
| @@ -1510,30 +1492,23 @@ static void handle_update(struct work_struct *work) | |||
| 1510 | /** | 1492 | /** |
| 1511 | * cpufreq_out_of_sync - If actual and saved CPU frequency differs, we're | 1493 | * cpufreq_out_of_sync - If actual and saved CPU frequency differs, we're |
| 1512 | * in deep trouble. | 1494 | * in deep trouble. |
| 1513 | * @cpu: cpu number | 1495 | * @policy: policy managing CPUs |
| 1514 | * @old_freq: CPU frequency the kernel thinks the CPU runs at | ||
| 1515 | * @new_freq: CPU frequency the CPU actually runs at | 1496 | * @new_freq: CPU frequency the CPU actually runs at |
| 1516 | * | 1497 | * |
| 1517 | * We adjust to current frequency first, and need to clean up later. | 1498 | * We adjust to current frequency first, and need to clean up later. |
| 1518 | * So either call to cpufreq_update_policy() or schedule handle_update()). | 1499 | * So either call to cpufreq_update_policy() or schedule handle_update()). |
| 1519 | */ | 1500 | */ |
| 1520 | static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq, | 1501 | static void cpufreq_out_of_sync(struct cpufreq_policy *policy, |
| 1521 | unsigned int new_freq) | 1502 | unsigned int new_freq) |
| 1522 | { | 1503 | { |
| 1523 | struct cpufreq_policy *policy; | ||
| 1524 | struct cpufreq_freqs freqs; | 1504 | struct cpufreq_freqs freqs; |
| 1525 | unsigned long flags; | ||
| 1526 | 1505 | ||
| 1527 | pr_debug("Warning: CPU frequency out of sync: cpufreq and timing core thinks of %u, is %u kHz\n", | 1506 | pr_debug("Warning: CPU frequency out of sync: cpufreq and timing core thinks of %u, is %u kHz\n", |
| 1528 | old_freq, new_freq); | 1507 | policy->cur, new_freq); |
| 1529 | 1508 | ||
| 1530 | freqs.old = old_freq; | 1509 | freqs.old = policy->cur; |
| 1531 | freqs.new = new_freq; | 1510 | freqs.new = new_freq; |
| 1532 | 1511 | ||
| 1533 | read_lock_irqsave(&cpufreq_driver_lock, flags); | ||
| 1534 | policy = per_cpu(cpufreq_cpu_data, cpu); | ||
| 1535 | read_unlock_irqrestore(&cpufreq_driver_lock, flags); | ||
| 1536 | |||
| 1537 | cpufreq_freq_transition_begin(policy, &freqs); | 1512 | cpufreq_freq_transition_begin(policy, &freqs); |
| 1538 | cpufreq_freq_transition_end(policy, &freqs, 0); | 1513 | cpufreq_freq_transition_end(policy, &freqs, 0); |
| 1539 | } | 1514 | } |
| @@ -1583,22 +1558,21 @@ unsigned int cpufreq_quick_get_max(unsigned int cpu) | |||
| 1583 | } | 1558 | } |
| 1584 | EXPORT_SYMBOL(cpufreq_quick_get_max); | 1559 | EXPORT_SYMBOL(cpufreq_quick_get_max); |
| 1585 | 1560 | ||
| 1586 | static unsigned int __cpufreq_get(unsigned int cpu) | 1561 | static unsigned int __cpufreq_get(struct cpufreq_policy *policy) |
| 1587 | { | 1562 | { |
| 1588 | struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu); | ||
| 1589 | unsigned int ret_freq = 0; | 1563 | unsigned int ret_freq = 0; |
| 1590 | 1564 | ||
| 1591 | if (!cpufreq_driver->get) | 1565 | if (!cpufreq_driver->get) |
| 1592 | return ret_freq; | 1566 | return ret_freq; |
| 1593 | 1567 | ||
| 1594 | ret_freq = cpufreq_driver->get(cpu); | 1568 | ret_freq = cpufreq_driver->get(policy->cpu); |
| 1595 | 1569 | ||
| 1596 | if (ret_freq && policy->cur && | 1570 | if (ret_freq && policy->cur && |
| 1597 | !(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) { | 1571 | !(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) { |
| 1598 | /* verify no discrepancy between actual and | 1572 | /* verify no discrepancy between actual and |
| 1599 | saved value exists */ | 1573 | saved value exists */ |
| 1600 | if (unlikely(ret_freq != policy->cur)) { | 1574 | if (unlikely(ret_freq != policy->cur)) { |
| 1601 | cpufreq_out_of_sync(cpu, policy->cur, ret_freq); | 1575 | cpufreq_out_of_sync(policy, ret_freq); |
| 1602 | schedule_work(&policy->update); | 1576 | schedule_work(&policy->update); |
| 1603 | } | 1577 | } |
| 1604 | } | 1578 | } |
| @@ -1619,7 +1593,7 @@ unsigned int cpufreq_get(unsigned int cpu) | |||
| 1619 | 1593 | ||
| 1620 | if (policy) { | 1594 | if (policy) { |
| 1621 | down_read(&policy->rwsem); | 1595 | down_read(&policy->rwsem); |
| 1622 | ret_freq = __cpufreq_get(cpu); | 1596 | ret_freq = __cpufreq_get(policy); |
| 1623 | up_read(&policy->rwsem); | 1597 | up_read(&policy->rwsem); |
| 1624 | 1598 | ||
| 1625 | cpufreq_cpu_put(policy); | 1599 | cpufreq_cpu_put(policy); |
| @@ -1682,7 +1656,7 @@ void cpufreq_suspend(void) | |||
| 1682 | 1656 | ||
| 1683 | pr_debug("%s: Suspending Governors\n", __func__); | 1657 | pr_debug("%s: Suspending Governors\n", __func__); |
| 1684 | 1658 | ||
| 1685 | list_for_each_entry(policy, &cpufreq_policy_list, policy_list) { | 1659 | for_each_policy(policy) { |
| 1686 | if (__cpufreq_governor(policy, CPUFREQ_GOV_STOP)) | 1660 | if (__cpufreq_governor(policy, CPUFREQ_GOV_STOP)) |
| 1687 | pr_err("%s: Failed to stop governor for policy: %p\n", | 1661 | pr_err("%s: Failed to stop governor for policy: %p\n", |
| 1688 | __func__, policy); | 1662 | __func__, policy); |
| @@ -1716,7 +1690,7 @@ void cpufreq_resume(void) | |||
| 1716 | 1690 | ||
| 1717 | pr_debug("%s: Resuming Governors\n", __func__); | 1691 | pr_debug("%s: Resuming Governors\n", __func__); |
| 1718 | 1692 | ||
| 1719 | list_for_each_entry(policy, &cpufreq_policy_list, policy_list) { | 1693 | for_each_policy(policy) { |
| 1720 | if (cpufreq_driver->resume && cpufreq_driver->resume(policy)) | 1694 | if (cpufreq_driver->resume && cpufreq_driver->resume(policy)) |
| 1721 | pr_err("%s: Failed to resume driver: %p\n", __func__, | 1695 | pr_err("%s: Failed to resume driver: %p\n", __func__, |
| 1722 | policy); | 1696 | policy); |
| @@ -2006,10 +1980,6 @@ int cpufreq_driver_target(struct cpufreq_policy *policy, | |||
| 2006 | } | 1980 | } |
| 2007 | EXPORT_SYMBOL_GPL(cpufreq_driver_target); | 1981 | EXPORT_SYMBOL_GPL(cpufreq_driver_target); |
| 2008 | 1982 | ||
| 2009 | /* | ||
| 2010 | * when "event" is CPUFREQ_GOV_LIMITS | ||
| 2011 | */ | ||
| 2012 | |||
| 2013 | static int __cpufreq_governor(struct cpufreq_policy *policy, | 1983 | static int __cpufreq_governor(struct cpufreq_policy *policy, |
| 2014 | unsigned int event) | 1984 | unsigned int event) |
| 2015 | { | 1985 | { |
| @@ -2107,7 +2077,7 @@ int cpufreq_register_governor(struct cpufreq_governor *governor) | |||
| 2107 | 2077 | ||
| 2108 | governor->initialized = 0; | 2078 | governor->initialized = 0; |
| 2109 | err = -EBUSY; | 2079 | err = -EBUSY; |
| 2110 | if (__find_governor(governor->name) == NULL) { | 2080 | if (!find_governor(governor->name)) { |
| 2111 | err = 0; | 2081 | err = 0; |
| 2112 | list_add(&governor->governor_list, &cpufreq_governor_list); | 2082 | list_add(&governor->governor_list, &cpufreq_governor_list); |
| 2113 | } | 2083 | } |
| @@ -2307,8 +2277,7 @@ int cpufreq_update_policy(unsigned int cpu) | |||
| 2307 | policy->cur = new_policy.cur; | 2277 | policy->cur = new_policy.cur; |
| 2308 | } else { | 2278 | } else { |
| 2309 | if (policy->cur != new_policy.cur && has_target()) | 2279 | if (policy->cur != new_policy.cur && has_target()) |
| 2310 | cpufreq_out_of_sync(cpu, policy->cur, | 2280 | cpufreq_out_of_sync(policy, new_policy.cur); |
| 2311 | new_policy.cur); | ||
| 2312 | } | 2281 | } |
| 2313 | } | 2282 | } |
| 2314 | 2283 | ||
| @@ -2364,7 +2333,7 @@ static int cpufreq_boost_set_sw(int state) | |||
| 2364 | struct cpufreq_policy *policy; | 2333 | struct cpufreq_policy *policy; |
| 2365 | int ret = -EINVAL; | 2334 | int ret = -EINVAL; |
| 2366 | 2335 | ||
| 2367 | list_for_each_entry(policy, &cpufreq_policy_list, policy_list) { | 2336 | for_each_policy(policy) { |
| 2368 | freq_table = cpufreq_frequency_get_table(policy->cpu); | 2337 | freq_table = cpufreq_frequency_get_table(policy->cpu); |
| 2369 | if (freq_table) { | 2338 | if (freq_table) { |
| 2370 | ret = cpufreq_frequency_table_cpuinfo(policy, | 2339 | ret = cpufreq_frequency_table_cpuinfo(policy, |
| @@ -2454,9 +2423,6 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) | |||
| 2454 | 2423 | ||
| 2455 | pr_debug("trying to register driver %s\n", driver_data->name); | 2424 | pr_debug("trying to register driver %s\n", driver_data->name); |
| 2456 | 2425 | ||
| 2457 | if (driver_data->setpolicy) | ||
| 2458 | driver_data->flags |= CPUFREQ_CONST_LOOPS; | ||
| 2459 | |||
| 2460 | write_lock_irqsave(&cpufreq_driver_lock, flags); | 2426 | write_lock_irqsave(&cpufreq_driver_lock, flags); |
| 2461 | if (cpufreq_driver) { | 2427 | if (cpufreq_driver) { |
| 2462 | write_unlock_irqrestore(&cpufreq_driver_lock, flags); | 2428 | write_unlock_irqrestore(&cpufreq_driver_lock, flags); |
| @@ -2465,6 +2431,9 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) | |||
| 2465 | cpufreq_driver = driver_data; | 2431 | cpufreq_driver = driver_data; |
| 2466 | write_unlock_irqrestore(&cpufreq_driver_lock, flags); | 2432 | write_unlock_irqrestore(&cpufreq_driver_lock, flags); |
| 2467 | 2433 | ||
| 2434 | if (driver_data->setpolicy) | ||
| 2435 | driver_data->flags |= CPUFREQ_CONST_LOOPS; | ||
| 2436 | |||
| 2468 | if (cpufreq_boost_supported()) { | 2437 | if (cpufreq_boost_supported()) { |
| 2469 | /* | 2438 | /* |
| 2470 | * Check if driver provides function to enable boost - | 2439 | * Check if driver provides function to enable boost - |
| @@ -2485,23 +2454,12 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) | |||
| 2485 | if (ret) | 2454 | if (ret) |
| 2486 | goto err_boost_unreg; | 2455 | goto err_boost_unreg; |
| 2487 | 2456 | ||
| 2488 | if (!(cpufreq_driver->flags & CPUFREQ_STICKY)) { | 2457 | if (!(cpufreq_driver->flags & CPUFREQ_STICKY) && |
| 2489 | int i; | 2458 | list_empty(&cpufreq_policy_list)) { |
| 2490 | ret = -ENODEV; | ||
| 2491 | |||
| 2492 | /* check for at least one working CPU */ | ||
| 2493 | for (i = 0; i < nr_cpu_ids; i++) | ||
| 2494 | if (cpu_possible(i) && per_cpu(cpufreq_cpu_data, i)) { | ||
| 2495 | ret = 0; | ||
| 2496 | break; | ||
| 2497 | } | ||
| 2498 | |||
| 2499 | /* if all ->init() calls failed, unregister */ | 2459 | /* if all ->init() calls failed, unregister */ |
| 2500 | if (ret) { | 2460 | pr_debug("%s: No CPU initialized for driver %s\n", __func__, |
| 2501 | pr_debug("no CPU initialized for driver %s\n", | 2461 | driver_data->name); |
| 2502 | driver_data->name); | 2462 | goto err_if_unreg; |
| 2503 | goto err_if_unreg; | ||
| 2504 | } | ||
| 2505 | } | 2463 | } |
| 2506 | 2464 | ||
| 2507 | register_hotcpu_notifier(&cpufreq_cpu_notifier); | 2465 | register_hotcpu_notifier(&cpufreq_cpu_notifier); |
| @@ -2556,6 +2514,14 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver) | |||
| 2556 | } | 2514 | } |
| 2557 | EXPORT_SYMBOL_GPL(cpufreq_unregister_driver); | 2515 | EXPORT_SYMBOL_GPL(cpufreq_unregister_driver); |
| 2558 | 2516 | ||
| 2517 | /* | ||
| 2518 | * Stop cpufreq at shutdown to make sure it isn't holding any locks | ||
| 2519 | * or mutexes when secondary CPUs are halted. | ||
| 2520 | */ | ||
| 2521 | static struct syscore_ops cpufreq_syscore_ops = { | ||
| 2522 | .shutdown = cpufreq_suspend, | ||
| 2523 | }; | ||
| 2524 | |||
| 2559 | static int __init cpufreq_core_init(void) | 2525 | static int __init cpufreq_core_init(void) |
| 2560 | { | 2526 | { |
| 2561 | if (cpufreq_disabled()) | 2527 | if (cpufreq_disabled()) |
| @@ -2564,6 +2530,8 @@ static int __init cpufreq_core_init(void) | |||
| 2564 | cpufreq_global_kobject = kobject_create(); | 2530 | cpufreq_global_kobject = kobject_create(); |
| 2565 | BUG_ON(!cpufreq_global_kobject); | 2531 | BUG_ON(!cpufreq_global_kobject); |
| 2566 | 2532 | ||
| 2533 | register_syscore_ops(&cpufreq_syscore_ops); | ||
| 2534 | |||
| 2567 | return 0; | 2535 | return 0; |
| 2568 | } | 2536 | } |
| 2569 | core_initcall(cpufreq_core_init); | 2537 | core_initcall(cpufreq_core_init); |
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index 0cd9b4dcef99..5e370a30a964 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c | |||
| @@ -18,7 +18,6 @@ | |||
| 18 | static spinlock_t cpufreq_stats_lock; | 18 | static spinlock_t cpufreq_stats_lock; |
| 19 | 19 | ||
| 20 | struct cpufreq_stats { | 20 | struct cpufreq_stats { |
| 21 | unsigned int cpu; | ||
| 22 | unsigned int total_trans; | 21 | unsigned int total_trans; |
| 23 | unsigned long long last_time; | 22 | unsigned long long last_time; |
| 24 | unsigned int max_state; | 23 | unsigned int max_state; |
| @@ -31,50 +30,33 @@ struct cpufreq_stats { | |||
| 31 | #endif | 30 | #endif |
| 32 | }; | 31 | }; |
| 33 | 32 | ||
| 34 | static DEFINE_PER_CPU(struct cpufreq_stats *, cpufreq_stats_table); | 33 | static int cpufreq_stats_update(struct cpufreq_stats *stats) |
| 35 | |||
| 36 | struct cpufreq_stats_attribute { | ||
| 37 | struct attribute attr; | ||
| 38 | ssize_t(*show) (struct cpufreq_stats *, char *); | ||
| 39 | }; | ||
| 40 | |||
| 41 | static int cpufreq_stats_update(unsigned int cpu) | ||
| 42 | { | 34 | { |
| 43 | struct cpufreq_stats *stat; | 35 | unsigned long long cur_time = get_jiffies_64(); |
| 44 | unsigned long long cur_time; | ||
| 45 | 36 | ||
| 46 | cur_time = get_jiffies_64(); | ||
| 47 | spin_lock(&cpufreq_stats_lock); | 37 | spin_lock(&cpufreq_stats_lock); |
| 48 | stat = per_cpu(cpufreq_stats_table, cpu); | 38 | stats->time_in_state[stats->last_index] += cur_time - stats->last_time; |
| 49 | if (stat->time_in_state) | 39 | stats->last_time = cur_time; |
| 50 | stat->time_in_state[stat->last_index] += | ||
| 51 | cur_time - stat->last_time; | ||
| 52 | stat->last_time = cur_time; | ||
| 53 | spin_unlock(&cpufreq_stats_lock); | 40 | spin_unlock(&cpufreq_stats_lock); |
| 54 | return 0; | 41 | return 0; |
| 55 | } | 42 | } |
| 56 | 43 | ||
| 57 | static ssize_t show_total_trans(struct cpufreq_policy *policy, char *buf) | 44 | static ssize_t show_total_trans(struct cpufreq_policy *policy, char *buf) |
| 58 | { | 45 | { |
| 59 | struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, policy->cpu); | 46 | return sprintf(buf, "%d\n", policy->stats->total_trans); |
| 60 | if (!stat) | ||
| 61 | return 0; | ||
| 62 | return sprintf(buf, "%d\n", | ||
| 63 | per_cpu(cpufreq_stats_table, stat->cpu)->total_trans); | ||
| 64 | } | 47 | } |
| 65 | 48 | ||
| 66 | static ssize_t show_time_in_state(struct cpufreq_policy *policy, char *buf) | 49 | static ssize_t show_time_in_state(struct cpufreq_policy *policy, char *buf) |
| 67 | { | 50 | { |
| 51 | struct cpufreq_stats *stats = policy->stats; | ||
| 68 | ssize_t len = 0; | 52 | ssize_t len = 0; |
| 69 | int i; | 53 | int i; |
| 70 | struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, policy->cpu); | 54 | |
| 71 | if (!stat) | 55 | cpufreq_stats_update(stats); |
| 72 | return 0; | 56 | for (i = 0; i < stats->state_num; i++) { |
| 73 | cpufreq_stats_update(stat->cpu); | 57 | len += sprintf(buf + len, "%u %llu\n", stats->freq_table[i], |
| 74 | for (i = 0; i < stat->state_num; i++) { | ||
| 75 | len += sprintf(buf + len, "%u %llu\n", stat->freq_table[i], | ||
| 76 | (unsigned long long) | 58 | (unsigned long long) |
| 77 | jiffies_64_to_clock_t(stat->time_in_state[i])); | 59 | jiffies_64_to_clock_t(stats->time_in_state[i])); |
| 78 | } | 60 | } |
| 79 | return len; | 61 | return len; |
| 80 | } | 62 | } |
| @@ -82,38 +64,35 @@ static ssize_t show_time_in_state(struct cpufreq_policy *policy, char *buf) | |||
| 82 | #ifdef CONFIG_CPU_FREQ_STAT_DETAILS | 64 | #ifdef CONFIG_CPU_FREQ_STAT_DETAILS |
| 83 | static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf) | 65 | static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf) |
| 84 | { | 66 | { |
| 67 | struct cpufreq_stats *stats = policy->stats; | ||
| 85 | ssize_t len = 0; | 68 | ssize_t len = 0; |
| 86 | int i, j; | 69 | int i, j; |
| 87 | 70 | ||
| 88 | struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, policy->cpu); | ||
| 89 | if (!stat) | ||
| 90 | return 0; | ||
| 91 | cpufreq_stats_update(stat->cpu); | ||
| 92 | len += snprintf(buf + len, PAGE_SIZE - len, " From : To\n"); | 71 | len += snprintf(buf + len, PAGE_SIZE - len, " From : To\n"); |
| 93 | len += snprintf(buf + len, PAGE_SIZE - len, " : "); | 72 | len += snprintf(buf + len, PAGE_SIZE - len, " : "); |
| 94 | for (i = 0; i < stat->state_num; i++) { | 73 | for (i = 0; i < stats->state_num; i++) { |
| 95 | if (len >= PAGE_SIZE) | 74 | if (len >= PAGE_SIZE) |
| 96 | break; | 75 | break; |
| 97 | len += snprintf(buf + len, PAGE_SIZE - len, "%9u ", | 76 | len += snprintf(buf + len, PAGE_SIZE - len, "%9u ", |
| 98 | stat->freq_table[i]); | 77 | stats->freq_table[i]); |
| 99 | } | 78 | } |
| 100 | if (len >= PAGE_SIZE) | 79 | if (len >= PAGE_SIZE) |
| 101 | return PAGE_SIZE; | 80 | return PAGE_SIZE; |
| 102 | 81 | ||
| 103 | len += snprintf(buf + len, PAGE_SIZE - len, "\n"); | 82 | len += snprintf(buf + len, PAGE_SIZE - len, "\n"); |
| 104 | 83 | ||
| 105 | for (i = 0; i < stat->state_num; i++) { | 84 | for (i = 0; i < stats->state_num; i++) { |
| 106 | if (len >= PAGE_SIZE) | 85 | if (len >= PAGE_SIZE) |
| 107 | break; | 86 | break; |
| 108 | 87 | ||
| 109 | len += snprintf(buf + len, PAGE_SIZE - len, "%9u: ", | 88 | len += snprintf(buf + len, PAGE_SIZE - len, "%9u: ", |
| 110 | stat->freq_table[i]); | 89 | stats->freq_table[i]); |
| 111 | 90 | ||
| 112 | for (j = 0; j < stat->state_num; j++) { | 91 | for (j = 0; j < stats->state_num; j++) { |
| 113 | if (len >= PAGE_SIZE) | 92 | if (len >= PAGE_SIZE) |
| 114 | break; | 93 | break; |
| 115 | len += snprintf(buf + len, PAGE_SIZE - len, "%9u ", | 94 | len += snprintf(buf + len, PAGE_SIZE - len, "%9u ", |
| 116 | stat->trans_table[i*stat->max_state+j]); | 95 | stats->trans_table[i*stats->max_state+j]); |
| 117 | } | 96 | } |
| 118 | if (len >= PAGE_SIZE) | 97 | if (len >= PAGE_SIZE) |
| 119 | break; | 98 | break; |
| @@ -142,28 +121,29 @@ static struct attribute_group stats_attr_group = { | |||
| 142 | .name = "stats" | 121 | .name = "stats" |
| 143 | }; | 122 | }; |
| 144 | 123 | ||
| 145 | static int freq_table_get_index(struct cpufreq_stats *stat, unsigned int freq) | 124 | static int freq_table_get_index(struct cpufreq_stats *stats, unsigned int freq) |
| 146 | { | 125 | { |
| 147 | int index; | 126 | int index; |
| 148 | for (index = 0; index < stat->max_state; index++) | 127 | for (index = 0; index < stats->max_state; index++) |
| 149 | if (stat->freq_table[index] == freq) | 128 | if (stats->freq_table[index] == freq) |
| 150 | return index; | 129 | return index; |
| 151 | return -1; | 130 | return -1; |
| 152 | } | 131 | } |
| 153 | 132 | ||
| 154 | static void __cpufreq_stats_free_table(struct cpufreq_policy *policy) | 133 | static void __cpufreq_stats_free_table(struct cpufreq_policy *policy) |
| 155 | { | 134 | { |
| 156 | struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, policy->cpu); | 135 | struct cpufreq_stats *stats = policy->stats; |
| 157 | 136 | ||
| 158 | if (!stat) | 137 | /* Already freed */ |
| 138 | if (!stats) | ||
| 159 | return; | 139 | return; |
| 160 | 140 | ||
| 161 | pr_debug("%s: Free stat table\n", __func__); | 141 | pr_debug("%s: Free stats table\n", __func__); |
| 162 | 142 | ||
| 163 | sysfs_remove_group(&policy->kobj, &stats_attr_group); | 143 | sysfs_remove_group(&policy->kobj, &stats_attr_group); |
| 164 | kfree(stat->time_in_state); | 144 | kfree(stats->time_in_state); |
| 165 | kfree(stat); | 145 | kfree(stats); |
| 166 | per_cpu(cpufreq_stats_table, policy->cpu) = NULL; | 146 | policy->stats = NULL; |
| 167 | } | 147 | } |
| 168 | 148 | ||
| 169 | static void cpufreq_stats_free_table(unsigned int cpu) | 149 | static void cpufreq_stats_free_table(unsigned int cpu) |
| @@ -174,37 +154,33 @@ static void cpufreq_stats_free_table(unsigned int cpu) | |||
| 174 | if (!policy) | 154 | if (!policy) |
| 175 | return; | 155 | return; |
| 176 | 156 | ||
| 177 | if (cpufreq_frequency_get_table(policy->cpu)) | 157 | __cpufreq_stats_free_table(policy); |
| 178 | __cpufreq_stats_free_table(policy); | ||
| 179 | 158 | ||
| 180 | cpufreq_cpu_put(policy); | 159 | cpufreq_cpu_put(policy); |
| 181 | } | 160 | } |
| 182 | 161 | ||
| 183 | static int __cpufreq_stats_create_table(struct cpufreq_policy *policy) | 162 | static int __cpufreq_stats_create_table(struct cpufreq_policy *policy) |
| 184 | { | 163 | { |
| 185 | unsigned int i, count = 0, ret = 0; | 164 | unsigned int i = 0, count = 0, ret = -ENOMEM; |
| 186 | struct cpufreq_stats *stat; | 165 | struct cpufreq_stats *stats; |
| 187 | unsigned int alloc_size; | 166 | unsigned int alloc_size; |
| 188 | unsigned int cpu = policy->cpu; | 167 | unsigned int cpu = policy->cpu; |
| 189 | struct cpufreq_frequency_table *pos, *table; | 168 | struct cpufreq_frequency_table *pos, *table; |
| 190 | 169 | ||
| 170 | /* We need cpufreq table for creating stats table */ | ||
| 191 | table = cpufreq_frequency_get_table(cpu); | 171 | table = cpufreq_frequency_get_table(cpu); |
| 192 | if (unlikely(!table)) | 172 | if (unlikely(!table)) |
| 193 | return 0; | 173 | return 0; |
| 194 | 174 | ||
| 195 | if (per_cpu(cpufreq_stats_table, cpu)) | 175 | /* stats already initialized */ |
| 196 | return -EBUSY; | 176 | if (policy->stats) |
| 197 | stat = kzalloc(sizeof(*stat), GFP_KERNEL); | 177 | return -EEXIST; |
| 198 | if ((stat) == NULL) | ||
| 199 | return -ENOMEM; | ||
| 200 | |||
| 201 | ret = sysfs_create_group(&policy->kobj, &stats_attr_group); | ||
| 202 | if (ret) | ||
| 203 | goto error_out; | ||
| 204 | 178 | ||
| 205 | stat->cpu = cpu; | 179 | stats = kzalloc(sizeof(*stats), GFP_KERNEL); |
| 206 | per_cpu(cpufreq_stats_table, cpu) = stat; | 180 | if (!stats) |
| 181 | return -ENOMEM; | ||
| 207 | 182 | ||
| 183 | /* Find total allocation size */ | ||
| 208 | cpufreq_for_each_valid_entry(pos, table) | 184 | cpufreq_for_each_valid_entry(pos, table) |
| 209 | count++; | 185 | count++; |
| 210 | 186 | ||
| @@ -213,32 +189,40 @@ static int __cpufreq_stats_create_table(struct cpufreq_policy *policy) | |||
| 213 | #ifdef CONFIG_CPU_FREQ_STAT_DETAILS | 189 | #ifdef CONFIG_CPU_FREQ_STAT_DETAILS |
| 214 | alloc_size += count * count * sizeof(int); | 190 | alloc_size += count * count * sizeof(int); |
| 215 | #endif | 191 | #endif |
| 216 | stat->max_state = count; | 192 | |
| 217 | stat->time_in_state = kzalloc(alloc_size, GFP_KERNEL); | 193 | /* Allocate memory for time_in_state/freq_table/trans_table in one go */ |
| 218 | if (!stat->time_in_state) { | 194 | stats->time_in_state = kzalloc(alloc_size, GFP_KERNEL); |
| 219 | ret = -ENOMEM; | 195 | if (!stats->time_in_state) |
| 220 | goto error_alloc; | 196 | goto free_stat; |
| 221 | } | 197 | |
| 222 | stat->freq_table = (unsigned int *)(stat->time_in_state + count); | 198 | stats->freq_table = (unsigned int *)(stats->time_in_state + count); |
| 223 | 199 | ||
| 224 | #ifdef CONFIG_CPU_FREQ_STAT_DETAILS | 200 | #ifdef CONFIG_CPU_FREQ_STAT_DETAILS |
| 225 | stat->trans_table = stat->freq_table + count; | 201 | stats->trans_table = stats->freq_table + count; |
| 226 | #endif | 202 | #endif |
| 227 | i = 0; | 203 | |
| 204 | stats->max_state = count; | ||
| 205 | |||
| 206 | /* Find valid-unique entries */ | ||
| 228 | cpufreq_for_each_valid_entry(pos, table) | 207 | cpufreq_for_each_valid_entry(pos, table) |
| 229 | if (freq_table_get_index(stat, pos->frequency) == -1) | 208 | if (freq_table_get_index(stats, pos->frequency) == -1) |
| 230 | stat->freq_table[i++] = pos->frequency; | 209 | stats->freq_table[i++] = pos->frequency; |
| 231 | stat->state_num = i; | 210 | |
| 232 | spin_lock(&cpufreq_stats_lock); | 211 | stats->state_num = i; |
| 233 | stat->last_time = get_jiffies_64(); | 212 | stats->last_time = get_jiffies_64(); |
| 234 | stat->last_index = freq_table_get_index(stat, policy->cur); | 213 | stats->last_index = freq_table_get_index(stats, policy->cur); |
| 235 | spin_unlock(&cpufreq_stats_lock); | 214 | |
| 236 | return 0; | 215 | policy->stats = stats; |
| 237 | error_alloc: | 216 | ret = sysfs_create_group(&policy->kobj, &stats_attr_group); |
| 238 | sysfs_remove_group(&policy->kobj, &stats_attr_group); | 217 | if (!ret) |
| 239 | error_out: | 218 | return 0; |
| 240 | kfree(stat); | 219 | |
| 241 | per_cpu(cpufreq_stats_table, cpu) = NULL; | 220 | /* We failed, release resources */ |
| 221 | policy->stats = NULL; | ||
| 222 | kfree(stats->time_in_state); | ||
| 223 | free_stat: | ||
| 224 | kfree(stats); | ||
| 225 | |||
| 242 | return ret; | 226 | return ret; |
| 243 | } | 227 | } |
| 244 | 228 | ||
| @@ -259,30 +243,12 @@ static void cpufreq_stats_create_table(unsigned int cpu) | |||
| 259 | cpufreq_cpu_put(policy); | 243 | cpufreq_cpu_put(policy); |
| 260 | } | 244 | } |
| 261 | 245 | ||
| 262 | static void cpufreq_stats_update_policy_cpu(struct cpufreq_policy *policy) | ||
| 263 | { | ||
| 264 | struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, | ||
| 265 | policy->last_cpu); | ||
| 266 | |||
| 267 | pr_debug("Updating stats_table for new_cpu %u from last_cpu %u\n", | ||
| 268 | policy->cpu, policy->last_cpu); | ||
| 269 | per_cpu(cpufreq_stats_table, policy->cpu) = per_cpu(cpufreq_stats_table, | ||
| 270 | policy->last_cpu); | ||
| 271 | per_cpu(cpufreq_stats_table, policy->last_cpu) = NULL; | ||
| 272 | stat->cpu = policy->cpu; | ||
| 273 | } | ||
| 274 | |||
| 275 | static int cpufreq_stat_notifier_policy(struct notifier_block *nb, | 246 | static int cpufreq_stat_notifier_policy(struct notifier_block *nb, |
| 276 | unsigned long val, void *data) | 247 | unsigned long val, void *data) |
| 277 | { | 248 | { |
| 278 | int ret = 0; | 249 | int ret = 0; |
| 279 | struct cpufreq_policy *policy = data; | 250 | struct cpufreq_policy *policy = data; |
| 280 | 251 | ||
| 281 | if (val == CPUFREQ_UPDATE_POLICY_CPU) { | ||
| 282 | cpufreq_stats_update_policy_cpu(policy); | ||
| 283 | return 0; | ||
| 284 | } | ||
| 285 | |||
| 286 | if (val == CPUFREQ_CREATE_POLICY) | 252 | if (val == CPUFREQ_CREATE_POLICY) |
| 287 | ret = __cpufreq_stats_create_table(policy); | 253 | ret = __cpufreq_stats_create_table(policy); |
| 288 | else if (val == CPUFREQ_REMOVE_POLICY) | 254 | else if (val == CPUFREQ_REMOVE_POLICY) |
| @@ -295,35 +261,45 @@ static int cpufreq_stat_notifier_trans(struct notifier_block *nb, | |||
| 295 | unsigned long val, void *data) | 261 | unsigned long val, void *data) |
| 296 | { | 262 | { |
| 297 | struct cpufreq_freqs *freq = data; | 263 | struct cpufreq_freqs *freq = data; |
| 298 | struct cpufreq_stats *stat; | 264 | struct cpufreq_policy *policy = cpufreq_cpu_get(freq->cpu); |
| 265 | struct cpufreq_stats *stats; | ||
| 299 | int old_index, new_index; | 266 | int old_index, new_index; |
| 300 | 267 | ||
| 301 | if (val != CPUFREQ_POSTCHANGE) | 268 | if (!policy) { |
| 269 | pr_err("%s: No policy found\n", __func__); | ||
| 302 | return 0; | 270 | return 0; |
| 271 | } | ||
| 303 | 272 | ||
| 304 | stat = per_cpu(cpufreq_stats_table, freq->cpu); | 273 | if (val != CPUFREQ_POSTCHANGE) |
| 305 | if (!stat) | 274 | goto put_policy; |
| 306 | return 0; | ||
| 307 | 275 | ||
| 308 | old_index = stat->last_index; | 276 | if (!policy->stats) { |
| 309 | new_index = freq_table_get_index(stat, freq->new); | 277 | pr_debug("%s: No stats found\n", __func__); |
| 278 | goto put_policy; | ||
| 279 | } | ||
| 310 | 280 | ||
| 311 | /* We can't do stat->time_in_state[-1]= .. */ | 281 | stats = policy->stats; |
| 312 | if (old_index == -1 || new_index == -1) | 282 | |
| 313 | return 0; | 283 | old_index = stats->last_index; |
| 284 | new_index = freq_table_get_index(stats, freq->new); | ||
| 314 | 285 | ||
| 315 | cpufreq_stats_update(freq->cpu); | 286 | /* We can't do stats->time_in_state[-1]= .. */ |
| 287 | if (old_index == -1 || new_index == -1) | ||
| 288 | goto put_policy; | ||
| 316 | 289 | ||
| 317 | if (old_index == new_index) | 290 | if (old_index == new_index) |
| 318 | return 0; | 291 | goto put_policy; |
| 319 | 292 | ||
| 320 | spin_lock(&cpufreq_stats_lock); | 293 | cpufreq_stats_update(stats); |
| 321 | stat->last_index = new_index; | 294 | |
| 295 | stats->last_index = new_index; | ||
| 322 | #ifdef CONFIG_CPU_FREQ_STAT_DETAILS | 296 | #ifdef CONFIG_CPU_FREQ_STAT_DETAILS |
| 323 | stat->trans_table[old_index * stat->max_state + new_index]++; | 297 | stats->trans_table[old_index * stats->max_state + new_index]++; |
| 324 | #endif | 298 | #endif |
| 325 | stat->total_trans++; | 299 | stats->total_trans++; |
| 326 | spin_unlock(&cpufreq_stats_lock); | 300 | |
| 301 | put_policy: | ||
| 302 | cpufreq_cpu_put(policy); | ||
| 327 | return 0; | 303 | return 0; |
| 328 | } | 304 | } |
| 329 | 305 | ||
| @@ -374,8 +350,7 @@ static void __exit cpufreq_stats_exit(void) | |||
| 374 | } | 350 | } |
| 375 | 351 | ||
| 376 | MODULE_AUTHOR("Zou Nan hai <nanhai.zou@intel.com>"); | 352 | MODULE_AUTHOR("Zou Nan hai <nanhai.zou@intel.com>"); |
| 377 | MODULE_DESCRIPTION("'cpufreq_stats' - A driver to export cpufreq stats " | 353 | MODULE_DESCRIPTION("Export cpufreq stats via sysfs"); |
| 378 | "through sysfs filesystem"); | ||
| 379 | MODULE_LICENSE("GPL"); | 354 | MODULE_LICENSE("GPL"); |
| 380 | 355 | ||
| 381 | module_init(cpufreq_stats_init); | 356 | module_init(cpufreq_stats_init); |
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 742eefba12c2..872c5772c5d3 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c | |||
| @@ -148,6 +148,8 @@ struct perf_limits { | |||
| 148 | int32_t min_perf; | 148 | int32_t min_perf; |
| 149 | int max_policy_pct; | 149 | int max_policy_pct; |
| 150 | int max_sysfs_pct; | 150 | int max_sysfs_pct; |
| 151 | int min_policy_pct; | ||
| 152 | int min_sysfs_pct; | ||
| 151 | }; | 153 | }; |
| 152 | 154 | ||
| 153 | static struct perf_limits limits = { | 155 | static struct perf_limits limits = { |
| @@ -159,6 +161,8 @@ static struct perf_limits limits = { | |||
| 159 | .min_perf = 0, | 161 | .min_perf = 0, |
| 160 | .max_policy_pct = 100, | 162 | .max_policy_pct = 100, |
| 161 | .max_sysfs_pct = 100, | 163 | .max_sysfs_pct = 100, |
| 164 | .min_policy_pct = 0, | ||
| 165 | .min_sysfs_pct = 0, | ||
| 162 | }; | 166 | }; |
| 163 | 167 | ||
| 164 | static inline void pid_reset(struct _pid *pid, int setpoint, int busy, | 168 | static inline void pid_reset(struct _pid *pid, int setpoint, int busy, |
| @@ -338,6 +342,33 @@ static void __init intel_pstate_debug_expose_params(void) | |||
| 338 | return sprintf(buf, "%u\n", limits.object); \ | 342 | return sprintf(buf, "%u\n", limits.object); \ |
| 339 | } | 343 | } |
| 340 | 344 | ||
| 345 | static ssize_t show_turbo_pct(struct kobject *kobj, | ||
| 346 | struct attribute *attr, char *buf) | ||
| 347 | { | ||
| 348 | struct cpudata *cpu; | ||
| 349 | int total, no_turbo, turbo_pct; | ||
| 350 | uint32_t turbo_fp; | ||
| 351 | |||
| 352 | cpu = all_cpu_data[0]; | ||
| 353 | |||
| 354 | total = cpu->pstate.turbo_pstate - cpu->pstate.min_pstate + 1; | ||
| 355 | no_turbo = cpu->pstate.max_pstate - cpu->pstate.min_pstate + 1; | ||
| 356 | turbo_fp = div_fp(int_tofp(no_turbo), int_tofp(total)); | ||
| 357 | turbo_pct = 100 - fp_toint(mul_fp(turbo_fp, int_tofp(100))); | ||
| 358 | return sprintf(buf, "%u\n", turbo_pct); | ||
| 359 | } | ||
| 360 | |||
| 361 | static ssize_t show_num_pstates(struct kobject *kobj, | ||
| 362 | struct attribute *attr, char *buf) | ||
| 363 | { | ||
| 364 | struct cpudata *cpu; | ||
| 365 | int total; | ||
| 366 | |||
| 367 | cpu = all_cpu_data[0]; | ||
| 368 | total = cpu->pstate.turbo_pstate - cpu->pstate.min_pstate + 1; | ||
| 369 | return sprintf(buf, "%u\n", total); | ||
| 370 | } | ||
| 371 | |||
| 341 | static ssize_t show_no_turbo(struct kobject *kobj, | 372 | static ssize_t show_no_turbo(struct kobject *kobj, |
| 342 | struct attribute *attr, char *buf) | 373 | struct attribute *attr, char *buf) |
| 343 | { | 374 | { |
| @@ -404,7 +435,9 @@ static ssize_t store_min_perf_pct(struct kobject *a, struct attribute *b, | |||
| 404 | ret = sscanf(buf, "%u", &input); | 435 | ret = sscanf(buf, "%u", &input); |
| 405 | if (ret != 1) | 436 | if (ret != 1) |
| 406 | return -EINVAL; | 437 | return -EINVAL; |
| 407 | limits.min_perf_pct = clamp_t(int, input, 0 , 100); | 438 | |
| 439 | limits.min_sysfs_pct = clamp_t(int, input, 0 , 100); | ||
| 440 | limits.min_perf_pct = max(limits.min_policy_pct, limits.min_sysfs_pct); | ||
| 408 | limits.min_perf = div_fp(int_tofp(limits.min_perf_pct), int_tofp(100)); | 441 | limits.min_perf = div_fp(int_tofp(limits.min_perf_pct), int_tofp(100)); |
| 409 | 442 | ||
| 410 | if (hwp_active) | 443 | if (hwp_active) |
| @@ -418,11 +451,15 @@ show_one(min_perf_pct, min_perf_pct); | |||
| 418 | define_one_global_rw(no_turbo); | 451 | define_one_global_rw(no_turbo); |
| 419 | define_one_global_rw(max_perf_pct); | 452 | define_one_global_rw(max_perf_pct); |
| 420 | define_one_global_rw(min_perf_pct); | 453 | define_one_global_rw(min_perf_pct); |
| 454 | define_one_global_ro(turbo_pct); | ||
| 455 | define_one_global_ro(num_pstates); | ||
| 421 | 456 | ||
| 422 | static struct attribute *intel_pstate_attributes[] = { | 457 | static struct attribute *intel_pstate_attributes[] = { |
| 423 | &no_turbo.attr, | 458 | &no_turbo.attr, |
| 424 | &max_perf_pct.attr, | 459 | &max_perf_pct.attr, |
| 425 | &min_perf_pct.attr, | 460 | &min_perf_pct.attr, |
| 461 | &turbo_pct.attr, | ||
| 462 | &num_pstates.attr, | ||
| 426 | NULL | 463 | NULL |
| 427 | }; | 464 | }; |
| 428 | 465 | ||
| @@ -825,6 +862,7 @@ static const struct x86_cpu_id intel_pstate_cpu_ids[] = { | |||
| 825 | ICPU(0x46, core_params), | 862 | ICPU(0x46, core_params), |
| 826 | ICPU(0x47, core_params), | 863 | ICPU(0x47, core_params), |
| 827 | ICPU(0x4c, byt_params), | 864 | ICPU(0x4c, byt_params), |
| 865 | ICPU(0x4e, core_params), | ||
| 828 | ICPU(0x4f, core_params), | 866 | ICPU(0x4f, core_params), |
| 829 | ICPU(0x56, core_params), | 867 | ICPU(0x56, core_params), |
| 830 | {} | 868 | {} |
| @@ -887,7 +925,9 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy) | |||
| 887 | if (!policy->cpuinfo.max_freq) | 925 | if (!policy->cpuinfo.max_freq) |
| 888 | return -ENODEV; | 926 | return -ENODEV; |
| 889 | 927 | ||
| 890 | if (policy->policy == CPUFREQ_POLICY_PERFORMANCE) { | 928 | if (policy->policy == CPUFREQ_POLICY_PERFORMANCE && |
| 929 | policy->max >= policy->cpuinfo.max_freq) { | ||
| 930 | limits.min_policy_pct = 100; | ||
| 891 | limits.min_perf_pct = 100; | 931 | limits.min_perf_pct = 100; |
| 892 | limits.min_perf = int_tofp(1); | 932 | limits.min_perf = int_tofp(1); |
| 893 | limits.max_policy_pct = 100; | 933 | limits.max_policy_pct = 100; |
| @@ -897,8 +937,9 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy) | |||
| 897 | return 0; | 937 | return 0; |
| 898 | } | 938 | } |
| 899 | 939 | ||
| 900 | limits.min_perf_pct = (policy->min * 100) / policy->cpuinfo.max_freq; | 940 | limits.min_policy_pct = (policy->min * 100) / policy->cpuinfo.max_freq; |
| 901 | limits.min_perf_pct = clamp_t(int, limits.min_perf_pct, 0 , 100); | 941 | limits.min_policy_pct = clamp_t(int, limits.min_policy_pct, 0 , 100); |
| 942 | limits.min_perf_pct = max(limits.min_policy_pct, limits.min_sysfs_pct); | ||
| 902 | limits.min_perf = div_fp(int_tofp(limits.min_perf_pct), int_tofp(100)); | 943 | limits.min_perf = div_fp(int_tofp(limits.min_perf_pct), int_tofp(100)); |
| 903 | 944 | ||
| 904 | limits.max_policy_pct = (policy->max * 100) / policy->cpuinfo.max_freq; | 945 | limits.max_policy_pct = (policy->max * 100) / policy->cpuinfo.max_freq; |
| @@ -978,6 +1019,7 @@ static struct cpufreq_driver intel_pstate_driver = { | |||
| 978 | 1019 | ||
| 979 | static int __initdata no_load; | 1020 | static int __initdata no_load; |
| 980 | static int __initdata no_hwp; | 1021 | static int __initdata no_hwp; |
| 1022 | static int __initdata hwp_only; | ||
| 981 | static unsigned int force_load; | 1023 | static unsigned int force_load; |
| 982 | 1024 | ||
| 983 | static int intel_pstate_msrs_not_valid(void) | 1025 | static int intel_pstate_msrs_not_valid(void) |
| @@ -1175,6 +1217,9 @@ static int __init intel_pstate_init(void) | |||
| 1175 | if (cpu_has(c,X86_FEATURE_HWP) && !no_hwp) | 1217 | if (cpu_has(c,X86_FEATURE_HWP) && !no_hwp) |
| 1176 | intel_pstate_hwp_enable(); | 1218 | intel_pstate_hwp_enable(); |
| 1177 | 1219 | ||
| 1220 | if (!hwp_active && hwp_only) | ||
| 1221 | goto out; | ||
| 1222 | |||
| 1178 | rc = cpufreq_register_driver(&intel_pstate_driver); | 1223 | rc = cpufreq_register_driver(&intel_pstate_driver); |
| 1179 | if (rc) | 1224 | if (rc) |
| 1180 | goto out; | 1225 | goto out; |
| @@ -1209,6 +1254,8 @@ static int __init intel_pstate_setup(char *str) | |||
| 1209 | no_hwp = 1; | 1254 | no_hwp = 1; |
| 1210 | if (!strcmp(str, "force")) | 1255 | if (!strcmp(str, "force")) |
| 1211 | force_load = 1; | 1256 | force_load = 1; |
| 1257 | if (!strcmp(str, "hwp_only")) | ||
| 1258 | hwp_only = 1; | ||
| 1212 | return 0; | 1259 | return 0; |
| 1213 | } | 1260 | } |
| 1214 | early_param("intel_pstate", intel_pstate_setup); | 1261 | early_param("intel_pstate", intel_pstate_setup); |
diff --git a/drivers/cpufreq/ls1x-cpufreq.c b/drivers/cpufreq/ls1x-cpufreq.c index 25fbd6a1374f..f0913eee2f50 100644 --- a/drivers/cpufreq/ls1x-cpufreq.c +++ b/drivers/cpufreq/ls1x-cpufreq.c | |||
| @@ -210,7 +210,6 @@ out: | |||
| 210 | static struct platform_driver ls1x_cpufreq_platdrv = { | 210 | static struct platform_driver ls1x_cpufreq_platdrv = { |
| 211 | .driver = { | 211 | .driver = { |
| 212 | .name = "ls1x-cpufreq", | 212 | .name = "ls1x-cpufreq", |
| 213 | .owner = THIS_MODULE, | ||
| 214 | }, | 213 | }, |
| 215 | .probe = ls1x_cpufreq_probe, | 214 | .probe = ls1x_cpufreq_probe, |
| 216 | .remove = ls1x_cpufreq_remove, | 215 | .remove = ls1x_cpufreq_remove, |
diff --git a/drivers/cpufreq/sfi-cpufreq.c b/drivers/cpufreq/sfi-cpufreq.c new file mode 100644 index 000000000000..ffa3389e535b --- /dev/null +++ b/drivers/cpufreq/sfi-cpufreq.c | |||
| @@ -0,0 +1,136 @@ | |||
| 1 | /* | ||
| 2 | * SFI Performance States Driver | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License as published by | ||
| 6 | * the Free Software Foundation; either version 2 of the License. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, but | ||
| 9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 11 | * General Public License for more details. | ||
| 12 | * | ||
| 13 | * Author: Vishwesh M Rudramuni <vishwesh.m.rudramuni@intel.com> | ||
| 14 | * Author: Srinidhi Kasagar <srinidhi.kasagar@intel.com> | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/cpufreq.h> | ||
| 18 | #include <linux/init.h> | ||
| 19 | #include <linux/kernel.h> | ||
| 20 | #include <linux/module.h> | ||
| 21 | #include <linux/sfi.h> | ||
| 22 | #include <linux/slab.h> | ||
| 23 | #include <linux/smp.h> | ||
| 24 | |||
| 25 | #include <asm/msr.h> | ||
| 26 | |||
| 27 | struct cpufreq_frequency_table *freq_table; | ||
| 28 | static struct sfi_freq_table_entry *sfi_cpufreq_array; | ||
| 29 | static int num_freq_table_entries; | ||
| 30 | |||
| 31 | static int sfi_parse_freq(struct sfi_table_header *table) | ||
| 32 | { | ||
| 33 | struct sfi_table_simple *sb; | ||
| 34 | struct sfi_freq_table_entry *pentry; | ||
| 35 | int totallen; | ||
| 36 | |||
| 37 | sb = (struct sfi_table_simple *)table; | ||
| 38 | num_freq_table_entries = SFI_GET_NUM_ENTRIES(sb, | ||
| 39 | struct sfi_freq_table_entry); | ||
| 40 | if (num_freq_table_entries <= 1) { | ||
| 41 | pr_err("No p-states discovered\n"); | ||
| 42 | return -ENODEV; | ||
| 43 | } | ||
| 44 | |||
| 45 | pentry = (struct sfi_freq_table_entry *)sb->pentry; | ||
| 46 | totallen = num_freq_table_entries * sizeof(*pentry); | ||
| 47 | |||
| 48 | sfi_cpufreq_array = kzalloc(totallen, GFP_KERNEL); | ||
| 49 | if (!sfi_cpufreq_array) | ||
| 50 | return -ENOMEM; | ||
| 51 | |||
| 52 | memcpy(sfi_cpufreq_array, pentry, totallen); | ||
| 53 | |||
| 54 | return 0; | ||
| 55 | } | ||
| 56 | |||
| 57 | static int sfi_cpufreq_target(struct cpufreq_policy *policy, unsigned int index) | ||
| 58 | { | ||
| 59 | unsigned int next_perf_state = 0; /* Index into perf table */ | ||
| 60 | u32 lo, hi; | ||
| 61 | |||
| 62 | next_perf_state = policy->freq_table[index].driver_data; | ||
| 63 | |||
| 64 | rdmsr_on_cpu(policy->cpu, MSR_IA32_PERF_CTL, &lo, &hi); | ||
| 65 | lo = (lo & ~INTEL_PERF_CTL_MASK) | | ||
| 66 | ((u32) sfi_cpufreq_array[next_perf_state].ctrl_val & | ||
| 67 | INTEL_PERF_CTL_MASK); | ||
| 68 | wrmsr_on_cpu(policy->cpu, MSR_IA32_PERF_CTL, lo, hi); | ||
| 69 | |||
| 70 | return 0; | ||
| 71 | } | ||
| 72 | |||
| 73 | static int sfi_cpufreq_cpu_init(struct cpufreq_policy *policy) | ||
| 74 | { | ||
| 75 | policy->shared_type = CPUFREQ_SHARED_TYPE_HW; | ||
| 76 | policy->cpuinfo.transition_latency = 100000; /* 100us */ | ||
| 77 | |||
| 78 | return cpufreq_table_validate_and_show(policy, freq_table); | ||
| 79 | } | ||
| 80 | |||
| 81 | static struct cpufreq_driver sfi_cpufreq_driver = { | ||
| 82 | .flags = CPUFREQ_CONST_LOOPS, | ||
| 83 | .verify = cpufreq_generic_frequency_table_verify, | ||
| 84 | .target_index = sfi_cpufreq_target, | ||
| 85 | .init = sfi_cpufreq_cpu_init, | ||
| 86 | .name = "sfi-cpufreq", | ||
| 87 | .attr = cpufreq_generic_attr, | ||
| 88 | }; | ||
| 89 | |||
| 90 | static int __init sfi_cpufreq_init(void) | ||
| 91 | { | ||
| 92 | int ret, i; | ||
| 93 | |||
| 94 | /* parse the freq table from SFI */ | ||
| 95 | ret = sfi_table_parse(SFI_SIG_FREQ, NULL, NULL, sfi_parse_freq); | ||
| 96 | if (ret) | ||
| 97 | return ret; | ||
| 98 | |||
| 99 | freq_table = kzalloc(sizeof(*freq_table) * | ||
| 100 | (num_freq_table_entries + 1), GFP_KERNEL); | ||
| 101 | if (!freq_table) { | ||
| 102 | ret = -ENOMEM; | ||
| 103 | goto err_free_array; | ||
| 104 | } | ||
| 105 | |||
| 106 | for (i = 0; i < num_freq_table_entries; i++) { | ||
| 107 | freq_table[i].driver_data = i; | ||
| 108 | freq_table[i].frequency = sfi_cpufreq_array[i].freq_mhz * 1000; | ||
| 109 | } | ||
| 110 | freq_table[i].frequency = CPUFREQ_TABLE_END; | ||
| 111 | |||
| 112 | ret = cpufreq_register_driver(&sfi_cpufreq_driver); | ||
| 113 | if (ret) | ||
| 114 | goto err_free_tbl; | ||
| 115 | |||
| 116 | return ret; | ||
| 117 | |||
| 118 | err_free_tbl: | ||
| 119 | kfree(freq_table); | ||
| 120 | err_free_array: | ||
| 121 | kfree(sfi_cpufreq_array); | ||
| 122 | return ret; | ||
| 123 | } | ||
| 124 | late_initcall(sfi_cpufreq_init); | ||
| 125 | |||
| 126 | static void __exit sfi_cpufreq_exit(void) | ||
| 127 | { | ||
| 128 | cpufreq_unregister_driver(&sfi_cpufreq_driver); | ||
| 129 | kfree(freq_table); | ||
| 130 | kfree(sfi_cpufreq_array); | ||
| 131 | } | ||
| 132 | module_exit(sfi_cpufreq_exit); | ||
| 133 | |||
| 134 | MODULE_AUTHOR("Vishwesh M Rudramuni <vishwesh.m.rudramuni@intel.com>"); | ||
| 135 | MODULE_DESCRIPTION("SFI Performance-States Driver"); | ||
| 136 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/sfi/sfi_core.c b/drivers/sfi/sfi_core.c index 1e824fb1649b..296db7a69c27 100644 --- a/drivers/sfi/sfi_core.c +++ b/drivers/sfi/sfi_core.c | |||
| @@ -161,7 +161,7 @@ static int sfi_verify_table(struct sfi_table_header *table) | |||
| 161 | * Check for common case that we can re-use mapping to SYST, | 161 | * Check for common case that we can re-use mapping to SYST, |
| 162 | * which requires syst_pa, syst_va to be initialized. | 162 | * which requires syst_pa, syst_va to be initialized. |
| 163 | */ | 163 | */ |
| 164 | struct sfi_table_header *sfi_map_table(u64 pa) | 164 | static struct sfi_table_header *sfi_map_table(u64 pa) |
| 165 | { | 165 | { |
| 166 | struct sfi_table_header *th; | 166 | struct sfi_table_header *th; |
| 167 | u32 length; | 167 | u32 length; |
| @@ -189,7 +189,7 @@ struct sfi_table_header *sfi_map_table(u64 pa) | |||
| 189 | * Undoes effect of sfi_map_table() by unmapping table | 189 | * Undoes effect of sfi_map_table() by unmapping table |
| 190 | * if it did not completely fit on same page as SYST. | 190 | * if it did not completely fit on same page as SYST. |
| 191 | */ | 191 | */ |
| 192 | void sfi_unmap_table(struct sfi_table_header *th) | 192 | static void sfi_unmap_table(struct sfi_table_header *th) |
| 193 | { | 193 | { |
| 194 | if (!TABLE_ON_PAGE(syst_va, th, th->len)) | 194 | if (!TABLE_ON_PAGE(syst_va, th, th->len)) |
| 195 | sfi_unmap_memory(th, TABLE_ON_PAGE(th, th, th->len) ? | 195 | sfi_unmap_memory(th, TABLE_ON_PAGE(th, th, th->len) ? |
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 4d078cebafd2..2ee4888c1f47 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h | |||
| @@ -66,8 +66,6 @@ struct cpufreq_policy { | |||
| 66 | unsigned int shared_type; /* ACPI: ANY or ALL affected CPUs | 66 | unsigned int shared_type; /* ACPI: ANY or ALL affected CPUs |
| 67 | should set cpufreq */ | 67 | should set cpufreq */ |
| 68 | unsigned int cpu; /* cpu nr of CPU managing this policy */ | 68 | unsigned int cpu; /* cpu nr of CPU managing this policy */ |
| 69 | unsigned int last_cpu; /* cpu nr of previous CPU that managed | ||
| 70 | * this policy */ | ||
| 71 | struct clk *clk; | 69 | struct clk *clk; |
| 72 | struct cpufreq_cpuinfo cpuinfo;/* see above */ | 70 | struct cpufreq_cpuinfo cpuinfo;/* see above */ |
| 73 | 71 | ||
| @@ -113,6 +111,9 @@ struct cpufreq_policy { | |||
| 113 | wait_queue_head_t transition_wait; | 111 | wait_queue_head_t transition_wait; |
| 114 | struct task_struct *transition_task; /* Task which is doing the transition */ | 112 | struct task_struct *transition_task; /* Task which is doing the transition */ |
| 115 | 113 | ||
| 114 | /* cpufreq-stats */ | ||
| 115 | struct cpufreq_stats *stats; | ||
| 116 | |||
| 116 | /* For cpufreq driver's internal use */ | 117 | /* For cpufreq driver's internal use */ |
| 117 | void *driver_data; | 118 | void *driver_data; |
| 118 | }; | 119 | }; |
| @@ -367,9 +368,8 @@ static inline void cpufreq_resume(void) {} | |||
| 367 | #define CPUFREQ_INCOMPATIBLE (1) | 368 | #define CPUFREQ_INCOMPATIBLE (1) |
| 368 | #define CPUFREQ_NOTIFY (2) | 369 | #define CPUFREQ_NOTIFY (2) |
| 369 | #define CPUFREQ_START (3) | 370 | #define CPUFREQ_START (3) |
| 370 | #define CPUFREQ_UPDATE_POLICY_CPU (4) | 371 | #define CPUFREQ_CREATE_POLICY (4) |
| 371 | #define CPUFREQ_CREATE_POLICY (5) | 372 | #define CPUFREQ_REMOVE_POLICY (5) |
| 372 | #define CPUFREQ_REMOVE_POLICY (6) | ||
| 373 | 373 | ||
| 374 | #ifdef CONFIG_CPU_FREQ | 374 | #ifdef CONFIG_CPU_FREQ |
| 375 | int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list); | 375 | int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list); |
