* pm-cpuidle: cpuidle: Check for dev before deregistering it. intel_idle: Fixed C6 state on Avoton/Rangeley processors * pm-cpufreq: cpufreq: fix garbage kobjects on errors during suspend/resume cpufreq: suspend governors on system suspend/hibernate
Unified · Split
| @@ -29,6 +29,7 @@ · 28 unmodified lines | ||
| 29 | 29 | #include <linux/async.h> |
| 30 | 30 | #include <linux/suspend.h> |
| 31 | 31 | #include <trace/events/power.h> |
| 32 | +#include <linux/cpufreq.h> | |
| 32 | 33 | #include <linux/cpuidle.h> |
| 33 | 34 | #include <linux/timer.h> |
| 34 | 35 | |
| @@ -540,6 +541,7 @@ static void dpm_resume_noirq(pm_message_t state) · 505 unmodified lines | ||
| 540 | 541 | dpm_show_time(starttime, state, "noirq"); |
| 541 | 542 | resume_device_irqs(); |
| 542 | 543 | cpuidle_resume(); |
| 544 | + cpufreq_resume(); | |
| 543 | 545 | } |
| 544 | 546 | |
| 545 | 547 | /** |
| @@ -955,6 +957,7 @@ static int dpm_suspend_noirq(pm_message_t state) · 409 unmodified lines | ||
| 955 | 957 | ktime_t starttime = ktime_get(); |
| 956 | 958 | int error = 0; |
| 957 | 959 | |
| 960 | + cpufreq_suspend(); | |
| 958 | 961 | cpuidle_pause(); |
| 959 | 962 | suspend_device_irqs(); |
| 960 | 963 | mutex_lock(&dpm_list_mtx); |
| @@ -26,6 +26,7 @@ · 25 unmodified lines | ||
| 26 | 26 | #include <linux/module.h> |
| 27 | 27 | #include <linux/mutex.h> |
| 28 | 28 | #include <linux/slab.h> |
| 29 | +#include <linux/suspend.h> | |
| 29 | 30 | #include <linux/syscore_ops.h> |
| 30 | 31 | #include <linux/tick.h> |
| 31 | 32 | #include <trace/events/power.h> |
| @@ -47,6 +48,9 @@ static LIST_HEAD(cpufreq_policy_list); · 15 unmodified lines | ||
| 47 | 48 | static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN], cpufreq_cpu_governor); |
| 48 | 49 | #endif |
| 49 | 50 | |
| 51 | +/* Flag to suspend/resume CPUFreq governors */ | |
| 52 | +static bool cpufreq_suspended; | |
| 53 | + | |
| 50 | 54 | static inline bool has_target(void) |
| 51 | 55 | { |
| 52 | 56 | return cpufreq_driver->target_index || cpufreq_driver->target; |
| @@ -1462,6 +1466,41 @@ static struct subsys_interface cpufreq_interface = { · 1409 unmodified lines | ||
| 1462 | 1466 | .remove_dev = cpufreq_remove_dev, |
| 1463 | 1467 | }; |
| 1464 | 1468 | |
| 1469 | +void cpufreq_suspend(void) | |
| 1470 | +{ | |
| 1471 | + struct cpufreq_policy *policy; | |
| 1472 | + | |
| 1473 | + if (!has_target()) | |
| 1474 | + return; | |
| 1475 | + | |
| 1476 | + pr_debug("%s: Suspending Governors\n", __func__); | |
| 1477 | + | |
| 1478 | + list_for_each_entry(policy, &cpufreq_policy_list, policy_list) | |
| 1479 | + if (__cpufreq_governor(policy, CPUFREQ_GOV_STOP)) | |
| 1480 | + pr_err("%s: Failed to stop governor for policy: %p\n", | |
| 1481 | + __func__, policy); | |
| 1482 | + | |
| 1483 | + cpufreq_suspended = true; | |
| 1484 | +} | |
| 1485 | + | |
| 1486 | +void cpufreq_resume(void) | |
| 1487 | +{ | |
| 1488 | + struct cpufreq_policy *policy; | |
| 1489 | + | |
| 1490 | + if (!has_target()) | |
| 1491 | + return; | |
| 1492 | + | |
| 1493 | + pr_debug("%s: Resuming Governors\n", __func__); | |
| 1494 | + | |
| 1495 | + cpufreq_suspended = false; | |
| 1496 | + | |
| 1497 | + list_for_each_entry(policy, &cpufreq_policy_list, policy_list) | |
| 1498 | + if (__cpufreq_governor(policy, CPUFREQ_GOV_START) | |
| 1499 | + || __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS)) | |
| 1500 | + pr_err("%s: Failed to start governor for policy: %p\n", | |
| 1501 | + __func__, policy); | |
| 1502 | +} | |
| 1503 | + | |
| 1465 | 1504 | /** |
| 1466 | 1505 | * cpufreq_bp_suspend - Prepare the boot CPU for system suspend. |
| 1467 | 1506 | * |
| @@ -1764,6 +1803,10 @@ static int __cpufreq_governor(struct cpufreq_policy *policy, · 296 unmodified lines | ||
| 1764 | 1803 | struct cpufreq_governor *gov = NULL; |
| 1765 | 1804 | #endif |
| 1766 | 1805 | |
| 1806 | + /* Don't start any governor operations if we are entering suspend */ | |
| 1807 | + if (cpufreq_suspended) | |
| 1808 | + return 0; | |
| 1809 | + | |
| 1767 | 1810 | if (policy->governor->max_transition_latency && |
| 1768 | 1811 | policy->cpuinfo.transition_latency > |
| 1769 | 1812 | policy->governor->max_transition_latency) { |
| @@ -2076,9 +2119,6 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb, · 306 unmodified lines | ||
| 2076 | 2119 | dev = get_cpu_device(cpu); |
| 2077 | 2120 | if (dev) { |
| 2078 | 2121 | |
| 2079 | − if (action & CPU_TASKS_FROZEN) | |
| 2080 | − frozen = true; | |
| 2081 | − | |
| 2082 | 2122 | switch (action & ~CPU_TASKS_FROZEN) { |
| 2083 | 2123 | case CPU_ONLINE: |
| 2084 | 2124 | __cpufreq_add_dev(dev, NULL, frozen); |
| @@ -400,7 +400,7 @@ EXPORT_SYMBOL_GPL(cpuidle_register_device); · 399 unmodified lines | ||
| 400 | 400 | */ |
| 401 | 401 | void cpuidle_unregister_device(struct cpuidle_device *dev) |
| 402 | 402 | { |
| 403 | − if (dev->registered == 0) | |
| 403 | + if (!dev || dev->registered == 0) | |
| 404 | 404 | return; |
| 405 | 405 | |
| 406 | 406 | cpuidle_pause_and_lock(); |
| @@ -329,7 +329,7 @@ static struct cpuidle_state atom_cstates[] __initdata = { · 328 unmodified lines | ||
| 329 | 329 | { |
| 330 | 330 | .enter = NULL } |
| 331 | 331 | }; |
| 332 | −static struct cpuidle_state avn_cstates[CPUIDLE_STATE_MAX] = { | |
| 332 | +static struct cpuidle_state avn_cstates[] __initdata = { | |
| 333 | 333 | { |
| 334 | 334 | .name = "C1-AVN", |
| 335 | 335 | .desc = "MWAIT 0x00", |
| @@ -340,7 +340,7 @@ static struct cpuidle_state avn_cstates[CPUIDLE_STATE_MAX] = { · 4 unmodified lines | ||
| 340 | 340 | { |
| 341 | 341 | .name = "C6-AVN", |
| 342 | 342 | .desc = "MWAIT 0x51", |
| 343 | − .flags = MWAIT2flg(0x58) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, | |
| 343 | + .flags = MWAIT2flg(0x51) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, | |
| 344 | 344 | .exit_latency = 15, |
| 345 | 345 | .target_residency = 45, |
| 346 | 346 | .enter = &intel_idle }, |
| @@ -280,6 +280,14 @@ cpufreq_verify_within_cpu_limits(struct cpufreq_policy *policy) · 279 unmodified lines | ||
| 280 | 280 | policy->cpuinfo.max_freq); |
| 281 | 281 | } |
| 282 | 282 | |
| 283 | +#ifdef CONFIG_CPU_FREQ | |
| 284 | +void cpufreq_suspend(void); | |
| 285 | +void cpufreq_resume(void); | |
| 286 | +#else | |
| 287 | +static inline void cpufreq_suspend(void) {} | |
| 288 | +static inline void cpufreq_resume(void) {} | |
| 289 | +#endif | |
| 290 | + | |
| 283 | 291 | /********************************************************************* |
| 284 | 292 | * CPUFREQ NOTIFIER INTERFACE * |
| 285 | 293 | *********************************************************************/ |