Commit ce441011 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

PM / Suspend: Fix ordering of calls in suspend error paths

The ACPI suspend code calls suspend_nvs_free() at a wrong place,
which may lead to a memory leak if there's an error executing
acpi_pm_prepare(), because acpi_pm_finish() will not be called in
that case.  However, the root cause of this problem is the
apparently confusing ordering of calls in suspend error paths that
needs to be fixed.

In addition to that, fix a typo in a label name in suspend.c.
Signed-off-by: default avatarRafael J. Wysocki <rjw@sisk.pl>
Acked-by: default avatarLen Brown <len.brown@intel.com>
parent d074ee02
...@@ -61,14 +61,15 @@ typedef int __bitwise suspend_state_t; ...@@ -61,14 +61,15 @@ typedef int __bitwise suspend_state_t;
* before device drivers' late suspend callbacks are executed. It returns * before device drivers' late suspend callbacks are executed. It returns
* 0 on success or a negative error code otherwise, in which case the * 0 on success or a negative error code otherwise, in which case the
* system cannot enter the desired sleep state (@prepare_late(), @enter(), * system cannot enter the desired sleep state (@prepare_late(), @enter(),
* @wake(), and @finish() will not be called in that case). * and @wake() will not be called in that case).
* *
* @prepare_late: Finish preparing the platform for entering the system sleep * @prepare_late: Finish preparing the platform for entering the system sleep
* state indicated by @begin(). * state indicated by @begin().
* @prepare_late is called before disabling nonboot CPUs and after * @prepare_late is called before disabling nonboot CPUs and after
* device drivers' late suspend callbacks have been executed. It returns * device drivers' late suspend callbacks have been executed. It returns
* 0 on success or a negative error code otherwise, in which case the * 0 on success or a negative error code otherwise, in which case the
* system cannot enter the desired sleep state (@enter() and @wake()). * system cannot enter the desired sleep state (@enter() will not be
* executed).
* *
* @enter: Enter the system sleep state indicated by @begin() or represented by * @enter: Enter the system sleep state indicated by @begin() or represented by
* the argument if @begin() is not implemented. * the argument if @begin() is not implemented.
...@@ -81,14 +82,15 @@ typedef int __bitwise suspend_state_t; ...@@ -81,14 +82,15 @@ typedef int __bitwise suspend_state_t;
* resume callbacks are executed. * resume callbacks are executed.
* This callback is optional, but should be implemented by the platforms * This callback is optional, but should be implemented by the platforms
* that implement @prepare_late(). If implemented, it is always called * that implement @prepare_late(). If implemented, it is always called
* after @enter(), even if @enter() fails. * after @prepare_late and @enter(), even if one of them fails.
* *
* @finish: Finish wake-up of the platform. * @finish: Finish wake-up of the platform.
* @finish is called right prior to calling device drivers' regular suspend * @finish is called right prior to calling device drivers' regular suspend
* callbacks. * callbacks.
* This callback is optional, but should be implemented by the platforms * This callback is optional, but should be implemented by the platforms
* that implement @prepare(). If implemented, it is always called after * that implement @prepare(). If implemented, it is always called after
* @enter() and @wake(), if implemented, even if any of them fails. * @enter() and @wake(), even if any of them fails. It is executed after
* a failing @prepare.
* *
* @end: Called by the PM core right after resuming devices, to indicate to * @end: Called by the PM core right after resuming devices, to indicate to
* the platform that the system has returned to the working state or * the platform that the system has returned to the working state or
......
...@@ -136,19 +136,19 @@ static int suspend_enter(suspend_state_t state) ...@@ -136,19 +136,19 @@ static int suspend_enter(suspend_state_t state)
if (suspend_ops->prepare) { if (suspend_ops->prepare) {
error = suspend_ops->prepare(); error = suspend_ops->prepare();
if (error) if (error)
return error; goto Platform_finish;
} }
error = dpm_suspend_noirq(PMSG_SUSPEND); error = dpm_suspend_noirq(PMSG_SUSPEND);
if (error) { if (error) {
printk(KERN_ERR "PM: Some devices failed to power down\n"); printk(KERN_ERR "PM: Some devices failed to power down\n");
goto Platfrom_finish; goto Platform_finish;
} }
if (suspend_ops->prepare_late) { if (suspend_ops->prepare_late) {
error = suspend_ops->prepare_late(); error = suspend_ops->prepare_late();
if (error) if (error)
goto Power_up_devices; goto Platform_wake;
} }
if (suspend_test(TEST_PLATFORM)) if (suspend_test(TEST_PLATFORM))
...@@ -180,10 +180,9 @@ static int suspend_enter(suspend_state_t state) ...@@ -180,10 +180,9 @@ static int suspend_enter(suspend_state_t state)
if (suspend_ops->wake) if (suspend_ops->wake)
suspend_ops->wake(); suspend_ops->wake();
Power_up_devices:
dpm_resume_noirq(PMSG_RESUME); dpm_resume_noirq(PMSG_RESUME);
Platfrom_finish: Platform_finish:
if (suspend_ops->finish) if (suspend_ops->finish)
suspend_ops->finish(); suspend_ops->finish();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment