]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
PM / Suspend: Fix ordering of calls in suspend error paths
authorRafael J. Wysocki <rjw@sisk.pl>
Wed, 7 Jul 2010 21:43:45 +0000 (23:43 +0200)
committerRafael J. Wysocki <rjw@sisk.pl>
Mon, 19 Jul 2010 00:00:35 +0000 (02:00 +0200)
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: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Len Brown <len.brown@intel.com>
include/linux/suspend.h
kernel/power/suspend.c

index bf1bab7b059c880fa0410a515d6c1c8834ce6974..4af270ec2204424db83ee330a74e891adb99959b 100644 (file)
@@ -61,14 +61,15 @@ typedef int __bitwise suspend_state_t;
  *     before device drivers' late suspend callbacks are executed.  It returns
  *     0 on success or a negative error code otherwise, in which case the
  *     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
  *     state indicated by @begin().
  *     @prepare_late is called before disabling nonboot CPUs and after
  *     device drivers' late suspend callbacks have been executed.  It returns
  *     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
  *     the argument if @begin() is not implemented.
@@ -81,14 +82,15 @@ typedef int __bitwise suspend_state_t;
  *     resume callbacks are executed.
  *     This callback is optional, but should be implemented by the platforms
  *     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 is called right prior to calling device drivers' regular suspend
  *     callbacks.
  *     This callback is optional, but should be implemented by the platforms
  *     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
  *     the platform that the system has returned to the working state or
index 5f8d09f94325df73501e51af648cdf4249f06ec1..7335952ee473956e6a1e7b57f3d397220e6c5536 100644 (file)
@@ -136,19 +136,19 @@ static int suspend_enter(suspend_state_t state)
        if (suspend_ops->prepare) {
                error = suspend_ops->prepare();
                if (error)
-                       return error;
+                       goto Platform_finish;
        }
 
        error = dpm_suspend_noirq(PMSG_SUSPEND);
        if (error) {
                printk(KERN_ERR "PM: Some devices failed to power down\n");
-               goto Platfrom_finish;
+               goto Platform_finish;
        }
 
        if (suspend_ops->prepare_late) {
                error = suspend_ops->prepare_late();
                if (error)
-                       goto Power_up_devices;
+                       goto Platform_wake;
        }
 
        if (suspend_test(TEST_PLATFORM))
@@ -180,10 +180,9 @@ static int suspend_enter(suspend_state_t state)
        if (suspend_ops->wake)
                suspend_ops->wake();
 
- Power_up_devices:
        dpm_resume_noirq(PMSG_RESUME);
 
- Platfrom_finish:
+ Platform_finish:
        if (suspend_ops->finish)
                suspend_ops->finish();