Skip to content

Commit 7cdcec9

Browse files
committed
Merge branches 'pm-cpuidle' and 'pm-cpufreq'
* 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
3 parents dc1ccc4 + 813e8e3 + 2167e23 commit 7cdcec9

File tree

5 files changed

+57
-6
lines changed

5 files changed

+57
-6
lines changed

drivers/base/power/main.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include <linux/async.h>
3030
#include <linux/suspend.h>
3131
#include <trace/events/power.h>
32+
#include <linux/cpufreq.h>
3233
#include <linux/cpuidle.h>
3334
#include <linux/timer.h>
3435

@@ -540,6 +541,7 @@ static void dpm_resume_noirq(pm_message_t state)
540541
dpm_show_time(starttime, state, "noirq");
541542
resume_device_irqs();
542543
cpuidle_resume();
544+
cpufreq_resume();
543545
}
544546

545547
/**
@@ -955,6 +957,7 @@ static int dpm_suspend_noirq(pm_message_t state)
955957
ktime_t starttime = ktime_get();
956958
int error = 0;
957959

960+
cpufreq_suspend();
958961
cpuidle_pause();
959962
suspend_device_irqs();
960963
mutex_lock(&dpm_list_mtx);

drivers/cpufreq/cpufreq.c

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <linux/module.h>
2727
#include <linux/mutex.h>
2828
#include <linux/slab.h>
29+
#include <linux/suspend.h>
2930
#include <linux/syscore_ops.h>
3031
#include <linux/tick.h>
3132
#include <trace/events/power.h>
@@ -47,6 +48,9 @@ static LIST_HEAD(cpufreq_policy_list);
4748
static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN], cpufreq_cpu_governor);
4849
#endif
4950

51+
/* Flag to suspend/resume CPUFreq governors */
52+
static bool cpufreq_suspended;
53+
5054
static inline bool has_target(void)
5155
{
5256
return cpufreq_driver->target_index || cpufreq_driver->target;
@@ -1462,6 +1466,41 @@ static struct subsys_interface cpufreq_interface = {
14621466
.remove_dev = cpufreq_remove_dev,
14631467
};
14641468

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+
14651504
/**
14661505
* cpufreq_bp_suspend - Prepare the boot CPU for system suspend.
14671506
*
@@ -1764,6 +1803,10 @@ static int __cpufreq_governor(struct cpufreq_policy *policy,
17641803
struct cpufreq_governor *gov = NULL;
17651804
#endif
17661805

1806+
/* Don't start any governor operations if we are entering suspend */
1807+
if (cpufreq_suspended)
1808+
return 0;
1809+
17671810
if (policy->governor->max_transition_latency &&
17681811
policy->cpuinfo.transition_latency >
17691812
policy->governor->max_transition_latency) {
@@ -2076,9 +2119,6 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb,
20762119
dev = get_cpu_device(cpu);
20772120
if (dev) {
20782121

2079-
if (action & CPU_TASKS_FROZEN)
2080-
frozen = true;
2081-
20822122
switch (action & ~CPU_TASKS_FROZEN) {
20832123
case CPU_ONLINE:
20842124
__cpufreq_add_dev(dev, NULL, frozen);

drivers/cpuidle/cpuidle.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,7 @@ EXPORT_SYMBOL_GPL(cpuidle_register_device);
400400
*/
401401
void cpuidle_unregister_device(struct cpuidle_device *dev)
402402
{
403-
if (dev->registered == 0)
403+
if (!dev || dev->registered == 0)
404404
return;
405405

406406
cpuidle_pause_and_lock();

drivers/idle/intel_idle.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ static struct cpuidle_state atom_cstates[] __initdata = {
329329
{
330330
.enter = NULL }
331331
};
332-
static struct cpuidle_state avn_cstates[CPUIDLE_STATE_MAX] = {
332+
static struct cpuidle_state avn_cstates[] __initdata = {
333333
{
334334
.name = "C1-AVN",
335335
.desc = "MWAIT 0x00",
@@ -340,7 +340,7 @@ static struct cpuidle_state avn_cstates[CPUIDLE_STATE_MAX] = {
340340
{
341341
.name = "C6-AVN",
342342
.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,
344344
.exit_latency = 15,
345345
.target_residency = 45,
346346
.enter = &intel_idle },

include/linux/cpufreq.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,14 @@ cpufreq_verify_within_cpu_limits(struct cpufreq_policy *policy)
280280
policy->cpuinfo.max_freq);
281281
}
282282

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+
283291
/*********************************************************************
284292
* CPUFREQ NOTIFIER INTERFACE *
285293
*********************************************************************/

0 commit comments

Comments
 (0)