hc
2023-12-08 01573e231f18eb2d99162747186f59511f56b64d
kernel/kernel/power/main.c
....@@ -1,11 +1,9 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * kernel/power/main.c - PM subsystem core functionality.
34 *
45 * Copyright (c) 2003 Patrick Mochel
56 * Copyright (c) 2003 Open Source Development Lab
6
- *
7
- * This file is released under the GPLv2
8
- *
97 */
108
119 #include <linux/export.h>
....@@ -16,6 +14,8 @@
1614 #include <linux/debugfs.h>
1715 #include <linux/seq_file.h>
1816 #include <linux/suspend.h>
17
+#include <linux/syscalls.h>
18
+#include <linux/pm_runtime.h>
1919
2020 #include "power.h"
2121
....@@ -51,6 +51,19 @@
5151 }
5252 EXPORT_SYMBOL_GPL(unlock_system_sleep);
5353
54
+void ksys_sync_helper(void)
55
+{
56
+ ktime_t start;
57
+ long elapsed_msecs;
58
+
59
+ start = ktime_get();
60
+ ksys_sync();
61
+ elapsed_msecs = ktime_to_ms(ktime_sub(ktime_get(), start));
62
+ pr_info("Filesystems sync: %ld.%03ld seconds\n",
63
+ elapsed_msecs / MSEC_PER_SEC, elapsed_msecs % MSEC_PER_SEC);
64
+}
65
+EXPORT_SYMBOL_GPL(ksys_sync_helper);
66
+
5467 /* Routines for PM-transition notifications */
5568
5669 static BLOCKING_NOTIFIER_HEAD(pm_chain_head);
....@@ -67,18 +80,18 @@
6780 }
6881 EXPORT_SYMBOL_GPL(unregister_pm_notifier);
6982
70
-int __pm_notifier_call_chain(unsigned long val, int nr_to_call, int *nr_calls)
83
+int pm_notifier_call_chain_robust(unsigned long val_up, unsigned long val_down)
7184 {
7285 int ret;
7386
74
- ret = __blocking_notifier_call_chain(&pm_chain_head, val, NULL,
75
- nr_to_call, nr_calls);
87
+ ret = blocking_notifier_call_chain_robust(&pm_chain_head, val_up, val_down, NULL);
7688
7789 return notifier_to_errno(ret);
7890 }
91
+
7992 int pm_notifier_call_chain(unsigned long val)
8093 {
81
- return __pm_notifier_call_chain(val, -1, NULL);
94
+ return blocking_notifier_call_chain(&pm_chain_head, val, NULL);
8295 }
8396
8497 /* If set, devices may be suspended and resumed asynchronously. */
....@@ -177,6 +190,38 @@
177190 }
178191
179192 power_attr(mem_sleep);
193
+
194
+/*
195
+ * sync_on_suspend: invoke ksys_sync_helper() before suspend.
196
+ *
197
+ * show() returns whether ksys_sync_helper() is invoked before suspend.
198
+ * store() accepts 0 or 1. 0 disables ksys_sync_helper() and 1 enables it.
199
+ */
200
+bool sync_on_suspend_enabled = !IS_ENABLED(CONFIG_SUSPEND_SKIP_SYNC);
201
+
202
+static ssize_t sync_on_suspend_show(struct kobject *kobj,
203
+ struct kobj_attribute *attr, char *buf)
204
+{
205
+ return sprintf(buf, "%d\n", sync_on_suspend_enabled);
206
+}
207
+
208
+static ssize_t sync_on_suspend_store(struct kobject *kobj,
209
+ struct kobj_attribute *attr,
210
+ const char *buf, size_t n)
211
+{
212
+ unsigned long val;
213
+
214
+ if (kstrtoul(buf, 10, &val))
215
+ return -EINVAL;
216
+
217
+ if (val > 1)
218
+ return -EINVAL;
219
+
220
+ sync_on_suspend_enabled = !!val;
221
+ return n;
222
+}
223
+
224
+power_attr(sync_on_suspend);
180225 #endif /* CONFIG_SUSPEND */
181226
182227 #ifdef CONFIG_PM_SLEEP_DEBUG
....@@ -403,23 +448,12 @@
403448
404449 return 0;
405450 }
406
-
407
-static int suspend_stats_open(struct inode *inode, struct file *file)
408
-{
409
- return single_open(file, suspend_stats_show, NULL);
410
-}
411
-
412
-static const struct file_operations suspend_stats_operations = {
413
- .open = suspend_stats_open,
414
- .read = seq_read,
415
- .llseek = seq_lseek,
416
- .release = single_release,
417
-};
451
+DEFINE_SHOW_ATTRIBUTE(suspend_stats);
418452
419453 static int __init pm_debugfs_init(void)
420454 {
421455 debugfs_create_file("suspend_stats", S_IFREG | S_IRUGO,
422
- NULL, NULL, &suspend_stats_operations);
456
+ NULL, NULL, &suspend_stats_fops);
423457 return 0;
424458 }
425459
....@@ -470,7 +504,10 @@
470504 struct kobj_attribute *attr,
471505 char *buf)
472506 {
473
- return pm_wakeup_irq ? sprintf(buf, "%u\n", pm_wakeup_irq) : -ENODATA;
507
+ if (!pm_wakeup_irq())
508
+ return -ENODATA;
509
+
510
+ return sprintf(buf, "%u\n", pm_wakeup_irq());
474511 }
475512
476513 power_attr_ro(pm_wakeup_irq);
....@@ -500,6 +537,13 @@
500537 }
501538
502539 power_attr(pm_debug_messages);
540
+
541
+static int __init pm_debug_messages_setup(char *str)
542
+{
543
+ pm_debug_messages_on = true;
544
+ return 1;
545
+}
546
+__setup("pm_debug_messages", pm_debug_messages_setup);
503547
504548 /**
505549 * __pm_pr_dbg - Print a suspend debug message to the kernel log.
....@@ -535,7 +579,6 @@
535579 #endif /* CONFIG_PM_SLEEP_DEBUG */
536580
537581 struct kobject *power_kobj;
538
-EXPORT_SYMBOL_GPL(power_kobj);
539582
540583 /**
541584 * state - control system sleep states.
....@@ -580,7 +623,7 @@
580623 len = p ? p - buf : n;
581624
582625 /* Check hibernation first. */
583
- if (len == 4 && !strncmp(buf, "disk", len))
626
+ if (len == 4 && str_has_prefix(buf, "disk"))
584627 return PM_SUSPEND_MAX;
585628
586629 #ifdef CONFIG_SUSPEND
....@@ -854,6 +897,7 @@
854897 &wakeup_count_attr.attr,
855898 #ifdef CONFIG_SUSPEND
856899 &mem_sleep_attr.attr,
900
+ &sync_on_suspend_attr.attr,
857901 #endif
858902 #ifdef CONFIG_PM_AUTOSLEEP
859903 &autosleep_attr.attr,