Commit 5950e5d5 authored by Peter Zijlstra's avatar Peter Zijlstra
Browse files

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: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
Link: https://lore.kernel.org/r/20220822114648.725003428@infradead.org
parent 0b9d46fc
Loading
Loading
Loading
Loading
+8 −4
Original line number Diff line number Diff line
@@ -541,12 +541,14 @@ void acpi_s2idle_setup(void)

int acpi_register_lps0_dev(struct acpi_s2idle_dev_ops *arg)
{
	unsigned int sleep_flags;

	if (!lps0_device_handle || sleep_no_lps0)
		return -ENODEV;

	lock_system_sleep();
	sleep_flags = lock_system_sleep();
	list_add(&arg->list_node, &lps0_s2idle_devops_head);
	unlock_system_sleep();
	unlock_system_sleep(sleep_flags);

	return 0;
}
@@ -554,12 +556,14 @@ EXPORT_SYMBOL_GPL(acpi_register_lps0_dev);

void acpi_unregister_lps0_dev(struct acpi_s2idle_dev_ops *arg)
{
	unsigned int sleep_flags;

	if (!lps0_device_handle || sleep_no_lps0)
		return;

	lock_system_sleep();
	sleep_flags = lock_system_sleep();
	list_del(&arg->list_node);
	unlock_system_sleep();
	unlock_system_sleep(sleep_flags);
}
EXPORT_SYMBOL_GPL(acpi_unregister_lps0_dev);

+4 −3
Original line number Diff line number Diff line
@@ -998,8 +998,9 @@ void
spi_dv_device(struct scsi_device *sdev)
{
	struct scsi_target *starget = sdev->sdev_target;
	u8 *buffer;
	const int len = SPI_MAX_ECHO_BUFFER_SIZE*2;
	unsigned int sleep_flags;
	u8 *buffer;

	/*
	 * Because this function and the power management code both call
@@ -1007,7 +1008,7 @@ spi_dv_device(struct scsi_device *sdev)
	 * while suspend or resume is in progress. Hence the
	 * lock/unlock_system_sleep() calls.
	 */
	lock_system_sleep();
	sleep_flags = lock_system_sleep();

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

unlock_system_sleep:
	unlock_system_sleep();
	unlock_system_sleep(sleep_flags);
}
EXPORT_SYMBOL(spi_dv_device);

+4 −4
Original line number Diff line number Diff line
@@ -510,8 +510,8 @@ extern bool pm_save_wakeup_count(unsigned int count);
extern void pm_wakep_autosleep_enabled(bool set);
extern void pm_print_active_wakeup_sources(void);

extern void lock_system_sleep(void);
extern void unlock_system_sleep(void);
extern unsigned int lock_system_sleep(void);
extern void unlock_system_sleep(unsigned int);

#else /* !CONFIG_PM_SLEEP */

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

static inline void lock_system_sleep(void) {}
static inline void unlock_system_sleep(void) {}
static inline unsigned int lock_system_sleep(void) { return 0; }
static inline void unlock_system_sleep(unsigned int flags) {}

#endif /* !CONFIG_PM_SLEEP */

+22 −13
Original line number Diff line number Diff line
@@ -92,20 +92,24 @@ bool hibernation_available(void)
 */
void hibernation_set_ops(const struct platform_hibernation_ops *ops)
{
	unsigned int sleep_flags;

	if (ops && !(ops->begin && ops->end &&  ops->pre_snapshot
	    && ops->prepare && ops->finish && ops->enter && ops->pre_restore
	    && ops->restore_cleanup && ops->leave)) {
		WARN_ON(1);
		return;
	}
	lock_system_sleep();

	sleep_flags = lock_system_sleep();

	hibernation_ops = ops;
	if (ops)
		hibernation_mode = HIBERNATION_PLATFORM;
	else if (hibernation_mode == HIBERNATION_PLATFORM)
		hibernation_mode = HIBERNATION_SHUTDOWN;

	unlock_system_sleep();
	unlock_system_sleep(sleep_flags);
}
EXPORT_SYMBOL_GPL(hibernation_set_ops);

@@ -713,6 +717,7 @@ static int load_image_and_restore(void)
int hibernate(void)
{
	bool snapshot_test = false;
	unsigned int sleep_flags;
	int error;

	if (!hibernation_available()) {
@@ -720,7 +725,7 @@ int hibernate(void)
		return -EPERM;
	}

	lock_system_sleep();
	sleep_flags = lock_system_sleep();
	/* The snapshot device should not be opened while we're running */
	if (!hibernate_acquire()) {
		error = -EBUSY;
@@ -794,7 +799,7 @@ int hibernate(void)
	pm_restore_console();
	hibernate_release();
 Unlock:
	unlock_system_sleep();
	unlock_system_sleep(sleep_flags);
	pr_info("hibernation exit\n");

	return error;
@@ -809,9 +814,10 @@ int hibernate(void)
 */
int hibernate_quiet_exec(int (*func)(void *data), void *data)
{
	unsigned int sleep_flags;
	int error;

	lock_system_sleep();
	sleep_flags = lock_system_sleep();

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

unlock:
	unlock_system_sleep();
	unlock_system_sleep(sleep_flags);

	return error;
}
@@ -1100,11 +1106,12 @@ static ssize_t disk_show(struct kobject *kobj, struct kobj_attribute *attr,
static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr,
			  const char *buf, size_t n)
{
	int mode = HIBERNATION_INVALID;
	unsigned int sleep_flags;
	int error = 0;
	int i;
	int len;
	char *p;
	int mode = HIBERNATION_INVALID;
	int i;

	if (!hibernation_available())
		return -EPERM;
@@ -1112,7 +1119,7 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr,
	p = memchr(buf, '\n', n);
	len = p ? p - buf : n;

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

@@ -1158,9 +1165,10 @@ static ssize_t resume_show(struct kobject *kobj, struct kobj_attribute *attr,
static ssize_t resume_store(struct kobject *kobj, struct kobj_attribute *attr,
			    const char *buf, size_t n)
{
	dev_t res;
	unsigned int sleep_flags;
	int len = n;
	char *name;
	dev_t res;

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

	lock_system_sleep();
	sleep_flags = lock_system_sleep();
	swsusp_resume_device = res;
	unlock_system_sleep();
	unlock_system_sleep(sleep_flags);

	pm_pr_dbg("Configured hibernation resume from disk to %u\n",
		  swsusp_resume_device);
	noresume = 0;
+10 −6
Original line number Diff line number Diff line
@@ -21,14 +21,16 @@

#ifdef CONFIG_PM_SLEEP

void lock_system_sleep(void)
unsigned int lock_system_sleep(void)
{
	unsigned int flags = current->flags;
	current->flags |= PF_FREEZER_SKIP;
	mutex_lock(&system_transition_mutex);
	return flags;
}
EXPORT_SYMBOL_GPL(lock_system_sleep);

void unlock_system_sleep(void)
void unlock_system_sleep(unsigned int flags)
{
	/*
	 * Don't use freezer_count() because we don't want the call to
@@ -46,6 +48,7 @@ void unlock_system_sleep(void)
	 * Which means, if we use try_to_freeze() here, it would make them
	 * enter the refrigerator, thus causing hibernation to lockup.
	 */
	if (!(flags & PF_FREEZER_SKIP))
		current->flags &= ~PF_FREEZER_SKIP;
	mutex_unlock(&system_transition_mutex);
}
@@ -263,16 +266,17 @@ static ssize_t pm_test_show(struct kobject *kobj, struct kobj_attribute *attr,
static ssize_t pm_test_store(struct kobject *kobj, struct kobj_attribute *attr,
				const char *buf, size_t n)
{
	unsigned int sleep_flags;
	const char * const *s;
	int error = -EINVAL;
	int level;
	char *p;
	int len;
	int error = -EINVAL;

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

	lock_system_sleep();
	sleep_flags = lock_system_sleep();

	level = TEST_FIRST;
	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,
			break;
		}

	unlock_system_sleep();
	unlock_system_sleep(sleep_flags);

	return error ? error : n;
}
Loading