PM: Do not hold dpm_list_mtx while disabling/enabling nonboot CPUs
[safe/jmp/linux-2.6] / kernel / power / main.c
index 19122cf..8680282 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/freezer.h>
 #include <linux/vmstat.h>
 #include <linux/syscalls.h>
-#include <linux/ftrace.h>
 
 #include "power.h"
 
@@ -58,16 +57,6 @@ int pm_notifier_call_chain(unsigned long val)
 #ifdef CONFIG_PM_DEBUG
 int pm_test_level = TEST_NONE;
 
-static int suspend_test(int level)
-{
-       if (pm_test_level == level) {
-               printk(KERN_INFO "suspend debug: Waiting for 5 seconds.\n");
-               mdelay(5000);
-               return 1;
-       }
-       return 0;
-}
-
 static const char * const pm_tests[__TEST_AFTER_LAST] = {
        [TEST_NONE] = "none",
        [TEST_CORE] = "core",
@@ -126,14 +115,24 @@ static ssize_t pm_test_store(struct kobject *kobj, struct kobj_attribute *attr,
 }
 
 power_attr(pm_test);
-#else /* !CONFIG_PM_DEBUG */
-static inline int suspend_test(int level) { return 0; }
-#endif /* !CONFIG_PM_DEBUG */
+#endif /* CONFIG_PM_DEBUG */
 
 #endif /* CONFIG_PM_SLEEP */
 
 #ifdef CONFIG_SUSPEND
 
+static int suspend_test(int level)
+{
+#ifdef CONFIG_PM_DEBUG
+       if (pm_test_level == level) {
+               printk(KERN_INFO "suspend debug: Waiting for 5 seconds.\n");
+               mdelay(5000);
+               return 1;
+       }
+#endif /* !CONFIG_PM_DEBUG */
+       return 0;
+}
+
 #ifdef CONFIG_PM_TEST_SUSPEND
 
 /*
@@ -174,7 +173,7 @@ static void suspend_test_finish(const char *label)
         * has some performance issues.  The stack dump of a WARN_ON
         * is more likely to get the right attention than a printk...
         */
-       WARN_ON(msec > (TEST_SUSPEND_SECONDS * 1000));
+       WARN(msec > (TEST_SUSPEND_SECONDS * 1000), "Component: %s\n", label);
 }
 
 #else
@@ -288,25 +287,60 @@ void __attribute__ ((weak)) arch_suspend_enable_irqs(void)
  */
 static int suspend_enter(suspend_state_t state)
 {
-       int error = 0;
+       int error;
 
-       device_pm_lock();
-       arch_suspend_disable_irqs();
-       BUG_ON(!irqs_disabled());
+       if (suspend_ops->prepare) {
+               error = suspend_ops->prepare();
+               if (error)
+                       return error;
+       }
 
-       if ((error = device_power_down(PMSG_SUSPEND))) {
+       error = device_power_down(PMSG_SUSPEND);
+       if (error) {
                printk(KERN_ERR "PM: Some devices failed to power down\n");
-               goto Done;
+               goto Platfrom_finish;
+       }
+
+       if (suspend_ops->prepare_late) {
+               error = suspend_ops->prepare_late();
+               if (error)
+                       goto Power_up_devices;
        }
 
-       if (!suspend_test(TEST_CORE))
-               error = suspend_ops->enter(state);
+       if (suspend_test(TEST_PLATFORM))
+               goto Platform_wake;
+
+       error = disable_nonboot_cpus();
+       if (error || suspend_test(TEST_CPUS))
+               goto Enable_cpus;
+
+       arch_suspend_disable_irqs();
+       BUG_ON(!irqs_disabled());
+
+       error = sysdev_suspend(PMSG_SUSPEND);
+       if (!error) {
+               if (!suspend_test(TEST_CORE))
+                       error = suspend_ops->enter(state);
+               sysdev_resume();
+       }
 
-       device_power_up(PMSG_RESUME);
- Done:
        arch_suspend_enable_irqs();
        BUG_ON(irqs_disabled());
-       device_pm_unlock();
+
+ Enable_cpus:
+       enable_nonboot_cpus();
+
+ Platform_wake:
+       if (suspend_ops->wake)
+               suspend_ops->wake();
+
+ Power_up_devices:
+       device_power_up(PMSG_RESUME);
+
+ Platfrom_finish:
+       if (suspend_ops->finish)
+               suspend_ops->finish();
+
        return error;
 }
 
@@ -317,7 +351,7 @@ static int suspend_enter(suspend_state_t state)
  */
 int suspend_devices_and_enter(suspend_state_t state)
 {
-       int error, ftrace_save;
+       int error;
 
        if (!suspend_ops)
                return -ENOSYS;
@@ -328,7 +362,6 @@ int suspend_devices_and_enter(suspend_state_t state)
                        goto Close;
        }
        suspend_console();
-       ftrace_save = __ftrace_enabled_save();
        suspend_test_start();
        error = device_suspend(PMSG_SUSPEND);
        if (error) {
@@ -339,28 +372,12 @@ int suspend_devices_and_enter(suspend_state_t state)
        if (suspend_test(TEST_DEVICES))
                goto Recover_platform;
 
-       if (suspend_ops->prepare) {
-               error = suspend_ops->prepare();
-               if (error)
-                       goto Resume_devices;
-       }
-
-       if (suspend_test(TEST_PLATFORM))
-               goto Finish;
-
-       error = disable_nonboot_cpus();
-       if (!error && !suspend_test(TEST_CPUS))
-               suspend_enter(state);
+       suspend_enter(state);
 
-       enable_nonboot_cpus();
- Finish:
-       if (suspend_ops->finish)
-               suspend_ops->finish();
  Resume_devices:
        suspend_test_start();
        device_resume(PMSG_RESUME);
        suspend_test_finish("resume devices");
-       __ftrace_enabled_restore(ftrace_save);
        resume_console();
  Close:
        if (suspend_ops->end)
@@ -618,7 +635,7 @@ static void __init test_wakealarm(struct rtc_device *rtc, suspend_state_t state)
        /* this may fail if the RTC hasn't been initialized */
        status = rtc_read_time(rtc, &alm.time);
        if (status < 0) {
-               printk(err_readtime, rtc->dev.bus_id, status);
+               printk(err_readtime, dev_name(&rtc->dev), status);
                return;
        }
        rtc_tm_to_time(&alm.time, &now);
@@ -629,7 +646,7 @@ static void __init test_wakealarm(struct rtc_device *rtc, suspend_state_t state)
 
        status = rtc_set_alarm(rtc, &alm);
        if (status < 0) {
-               printk(err_wakealarm, rtc->dev.bus_id, status);
+               printk(err_wakealarm, dev_name(&rtc->dev), status);
                return;
        }
 
@@ -663,7 +680,7 @@ static int __init has_wakealarm(struct device *dev, void *name_ptr)
        if (!device_may_wakeup(candidate->dev.parent))
                return 0;
 
-       *(char **)name_ptr = dev->bus_id;
+       *(const char **)name_ptr = dev_name(dev);
        return 1;
 }