ARM64: DTS: Add rk3399-firefly uart4 device, node as /dev/ttyS1
[firefly-linux-kernel-4.4.55.git] / kernel / power / suspend.c
index f9fe133c13e24de8e91f4ea81abebe6c58a3fd23..024411816ccf2c5110247ce9be5817f1fdc9deed 100644 (file)
 #include <linux/suspend.h>
 #include <linux/syscore_ops.h>
 #include <linux/ftrace.h>
+#include <linux/rtc.h>
 #include <trace/events/power.h>
 #include <linux/compiler.h>
 #include <linux/moduleparam.h>
+#include <linux/wakeup_reason.h>
 
 #include "power.h"
 
@@ -312,7 +314,8 @@ void __weak arch_suspend_enable_irqs(void)
  */
 static int suspend_enter(suspend_state_t state, bool *wakeup)
 {
-       int error;
+       char suspend_abort[MAX_SUSPEND_ABORT_LEN];
+       int error, last_dev;
 
        error = platform_suspend_prepare(state);
        if (error)
@@ -320,7 +323,11 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
 
        error = dpm_suspend_late(PMSG_SUSPEND);
        if (error) {
+               last_dev = suspend_stats.last_failed_dev + REC_FAILED_NUM - 1;
+               last_dev %= REC_FAILED_NUM;
                printk(KERN_ERR "PM: late suspend of devices failed\n");
+               log_suspend_abort_reason("%s device failed to power down",
+                       suspend_stats.failed_devs[last_dev]);
                goto Platform_finish;
        }
        error = platform_suspend_prepare_late(state);
@@ -329,7 +336,11 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
 
        error = dpm_suspend_noirq(PMSG_SUSPEND);
        if (error) {
+               last_dev = suspend_stats.last_failed_dev + REC_FAILED_NUM - 1;
+               last_dev %= REC_FAILED_NUM;
                printk(KERN_ERR "PM: noirq suspend of devices failed\n");
+               log_suspend_abort_reason("noirq suspend of %s device failed",
+                       suspend_stats.failed_devs[last_dev]);
                goto Platform_early_resume;
        }
        error = platform_suspend_prepare_noirq(state);
@@ -353,8 +364,10 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
        }
 
        error = disable_nonboot_cpus();
-       if (error || suspend_test(TEST_CPUS))
+       if (error || suspend_test(TEST_CPUS)) {
+               log_suspend_abort_reason("Disabling non-boot cpus failed");
                goto Enable_cpus;
+       }
 
        arch_suspend_disable_irqs();
        BUG_ON(!irqs_disabled());
@@ -370,6 +383,9 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
                                state, false);
                        events_check_enabled = false;
                } else if (*wakeup) {
+                       pm_get_active_wakeup_sources(suspend_abort,
+                               MAX_SUSPEND_ABORT_LEN);
+                       log_suspend_abort_reason(suspend_abort);
                        error = -EBUSY;
                }
                syscore_resume();
@@ -417,6 +433,7 @@ int suspend_devices_and_enter(suspend_state_t state)
        error = dpm_suspend_start(PMSG_SUSPEND);
        if (error) {
                pr_err("PM: Some devices failed to suspend, or early wake event detected\n");
+               log_suspend_abort_reason("Some devices failed to suspend, or early wake event detected");
                goto Recover_platform;
        }
        suspend_test_finish("suspend devices");
@@ -518,6 +535,18 @@ static int enter_state(suspend_state_t state)
        return error;
 }
 
+static void pm_suspend_marker(char *annotation)
+{
+       struct timespec ts;
+       struct rtc_time tm;
+
+       getnstimeofday(&ts);
+       rtc_time_to_tm(ts.tv_sec, &tm);
+       pr_info("PM: suspend %s %d-%02d-%02d %02d:%02d:%02d.%09lu UTC\n",
+               annotation, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
+               tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec);
+}
+
 /**
  * pm_suspend - Externally visible function for suspending the system.
  * @state: System sleep state to enter.
@@ -532,6 +561,7 @@ int pm_suspend(suspend_state_t state)
        if (state <= PM_SUSPEND_ON || state >= PM_SUSPEND_MAX)
                return -EINVAL;
 
+       pm_suspend_marker("entry");
        error = enter_state(state);
        if (error) {
                suspend_stats.fail++;
@@ -539,6 +569,7 @@ int pm_suspend(suspend_state_t state)
        } else {
                suspend_stats.success++;
        }
+       pm_suspend_marker("exit");
        return error;
 }
 EXPORT_SYMBOL(pm_suspend);