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