]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - kernel/power/disk.c
PM: Rework handling of interrupts during suspend-resume
[linux-2.6-omap-h63xx.git] / kernel / power / disk.c
index 4a4a206b1979c657c887df31907166080a004d8f..320bb0949bdf97e0a62356f2e54b6dbb2392d9ee 100644 (file)
@@ -214,7 +214,7 @@ static int create_image(int platform_mode)
                return error;
 
        device_pm_lock();
-       local_irq_disable();
+
        /* At this point, device_suspend() has been called, but *not*
         * device_power_down(). We *must* call device_power_down() now.
         * Otherwise, drivers for some devices (e.g. interrupt controllers)
@@ -225,8 +225,11 @@ static int create_image(int platform_mode)
        if (error) {
                printk(KERN_ERR "PM: Some devices failed to power down, "
                        "aborting hibernation\n");
-               goto Enable_irqs;
+               goto Unlock;
        }
+
+       local_irq_disable();
+
        sysdev_suspend(PMSG_FREEZE);
        if (error) {
                printk(KERN_ERR "PM: Some devices failed to power down, "
@@ -252,12 +255,16 @@ static int create_image(int platform_mode)
        /* NOTE:  device_power_up() is just a resume() for devices
         * that suspended with irqs off ... no overall powerup.
         */
+
  Power_up_devices:
+       local_irq_enable();
+
        device_power_up(in_suspend ?
                (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE);
- Enable_irqs:
-       local_irq_enable();
+
+ Unlock:
        device_pm_unlock();
+
        return error;
 }
 
@@ -336,13 +343,16 @@ static int resume_target_kernel(void)
        int error;
 
        device_pm_lock();
-       local_irq_disable();
+
        error = device_power_down(PMSG_QUIESCE);
        if (error) {
                printk(KERN_ERR "PM: Some devices failed to power down, "
                        "aborting resume\n");
-               goto Enable_irqs;
+               goto Unlock;
        }
+
+       local_irq_disable();
+
        sysdev_suspend(PMSG_QUIESCE);
        /* We'll ignore saved state, but this gets preempt count (etc) right */
        save_processor_state();
@@ -366,11 +376,16 @@ static int resume_target_kernel(void)
        swsusp_free();
        restore_processor_state();
        touch_softlockup_watchdog();
+
        sysdev_resume();
-       device_power_up(PMSG_RECOVER);
- Enable_irqs:
+
        local_irq_enable();
+
+       device_power_up(PMSG_RECOVER);
+
+ Unlock:
        device_pm_unlock();
+
        return error;
 }
 
@@ -447,15 +462,16 @@ int hibernation_platform_enter(void)
                goto Finish;
 
        device_pm_lock();
-       local_irq_disable();
+
        error = device_power_down(PMSG_HIBERNATE);
        if (!error) {
+               local_irq_disable();
                sysdev_suspend(PMSG_HIBERNATE);
                hibernation_ops->enter();
                /* We should never get here */
                while (1);
        }
-       local_irq_enable();
+
        device_pm_unlock();
 
        /*
@@ -464,12 +480,15 @@ int hibernation_platform_enter(void)
         */
  Finish:
        hibernation_ops->finish();
+
  Resume_devices:
        entering_platform_hibernation = false;
        device_resume(PMSG_RESTORE);
        resume_console();
+
  Close:
        hibernation_ops->end();
+
        return error;
 }