Merge git://git.kernel.org/pub/scm/linux/kernel/git/wim/linux-watchdog
[firefly-linux-kernel-4.4.55.git] / kernel / power / suspend.c
index 1c41ba215419d4d086fc27113caa20bcc8a81d6d..b6b71ad2208fd1a0a04bd31fe4437f6d99bf7f9d 100644 (file)
@@ -44,6 +44,7 @@ void suspend_set_ops(const struct platform_suspend_ops *ops)
        suspend_ops = ops;
        mutex_unlock(&pm_mutex);
 }
+EXPORT_SYMBOL_GPL(suspend_set_ops);
 
 bool valid_state(suspend_state_t state)
 {
@@ -65,6 +66,7 @@ int suspend_valid_only_mem(suspend_state_t state)
 {
        return state == PM_SUSPEND_MEM;
 }
+EXPORT_SYMBOL_GPL(suspend_valid_only_mem);
 
 static int suspend_test(int level)
 {
@@ -126,12 +128,13 @@ void __attribute__ ((weak)) arch_suspend_enable_irqs(void)
 }
 
 /**
- *     suspend_enter - enter the desired system sleep state.
- *     @state:         state to enter
+ * suspend_enter - enter the desired system sleep state.
+ * @state: State to enter
+ * @wakeup: Returns information that suspend should not be entered again.
  *
- *     This function should be called after devices have been suspended.
+ * 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 *wakeup)
 {
        int error;
 
@@ -165,7 +168,8 @@ static int suspend_enter(suspend_state_t state)
 
        error = syscore_suspend();
        if (!error) {
-               if (!(suspend_test(TEST_CORE) || pm_wakeup_pending())) {
+               *wakeup = pm_wakeup_pending();
+               if (!(suspend_test(TEST_CORE) || *wakeup)) {
                        error = suspend_ops->enter(state);
                        events_check_enabled = false;
                }
@@ -199,6 +203,7 @@ static int suspend_enter(suspend_state_t state)
 int suspend_devices_and_enter(suspend_state_t state)
 {
        int error;
+       bool wakeup = false;
 
        if (!suspend_ops)
                return -ENOSYS;
@@ -220,7 +225,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, &wakeup);
+       } while (!error && !wakeup
+               && suspend_ops->suspend_again && suspend_ops->suspend_again());
 
  Resume_devices:
        suspend_test_start();