Skip to content

Commit 5950e5d

Browse files
author
Peter Zijlstra
committed
freezer: Have {,un}lock_system_sleep() save/restore flags
Rafael explained that the reason for having both PF_NOFREEZE and PF_FREEZER_SKIP is that {,un}lock_system_sleep() is callable from kthread context that has previously called set_freezable(). In preparation of merging the flags, have {,un}lock_system_slee() save and restore current->flags. Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Link: https://lore.kernel.org/r/20220822114648.725003428@infradead.org
1 parent 0b9d46f commit 5950e5d

7 files changed

Lines changed: 70 additions & 44 deletions

File tree

drivers/acpi/x86/s2idle.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -541,25 +541,29 @@ void acpi_s2idle_setup(void)
541541

542542
int acpi_register_lps0_dev(struct acpi_s2idle_dev_ops *arg)
543543
{
544+
unsigned int sleep_flags;
545+
544546
if (!lps0_device_handle || sleep_no_lps0)
545547
return -ENODEV;
546548

547-
lock_system_sleep();
549+
sleep_flags = lock_system_sleep();
548550
list_add(&arg->list_node, &lps0_s2idle_devops_head);
549-
unlock_system_sleep();
551+
unlock_system_sleep(sleep_flags);
550552

551553
return 0;
552554
}
553555
EXPORT_SYMBOL_GPL(acpi_register_lps0_dev);
554556

555557
void acpi_unregister_lps0_dev(struct acpi_s2idle_dev_ops *arg)
556558
{
559+
unsigned int sleep_flags;
560+
557561
if (!lps0_device_handle || sleep_no_lps0)
558562
return;
559563

560-
lock_system_sleep();
564+
sleep_flags = lock_system_sleep();
561565
list_del(&arg->list_node);
562-
unlock_system_sleep();
566+
unlock_system_sleep(sleep_flags);
563567
}
564568
EXPORT_SYMBOL_GPL(acpi_unregister_lps0_dev);
565569

drivers/scsi/scsi_transport_spi.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -998,16 +998,17 @@ void
998998
spi_dv_device(struct scsi_device *sdev)
999999
{
10001000
struct scsi_target *starget = sdev->sdev_target;
1001-
u8 *buffer;
10021001
const int len = SPI_MAX_ECHO_BUFFER_SIZE*2;
1002+
unsigned int sleep_flags;
1003+
u8 *buffer;
10031004

10041005
/*
10051006
* Because this function and the power management code both call
10061007
* scsi_device_quiesce(), it is not safe to perform domain validation
10071008
* while suspend or resume is in progress. Hence the
10081009
* lock/unlock_system_sleep() calls.
10091010
*/
1010-
lock_system_sleep();
1011+
sleep_flags = lock_system_sleep();
10111012

10121013
if (scsi_autopm_get_device(sdev))
10131014
goto unlock_system_sleep;
@@ -1058,7 +1059,7 @@ spi_dv_device(struct scsi_device *sdev)
10581059
scsi_autopm_put_device(sdev);
10591060

10601061
unlock_system_sleep:
1061-
unlock_system_sleep();
1062+
unlock_system_sleep(sleep_flags);
10621063
}
10631064
EXPORT_SYMBOL(spi_dv_device);
10641065

include/linux/suspend.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -510,8 +510,8 @@ extern bool pm_save_wakeup_count(unsigned int count);
510510
extern void pm_wakep_autosleep_enabled(bool set);
511511
extern void pm_print_active_wakeup_sources(void);
512512

513-
extern void lock_system_sleep(void);
514-
extern void unlock_system_sleep(void);
513+
extern unsigned int lock_system_sleep(void);
514+
extern void unlock_system_sleep(unsigned int);
515515

516516
#else /* !CONFIG_PM_SLEEP */
517517

@@ -534,8 +534,8 @@ static inline void pm_system_wakeup(void) {}
534534
static inline void pm_wakeup_clear(bool reset) {}
535535
static inline void pm_system_irq_wakeup(unsigned int irq_number) {}
536536

537-
static inline void lock_system_sleep(void) {}
538-
static inline void unlock_system_sleep(void) {}
537+
static inline unsigned int lock_system_sleep(void) { return 0; }
538+
static inline void unlock_system_sleep(unsigned int flags) {}
539539

540540
#endif /* !CONFIG_PM_SLEEP */
541541

kernel/power/hibernate.c

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -92,20 +92,24 @@ bool hibernation_available(void)
9292
*/
9393
void hibernation_set_ops(const struct platform_hibernation_ops *ops)
9494
{
95+
unsigned int sleep_flags;
96+
9597
if (ops && !(ops->begin && ops->end && ops->pre_snapshot
9698
&& ops->prepare && ops->finish && ops->enter && ops->pre_restore
9799
&& ops->restore_cleanup && ops->leave)) {
98100
WARN_ON(1);
99101
return;
100102
}
101-
lock_system_sleep();
103+
104+
sleep_flags = lock_system_sleep();
105+
102106
hibernation_ops = ops;
103107
if (ops)
104108
hibernation_mode = HIBERNATION_PLATFORM;
105109
else if (hibernation_mode == HIBERNATION_PLATFORM)
106110
hibernation_mode = HIBERNATION_SHUTDOWN;
107111

108-
unlock_system_sleep();
112+
unlock_system_sleep(sleep_flags);
109113
}
110114
EXPORT_SYMBOL_GPL(hibernation_set_ops);
111115

@@ -713,14 +717,15 @@ static int load_image_and_restore(void)
713717
int hibernate(void)
714718
{
715719
bool snapshot_test = false;
720+
unsigned int sleep_flags;
716721
int error;
717722

718723
if (!hibernation_available()) {
719724
pm_pr_dbg("Hibernation not available.\n");
720725
return -EPERM;
721726
}
722727

723-
lock_system_sleep();
728+
sleep_flags = lock_system_sleep();
724729
/* The snapshot device should not be opened while we're running */
725730
if (!hibernate_acquire()) {
726731
error = -EBUSY;
@@ -794,7 +799,7 @@ int hibernate(void)
794799
pm_restore_console();
795800
hibernate_release();
796801
Unlock:
797-
unlock_system_sleep();
802+
unlock_system_sleep(sleep_flags);
798803
pr_info("hibernation exit\n");
799804

800805
return error;
@@ -809,9 +814,10 @@ int hibernate(void)
809814
*/
810815
int hibernate_quiet_exec(int (*func)(void *data), void *data)
811816
{
817+
unsigned int sleep_flags;
812818
int error;
813819

814-
lock_system_sleep();
820+
sleep_flags = lock_system_sleep();
815821

816822
if (!hibernate_acquire()) {
817823
error = -EBUSY;
@@ -891,7 +897,7 @@ int hibernate_quiet_exec(int (*func)(void *data), void *data)
891897
hibernate_release();
892898

893899
unlock:
894-
unlock_system_sleep();
900+
unlock_system_sleep(sleep_flags);
895901

896902
return error;
897903
}
@@ -1100,19 +1106,20 @@ static ssize_t disk_show(struct kobject *kobj, struct kobj_attribute *attr,
11001106
static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr,
11011107
const char *buf, size_t n)
11021108
{
1109+
int mode = HIBERNATION_INVALID;
1110+
unsigned int sleep_flags;
11031111
int error = 0;
1104-
int i;
11051112
int len;
11061113
char *p;
1107-
int mode = HIBERNATION_INVALID;
1114+
int i;
11081115

11091116
if (!hibernation_available())
11101117
return -EPERM;
11111118

11121119
p = memchr(buf, '\n', n);
11131120
len = p ? p - buf : n;
11141121

1115-
lock_system_sleep();
1122+
sleep_flags = lock_system_sleep();
11161123
for (i = HIBERNATION_FIRST; i <= HIBERNATION_MAX; i++) {
11171124
if (len == strlen(hibernation_modes[i])
11181125
&& !strncmp(buf, hibernation_modes[i], len)) {
@@ -1142,7 +1149,7 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr,
11421149
if (!error)
11431150
pm_pr_dbg("Hibernation mode set to '%s'\n",
11441151
hibernation_modes[mode]);
1145-
unlock_system_sleep();
1152+
unlock_system_sleep(sleep_flags);
11461153
return error ? error : n;
11471154
}
11481155

@@ -1158,9 +1165,10 @@ static ssize_t resume_show(struct kobject *kobj, struct kobj_attribute *attr,
11581165
static ssize_t resume_store(struct kobject *kobj, struct kobj_attribute *attr,
11591166
const char *buf, size_t n)
11601167
{
1161-
dev_t res;
1168+
unsigned int sleep_flags;
11621169
int len = n;
11631170
char *name;
1171+
dev_t res;
11641172

11651173
if (len && buf[len-1] == '\n')
11661174
len--;
@@ -1173,9 +1181,10 @@ static ssize_t resume_store(struct kobject *kobj, struct kobj_attribute *attr,
11731181
if (!res)
11741182
return -EINVAL;
11751183

1176-
lock_system_sleep();
1184+
sleep_flags = lock_system_sleep();
11771185
swsusp_resume_device = res;
1178-
unlock_system_sleep();
1186+
unlock_system_sleep(sleep_flags);
1187+
11791188
pm_pr_dbg("Configured hibernation resume from disk to %u\n",
11801189
swsusp_resume_device);
11811190
noresume = 0;

kernel/power/main.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,16 @@
2121

2222
#ifdef CONFIG_PM_SLEEP
2323

24-
void lock_system_sleep(void)
24+
unsigned int lock_system_sleep(void)
2525
{
26+
unsigned int flags = current->flags;
2627
current->flags |= PF_FREEZER_SKIP;
2728
mutex_lock(&system_transition_mutex);
29+
return flags;
2830
}
2931
EXPORT_SYMBOL_GPL(lock_system_sleep);
3032

31-
void unlock_system_sleep(void)
33+
void unlock_system_sleep(unsigned int flags)
3234
{
3335
/*
3436
* Don't use freezer_count() because we don't want the call to
@@ -46,7 +48,8 @@ void unlock_system_sleep(void)
4648
* Which means, if we use try_to_freeze() here, it would make them
4749
* enter the refrigerator, thus causing hibernation to lockup.
4850
*/
49-
current->flags &= ~PF_FREEZER_SKIP;
51+
if (!(flags & PF_FREEZER_SKIP))
52+
current->flags &= ~PF_FREEZER_SKIP;
5053
mutex_unlock(&system_transition_mutex);
5154
}
5255
EXPORT_SYMBOL_GPL(unlock_system_sleep);
@@ -263,16 +266,17 @@ static ssize_t pm_test_show(struct kobject *kobj, struct kobj_attribute *attr,
263266
static ssize_t pm_test_store(struct kobject *kobj, struct kobj_attribute *attr,
264267
const char *buf, size_t n)
265268
{
269+
unsigned int sleep_flags;
266270
const char * const *s;
271+
int error = -EINVAL;
267272
int level;
268273
char *p;
269274
int len;
270-
int error = -EINVAL;
271275

272276
p = memchr(buf, '\n', n);
273277
len = p ? p - buf : n;
274278

275-
lock_system_sleep();
279+
sleep_flags = lock_system_sleep();
276280

277281
level = TEST_FIRST;
278282
for (s = &pm_tests[level]; level <= TEST_MAX; s++, level++)
@@ -282,7 +286,7 @@ static ssize_t pm_test_store(struct kobject *kobj, struct kobj_attribute *attr,
282286
break;
283287
}
284288

285-
unlock_system_sleep();
289+
unlock_system_sleep(sleep_flags);
286290

287291
return error ? error : n;
288292
}

kernel/power/suspend.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,11 @@ EXPORT_SYMBOL_GPL(pm_suspend_default_s2idle);
7575

7676
void s2idle_set_ops(const struct platform_s2idle_ops *ops)
7777
{
78-
lock_system_sleep();
78+
unsigned int sleep_flags;
79+
80+
sleep_flags = lock_system_sleep();
7981
s2idle_ops = ops;
80-
unlock_system_sleep();
82+
unlock_system_sleep(sleep_flags);
8183
}
8284

8385
static void s2idle_begin(void)
@@ -200,7 +202,9 @@ __setup("mem_sleep_default=", mem_sleep_default_setup);
200202
*/
201203
void suspend_set_ops(const struct platform_suspend_ops *ops)
202204
{
203-
lock_system_sleep();
205+
unsigned int sleep_flags;
206+
207+
sleep_flags = lock_system_sleep();
204208

205209
suspend_ops = ops;
206210

@@ -216,7 +220,7 @@ void suspend_set_ops(const struct platform_suspend_ops *ops)
216220
mem_sleep_current = PM_SUSPEND_MEM;
217221
}
218222

219-
unlock_system_sleep();
223+
unlock_system_sleep(sleep_flags);
220224
}
221225
EXPORT_SYMBOL_GPL(suspend_set_ops);
222226

0 commit comments

Comments
 (0)