PM / hibernate: Call platform_leave() in suspend path too
authorBjørn Mork <bjorn@mork.no>
Wed, 4 Dec 2013 15:06:58 +0000 (16:06 +0100)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Mon, 6 Jan 2014 13:08:39 +0000 (14:08 +0100)
Since create_image() only executes platform_leave() if in_suspend is
not set, enable_nonboot_cpus() is run by it with EC transactions
blocked (on ACPI systems) in the image creation code path (that is,
for in_suspend set), which may cause CPU online to fail for the CPUs
in question.  In particular, this causes the acpi_cpufreq driver's
initialization to fail for those CPUs on some systems with the
following dmesg:

 cpufreq: adding CPU 1
 acpi_cpufreq_cpu_init
 cpufreq: FREQ: 1401000 - CPU: 0
 ACPI Exception: AE_BAD_PARAMETER, Returned by Handler for [EmbeddedControl] (20130725/evregion-287)
 ACPI Error: Method parse/execution failed [\_SB_.PCI0.LPC_.EC__.LPMD] (Node ffff88023249ab28), AE_BAD_PARAMETER (20130725/psparse-536)
 ACPI Error: Method parse/execution failed [\_PR_.CPU0._PPC] (Node ffff88023270e3f8), AE_BAD_PARAMETER (20130725/psparse-536)
 ACPI Error: Method parse/execution failed [\_PR_.CPU1._PPC] (Node ffff88023270e290), AE_BAD_PARAMETER (20130725/psparse-536)
 ACPI Exception: AE_BAD_PARAMETER, Evaluating _PPC (20130725/processor_perflib-140)
 cpufreq: initialization failed
 CPU1 is up

To fix this problem, modify create_image() to execute platform_leave()
unconditionally.  [rjw: This shouldn't lead to any significant side
effects on ACPI systems.]

Signed-off-by: Bjørn Mork <bjorn@mork.no>
[rjw: Changelog]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
kernel/power/hibernate.c

index bc13d08..37170d4 100644 (file)
@@ -294,10 +294,10 @@ static int create_image(int platform_mode)
                        error);
        /* Restore control flow magically appears here */
        restore_processor_state();
-       if (!in_suspend) {
+       if (!in_suspend)
                events_check_enabled = false;
-               platform_leave(platform_mode);
-       }
+
+       platform_leave(platform_mode);
 
  Power_up:
        syscore_resume();