0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/init.h>
0009 #include <linux/rtc.h>
0010
0011 #include "power.h"
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021 #define TEST_SUSPEND_SECONDS 10
0022
0023 static unsigned long suspend_test_start_time;
0024 static u32 test_repeat_count_max = 1;
0025 static u32 test_repeat_count_current;
0026
0027 void suspend_test_start(void)
0028 {
0029
0030
0031
0032
0033 suspend_test_start_time = jiffies;
0034 }
0035
0036 void suspend_test_finish(const char *label)
0037 {
0038 long nj = jiffies - suspend_test_start_time;
0039 unsigned msec;
0040
0041 msec = jiffies_to_msecs(abs(nj));
0042 pr_info("PM: %s took %d.%03d seconds\n", label,
0043 msec / 1000, msec % 1000);
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053 WARN(msec > (TEST_SUSPEND_SECONDS * 1000),
0054 "Component: %s, time: %u\n", label, msec);
0055 }
0056
0057
0058
0059
0060
0061
0062 static void __init test_wakealarm(struct rtc_device *rtc, suspend_state_t state)
0063 {
0064 static char err_readtime[] __initdata =
0065 KERN_ERR "PM: can't read %s time, err %d\n";
0066 static char err_wakealarm [] __initdata =
0067 KERN_ERR "PM: can't set %s wakealarm, err %d\n";
0068 static char err_suspend[] __initdata =
0069 KERN_ERR "PM: suspend test failed, error %d\n";
0070 static char info_test[] __initdata =
0071 KERN_INFO "PM: test RTC wakeup from '%s' suspend\n";
0072
0073 time64_t now;
0074 struct rtc_wkalrm alm;
0075 int status;
0076
0077
0078 repeat:
0079 status = rtc_read_time(rtc, &alm.time);
0080 if (status < 0) {
0081 printk(err_readtime, dev_name(&rtc->dev), status);
0082 return;
0083 }
0084 now = rtc_tm_to_time64(&alm.time);
0085
0086 memset(&alm, 0, sizeof alm);
0087 rtc_time64_to_tm(now + TEST_SUSPEND_SECONDS, &alm.time);
0088 alm.enabled = true;
0089
0090 status = rtc_set_alarm(rtc, &alm);
0091 if (status < 0) {
0092 printk(err_wakealarm, dev_name(&rtc->dev), status);
0093 return;
0094 }
0095
0096 if (state == PM_SUSPEND_MEM) {
0097 printk(info_test, pm_states[state]);
0098 status = pm_suspend(state);
0099 if (status == -ENODEV)
0100 state = PM_SUSPEND_STANDBY;
0101 }
0102 if (state == PM_SUSPEND_STANDBY) {
0103 printk(info_test, pm_states[state]);
0104 status = pm_suspend(state);
0105 if (status < 0)
0106 state = PM_SUSPEND_TO_IDLE;
0107 }
0108 if (state == PM_SUSPEND_TO_IDLE) {
0109 printk(info_test, pm_states[state]);
0110 status = pm_suspend(state);
0111 }
0112
0113 if (status < 0)
0114 printk(err_suspend, status);
0115
0116 test_repeat_count_current++;
0117 if (test_repeat_count_current < test_repeat_count_max)
0118 goto repeat;
0119
0120
0121
0122
0123
0124 alm.enabled = false;
0125 rtc_set_alarm(rtc, &alm);
0126 }
0127
0128 static int __init has_wakealarm(struct device *dev, const void *data)
0129 {
0130 struct rtc_device *candidate = to_rtc_device(dev);
0131
0132 if (!test_bit(RTC_FEATURE_ALARM, candidate->features))
0133 return 0;
0134 if (!device_may_wakeup(candidate->dev.parent))
0135 return 0;
0136
0137 return 1;
0138 }
0139
0140
0141
0142
0143
0144
0145 static const char *test_state_label __initdata;
0146
0147 static char warn_bad_state[] __initdata =
0148 KERN_WARNING "PM: can't test '%s' suspend state\n";
0149
0150 static int __init setup_test_suspend(char *value)
0151 {
0152 int i;
0153 char *repeat;
0154 char *suspend_type;
0155
0156
0157 value++;
0158 suspend_type = strsep(&value, ",");
0159 if (!suspend_type)
0160 return 1;
0161
0162 repeat = strsep(&value, ",");
0163 if (repeat) {
0164 if (kstrtou32(repeat, 0, &test_repeat_count_max))
0165 return 1;
0166 }
0167
0168 for (i = PM_SUSPEND_MIN; i < PM_SUSPEND_MAX; i++)
0169 if (!strcmp(pm_labels[i], suspend_type)) {
0170 test_state_label = pm_labels[i];
0171 return 1;
0172 }
0173
0174 printk(warn_bad_state, suspend_type);
0175 return 1;
0176 }
0177 __setup("test_suspend", setup_test_suspend);
0178
0179 static int __init test_suspend(void)
0180 {
0181 static char warn_no_rtc[] __initdata =
0182 KERN_WARNING "PM: no wakealarm-capable RTC driver is ready\n";
0183
0184 struct rtc_device *rtc = NULL;
0185 struct device *dev;
0186 suspend_state_t test_state;
0187
0188
0189 if (!test_state_label)
0190 return 0;
0191
0192 for (test_state = PM_SUSPEND_MIN; test_state < PM_SUSPEND_MAX; test_state++) {
0193 const char *state_label = pm_states[test_state];
0194
0195 if (state_label && !strcmp(test_state_label, state_label))
0196 break;
0197 }
0198 if (test_state == PM_SUSPEND_MAX) {
0199 printk(warn_bad_state, test_state_label);
0200 return 0;
0201 }
0202
0203
0204 dev = class_find_device(rtc_class, NULL, NULL, has_wakealarm);
0205 if (dev) {
0206 rtc = rtc_class_open(dev_name(dev));
0207 put_device(dev);
0208 }
0209 if (!rtc) {
0210 printk(warn_no_rtc);
0211 return 0;
0212 }
0213
0214
0215 test_wakealarm(rtc, test_state);
0216 rtc_class_close(rtc);
0217 return 0;
0218 }
0219 late_initcall(test_suspend);