Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 350998
b: refs/heads/master
c: 7e73c5a
h: refs/heads/master
v: v3
  • Loading branch information
Zhang Rui authored and Rafael J. Wysocki committed Feb 9, 2013
1 parent 08545b8 commit e1ce09a
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 16 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: fbadc58dd3a52c330c8f3926aa93011bf9d91fa0
refs/heads/master: 7e73c5ae6e7991a6c01f6d096ff8afaef4458c36
6 changes: 6 additions & 0 deletions trunk/drivers/base/power/wakeup.c
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,12 @@ static void wakeup_source_activate(struct wakeup_source *ws)
{
unsigned int cec;

/*
* active wakeup source should bring the system
* out of PM_SUSPEND_FREEZE state
*/
freeze_wake();

ws->active = true;
ws->active_count++;
ws->last_time = ktime_get();
Expand Down
6 changes: 5 additions & 1 deletion trunk/include/linux/suspend.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@ static inline void pm_restore_console(void)
typedef int __bitwise suspend_state_t;

#define PM_SUSPEND_ON ((__force suspend_state_t) 0)
#define PM_SUSPEND_STANDBY ((__force suspend_state_t) 1)
#define PM_SUSPEND_FREEZE ((__force suspend_state_t) 1)
#define PM_SUSPEND_STANDBY ((__force suspend_state_t) 2)
#define PM_SUSPEND_MEM ((__force suspend_state_t) 3)
#define PM_SUSPEND_MIN PM_SUSPEND_FREEZE
#define PM_SUSPEND_MAX ((__force suspend_state_t) 4)

enum suspend_stat_step {
Expand Down Expand Up @@ -192,6 +194,7 @@ struct platform_suspend_ops {
*/
extern void suspend_set_ops(const struct platform_suspend_ops *ops);
extern int suspend_valid_only_mem(suspend_state_t state);
extern void freeze_wake(void);

/**
* arch_suspend_disable_irqs - disable IRQs for suspend
Expand All @@ -217,6 +220,7 @@ extern int pm_suspend(suspend_state_t state);

static inline void suspend_set_ops(const struct platform_suspend_ops *ops) {}
static inline int pm_suspend(suspend_state_t state) { return -ENOSYS; }
static inline void freeze_wake(void) {}
#endif /* !CONFIG_SUSPEND */

/* struct pbe is used for creating lists of pages that should be restored
Expand Down
2 changes: 1 addition & 1 deletion trunk/kernel/power/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr,
static suspend_state_t decode_state(const char *buf, size_t n)
{
#ifdef CONFIG_SUSPEND
suspend_state_t state = PM_SUSPEND_STANDBY;
suspend_state_t state = PM_SUSPEND_MIN;
const char * const *s;
#endif
char *p;
Expand Down
69 changes: 56 additions & 13 deletions trunk/kernel/power/suspend.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,38 @@
#include "power.h"

const char *const pm_states[PM_SUSPEND_MAX] = {
[PM_SUSPEND_FREEZE] = "freeze",
[PM_SUSPEND_STANDBY] = "standby",
[PM_SUSPEND_MEM] = "mem",
};

static const struct platform_suspend_ops *suspend_ops;

static bool need_suspend_ops(suspend_state_t state)
{
return !!(state > PM_SUSPEND_FREEZE);
}

static DECLARE_WAIT_QUEUE_HEAD(suspend_freeze_wait_head);
static bool suspend_freeze_wake;

static void freeze_begin(void)
{
suspend_freeze_wake = false;
}

static void freeze_enter(void)
{
wait_event(suspend_freeze_wait_head, suspend_freeze_wake);
}

void freeze_wake(void)
{
suspend_freeze_wake = true;
wake_up(&suspend_freeze_wait_head);
}
EXPORT_SYMBOL_GPL(freeze_wake);

/**
* suspend_set_ops - Set the global suspend method table.
* @ops: Suspend operations to use.
Expand All @@ -50,8 +76,11 @@ EXPORT_SYMBOL_GPL(suspend_set_ops);

bool valid_state(suspend_state_t state)
{
if (state == PM_SUSPEND_FREEZE)
return true;
/*
* All states need lowlevel support and need to be valid to the lowlevel
* PM_SUSPEND_STANDBY and PM_SUSPEND_MEMORY states need lowlevel
* support and need to be valid to the lowlevel
* implementation, no valid callback implies that none are valid.
*/
return suspend_ops && suspend_ops->valid && suspend_ops->valid(state);
Expand Down Expand Up @@ -89,11 +118,11 @@ static int suspend_test(int level)
* hibernation). Run suspend notifiers, allocate the "suspend" console and
* freeze processes.
*/
static int suspend_prepare(void)
static int suspend_prepare(suspend_state_t state)
{
int error;

if (!suspend_ops || !suspend_ops->enter)
if (need_suspend_ops(state) && (!suspend_ops || !suspend_ops->enter))
return -EPERM;

pm_prepare_console();
Expand Down Expand Up @@ -137,7 +166,7 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
{
int error;

if (suspend_ops->prepare) {
if (need_suspend_ops(state) && suspend_ops->prepare) {
error = suspend_ops->prepare();
if (error)
goto Platform_finish;
Expand All @@ -149,12 +178,23 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
goto Platform_finish;
}

if (suspend_ops->prepare_late) {
if (need_suspend_ops(state) && suspend_ops->prepare_late) {
error = suspend_ops->prepare_late();
if (error)
goto Platform_wake;
}

/*
* PM_SUSPEND_FREEZE equals
* frozen processes + suspended devices + idle processors.
* Thus we should invoke freeze_enter() soon after
* all the devices are suspended.
*/
if (state == PM_SUSPEND_FREEZE) {
freeze_enter();
goto Platform_wake;
}

if (suspend_test(TEST_PLATFORM))
goto Platform_wake;

Expand Down Expand Up @@ -182,13 +222,13 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
enable_nonboot_cpus();

Platform_wake:
if (suspend_ops->wake)
if (need_suspend_ops(state) && suspend_ops->wake)
suspend_ops->wake();

dpm_resume_start(PMSG_RESUME);

Platform_finish:
if (suspend_ops->finish)
if (need_suspend_ops(state) && suspend_ops->finish)
suspend_ops->finish();

return error;
Expand All @@ -203,11 +243,11 @@ int suspend_devices_and_enter(suspend_state_t state)
int error;
bool wakeup = false;

if (!suspend_ops)
if (need_suspend_ops(state) && !suspend_ops)
return -ENOSYS;

trace_machine_suspend(state);
if (suspend_ops->begin) {
if (need_suspend_ops(state) && suspend_ops->begin) {
error = suspend_ops->begin(state);
if (error)
goto Close;
Expand All @@ -226,7 +266,7 @@ int suspend_devices_and_enter(suspend_state_t state)

do {
error = suspend_enter(state, &wakeup);
} while (!error && !wakeup
} while (!error && !wakeup && need_suspend_ops(state)
&& suspend_ops->suspend_again && suspend_ops->suspend_again());

Resume_devices:
Expand All @@ -236,13 +276,13 @@ int suspend_devices_and_enter(suspend_state_t state)
ftrace_start();
resume_console();
Close:
if (suspend_ops->end)
if (need_suspend_ops(state) && suspend_ops->end)
suspend_ops->end();
trace_machine_suspend(PWR_EVENT_EXIT);
return error;

Recover_platform:
if (suspend_ops->recover)
if (need_suspend_ops(state) && suspend_ops->recover)
suspend_ops->recover();
goto Resume_devices;
}
Expand Down Expand Up @@ -278,12 +318,15 @@ static int enter_state(suspend_state_t state)
if (!mutex_trylock(&pm_mutex))
return -EBUSY;

if (state == PM_SUSPEND_FREEZE)
freeze_begin();

printk(KERN_INFO "PM: Syncing filesystems ... ");
sys_sync();
printk("done.\n");

pr_debug("PM: Preparing system for %s sleep\n", pm_states[state]);
error = suspend_prepare();
error = suspend_prepare(state);
if (error)
goto Unlock;

Expand Down

0 comments on commit e1ce09a

Please sign in to comment.