Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ea00f4f4 authored by Lianwei Wang's avatar Lianwei Wang Committed by Rafael J. Wysocki
Browse files

PM / sleep: make PM notifiers called symmetrically



This makes pm notifier PREPARE/POST symmetrical: if PREPARE
fails, we will only undo what ever happened on PREPARE.

It fixes the unbalanced CPU hotplug enable in CPU PM notifier.

Signed-off-by: default avatarLianwei Wang <lianwei.wang@gmail.com>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent ca5f2b4c
Loading
Loading
Loading
Loading
+12 −8
Original line number Diff line number Diff line
@@ -647,7 +647,7 @@ static void power_down(void)
 */
int hibernate(void)
{
	int error;
	int error, nr_calls = 0;

	if (!hibernation_available()) {
		pr_debug("PM: Hibernation not available.\n");
@@ -662,9 +662,11 @@ int hibernate(void)
	}

	pm_prepare_console();
	error = pm_notifier_call_chain(PM_HIBERNATION_PREPARE);
	if (error)
	error = __pm_notifier_call_chain(PM_HIBERNATION_PREPARE, -1, &nr_calls);
	if (error) {
		nr_calls--;
		goto Exit;
	}

	printk(KERN_INFO "PM: Syncing filesystems ... ");
	sys_sync();
@@ -714,7 +716,7 @@ int hibernate(void)
	/* Don't bother checking whether freezer_test_done is true */
	freezer_test_done = false;
 Exit:
	pm_notifier_call_chain(PM_POST_HIBERNATION);
	__pm_notifier_call_chain(PM_POST_HIBERNATION, nr_calls, NULL);
	pm_restore_console();
	atomic_inc(&snapshot_device_available);
 Unlock:
@@ -740,7 +742,7 @@ int hibernate(void)
 */
static int software_resume(void)
{
	int error;
	int error, nr_calls = 0;
	unsigned int flags;

	/*
@@ -827,9 +829,11 @@ static int software_resume(void)
	}

	pm_prepare_console();
	error = pm_notifier_call_chain(PM_RESTORE_PREPARE);
	if (error)
	error = __pm_notifier_call_chain(PM_RESTORE_PREPARE, -1, &nr_calls);
	if (error) {
		nr_calls--;
		goto Close_Finish;
	}

	pr_debug("PM: Preparing processes for restore.\n");
	error = freeze_processes();
@@ -855,7 +859,7 @@ static int software_resume(void)
	unlock_device_hotplug();
	thaw_processes();
 Finish:
	pm_notifier_call_chain(PM_POST_RESTORE);
	__pm_notifier_call_chain(PM_POST_RESTORE, nr_calls, NULL);
	pm_restore_console();
	atomic_inc(&snapshot_device_available);
	/* For success case, the suspend path will release the lock */
+9 −2
Original line number Diff line number Diff line
@@ -38,12 +38,19 @@ int unregister_pm_notifier(struct notifier_block *nb)
}
EXPORT_SYMBOL_GPL(unregister_pm_notifier);

int pm_notifier_call_chain(unsigned long val)
int __pm_notifier_call_chain(unsigned long val, int nr_to_call, int *nr_calls)
{
	int ret = blocking_notifier_call_chain(&pm_chain_head, val, NULL);
	int ret;

	ret = __blocking_notifier_call_chain(&pm_chain_head, val, NULL,
						nr_to_call, nr_calls);

	return notifier_to_errno(ret);
}
int pm_notifier_call_chain(unsigned long val)
{
	return __pm_notifier_call_chain(val, -1, NULL);
}

/* If set, devices may be suspended and resumed asynchronously. */
int pm_async_enabled = 1;
+2 −0
Original line number Diff line number Diff line
@@ -200,6 +200,8 @@ static inline void suspend_test_finish(const char *label) {}

#ifdef CONFIG_PM_SLEEP
/* kernel/power/main.c */
extern int __pm_notifier_call_chain(unsigned long val, int nr_to_call,
				    int *nr_calls);
extern int pm_notifier_call_chain(unsigned long val);
#endif

+6 −4
Original line number Diff line number Diff line
@@ -266,16 +266,18 @@ static int suspend_test(int level)
 */
static int suspend_prepare(suspend_state_t state)
{
	int error;
	int error, nr_calls = 0;

	if (!sleep_state_supported(state))
		return -EPERM;

	pm_prepare_console();

	error = pm_notifier_call_chain(PM_SUSPEND_PREPARE);
	if (error)
	error = __pm_notifier_call_chain(PM_SUSPEND_PREPARE, -1, &nr_calls);
	if (error) {
		nr_calls--;
		goto Finish;
	}

	trace_suspend_resume(TPS("freeze_processes"), 0, true);
	error = suspend_freeze_processes();
@@ -286,7 +288,7 @@ static int suspend_prepare(suspend_state_t state)
	suspend_stats.failed_freeze++;
	dpm_save_failed_step(SUSPEND_FREEZE);
 Finish:
	pm_notifier_call_chain(PM_POST_SUSPEND);
	__pm_notifier_call_chain(PM_POST_SUSPEND, nr_calls, NULL);
	pm_restore_console();
	return error;
}
+8 −6
Original line number Diff line number Diff line
@@ -47,7 +47,7 @@ atomic_t snapshot_device_available = ATOMIC_INIT(1);
static int snapshot_open(struct inode *inode, struct file *filp)
{
	struct snapshot_data *data;
	int error;
	int error, nr_calls = 0;

	if (!hibernation_available())
		return -EPERM;
@@ -74,9 +74,9 @@ static int snapshot_open(struct inode *inode, struct file *filp)
			swap_type_of(swsusp_resume_device, 0, NULL) : -1;
		data->mode = O_RDONLY;
		data->free_bitmaps = false;
		error = pm_notifier_call_chain(PM_HIBERNATION_PREPARE);
		error = __pm_notifier_call_chain(PM_HIBERNATION_PREPARE, -1, &nr_calls);
		if (error)
			pm_notifier_call_chain(PM_POST_HIBERNATION);
			__pm_notifier_call_chain(PM_POST_HIBERNATION, --nr_calls, NULL);
	} else {
		/*
		 * Resuming.  We may need to wait for the image device to
@@ -86,13 +86,15 @@ static int snapshot_open(struct inode *inode, struct file *filp)

		data->swap = -1;
		data->mode = O_WRONLY;
		error = pm_notifier_call_chain(PM_RESTORE_PREPARE);
		error = __pm_notifier_call_chain(PM_RESTORE_PREPARE, -1, &nr_calls);
		if (!error) {
			error = create_basic_memory_bitmaps();
			data->free_bitmaps = !error;
		}
		} else
			nr_calls--;

		if (error)
			pm_notifier_call_chain(PM_POST_RESTORE);
			__pm_notifier_call_chain(PM_POST_RESTORE, nr_calls, NULL);
	}
	if (error)
		atomic_inc(&snapshot_device_available);