@@ -92,6 +92,13 @@ typedef int __bitwise suspend_state_t;
* @enter() and @wake(), even if any of them fails. It is executed after
* a failing @prepare.
*
+ * @suspend_again: Returns whether the system should suspend again (true) or
+ * not (false). If the platform wants to poll sensors or execute some
+ * code during suspended without invoking userspace and most of devices,
+ * suspend_again callback is the place assuming that periodic-wakeup or
+ * alarm-wakeup is already setup. This allows to execute some codes while
+ * being kept suspended in the view of userland and devices.
+ *
* @end: Called by the PM core right after resuming devices, to indicate to
* the platform that the system has returned to the working state or
* the transition to the sleep state has been aborted.
@@ -113,6 +120,7 @@ struct platform_suspend_ops {
int (*enter)(suspend_state_t state);
void (*wake)(void);
void (*finish)(void);
+ bool (*suspend_again)(void);
void (*end)(void);
void (*recover)(void);
};
@@ -128,10 +128,12 @@ void __attribute__ ((weak)) arch_suspend_enable_irqs(void)
/**
* suspend_enter - enter the desired system sleep state.
* @state: state to enter
+ * @pm_wkup_pending: indicates that the power transition in progress
+ * should be aborted.
*
* This function should be called after devices have been suspended.
*/
-static int suspend_enter(suspend_state_t state)
+static int suspend_enter(suspend_state_t state, bool *pm_wkup_pending)
{
int error;
@@ -167,7 +169,8 @@ static int suspend_enter(suspend_state_t state)
if (!error)
error = syscore_suspend();
if (!error) {
- if (!(suspend_test(TEST_CORE) || pm_wakeup_pending())) {
+ *pm_wkup_pending = pm_wakeup_pending();
+ if (!(suspend_test(TEST_CORE) || *pm_wkup_pending)) {
error = suspend_ops->enter(state);
events_check_enabled = false;
}
@@ -202,6 +205,7 @@ static int suspend_enter(suspend_state_t state)
int suspend_devices_and_enter(suspend_state_t state)
{
int error;
+ bool pm_wkup_pending = false;
if (!suspend_ops)
return -ENOSYS;
@@ -224,7 +228,10 @@ int suspend_devices_and_enter(suspend_state_t state)
if (suspend_test(TEST_DEVICES))
goto Recover_platform;
- error = suspend_enter(state);
+ do {
+ error = suspend_enter(state, &pm_wkup_pending);
+ } while (suspend_ops->suspend_again && suspend_ops->suspend_again() &&
+ !error && !pm_wkup_pending);
Resume_devices:
suspend_test_start();