1/* 2 * kernel/power/suspend_test.c - Suspend to RAM and standby test facility. 3 * 4 * Copyright (c) 2009 Pavel Machek <pavel@ucw.cz> 5 * 6 * This file is released under the GPLv2. 7 */ 8 9#include <linux/init.h> 10#include <linux/rtc.h> 11 12#include "power.h" 13 14/* 15 * We test the system suspend code by setting an RTC wakealarm a short 16 * time in the future, then suspending. Suspending the devices won't 17 * normally take long ... some systems only need a few milliseconds. 18 * 19 * The time it takes is system-specific though, so when we test this 20 * during system bootup we allow a LOT of time. 21 */ 22#define TEST_SUSPEND_SECONDS 10 23 24static unsigned long suspend_test_start_time; 25 26void suspend_test_start(void) 27{ 28 suspend_test_start_time = jiffies; 29} 30 31void suspend_test_finish(const char *label) 32{ 33 long nj = jiffies - suspend_test_start_time; 34 unsigned msec; 35 36 msec = jiffies_to_msecs(abs(nj)); 37 pr_info("PM: %s took %d.%03d seconds\n", label, 38 msec / 1000, msec % 1000); 39 40 /* Warning on suspend means the RTC alarm period needs to be 41 * larger -- the system was sooo slooowwww to suspend that the 42 * alarm (should have) fired before the system went to sleep! 43 * 44 * Warning on either suspend or resume also means the system 45 * has some performance issues. The stack dump of a WARN_ON 46 * is more likely to get the right attention than a printk... 47 */ 48 WARN(msec > (TEST_SUSPEND_SECONDS * 1000), 49 "Component: %s, time: %u\n", label, msec); 50} 51 52/* 53 * To test system suspend, we need a hands-off mechanism to resume the 54 * system. RTCs wake alarms are a common self-contained mechanism. 55 */ 56 57static void __init test_wakealarm(struct rtc_device *rtc, suspend_state_t state) 58{ 59 static char err_readtime[] __initdata = 60 KERN_ERR "PM: can't read %s time, err %d\n"; 61 static char err_wakealarm [] __initdata = 62 KERN_ERR "PM: can't set %s wakealarm, err %d\n"; 63 static char err_suspend[] __initdata = 64 KERN_ERR "PM: suspend test failed, error %d\n"; 65 static char info_test[] __initdata = 66 KERN_INFO "PM: test RTC wakeup from '%s' suspend\n"; 67 68 unsigned long now; 69 struct rtc_wkalrm alm; 70 int status; 71 72 /* this may fail if the RTC hasn't been initialized */ 73 status = rtc_read_time(rtc, &alm.time); 74 if (status < 0) { 75 printk(err_readtime, dev_name(&rtc->dev), status); 76 return; 77 } 78 rtc_tm_to_time(&alm.time, &now); 79 80 memset(&alm, 0, sizeof alm); 81 rtc_time_to_tm(now + TEST_SUSPEND_SECONDS, &alm.time); 82 alm.enabled = true; 83 84 status = rtc_set_alarm(rtc, &alm); 85 if (status < 0) { 86 printk(err_wakealarm, dev_name(&rtc->dev), status); 87 return; 88 } 89 90 if (state == PM_SUSPEND_MEM) { 91 printk(info_test, pm_states[state]); 92 status = pm_suspend(state); 93 if (status == -ENODEV) 94 state = PM_SUSPEND_STANDBY; 95 } 96 if (state == PM_SUSPEND_STANDBY) { 97 printk(info_test, pm_states[state]); 98 status = pm_suspend(state); 99 } 100 if (status < 0) 101 printk(err_suspend, status); 102 103 /* Some platforms can't detect that the alarm triggered the 104 * wakeup, or (accordingly) disable it after it afterwards. 105 * It's supposed to give oneshot behavior; cope. 106 */ 107 alm.enabled = false; 108 rtc_set_alarm(rtc, &alm); 109} 110 111static int __init has_wakealarm(struct device *dev, void *name_ptr) 112{ 113 struct rtc_device *candidate = to_rtc_device(dev); 114 115 if (!candidate->ops->set_alarm) 116 return 0; 117 if (!device_may_wakeup(candidate->dev.parent)) 118 return 0; 119 120 *(const char **)name_ptr = dev_name(dev); 121 return 1; 122} 123 124/* 125 * Kernel options like "test_suspend=mem" force suspend/resume sanity tests 126 * at startup time. They're normally disabled, for faster boot and because 127 * we can't know which states really work on this particular system. 128 */ 129static suspend_state_t test_state __initdata = PM_SUSPEND_ON; 130 131static char warn_bad_state[] __initdata = 132 KERN_WARNING "PM: can't test '%s' suspend state\n"; 133 134static int __init setup_test_suspend(char *value) 135{ 136 unsigned i; 137 138 /* "=mem" ==> "mem" */ 139 value++; 140 for (i = 0; i < PM_SUSPEND_MAX; i++) { 141 if (!pm_states[i]) 142 continue; 143 if (strcmp(pm_states[i], value) != 0) 144 continue; 145 test_state = (__force suspend_state_t) i; 146 return 0; 147 } 148 printk(warn_bad_state, value); 149 return 0; 150} 151__setup("test_suspend", setup_test_suspend); 152 153static int __init test_suspend(void) 154{ 155 static char warn_no_rtc[] __initdata = 156 KERN_WARNING "PM: no wakealarm-capable RTC driver is ready\n"; 157 158 char *pony = NULL; 159 struct rtc_device *rtc = NULL; 160 161 /* PM is initialized by now; is that state testable? */ 162 if (test_state == PM_SUSPEND_ON) 163 goto done; 164 if (!valid_state(test_state)) { 165 printk(warn_bad_state, pm_states[test_state]); 166 goto done; 167 } 168 169 /* RTCs have initialized by now too ... can we use one? */ 170 class_find_device(rtc_class, NULL, &pony, has_wakealarm); 171 if (pony) 172 rtc = rtc_class_open(pony); 173 if (!rtc) { 174 printk(warn_no_rtc); 175 goto done; 176 } 177 178 /* go for it */ 179 test_wakealarm(rtc, test_state); 180 rtc_class_close(rtc); 181done: 182 return 0; 183} 184late_initcall(test_suspend); 185