Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * kernel/power/suspend_test.c - Suspend to RAM and standby test facility.
0004  *
0005  * Copyright (c) 2009 Pavel Machek <pavel@ucw.cz>
0006  */
0007 
0008 #include <linux/init.h>
0009 #include <linux/rtc.h>
0010 
0011 #include "power.h"
0012 
0013 /*
0014  * We test the system suspend code by setting an RTC wakealarm a short
0015  * time in the future, then suspending.  Suspending the devices won't
0016  * normally take long ... some systems only need a few milliseconds.
0017  *
0018  * The time it takes is system-specific though, so when we test this
0019  * during system bootup we allow a LOT of time.
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     /* FIXME Use better timebase than "jiffies", ideally a clocksource.
0030      * What we want is a hardware counter that will work correctly even
0031      * during the irqs-are-off stages of the suspend/resume cycle...
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     /* Warning on suspend means the RTC alarm period needs to be
0046      * larger -- the system was sooo slooowwww to suspend that the
0047      * alarm (should have) fired before the system went to sleep!
0048      *
0049      * Warning on either suspend or resume also means the system
0050      * has some performance issues.  The stack dump of a WARN_ON
0051      * is more likely to get the right attention than a printk...
0052      */
0053     WARN(msec > (TEST_SUSPEND_SECONDS * 1000),
0054          "Component: %s, time: %u\n", label, msec);
0055 }
0056 
0057 /*
0058  * To test system suspend, we need a hands-off mechanism to resume the
0059  * system.  RTCs wake alarms are a common self-contained mechanism.
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     /* this may fail if the RTC hasn't been initialized */
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     /* Some platforms can't detect that the alarm triggered the
0121      * wakeup, or (accordingly) disable it after it afterwards.
0122      * It's supposed to give oneshot behavior; cope.
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  * Kernel options like "test_suspend=mem" force suspend/resume sanity tests
0142  * at startup time.  They're normally disabled, for faster boot and because
0143  * we can't know which states really work on this particular system.
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     /* example : "=mem[,N]" ==> "mem[,N]" */
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     /* PM is initialized by now; is that state testable? */
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     /* RTCs have initialized by now too ... can we use one? */
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     /* go for it */
0215     test_wakealarm(rtc, test_state);
0216     rtc_class_close(rtc);
0217     return 0;
0218 }
0219 late_initcall(test_suspend);