Merge tag 'pm-for-3.4' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull power management updates for 3.4 from Rafael Wysocki: "Assorted extensions and fixes including: * Introduction of early/late suspend/hibernation device callbacks. * Generic PM domains extensions and fixes. * devfreq updates from Axel Lin and MyungJoo Ham. * Device PM QoS updates. * Fixes of concurrency problems with wakeup sources. * System suspend and hibernation fixes." * tag 'pm-for-3.4' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (43 commits) PM / Domains: Check domain status during hibernation restore of devices PM / devfreq: add relation of recommended frequency. PM / shmobile: Make MTU2 driver use pm_genpd_dev_always_on() PM / shmobile: Make CMT driver use pm_genpd_dev_always_on() PM / shmobile: Make TMU driver use pm_genpd_dev_always_on() PM / Domains: Introduce "always on" device flag PM / Domains: Fix hibernation restore of devices, v2 PM / Domains: Fix handling of wakeup devices during system resume sh_mmcif / PM: Use PM QoS latency constraint tmio_mmc / PM: Use PM QoS latency constraint PM / QoS: Make it possible to expose PM QoS latency constraints PM / Sleep: JBD and JBD2 missing set_freezable() PM / Domains: Fix include for PM_GENERIC_DOMAINS=n case PM / Freezer: Remove references to TIF_FREEZE in comments PM / Sleep: Add more wakeup source initialization routines PM / Hibernate: Enable usermodehelpers in hibernate() error path PM / Sleep: Make __pm_stay_awake() delete wakeup source timers PM / Sleep: Fix race conditions related to wakeup source timer function PM / Sleep: Fix possible infinite loop during wakeup source destruction PM / Hibernate: print physical addresses consistently with other parts of kernel ...
This commit is contained in:
@@ -424,7 +424,7 @@ void daemonize(const char *name, ...)
|
||||
*/
|
||||
exit_mm(current);
|
||||
/*
|
||||
* We don't want to have TIF_FREEZE set if the system-wide hibernation
|
||||
* We don't want to get frozen, in case system-wide hibernation
|
||||
* or suspend transition begins right now.
|
||||
*/
|
||||
current->flags |= (PF_NOFREEZE | PF_KTHREAD);
|
||||
|
@@ -99,9 +99,9 @@ static void fake_signal_wake_up(struct task_struct *p)
|
||||
* freeze_task - send a freeze request to given task
|
||||
* @p: task to send the request to
|
||||
*
|
||||
* If @p is freezing, the freeze request is sent by setting %TIF_FREEZE
|
||||
* flag and either sending a fake signal to it or waking it up, depending
|
||||
* on whether it has %PF_FREEZER_NOSIG set.
|
||||
* If @p is freezing, the freeze request is sent either by sending a fake
|
||||
* signal (if it's not a kernel thread) or waking it up (if it's a kernel
|
||||
* thread).
|
||||
*
|
||||
* RETURNS:
|
||||
* %false, if @p is not freezing or already frozen; %true, otherwise
|
||||
|
@@ -1546,13 +1546,13 @@ int kernel_kexec(void)
|
||||
if (error)
|
||||
goto Resume_console;
|
||||
/* At this point, dpm_suspend_start() has been called,
|
||||
* but *not* dpm_suspend_noirq(). We *must* call
|
||||
* dpm_suspend_noirq() now. Otherwise, drivers for
|
||||
* but *not* dpm_suspend_end(). We *must* call
|
||||
* dpm_suspend_end() now. Otherwise, drivers for
|
||||
* some devices (e.g. interrupt controllers) become
|
||||
* desynchronized with the actual state of the
|
||||
* hardware at resume time, and evil weirdness ensues.
|
||||
*/
|
||||
error = dpm_suspend_noirq(PMSG_FREEZE);
|
||||
error = dpm_suspend_end(PMSG_FREEZE);
|
||||
if (error)
|
||||
goto Resume_devices;
|
||||
error = disable_nonboot_cpus();
|
||||
@@ -1579,7 +1579,7 @@ int kernel_kexec(void)
|
||||
local_irq_enable();
|
||||
Enable_cpus:
|
||||
enable_nonboot_cpus();
|
||||
dpm_resume_noirq(PMSG_RESTORE);
|
||||
dpm_resume_start(PMSG_RESTORE);
|
||||
Resume_devices:
|
||||
dpm_resume_end(PMSG_RESTORE);
|
||||
Resume_console:
|
||||
|
@@ -1,7 +1,8 @@
|
||||
|
||||
ccflags-$(CONFIG_PM_DEBUG) := -DDEBUG
|
||||
|
||||
obj-$(CONFIG_PM) += main.o qos.o
|
||||
obj-y += qos.o
|
||||
obj-$(CONFIG_PM) += main.o
|
||||
obj-$(CONFIG_VT_CONSOLE_SLEEP) += console.o
|
||||
obj-$(CONFIG_FREEZER) += process.o
|
||||
obj-$(CONFIG_SUSPEND) += suspend.o
|
||||
|
@@ -245,8 +245,8 @@ void swsusp_show_speed(struct timeval *start, struct timeval *stop,
|
||||
* create_image - Create a hibernation image.
|
||||
* @platform_mode: Whether or not to use the platform driver.
|
||||
*
|
||||
* Execute device drivers' .freeze_noirq() callbacks, create a hibernation image
|
||||
* and execute the drivers' .thaw_noirq() callbacks.
|
||||
* Execute device drivers' "late" and "noirq" freeze callbacks, create a
|
||||
* hibernation image and run the drivers' "noirq" and "early" thaw callbacks.
|
||||
*
|
||||
* Control reappears in this routine after the subsequent restore.
|
||||
*/
|
||||
@@ -254,7 +254,7 @@ static int create_image(int platform_mode)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = dpm_suspend_noirq(PMSG_FREEZE);
|
||||
error = dpm_suspend_end(PMSG_FREEZE);
|
||||
if (error) {
|
||||
printk(KERN_ERR "PM: Some devices failed to power down, "
|
||||
"aborting hibernation\n");
|
||||
@@ -306,7 +306,7 @@ static int create_image(int platform_mode)
|
||||
Platform_finish:
|
||||
platform_finish(platform_mode);
|
||||
|
||||
dpm_resume_noirq(in_suspend ?
|
||||
dpm_resume_start(in_suspend ?
|
||||
(error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE);
|
||||
|
||||
return error;
|
||||
@@ -343,13 +343,13 @@ int hibernation_snapshot(int platform_mode)
|
||||
* successful freezer test.
|
||||
*/
|
||||
freezer_test_done = true;
|
||||
goto Cleanup;
|
||||
goto Thaw;
|
||||
}
|
||||
|
||||
error = dpm_prepare(PMSG_FREEZE);
|
||||
if (error) {
|
||||
dpm_complete(PMSG_RECOVER);
|
||||
goto Cleanup;
|
||||
goto Thaw;
|
||||
}
|
||||
|
||||
suspend_console();
|
||||
@@ -385,6 +385,8 @@ int hibernation_snapshot(int platform_mode)
|
||||
platform_end(platform_mode);
|
||||
return error;
|
||||
|
||||
Thaw:
|
||||
thaw_kernel_threads();
|
||||
Cleanup:
|
||||
swsusp_free();
|
||||
goto Close;
|
||||
@@ -394,16 +396,16 @@ int hibernation_snapshot(int platform_mode)
|
||||
* resume_target_kernel - Restore system state from a hibernation image.
|
||||
* @platform_mode: Whether or not to use the platform driver.
|
||||
*
|
||||
* Execute device drivers' .freeze_noirq() callbacks, restore the contents of
|
||||
* highmem that have not been restored yet from the image and run the low-level
|
||||
* code that will restore the remaining contents of memory and switch to the
|
||||
* just restored target kernel.
|
||||
* Execute device drivers' "noirq" and "late" freeze callbacks, restore the
|
||||
* contents of highmem that have not been restored yet from the image and run
|
||||
* the low-level code that will restore the remaining contents of memory and
|
||||
* switch to the just restored target kernel.
|
||||
*/
|
||||
static int resume_target_kernel(bool platform_mode)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = dpm_suspend_noirq(PMSG_QUIESCE);
|
||||
error = dpm_suspend_end(PMSG_QUIESCE);
|
||||
if (error) {
|
||||
printk(KERN_ERR "PM: Some devices failed to power down, "
|
||||
"aborting resume\n");
|
||||
@@ -460,7 +462,7 @@ static int resume_target_kernel(bool platform_mode)
|
||||
Cleanup:
|
||||
platform_restore_cleanup(platform_mode);
|
||||
|
||||
dpm_resume_noirq(PMSG_RECOVER);
|
||||
dpm_resume_start(PMSG_RECOVER);
|
||||
|
||||
return error;
|
||||
}
|
||||
@@ -518,7 +520,7 @@ int hibernation_platform_enter(void)
|
||||
goto Resume_devices;
|
||||
}
|
||||
|
||||
error = dpm_suspend_noirq(PMSG_HIBERNATE);
|
||||
error = dpm_suspend_end(PMSG_HIBERNATE);
|
||||
if (error)
|
||||
goto Resume_devices;
|
||||
|
||||
@@ -549,7 +551,7 @@ int hibernation_platform_enter(void)
|
||||
Platform_finish:
|
||||
hibernation_ops->finish();
|
||||
|
||||
dpm_resume_noirq(PMSG_RESTORE);
|
||||
dpm_resume_start(PMSG_RESTORE);
|
||||
|
||||
Resume_devices:
|
||||
entering_platform_hibernation = false;
|
||||
@@ -616,7 +618,7 @@ int hibernate(void)
|
||||
/* Allocate memory management structures */
|
||||
error = create_basic_memory_bitmaps();
|
||||
if (error)
|
||||
goto Exit;
|
||||
goto Enable_umh;
|
||||
|
||||
printk(KERN_INFO "PM: Syncing filesystems ... ");
|
||||
sys_sync();
|
||||
@@ -624,15 +626,11 @@ int hibernate(void)
|
||||
|
||||
error = freeze_processes();
|
||||
if (error)
|
||||
goto Finish;
|
||||
goto Free_bitmaps;
|
||||
|
||||
error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM);
|
||||
if (error)
|
||||
if (error || freezer_test_done)
|
||||
goto Thaw;
|
||||
if (freezer_test_done) {
|
||||
freezer_test_done = false;
|
||||
goto Thaw;
|
||||
}
|
||||
|
||||
if (in_suspend) {
|
||||
unsigned int flags = 0;
|
||||
@@ -657,8 +655,13 @@ int hibernate(void)
|
||||
|
||||
Thaw:
|
||||
thaw_processes();
|
||||
Finish:
|
||||
|
||||
/* Don't bother checking whether freezer_test_done is true */
|
||||
freezer_test_done = false;
|
||||
|
||||
Free_bitmaps:
|
||||
free_basic_memory_bitmaps();
|
||||
Enable_umh:
|
||||
usermodehelper_enable();
|
||||
Exit:
|
||||
pm_notifier_call_chain(PM_POST_HIBERNATION);
|
||||
|
@@ -165,16 +165,20 @@ static int suspend_stats_show(struct seq_file *s, void *unused)
|
||||
last_errno %= REC_FAILED_NUM;
|
||||
last_step = suspend_stats.last_failed_step + REC_FAILED_NUM - 1;
|
||||
last_step %= REC_FAILED_NUM;
|
||||
seq_printf(s, "%s: %d\n%s: %d\n%s: %d\n%s: %d\n"
|
||||
"%s: %d\n%s: %d\n%s: %d\n%s: %d\n",
|
||||
seq_printf(s, "%s: %d\n%s: %d\n%s: %d\n%s: %d\n%s: %d\n"
|
||||
"%s: %d\n%s: %d\n%s: %d\n%s: %d\n%s: %d\n",
|
||||
"success", suspend_stats.success,
|
||||
"fail", suspend_stats.fail,
|
||||
"failed_freeze", suspend_stats.failed_freeze,
|
||||
"failed_prepare", suspend_stats.failed_prepare,
|
||||
"failed_suspend", suspend_stats.failed_suspend,
|
||||
"failed_suspend_late",
|
||||
suspend_stats.failed_suspend_late,
|
||||
"failed_suspend_noirq",
|
||||
suspend_stats.failed_suspend_noirq,
|
||||
"failed_resume", suspend_stats.failed_resume,
|
||||
"failed_resume_early",
|
||||
suspend_stats.failed_resume_early,
|
||||
"failed_resume_noirq",
|
||||
suspend_stats.failed_resume_noirq);
|
||||
seq_printf(s, "failures:\n last_failed_dev:\t%-s\n",
|
||||
@@ -287,16 +291,10 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
|
||||
|
||||
#ifdef CONFIG_SUSPEND
|
||||
for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++) {
|
||||
if (*s && len == strlen(*s) && !strncmp(buf, *s, len))
|
||||
if (*s && len == strlen(*s) && !strncmp(buf, *s, len)) {
|
||||
error = pm_suspend(state);
|
||||
break;
|
||||
}
|
||||
if (state < PM_SUSPEND_MAX && *s) {
|
||||
error = enter_state(state);
|
||||
if (error) {
|
||||
suspend_stats.fail++;
|
||||
dpm_save_failed_errno(error);
|
||||
} else
|
||||
suspend_stats.success++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@@ -177,13 +177,11 @@ extern const char *const pm_states[];
|
||||
|
||||
extern bool valid_state(suspend_state_t state);
|
||||
extern int suspend_devices_and_enter(suspend_state_t state);
|
||||
extern int enter_state(suspend_state_t state);
|
||||
#else /* !CONFIG_SUSPEND */
|
||||
static inline int suspend_devices_and_enter(suspend_state_t state)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
static inline int enter_state(suspend_state_t state) { return -ENOSYS; }
|
||||
static inline bool valid_state(suspend_state_t state) { return false; }
|
||||
#endif /* !CONFIG_SUSPEND */
|
||||
|
||||
@@ -234,16 +232,14 @@ static inline int suspend_freeze_processes(void)
|
||||
int error;
|
||||
|
||||
error = freeze_processes();
|
||||
|
||||
/*
|
||||
* freeze_processes() automatically thaws every task if freezing
|
||||
* fails. So we need not do anything extra upon error.
|
||||
*/
|
||||
if (error)
|
||||
goto Finish;
|
||||
return error;
|
||||
|
||||
error = freeze_kernel_threads();
|
||||
|
||||
/*
|
||||
* freeze_kernel_threads() thaws only kernel threads upon freezing
|
||||
* failure. So we have to thaw the userspace tasks ourselves.
|
||||
@@ -251,7 +247,6 @@ static inline int suspend_freeze_processes(void)
|
||||
if (error)
|
||||
thaw_processes();
|
||||
|
||||
Finish:
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@@ -53,11 +53,9 @@ static int try_to_freeze_tasks(bool user_only)
|
||||
* It is "frozen enough". If the task does wake
|
||||
* up, it will immediately call try_to_freeze.
|
||||
*
|
||||
* Because freeze_task() goes through p's
|
||||
* scheduler lock after setting TIF_FREEZE, it's
|
||||
* guaranteed that either we see TASK_RUNNING or
|
||||
* try_to_stop() after schedule() in ptrace/signal
|
||||
* stop sees TIF_FREEZE.
|
||||
* Because freeze_task() goes through p's scheduler lock, it's
|
||||
* guaranteed that TASK_STOPPED/TRACED -> TASK_RUNNING
|
||||
* transition can't race with task state testing here.
|
||||
*/
|
||||
if (!task_is_stopped_or_traced(p) &&
|
||||
!freezer_should_skip(p))
|
||||
@@ -98,13 +96,15 @@ static int try_to_freeze_tasks(bool user_only)
|
||||
elapsed_csecs / 100, elapsed_csecs % 100,
|
||||
todo - wq_busy, wq_busy);
|
||||
|
||||
read_lock(&tasklist_lock);
|
||||
do_each_thread(g, p) {
|
||||
if (!wakeup && !freezer_should_skip(p) &&
|
||||
p != current && freezing(p) && !frozen(p))
|
||||
sched_show_task(p);
|
||||
} while_each_thread(g, p);
|
||||
read_unlock(&tasklist_lock);
|
||||
if (!wakeup) {
|
||||
read_lock(&tasklist_lock);
|
||||
do_each_thread(g, p) {
|
||||
if (p != current && !freezer_should_skip(p)
|
||||
&& freezing(p) && !frozen(p))
|
||||
sched_show_task(p);
|
||||
} while_each_thread(g, p);
|
||||
read_unlock(&tasklist_lock);
|
||||
}
|
||||
} else {
|
||||
printk("(elapsed %d.%02d seconds) ", elapsed_csecs / 100,
|
||||
elapsed_csecs % 100);
|
||||
|
@@ -469,21 +469,18 @@ static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf,
|
||||
static int __init pm_qos_power_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
ret = register_pm_qos_misc(&cpu_dma_pm_qos);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "pm_qos_param: cpu_dma_latency setup failed\n");
|
||||
return ret;
|
||||
BUILD_BUG_ON(ARRAY_SIZE(pm_qos_array) != PM_QOS_NUM_CLASSES);
|
||||
|
||||
for (i = 1; i < PM_QOS_NUM_CLASSES; i++) {
|
||||
ret = register_pm_qos_misc(pm_qos_array[i]);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "pm_qos_param: %s setup failed\n",
|
||||
pm_qos_array[i]->name);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
ret = register_pm_qos_misc(&network_lat_pm_qos);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "pm_qos_param: network_latency setup failed\n");
|
||||
return ret;
|
||||
}
|
||||
ret = register_pm_qos_misc(&network_throughput_pm_qos);
|
||||
if (ret < 0)
|
||||
printk(KERN_ERR
|
||||
"pm_qos_param: network_throughput setup failed\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@@ -711,9 +711,10 @@ static void mark_nosave_pages(struct memory_bitmap *bm)
|
||||
list_for_each_entry(region, &nosave_regions, list) {
|
||||
unsigned long pfn;
|
||||
|
||||
pr_debug("PM: Marking nosave pages: %016lx - %016lx\n",
|
||||
region->start_pfn << PAGE_SHIFT,
|
||||
region->end_pfn << PAGE_SHIFT);
|
||||
pr_debug("PM: Marking nosave pages: [mem %#010llx-%#010llx]\n",
|
||||
(unsigned long long) region->start_pfn << PAGE_SHIFT,
|
||||
((unsigned long long) region->end_pfn << PAGE_SHIFT)
|
||||
- 1);
|
||||
|
||||
for (pfn = region->start_pfn; pfn < region->end_pfn; pfn++)
|
||||
if (pfn_valid(pfn)) {
|
||||
|
@@ -37,8 +37,8 @@ const char *const pm_states[PM_SUSPEND_MAX] = {
|
||||
static const struct platform_suspend_ops *suspend_ops;
|
||||
|
||||
/**
|
||||
* suspend_set_ops - Set the global suspend method table.
|
||||
* @ops: Pointer to ops structure.
|
||||
* suspend_set_ops - Set the global suspend method table.
|
||||
* @ops: Suspend operations to use.
|
||||
*/
|
||||
void suspend_set_ops(const struct platform_suspend_ops *ops)
|
||||
{
|
||||
@@ -58,11 +58,11 @@ bool valid_state(suspend_state_t state)
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend_valid_only_mem - generic memory-only valid callback
|
||||
* suspend_valid_only_mem - Generic memory-only valid callback.
|
||||
*
|
||||
* Platform drivers that implement mem suspend only and only need
|
||||
* to check for that in their .valid callback can use this instead
|
||||
* of rolling their own .valid callback.
|
||||
* Platform drivers that implement mem suspend only and only need to check for
|
||||
* that in their .valid() callback can use this instead of rolling their own
|
||||
* .valid() callback.
|
||||
*/
|
||||
int suspend_valid_only_mem(suspend_state_t state)
|
||||
{
|
||||
@@ -83,10 +83,11 @@ static int suspend_test(int level)
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend_prepare - Do prep work before entering low-power state.
|
||||
* suspend_prepare - Prepare for entering system sleep state.
|
||||
*
|
||||
* This is common code that is called for each state that we're entering.
|
||||
* Run suspend notifiers, allocate a console and stop all processes.
|
||||
* Common code run for every system sleep state that can be entered (except for
|
||||
* hibernation). Run suspend notifiers, allocate the "suspend" console and
|
||||
* freeze processes.
|
||||
*/
|
||||
static int suspend_prepare(void)
|
||||
{
|
||||
@@ -131,9 +132,9 @@ void __attribute__ ((weak)) arch_suspend_enable_irqs(void)
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend_enter - enter the desired system sleep state.
|
||||
* @state: State to enter
|
||||
* @wakeup: Returns information that suspend should not be entered again.
|
||||
* suspend_enter - Make the system enter the given sleep state.
|
||||
* @state: System sleep state to enter.
|
||||
* @wakeup: Returns information that the sleep state should not be re-entered.
|
||||
*
|
||||
* This function should be called after devices have been suspended.
|
||||
*/
|
||||
@@ -147,7 +148,7 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
|
||||
goto Platform_finish;
|
||||
}
|
||||
|
||||
error = dpm_suspend_noirq(PMSG_SUSPEND);
|
||||
error = dpm_suspend_end(PMSG_SUSPEND);
|
||||
if (error) {
|
||||
printk(KERN_ERR "PM: Some devices failed to power down\n");
|
||||
goto Platform_finish;
|
||||
@@ -189,7 +190,7 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
|
||||
if (suspend_ops->wake)
|
||||
suspend_ops->wake();
|
||||
|
||||
dpm_resume_noirq(PMSG_RESUME);
|
||||
dpm_resume_start(PMSG_RESUME);
|
||||
|
||||
Platform_finish:
|
||||
if (suspend_ops->finish)
|
||||
@@ -199,9 +200,8 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend_devices_and_enter - suspend devices and enter the desired system
|
||||
* sleep state.
|
||||
* @state: state to enter
|
||||
* suspend_devices_and_enter - Suspend devices and enter system sleep state.
|
||||
* @state: System sleep state to enter.
|
||||
*/
|
||||
int suspend_devices_and_enter(suspend_state_t state)
|
||||
{
|
||||
@@ -251,10 +251,10 @@ int suspend_devices_and_enter(suspend_state_t state)
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend_finish - Do final work before exiting suspend sequence.
|
||||
* suspend_finish - Clean up before finishing the suspend sequence.
|
||||
*
|
||||
* Call platform code to clean up, restart processes, and free the
|
||||
* console that we've allocated. This is not called for suspend-to-disk.
|
||||
* Call platform code to clean up, restart processes, and free the console that
|
||||
* we've allocated. This routine is not called for hibernation.
|
||||
*/
|
||||
static void suspend_finish(void)
|
||||
{
|
||||
@@ -265,16 +265,14 @@ static void suspend_finish(void)
|
||||
}
|
||||
|
||||
/**
|
||||
* enter_state - Do common work of entering low-power state.
|
||||
* @state: pm_state structure for state we're entering.
|
||||
* enter_state - Do common work needed to enter system sleep state.
|
||||
* @state: System sleep state to enter.
|
||||
*
|
||||
* Make sure we're the only ones trying to enter a sleep state. Fail
|
||||
* if someone has beat us to it, since we don't want anything weird to
|
||||
* happen when we wake up.
|
||||
* Then, do the setup for suspend, enter the state, and cleaup (after
|
||||
* we've woken up).
|
||||
* Make sure that no one else is trying to put the system into a sleep state.
|
||||
* Fail if that's not the case. Otherwise, prepare for system suspend, make the
|
||||
* system enter the given sleep state and clean up after wakeup.
|
||||
*/
|
||||
int enter_state(suspend_state_t state)
|
||||
static int enter_state(suspend_state_t state)
|
||||
{
|
||||
int error;
|
||||
|
||||
@@ -310,24 +308,26 @@ int enter_state(suspend_state_t state)
|
||||
}
|
||||
|
||||
/**
|
||||
* pm_suspend - Externally visible function for suspending system.
|
||||
* @state: Enumerated value of state to enter.
|
||||
* pm_suspend - Externally visible function for suspending the system.
|
||||
* @state: System sleep state to enter.
|
||||
*
|
||||
* Determine whether or not value is within range, get state
|
||||
* structure, and enter (above).
|
||||
* Check if the value of @state represents one of the supported states,
|
||||
* execute enter_state() and update system suspend statistics.
|
||||
*/
|
||||
int pm_suspend(suspend_state_t state)
|
||||
{
|
||||
int ret;
|
||||
if (state > PM_SUSPEND_ON && state < PM_SUSPEND_MAX) {
|
||||
ret = enter_state(state);
|
||||
if (ret) {
|
||||
suspend_stats.fail++;
|
||||
dpm_save_failed_errno(ret);
|
||||
} else
|
||||
suspend_stats.success++;
|
||||
return ret;
|
||||
int error;
|
||||
|
||||
if (state <= PM_SUSPEND_ON || state >= PM_SUSPEND_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
error = enter_state(state);
|
||||
if (error) {
|
||||
suspend_stats.fail++;
|
||||
dpm_save_failed_errno(error);
|
||||
} else {
|
||||
suspend_stats.success++;
|
||||
}
|
||||
return -EINVAL;
|
||||
return error;
|
||||
}
|
||||
EXPORT_SYMBOL(pm_suspend);
|
||||
|
@@ -249,16 +249,10 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
|
||||
}
|
||||
pm_restore_gfp_mask();
|
||||
error = hibernation_snapshot(data->platform_support);
|
||||
if (error) {
|
||||
thaw_kernel_threads();
|
||||
} else {
|
||||
if (!error) {
|
||||
error = put_user(in_suspend, (int __user *)arg);
|
||||
if (!error && !freezer_test_done)
|
||||
data->ready = 1;
|
||||
if (freezer_test_done) {
|
||||
freezer_test_done = false;
|
||||
thaw_kernel_threads();
|
||||
}
|
||||
data->ready = !freezer_test_done && !error;
|
||||
freezer_test_done = false;
|
||||
}
|
||||
break;
|
||||
|
||||
|
Reference in New Issue
Block a user