LCOV - code coverage report
Current view: top level - kernel/power - main.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 28 158 17.7 %
Date: 2023-07-19 18:55:55 Functions: 6 42 14.3 %

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

Generated by: LCOV version 1.14