Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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);