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
This commit is contained in:
@@ -29,6 +29,7 @@
|
|||||||
#include <linux/async.h>
|
#include <linux/async.h>
|
||||||
#include <linux/suspend.h>
|
#include <linux/suspend.h>
|
||||||
#include <trace/events/power.h>
|
#include <trace/events/power.h>
|
||||||
|
#include <linux/cpufreq.h>
|
||||||
#include <linux/cpuidle.h>
|
#include <linux/cpuidle.h>
|
||||||
#include <linux/timer.h>
|
#include <linux/timer.h>
|
||||||
|
|
||||||
@@ -540,6 +541,7 @@ static void dpm_resume_noirq(pm_message_t state)
|
|||||||
dpm_show_time(starttime, state, "noirq");
|
dpm_show_time(starttime, state, "noirq");
|
||||||
resume_device_irqs();
|
resume_device_irqs();
|
||||||
cpuidle_resume();
|
cpuidle_resume();
|
||||||
|
cpufreq_resume();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -955,6 +957,7 @@ static int dpm_suspend_noirq(pm_message_t state)
|
|||||||
ktime_t starttime = ktime_get();
|
ktime_t starttime = ktime_get();
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
|
cpufreq_suspend();
|
||||||
cpuidle_pause();
|
cpuidle_pause();
|
||||||
suspend_device_irqs();
|
suspend_device_irqs();
|
||||||
mutex_lock(&dpm_list_mtx);
|
mutex_lock(&dpm_list_mtx);
|
||||||
|
@@ -26,6 +26,7 @@
|
|||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
#include <linux/suspend.h>
|
||||||
#include <linux/syscore_ops.h>
|
#include <linux/syscore_ops.h>
|
||||||
#include <linux/tick.h>
|
#include <linux/tick.h>
|
||||||
#include <trace/events/power.h>
|
#include <trace/events/power.h>
|
||||||
@@ -47,6 +48,9 @@ static LIST_HEAD(cpufreq_policy_list);
|
|||||||
static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN], cpufreq_cpu_governor);
|
static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN], cpufreq_cpu_governor);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Flag to suspend/resume CPUFreq governors */
|
||||||
|
static bool cpufreq_suspended;
|
||||||
|
|
||||||
static inline bool has_target(void)
|
static inline bool has_target(void)
|
||||||
{
|
{
|
||||||
return cpufreq_driver->target_index || cpufreq_driver->target;
|
return cpufreq_driver->target_index || cpufreq_driver->target;
|
||||||
@@ -1462,6 +1466,41 @@ static struct subsys_interface cpufreq_interface = {
|
|||||||
.remove_dev = cpufreq_remove_dev,
|
.remove_dev = cpufreq_remove_dev,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void cpufreq_suspend(void)
|
||||||
|
{
|
||||||
|
struct cpufreq_policy *policy;
|
||||||
|
|
||||||
|
if (!has_target())
|
||||||
|
return;
|
||||||
|
|
||||||
|
pr_debug("%s: Suspending Governors\n", __func__);
|
||||||
|
|
||||||
|
list_for_each_entry(policy, &cpufreq_policy_list, policy_list)
|
||||||
|
if (__cpufreq_governor(policy, CPUFREQ_GOV_STOP))
|
||||||
|
pr_err("%s: Failed to stop governor for policy: %p\n",
|
||||||
|
__func__, policy);
|
||||||
|
|
||||||
|
cpufreq_suspended = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cpufreq_resume(void)
|
||||||
|
{
|
||||||
|
struct cpufreq_policy *policy;
|
||||||
|
|
||||||
|
if (!has_target())
|
||||||
|
return;
|
||||||
|
|
||||||
|
pr_debug("%s: Resuming Governors\n", __func__);
|
||||||
|
|
||||||
|
cpufreq_suspended = false;
|
||||||
|
|
||||||
|
list_for_each_entry(policy, &cpufreq_policy_list, policy_list)
|
||||||
|
if (__cpufreq_governor(policy, CPUFREQ_GOV_START)
|
||||||
|
|| __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS))
|
||||||
|
pr_err("%s: Failed to start governor for policy: %p\n",
|
||||||
|
__func__, policy);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cpufreq_bp_suspend - Prepare the boot CPU for system suspend.
|
* cpufreq_bp_suspend - Prepare the boot CPU for system suspend.
|
||||||
*
|
*
|
||||||
@@ -1764,6 +1803,10 @@ static int __cpufreq_governor(struct cpufreq_policy *policy,
|
|||||||
struct cpufreq_governor *gov = NULL;
|
struct cpufreq_governor *gov = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Don't start any governor operations if we are entering suspend */
|
||||||
|
if (cpufreq_suspended)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (policy->governor->max_transition_latency &&
|
if (policy->governor->max_transition_latency &&
|
||||||
policy->cpuinfo.transition_latency >
|
policy->cpuinfo.transition_latency >
|
||||||
policy->governor->max_transition_latency) {
|
policy->governor->max_transition_latency) {
|
||||||
@@ -2076,9 +2119,6 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb,
|
|||||||
dev = get_cpu_device(cpu);
|
dev = get_cpu_device(cpu);
|
||||||
if (dev) {
|
if (dev) {
|
||||||
|
|
||||||
if (action & CPU_TASKS_FROZEN)
|
|
||||||
frozen = true;
|
|
||||||
|
|
||||||
switch (action & ~CPU_TASKS_FROZEN) {
|
switch (action & ~CPU_TASKS_FROZEN) {
|
||||||
case CPU_ONLINE:
|
case CPU_ONLINE:
|
||||||
__cpufreq_add_dev(dev, NULL, frozen);
|
__cpufreq_add_dev(dev, NULL, frozen);
|
||||||
|
@@ -400,7 +400,7 @@ EXPORT_SYMBOL_GPL(cpuidle_register_device);
|
|||||||
*/
|
*/
|
||||||
void cpuidle_unregister_device(struct cpuidle_device *dev)
|
void cpuidle_unregister_device(struct cpuidle_device *dev)
|
||||||
{
|
{
|
||||||
if (dev->registered == 0)
|
if (!dev || dev->registered == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cpuidle_pause_and_lock();
|
cpuidle_pause_and_lock();
|
||||||
|
@@ -329,7 +329,7 @@ static struct cpuidle_state atom_cstates[] __initdata = {
|
|||||||
{
|
{
|
||||||
.enter = NULL }
|
.enter = NULL }
|
||||||
};
|
};
|
||||||
static struct cpuidle_state avn_cstates[CPUIDLE_STATE_MAX] = {
|
static struct cpuidle_state avn_cstates[] __initdata = {
|
||||||
{
|
{
|
||||||
.name = "C1-AVN",
|
.name = "C1-AVN",
|
||||||
.desc = "MWAIT 0x00",
|
.desc = "MWAIT 0x00",
|
||||||
@@ -340,7 +340,7 @@ static struct cpuidle_state avn_cstates[CPUIDLE_STATE_MAX] = {
|
|||||||
{
|
{
|
||||||
.name = "C6-AVN",
|
.name = "C6-AVN",
|
||||||
.desc = "MWAIT 0x51",
|
.desc = "MWAIT 0x51",
|
||||||
.flags = MWAIT2flg(0x58) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
|
.flags = MWAIT2flg(0x51) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
|
||||||
.exit_latency = 15,
|
.exit_latency = 15,
|
||||||
.target_residency = 45,
|
.target_residency = 45,
|
||||||
.enter = &intel_idle },
|
.enter = &intel_idle },
|
||||||
|
@@ -280,6 +280,14 @@ cpufreq_verify_within_cpu_limits(struct cpufreq_policy *policy)
|
|||||||
policy->cpuinfo.max_freq);
|
policy->cpuinfo.max_freq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_CPU_FREQ
|
||||||
|
void cpufreq_suspend(void);
|
||||||
|
void cpufreq_resume(void);
|
||||||
|
#else
|
||||||
|
static inline void cpufreq_suspend(void) {}
|
||||||
|
static inline void cpufreq_resume(void) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
* CPUFREQ NOTIFIER INTERFACE *
|
* CPUFREQ NOTIFIER INTERFACE *
|
||||||
*********************************************************************/
|
*********************************************************************/
|
||||||
|
Reference in New Issue
Block a user