PM: Split up sysdev_[suspend|resume] from device_power_[down|up]
[safe/jmp/linux-2.6] / kernel / power / main.c
index 95bff23..c9632f8 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
+#include <linux/kmod.h>
 #include <linux/init.h>
 #include <linux/console.h>
 #include <linux/cpu.h>
@@ -56,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",
@@ -124,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
 
 /*
@@ -172,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
@@ -236,6 +237,10 @@ static int suspend_prepare(void)
        if (error)
                goto Finish;
 
+       error = usermodehelper_disable();
+       if (error)
+               goto Finish;
+
        if (suspend_freeze_processes()) {
                error = -EAGAIN;
                goto Thaw;
@@ -255,6 +260,7 @@ static int suspend_prepare(void)
 
  Thaw:
        suspend_thaw_processes();
+       usermodehelper_enable();
  Finish:
        pm_notifier_call_chain(PM_POST_SUSPEND);
        pm_restore_console();
@@ -292,8 +298,12 @@ static int suspend_enter(suspend_state_t state)
                goto Done;
        }
 
-       if (!suspend_test(TEST_CORE))
-               error = suspend_ops->enter(state);
+       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:
@@ -373,6 +383,7 @@ int suspend_devices_and_enter(suspend_state_t state)
 static void suspend_finish(void)
 {
        suspend_thaw_processes();
+       usermodehelper_enable();
        pm_notifier_call_chain(PM_POST_SUSPEND);
        pm_restore_console();
 }
@@ -608,7 +619,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);
@@ -619,7 +630,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;
        }
 
@@ -635,6 +646,13 @@ static void __init test_wakealarm(struct rtc_device *rtc, suspend_state_t state)
        }
        if (status < 0)
                printk(err_suspend, status);
+
+       /* Some platforms can't detect that the alarm triggered the
+        * wakeup, or (accordingly) disable it after it afterwards.
+        * It's supposed to give oneshot behavior; cope.
+        */
+       alm.enabled = false;
+       rtc_set_alarm(rtc, &alm);
 }
 
 static int __init has_wakealarm(struct device *dev, void *name_ptr)
@@ -646,7 +664,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;
 }