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

Generated by: LCOV version 1.14