LCOV - code coverage report
Current view: top level - kernel/power - main.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 22 142 15.5 %
Date: 2022-12-09 01:23:36 Functions: 5 36 13.9 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-only
       2             : /*
       3             :  * kernel/power/main.c - PM subsystem core functionality.
       4             :  *
       5             :  * Copyright (c) 2003 Patrick Mochel
       6             :  * Copyright (c) 2003 Open Source Development Lab
       7             :  */
       8             : 
       9             : #include <linux/export.h>
      10             : #include <linux/kobject.h>
      11             : #include <linux/string.h>
      12             : #include <linux/pm-trace.h>
      13             : #include <linux/workqueue.h>
      14             : #include <linux/debugfs.h>
      15             : #include <linux/seq_file.h>
      16             : #include <linux/suspend.h>
      17             : #include <linux/syscalls.h>
      18             : #include <linux/pm_runtime.h>
      19             : 
      20             : #include "power.h"
      21             : 
      22             : #ifdef CONFIG_PM_SLEEP
      23             : 
      24           1 : void lock_system_sleep(void)
      25             : {
      26           1 :         current->flags |= PF_FREEZER_SKIP;
      27           1 :         mutex_lock(&system_transition_mutex);
      28           1 : }
      29             : EXPORT_SYMBOL_GPL(lock_system_sleep);
      30             : 
      31           1 : void unlock_system_sleep(void)
      32             : {
      33             :         /*
      34             :          * Don't use freezer_count() because we don't want the call to
      35             :          * try_to_freeze() here.
      36             :          *
      37             :          * Reason:
      38             :          * Fundamentally, we just don't need it, because freezing condition
      39             :          * doesn't come into effect until we release the
      40             :          * system_transition_mutex lock, since the freezer always works with
      41             :          * system_transition_mutex held.
      42             :          *
      43             :          * More importantly, in the case of hibernation,
      44             :          * unlock_system_sleep() gets called in snapshot_read() and
      45             :          * snapshot_write() when the freezing condition is still in effect.
      46             :          * Which means, if we use try_to_freeze() here, it would make them
      47             :          * enter the refrigerator, thus causing hibernation to lockup.
      48             :          */
      49           1 :         current->flags &= ~PF_FREEZER_SKIP;
      50           1 :         mutex_unlock(&system_transition_mutex);
      51           1 : }
      52             : EXPORT_SYMBOL_GPL(unlock_system_sleep);
      53             : 
      54           0 : void ksys_sync_helper(void)
      55             : {
      56             :         ktime_t start;
      57             :         long elapsed_msecs;
      58             : 
      59           0 :         start = ktime_get();
      60           0 :         ksys_sync();
      61           0 :         elapsed_msecs = ktime_to_ms(ktime_sub(ktime_get(), start));
      62           0 :         pr_info("Filesystems sync: %ld.%03ld seconds\n",
      63             :                 elapsed_msecs / MSEC_PER_SEC, elapsed_msecs % MSEC_PER_SEC);
      64           0 : }
      65             : EXPORT_SYMBOL_GPL(ksys_sync_helper);
      66             : 
      67             : /* Routines for PM-transition notifications */
      68             : 
      69             : static BLOCKING_NOTIFIER_HEAD(pm_chain_head);
      70             : 
      71           1 : int register_pm_notifier(struct notifier_block *nb)
      72             : {
      73           1 :         return blocking_notifier_chain_register(&pm_chain_head, nb);
      74             : }
      75             : EXPORT_SYMBOL_GPL(register_pm_notifier);
      76             : 
      77           0 : int unregister_pm_notifier(struct notifier_block *nb)
      78             : {
      79           0 :         return blocking_notifier_chain_unregister(&pm_chain_head, nb);
      80             : }
      81             : EXPORT_SYMBOL_GPL(unregister_pm_notifier);
      82             : 
      83           0 : int pm_notifier_call_chain_robust(unsigned long val_up, unsigned long val_down)
      84             : {
      85             :         int ret;
      86             : 
      87           0 :         ret = blocking_notifier_call_chain_robust(&pm_chain_head, val_up, val_down, NULL);
      88             : 
      89           0 :         return notifier_to_errno(ret);
      90             : }
      91             : 
      92           0 : int pm_notifier_call_chain(unsigned long val)
      93             : {
      94           0 :         return blocking_notifier_call_chain(&pm_chain_head, val, NULL);
      95             : }
      96             : 
      97             : /* If set, devices may be suspended and resumed asynchronously. */
      98             : int pm_async_enabled = 1;
      99             : 
     100           0 : static ssize_t pm_async_show(struct kobject *kobj, struct kobj_attribute *attr,
     101             :                              char *buf)
     102             : {
     103           0 :         return sprintf(buf, "%d\n", pm_async_enabled);
     104             : }
     105             : 
     106           0 : static ssize_t pm_async_store(struct kobject *kobj, struct kobj_attribute *attr,
     107             :                               const char *buf, size_t n)
     108             : {
     109             :         unsigned long val;
     110             : 
     111           0 :         if (kstrtoul(buf, 10, &val))
     112             :                 return -EINVAL;
     113             : 
     114           0 :         if (val > 1)
     115             :                 return -EINVAL;
     116             : 
     117           0 :         pm_async_enabled = val;
     118           0 :         return n;
     119             : }
     120             : 
     121             : power_attr(pm_async);
     122             : 
     123             : #ifdef CONFIG_SUSPEND
     124           0 : static ssize_t mem_sleep_show(struct kobject *kobj, struct kobj_attribute *attr,
     125             :                               char *buf)
     126             : {
     127           0 :         char *s = buf;
     128             :         suspend_state_t i;
     129             : 
     130           0 :         for (i = PM_SUSPEND_MIN; i < PM_SUSPEND_MAX; i++)
     131           0 :                 if (mem_sleep_states[i]) {
     132           0 :                         const char *label = mem_sleep_states[i];
     133             : 
     134           0 :                         if (mem_sleep_current == i)
     135           0 :                                 s += sprintf(s, "[%s] ", label);
     136             :                         else
     137           0 :                                 s += sprintf(s, "%s ", label);
     138             :                 }
     139             : 
     140             :         /* Convert the last space to a newline if needed. */
     141           0 :         if (s != buf)
     142           0 :                 *(s-1) = '\n';
     143             : 
     144           0 :         return (s - buf);
     145             : }
     146             : 
     147           0 : static suspend_state_t decode_suspend_state(const char *buf, size_t n)
     148             : {
     149             :         suspend_state_t state;
     150             :         char *p;
     151             :         int len;
     152             : 
     153           0 :         p = memchr(buf, '\n', n);
     154           0 :         len = p ? p - buf : n;
     155             : 
     156           0 :         for (state = PM_SUSPEND_MIN; state < PM_SUSPEND_MAX; state++) {
     157           0 :                 const char *label = mem_sleep_states[state];
     158             : 
     159           0 :                 if (label && len == strlen(label) && !strncmp(buf, label, len))
     160             :                         return state;
     161             :         }
     162             : 
     163             :         return PM_SUSPEND_ON;
     164             : }
     165             : 
     166           0 : static ssize_t mem_sleep_store(struct kobject *kobj, struct kobj_attribute *attr,
     167             :                                const char *buf, size_t n)
     168             : {
     169             :         suspend_state_t state;
     170             :         int error;
     171             : 
     172           0 :         error = pm_autosleep_lock();
     173             :         if (error)
     174             :                 return error;
     175             : 
     176             :         if (pm_autosleep_state() > PM_SUSPEND_ON) {
     177             :                 error = -EBUSY;
     178             :                 goto out;
     179             :         }
     180             : 
     181           0 :         state = decode_suspend_state(buf, n);
     182           0 :         if (state < PM_SUSPEND_MAX && state > PM_SUSPEND_ON)
     183           0 :                 mem_sleep_current = state;
     184             :         else
     185             :                 error = -EINVAL;
     186             : 
     187             :  out:
     188             :         pm_autosleep_unlock();
     189           0 :         return error ? error : n;
     190             : }
     191             : 
     192             : power_attr(mem_sleep);
     193             : 
     194             : /*
     195             :  * sync_on_suspend: invoke ksys_sync_helper() before suspend.
     196             :  *
     197             :  * show() returns whether ksys_sync_helper() is invoked before suspend.
     198             :  * store() accepts 0 or 1.  0 disables ksys_sync_helper() and 1 enables it.
     199             :  */
     200             : bool sync_on_suspend_enabled = !IS_ENABLED(CONFIG_SUSPEND_SKIP_SYNC);
     201             : 
     202           0 : static ssize_t sync_on_suspend_show(struct kobject *kobj,
     203             :                                    struct kobj_attribute *attr, char *buf)
     204             : {
     205           0 :         return sprintf(buf, "%d\n", sync_on_suspend_enabled);
     206             : }
     207             : 
     208           0 : static ssize_t sync_on_suspend_store(struct kobject *kobj,
     209             :                                     struct kobj_attribute *attr,
     210             :                                     const char *buf, size_t n)
     211             : {
     212             :         unsigned long val;
     213             : 
     214           0 :         if (kstrtoul(buf, 10, &val))
     215             :                 return -EINVAL;
     216             : 
     217           0 :         if (val > 1)
     218             :                 return -EINVAL;
     219             : 
     220           0 :         sync_on_suspend_enabled = !!val;
     221           0 :         return n;
     222             : }
     223             : 
     224             : power_attr(sync_on_suspend);
     225             : #endif /* CONFIG_SUSPEND */
     226             : 
     227             : #ifdef CONFIG_PM_SLEEP_DEBUG
     228             : int pm_test_level = TEST_NONE;
     229             : 
     230             : static const char * const pm_tests[__TEST_AFTER_LAST] = {
     231             :         [TEST_NONE] = "none",
     232             :         [TEST_CORE] = "core",
     233             :         [TEST_CPUS] = "processors",
     234             :         [TEST_PLATFORM] = "platform",
     235             :         [TEST_DEVICES] = "devices",
     236             :         [TEST_FREEZER] = "freezer",
     237             : };
     238             : 
     239             : static ssize_t pm_test_show(struct kobject *kobj, struct kobj_attribute *attr,
     240             :                                 char *buf)
     241             : {
     242             :         char *s = buf;
     243             :         int level;
     244             : 
     245             :         for (level = TEST_FIRST; level <= TEST_MAX; level++)
     246             :                 if (pm_tests[level]) {
     247             :                         if (level == pm_test_level)
     248             :                                 s += sprintf(s, "[%s] ", pm_tests[level]);
     249             :                         else
     250             :                                 s += sprintf(s, "%s ", pm_tests[level]);
     251             :                 }
     252             : 
     253             :         if (s != buf)
     254             :                 /* convert the last space to a newline */
     255             :                 *(s-1) = '\n';
     256             : 
     257             :         return (s - buf);
     258             : }
     259             : 
     260             : static ssize_t pm_test_store(struct kobject *kobj, struct kobj_attribute *attr,
     261             :                                 const char *buf, size_t n)
     262             : {
     263             :         const char * const *s;
     264             :         int level;
     265             :         char *p;
     266             :         int len;
     267             :         int error = -EINVAL;
     268             : 
     269             :         p = memchr(buf, '\n', n);
     270             :         len = p ? p - buf : n;
     271             : 
     272             :         lock_system_sleep();
     273             : 
     274             :         level = TEST_FIRST;
     275             :         for (s = &pm_tests[level]; level <= TEST_MAX; s++, level++)
     276             :                 if (*s && len == strlen(*s) && !strncmp(buf, *s, len)) {
     277             :                         pm_test_level = level;
     278             :                         error = 0;
     279             :                         break;
     280             :                 }
     281             : 
     282             :         unlock_system_sleep();
     283             : 
     284             :         return error ? error : n;
     285             : }
     286             : 
     287             : power_attr(pm_test);
     288             : #endif /* CONFIG_PM_SLEEP_DEBUG */
     289             : 
     290             : static char *suspend_step_name(enum suspend_stat_step step)
     291             : {
     292             :         switch (step) {
     293             :         case SUSPEND_FREEZE:
     294             :                 return "freeze";
     295             :         case SUSPEND_PREPARE:
     296             :                 return "prepare";
     297             :         case SUSPEND_SUSPEND:
     298             :                 return "suspend";
     299             :         case SUSPEND_SUSPEND_NOIRQ:
     300             :                 return "suspend_noirq";
     301             :         case SUSPEND_RESUME_NOIRQ:
     302             :                 return "resume_noirq";
     303             :         case SUSPEND_RESUME:
     304             :                 return "resume";
     305             :         default:
     306             :                 return "";
     307             :         }
     308             : }
     309             : 
     310             : #define suspend_attr(_name)                                     \
     311             : static ssize_t _name##_show(struct kobject *kobj,               \
     312             :                 struct kobj_attribute *attr, char *buf)         \
     313             : {                                                               \
     314             :         return sprintf(buf, "%d\n", suspend_stats._name);     \
     315             : }                                                               \
     316             : static struct kobj_attribute _name = __ATTR_RO(_name)
     317             : 
     318           0 : suspend_attr(success);
     319           0 : suspend_attr(fail);
     320           0 : suspend_attr(failed_freeze);
     321           0 : suspend_attr(failed_prepare);
     322           0 : suspend_attr(failed_suspend);
     323           0 : suspend_attr(failed_suspend_late);
     324           0 : suspend_attr(failed_suspend_noirq);
     325           0 : suspend_attr(failed_resume);
     326           0 : suspend_attr(failed_resume_early);
     327           0 : suspend_attr(failed_resume_noirq);
     328             : 
     329           0 : static ssize_t last_failed_dev_show(struct kobject *kobj,
     330             :                 struct kobj_attribute *attr, char *buf)
     331             : {
     332             :         int index;
     333           0 :         char *last_failed_dev = NULL;
     334             : 
     335           0 :         index = suspend_stats.last_failed_dev + REC_FAILED_NUM - 1;
     336           0 :         index %= REC_FAILED_NUM;
     337           0 :         last_failed_dev = suspend_stats.failed_devs[index];
     338             : 
     339           0 :         return sprintf(buf, "%s\n", last_failed_dev);
     340             : }
     341             : static struct kobj_attribute last_failed_dev = __ATTR_RO(last_failed_dev);
     342             : 
     343           0 : static ssize_t last_failed_errno_show(struct kobject *kobj,
     344             :                 struct kobj_attribute *attr, char *buf)
     345             : {
     346             :         int index;
     347             :         int last_failed_errno;
     348             : 
     349           0 :         index = suspend_stats.last_failed_errno + REC_FAILED_NUM - 1;
     350           0 :         index %= REC_FAILED_NUM;
     351           0 :         last_failed_errno = suspend_stats.errno[index];
     352             : 
     353           0 :         return sprintf(buf, "%d\n", last_failed_errno);
     354             : }
     355             : static struct kobj_attribute last_failed_errno = __ATTR_RO(last_failed_errno);
     356             : 
     357           0 : static ssize_t last_failed_step_show(struct kobject *kobj,
     358             :                 struct kobj_attribute *attr, char *buf)
     359             : {
     360             :         int index;
     361             :         enum suspend_stat_step step;
     362           0 :         char *last_failed_step = NULL;
     363             : 
     364           0 :         index = suspend_stats.last_failed_step + REC_FAILED_NUM - 1;
     365           0 :         index %= REC_FAILED_NUM;
     366           0 :         step = suspend_stats.failed_steps[index];
     367           0 :         last_failed_step = suspend_step_name(step);
     368             : 
     369           0 :         return sprintf(buf, "%s\n", last_failed_step);
     370             : }
     371             : static struct kobj_attribute last_failed_step = __ATTR_RO(last_failed_step);
     372             : 
     373             : static struct attribute *suspend_attrs[] = {
     374             :         &success.attr,
     375             :         &fail.attr,
     376             :         &failed_freeze.attr,
     377             :         &failed_prepare.attr,
     378             :         &failed_suspend.attr,
     379             :         &failed_suspend_late.attr,
     380             :         &failed_suspend_noirq.attr,
     381             :         &failed_resume.attr,
     382             :         &failed_resume_early.attr,
     383             :         &failed_resume_noirq.attr,
     384             :         &last_failed_dev.attr,
     385             :         &last_failed_errno.attr,
     386             :         &last_failed_step.attr,
     387             :         NULL,
     388             : };
     389             : 
     390             : static const struct attribute_group suspend_attr_group = {
     391             :         .name = "suspend_stats",
     392             :         .attrs = suspend_attrs,
     393             : };
     394             : 
     395             : #ifdef CONFIG_DEBUG_FS
     396             : static int suspend_stats_show(struct seq_file *s, void *unused)
     397             : {
     398             :         int i, index, last_dev, last_errno, last_step;
     399             : 
     400             :         last_dev = suspend_stats.last_failed_dev + REC_FAILED_NUM - 1;
     401             :         last_dev %= REC_FAILED_NUM;
     402             :         last_errno = suspend_stats.last_failed_errno + REC_FAILED_NUM - 1;
     403             :         last_errno %= REC_FAILED_NUM;
     404             :         last_step = suspend_stats.last_failed_step + REC_FAILED_NUM - 1;
     405             :         last_step %= REC_FAILED_NUM;
     406             :         seq_printf(s, "%s: %d\n%s: %d\n%s: %d\n%s: %d\n%s: %d\n"
     407             :                         "%s: %d\n%s: %d\n%s: %d\n%s: %d\n%s: %d\n",
     408             :                         "success", suspend_stats.success,
     409             :                         "fail", suspend_stats.fail,
     410             :                         "failed_freeze", suspend_stats.failed_freeze,
     411             :                         "failed_prepare", suspend_stats.failed_prepare,
     412             :                         "failed_suspend", suspend_stats.failed_suspend,
     413             :                         "failed_suspend_late",
     414             :                                 suspend_stats.failed_suspend_late,
     415             :                         "failed_suspend_noirq",
     416             :                                 suspend_stats.failed_suspend_noirq,
     417             :                         "failed_resume", suspend_stats.failed_resume,
     418             :                         "failed_resume_early",
     419             :                                 suspend_stats.failed_resume_early,
     420             :                         "failed_resume_noirq",
     421             :                                 suspend_stats.failed_resume_noirq);
     422             :         seq_printf(s,   "failures:\n  last_failed_dev:\t%-s\n",
     423             :                         suspend_stats.failed_devs[last_dev]);
     424             :         for (i = 1; i < REC_FAILED_NUM; i++) {
     425             :                 index = last_dev + REC_FAILED_NUM - i;
     426             :                 index %= REC_FAILED_NUM;
     427             :                 seq_printf(s, "\t\t\t%-s\n",
     428             :                         suspend_stats.failed_devs[index]);
     429             :         }
     430             :         seq_printf(s,   "  last_failed_errno:\t%-d\n",
     431             :                         suspend_stats.errno[last_errno]);
     432             :         for (i = 1; i < REC_FAILED_NUM; i++) {
     433             :                 index = last_errno + REC_FAILED_NUM - i;
     434             :                 index %= REC_FAILED_NUM;
     435             :                 seq_printf(s, "\t\t\t%-d\n",
     436             :                         suspend_stats.errno[index]);
     437             :         }
     438             :         seq_printf(s,   "  last_failed_step:\t%-s\n",
     439             :                         suspend_step_name(
     440             :                                 suspend_stats.failed_steps[last_step]));
     441             :         for (i = 1; i < REC_FAILED_NUM; i++) {
     442             :                 index = last_step + REC_FAILED_NUM - i;
     443             :                 index %= REC_FAILED_NUM;
     444             :                 seq_printf(s, "\t\t\t%-s\n",
     445             :                         suspend_step_name(
     446             :                                 suspend_stats.failed_steps[index]));
     447             :         }
     448             : 
     449             :         return 0;
     450             : }
     451             : DEFINE_SHOW_ATTRIBUTE(suspend_stats);
     452             : 
     453             : static int __init pm_debugfs_init(void)
     454             : {
     455             :         debugfs_create_file("suspend_stats", S_IFREG | S_IRUGO,
     456             :                         NULL, NULL, &suspend_stats_fops);
     457             :         return 0;
     458             : }
     459             : 
     460             : late_initcall(pm_debugfs_init);
     461             : #endif /* CONFIG_DEBUG_FS */
     462             : 
     463             : #endif /* CONFIG_PM_SLEEP */
     464             : 
     465             : #ifdef CONFIG_PM_SLEEP_DEBUG
     466             : /*
     467             :  * pm_print_times: print time taken by devices to suspend and resume.
     468             :  *
     469             :  * show() returns whether printing of suspend and resume times is enabled.
     470             :  * store() accepts 0 or 1.  0 disables printing and 1 enables it.
     471             :  */
     472             : bool pm_print_times_enabled;
     473             : 
     474             : static ssize_t pm_print_times_show(struct kobject *kobj,
     475             :                                    struct kobj_attribute *attr, char *buf)
     476             : {
     477             :         return sprintf(buf, "%d\n", pm_print_times_enabled);
     478             : }
     479             : 
     480             : static ssize_t pm_print_times_store(struct kobject *kobj,
     481             :                                     struct kobj_attribute *attr,
     482             :                                     const char *buf, size_t n)
     483             : {
     484             :         unsigned long val;
     485             : 
     486             :         if (kstrtoul(buf, 10, &val))
     487             :                 return -EINVAL;
     488             : 
     489             :         if (val > 1)
     490             :                 return -EINVAL;
     491             : 
     492             :         pm_print_times_enabled = !!val;
     493             :         return n;
     494             : }
     495             : 
     496             : power_attr(pm_print_times);
     497             : 
     498             : static inline void pm_print_times_init(void)
     499             : {
     500             :         pm_print_times_enabled = !!initcall_debug;
     501             : }
     502             : 
     503             : static ssize_t pm_wakeup_irq_show(struct kobject *kobj,
     504             :                                         struct kobj_attribute *attr,
     505             :                                         char *buf)
     506             : {
     507             :         if (!pm_wakeup_irq())
     508             :                 return -ENODATA;
     509             : 
     510             :         return sprintf(buf, "%u\n", pm_wakeup_irq());
     511             : }
     512             : 
     513             : power_attr_ro(pm_wakeup_irq);
     514             : 
     515             : bool pm_debug_messages_on __read_mostly;
     516             : 
     517             : static ssize_t pm_debug_messages_show(struct kobject *kobj,
     518             :                                       struct kobj_attribute *attr, char *buf)
     519             : {
     520             :         return sprintf(buf, "%d\n", pm_debug_messages_on);
     521             : }
     522             : 
     523             : static ssize_t pm_debug_messages_store(struct kobject *kobj,
     524             :                                        struct kobj_attribute *attr,
     525             :                                        const char *buf, size_t n)
     526             : {
     527             :         unsigned long val;
     528             : 
     529             :         if (kstrtoul(buf, 10, &val))
     530             :                 return -EINVAL;
     531             : 
     532             :         if (val > 1)
     533             :                 return -EINVAL;
     534             : 
     535             :         pm_debug_messages_on = !!val;
     536             :         return n;
     537             : }
     538             : 
     539             : power_attr(pm_debug_messages);
     540             : 
     541             : static int __init pm_debug_messages_setup(char *str)
     542             : {
     543             :         pm_debug_messages_on = true;
     544             :         return 1;
     545             : }
     546             : __setup("pm_debug_messages", pm_debug_messages_setup);
     547             : 
     548             : /**
     549             :  * __pm_pr_dbg - Print a suspend debug message to the kernel log.
     550             :  * @defer: Whether or not to use printk_deferred() to print the message.
     551             :  * @fmt: Message format.
     552             :  *
     553             :  * The message will be emitted if enabled through the pm_debug_messages
     554             :  * sysfs attribute.
     555             :  */
     556             : void __pm_pr_dbg(bool defer, const char *fmt, ...)
     557             : {
     558             :         struct va_format vaf;
     559             :         va_list args;
     560             : 
     561             :         if (!pm_debug_messages_on)
     562             :                 return;
     563             : 
     564             :         va_start(args, fmt);
     565             : 
     566             :         vaf.fmt = fmt;
     567             :         vaf.va = &args;
     568             : 
     569             :         if (defer)
     570             :                 printk_deferred(KERN_DEBUG "PM: %pV", &vaf);
     571             :         else
     572             :                 printk(KERN_DEBUG "PM: %pV", &vaf);
     573             : 
     574             :         va_end(args);
     575             : }
     576             : 
     577             : #else /* !CONFIG_PM_SLEEP_DEBUG */
     578             : static inline void pm_print_times_init(void) {}
     579             : #endif /* CONFIG_PM_SLEEP_DEBUG */
     580             : 
     581             : struct kobject *power_kobj;
     582             : 
     583             : /*
     584             :  * state - control system sleep states.
     585             :  *
     586             :  * show() returns available sleep state labels, which may be "mem", "standby",
     587             :  * "freeze" and "disk" (hibernation).
     588             :  * See Documentation/admin-guide/pm/sleep-states.rst for a description of
     589             :  * what they mean.
     590             :  *
     591             :  * store() accepts one of those strings, translates it into the proper
     592             :  * enumerated value, and initiates a suspend transition.
     593             :  */
     594           0 : static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr,
     595             :                           char *buf)
     596             : {
     597           0 :         char *s = buf;
     598             : #ifdef CONFIG_SUSPEND
     599             :         suspend_state_t i;
     600             : 
     601           0 :         for (i = PM_SUSPEND_MIN; i < PM_SUSPEND_MAX; i++)
     602           0 :                 if (pm_states[i])
     603           0 :                         s += sprintf(s,"%s ", pm_states[i]);
     604             : 
     605             : #endif
     606             :         if (hibernation_available())
     607             :                 s += sprintf(s, "disk ");
     608           0 :         if (s != buf)
     609             :                 /* convert the last space to a newline */
     610           0 :                 *(s-1) = '\n';
     611           0 :         return (s - buf);
     612             : }
     613             : 
     614           0 : static suspend_state_t decode_state(const char *buf, size_t n)
     615             : {
     616             : #ifdef CONFIG_SUSPEND
     617             :         suspend_state_t state;
     618             : #endif
     619             :         char *p;
     620             :         int len;
     621             : 
     622           0 :         p = memchr(buf, '\n', n);
     623           0 :         len = p ? p - buf : n;
     624             : 
     625             :         /* Check hibernation first. */
     626           0 :         if (len == 4 && str_has_prefix(buf, "disk"))
     627             :                 return PM_SUSPEND_MAX;
     628             : 
     629             : #ifdef CONFIG_SUSPEND
     630           0 :         for (state = PM_SUSPEND_MIN; state < PM_SUSPEND_MAX; state++) {
     631           0 :                 const char *label = pm_states[state];
     632             : 
     633           0 :                 if (label && len == strlen(label) && !strncmp(buf, label, len))
     634             :                         return state;
     635             :         }
     636             : #endif
     637             : 
     638             :         return PM_SUSPEND_ON;
     639             : }
     640             : 
     641           0 : static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
     642             :                            const char *buf, size_t n)
     643             : {
     644             :         suspend_state_t state;
     645             :         int error;
     646             : 
     647           0 :         error = pm_autosleep_lock();
     648             :         if (error)
     649             :                 return error;
     650             : 
     651             :         if (pm_autosleep_state() > PM_SUSPEND_ON) {
     652             :                 error = -EBUSY;
     653             :                 goto out;
     654             :         }
     655             : 
     656           0 :         state = decode_state(buf, n);
     657           0 :         if (state < PM_SUSPEND_MAX) {
     658           0 :                 if (state == PM_SUSPEND_MEM)
     659           0 :                         state = mem_sleep_current;
     660             : 
     661           0 :                 error = pm_suspend(state);
     662           0 :         } else if (state == PM_SUSPEND_MAX) {
     663             :                 error = hibernate();
     664             :         } else {
     665           0 :                 error = -EINVAL;
     666             :         }
     667             : 
     668             :  out:
     669             :         pm_autosleep_unlock();
     670           0 :         return error ? error : n;
     671             : }
     672             : 
     673             : power_attr(state);
     674             : 
     675             : #ifdef CONFIG_PM_SLEEP
     676             : /*
     677             :  * The 'wakeup_count' attribute, along with the functions defined in
     678             :  * drivers/base/power/wakeup.c, provides a means by which wakeup events can be
     679             :  * handled in a non-racy way.
     680             :  *
     681             :  * If a wakeup event occurs when the system is in a sleep state, it simply is
     682             :  * woken up.  In turn, if an event that would wake the system up from a sleep
     683             :  * state occurs when it is undergoing a transition to that sleep state, the
     684             :  * transition should be aborted.  Moreover, if such an event occurs when the
     685             :  * system is in the working state, an attempt to start a transition to the
     686             :  * given sleep state should fail during certain period after the detection of
     687             :  * the event.  Using the 'state' attribute alone is not sufficient to satisfy
     688             :  * these requirements, because a wakeup event may occur exactly when 'state'
     689             :  * is being written to and may be delivered to user space right before it is
     690             :  * frozen, so the event will remain only partially processed until the system is
     691             :  * woken up by another event.  In particular, it won't cause the transition to
     692             :  * a sleep state to be aborted.
     693             :  *
     694             :  * This difficulty may be overcome if user space uses 'wakeup_count' before
     695             :  * writing to 'state'.  It first should read from 'wakeup_count' and store
     696             :  * the read value.  Then, after carrying out its own preparations for the system
     697             :  * transition to a sleep state, it should write the stored value to
     698             :  * 'wakeup_count'.  If that fails, at least one wakeup event has occurred since
     699             :  * 'wakeup_count' was read and 'state' should not be written to.  Otherwise, it
     700             :  * is allowed to write to 'state', but the transition will be aborted if there
     701             :  * are any wakeup events detected after 'wakeup_count' was written to.
     702             :  */
     703             : 
     704           0 : static ssize_t wakeup_count_show(struct kobject *kobj,
     705             :                                 struct kobj_attribute *attr,
     706             :                                 char *buf)
     707             : {
     708             :         unsigned int val;
     709             : 
     710           0 :         return pm_get_wakeup_count(&val, true) ?
     711           0 :                 sprintf(buf, "%u\n", val) : -EINTR;
     712             : }
     713             : 
     714           0 : static ssize_t wakeup_count_store(struct kobject *kobj,
     715             :                                 struct kobj_attribute *attr,
     716             :                                 const char *buf, size_t n)
     717             : {
     718             :         unsigned int val;
     719             :         int error;
     720             : 
     721           0 :         error = pm_autosleep_lock();
     722             :         if (error)
     723             :                 return error;
     724             : 
     725             :         if (pm_autosleep_state() > PM_SUSPEND_ON) {
     726             :                 error = -EBUSY;
     727             :                 goto out;
     728             :         }
     729             : 
     730           0 :         error = -EINVAL;
     731           0 :         if (sscanf(buf, "%u", &val) == 1) {
     732           0 :                 if (pm_save_wakeup_count(val))
     733           0 :                         error = n;
     734             :                 else
     735           0 :                         pm_print_active_wakeup_sources();
     736             :         }
     737             : 
     738             :  out:
     739             :         pm_autosleep_unlock();
     740           0 :         return error;
     741             : }
     742             : 
     743             : power_attr(wakeup_count);
     744             : 
     745             : #ifdef CONFIG_PM_AUTOSLEEP
     746             : static ssize_t autosleep_show(struct kobject *kobj,
     747             :                               struct kobj_attribute *attr,
     748             :                               char *buf)
     749             : {
     750             :         suspend_state_t state = pm_autosleep_state();
     751             : 
     752             :         if (state == PM_SUSPEND_ON)
     753             :                 return sprintf(buf, "off\n");
     754             : 
     755             : #ifdef CONFIG_SUSPEND
     756             :         if (state < PM_SUSPEND_MAX)
     757             :                 return sprintf(buf, "%s\n", pm_states[state] ?
     758             :                                         pm_states[state] : "error");
     759             : #endif
     760             : #ifdef CONFIG_HIBERNATION
     761             :         return sprintf(buf, "disk\n");
     762             : #else
     763             :         return sprintf(buf, "error");
     764             : #endif
     765             : }
     766             : 
     767             : static ssize_t autosleep_store(struct kobject *kobj,
     768             :                                struct kobj_attribute *attr,
     769             :                                const char *buf, size_t n)
     770             : {
     771             :         suspend_state_t state = decode_state(buf, n);
     772             :         int error;
     773             : 
     774             :         if (state == PM_SUSPEND_ON
     775             :             && strcmp(buf, "off") && strcmp(buf, "off\n"))
     776             :                 return -EINVAL;
     777             : 
     778             :         if (state == PM_SUSPEND_MEM)
     779             :                 state = mem_sleep_current;
     780             : 
     781             :         error = pm_autosleep_set_state(state);
     782             :         return error ? error : n;
     783             : }
     784             : 
     785             : power_attr(autosleep);
     786             : #endif /* CONFIG_PM_AUTOSLEEP */
     787             : 
     788             : #ifdef CONFIG_PM_WAKELOCKS
     789             : static ssize_t wake_lock_show(struct kobject *kobj,
     790             :                               struct kobj_attribute *attr,
     791             :                               char *buf)
     792             : {
     793             :         return pm_show_wakelocks(buf, true);
     794             : }
     795             : 
     796             : static ssize_t wake_lock_store(struct kobject *kobj,
     797             :                                struct kobj_attribute *attr,
     798             :                                const char *buf, size_t n)
     799             : {
     800             :         int error = pm_wake_lock(buf);
     801             :         return error ? error : n;
     802             : }
     803             : 
     804             : power_attr(wake_lock);
     805             : 
     806             : static ssize_t wake_unlock_show(struct kobject *kobj,
     807             :                                 struct kobj_attribute *attr,
     808             :                                 char *buf)
     809             : {
     810             :         return pm_show_wakelocks(buf, false);
     811             : }
     812             : 
     813             : static ssize_t wake_unlock_store(struct kobject *kobj,
     814             :                                  struct kobj_attribute *attr,
     815             :                                  const char *buf, size_t n)
     816             : {
     817             :         int error = pm_wake_unlock(buf);
     818             :         return error ? error : n;
     819             : }
     820             : 
     821             : power_attr(wake_unlock);
     822             : 
     823             : #endif /* CONFIG_PM_WAKELOCKS */
     824             : #endif /* CONFIG_PM_SLEEP */
     825             : 
     826             : #ifdef CONFIG_PM_TRACE
     827             : int pm_trace_enabled;
     828             : 
     829             : static ssize_t pm_trace_show(struct kobject *kobj, struct kobj_attribute *attr,
     830             :                              char *buf)
     831             : {
     832             :         return sprintf(buf, "%d\n", pm_trace_enabled);
     833             : }
     834             : 
     835             : static ssize_t
     836             : pm_trace_store(struct kobject *kobj, struct kobj_attribute *attr,
     837             :                const char *buf, size_t n)
     838             : {
     839             :         int val;
     840             : 
     841             :         if (sscanf(buf, "%d", &val) == 1) {
     842             :                 pm_trace_enabled = !!val;
     843             :                 if (pm_trace_enabled) {
     844             :                         pr_warn("PM: Enabling pm_trace changes system date and time during resume.\n"
     845             :                                 "PM: Correct system time has to be restored manually after resume.\n");
     846             :                 }
     847             :                 return n;
     848             :         }
     849             :         return -EINVAL;
     850             : }
     851             : 
     852             : power_attr(pm_trace);
     853             : 
     854             : static ssize_t pm_trace_dev_match_show(struct kobject *kobj,
     855             :                                        struct kobj_attribute *attr,
     856             :                                        char *buf)
     857             : {
     858             :         return show_trace_dev_match(buf, PAGE_SIZE);
     859             : }
     860             : 
     861             : power_attr_ro(pm_trace_dev_match);
     862             : 
     863             : #endif /* CONFIG_PM_TRACE */
     864             : 
     865             : #ifdef CONFIG_FREEZER
     866           0 : static ssize_t pm_freeze_timeout_show(struct kobject *kobj,
     867             :                                       struct kobj_attribute *attr, char *buf)
     868             : {
     869           0 :         return sprintf(buf, "%u\n", freeze_timeout_msecs);
     870             : }
     871             : 
     872           0 : static ssize_t pm_freeze_timeout_store(struct kobject *kobj,
     873             :                                        struct kobj_attribute *attr,
     874             :                                        const char *buf, size_t n)
     875             : {
     876             :         unsigned long val;
     877             : 
     878           0 :         if (kstrtoul(buf, 10, &val))
     879             :                 return -EINVAL;
     880             : 
     881           0 :         freeze_timeout_msecs = val;
     882           0 :         return n;
     883             : }
     884             : 
     885             : power_attr(pm_freeze_timeout);
     886             : 
     887             : #endif  /* CONFIG_FREEZER*/
     888             : 
     889             : static struct attribute * g[] = {
     890             :         &state_attr.attr,
     891             : #ifdef CONFIG_PM_TRACE
     892             :         &pm_trace_attr.attr,
     893             :         &pm_trace_dev_match_attr.attr,
     894             : #endif
     895             : #ifdef CONFIG_PM_SLEEP
     896             :         &pm_async_attr.attr,
     897             :         &wakeup_count_attr.attr,
     898             : #ifdef CONFIG_SUSPEND
     899             :         &mem_sleep_attr.attr,
     900             :         &sync_on_suspend_attr.attr,
     901             : #endif
     902             : #ifdef CONFIG_PM_AUTOSLEEP
     903             :         &autosleep_attr.attr,
     904             : #endif
     905             : #ifdef CONFIG_PM_WAKELOCKS
     906             :         &wake_lock_attr.attr,
     907             :         &wake_unlock_attr.attr,
     908             : #endif
     909             : #ifdef CONFIG_PM_SLEEP_DEBUG
     910             :         &pm_test_attr.attr,
     911             :         &pm_print_times_attr.attr,
     912             :         &pm_wakeup_irq_attr.attr,
     913             :         &pm_debug_messages_attr.attr,
     914             : #endif
     915             : #endif
     916             : #ifdef CONFIG_FREEZER
     917             :         &pm_freeze_timeout_attr.attr,
     918             : #endif
     919             :         NULL,
     920             : };
     921             : 
     922             : static const struct attribute_group attr_group = {
     923             :         .attrs = g,
     924             : };
     925             : 
     926             : static const struct attribute_group *attr_groups[] = {
     927             :         &attr_group,
     928             : #ifdef CONFIG_PM_SLEEP
     929             :         &suspend_attr_group,
     930             : #endif
     931             :         NULL,
     932             : };
     933             : 
     934             : struct workqueue_struct *pm_wq;
     935             : EXPORT_SYMBOL_GPL(pm_wq);
     936             : 
     937           1 : static int __init pm_start_workqueue(void)
     938             : {
     939           1 :         pm_wq = alloc_workqueue("pm", WQ_FREEZABLE, 0);
     940             : 
     941           1 :         return pm_wq ? 0 : -ENOMEM;
     942             : }
     943             : 
     944           1 : static int __init pm_init(void)
     945             : {
     946           1 :         int error = pm_start_workqueue();
     947           1 :         if (error)
     948             :                 return error;
     949             :         hibernate_image_size_init();
     950             :         hibernate_reserved_size_init();
     951           1 :         pm_states_init();
     952           1 :         power_kobj = kobject_create_and_add("power", NULL);
     953           1 :         if (!power_kobj)
     954             :                 return -ENOMEM;
     955           1 :         error = sysfs_create_groups(power_kobj, attr_groups);
     956           1 :         if (error)
     957             :                 return error;
     958             :         pm_print_times_init();
     959           1 :         return pm_autosleep_init();
     960             : }
     961             : 
     962             : core_initcall(pm_init);

Generated by: LCOV version 1.14