aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/kexec.c8
-rw-r--r--kernel/power/disk.c39
-rw-r--r--kernel/power/main.c17
3 files changed, 44 insertions, 20 deletions
diff --git a/kernel/kexec.c b/kernel/kexec.c
index c7fd6692939d..dade9af6bf21 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -1454,7 +1454,6 @@ int kernel_kexec(void)
1454 if (error) 1454 if (error)
1455 goto Resume_devices; 1455 goto Resume_devices;
1456 device_pm_lock(); 1456 device_pm_lock();
1457 local_irq_disable();
1458 /* At this point, device_suspend() has been called, 1457 /* At this point, device_suspend() has been called,
1459 * but *not* device_power_down(). We *must* 1458 * but *not* device_power_down(). We *must*
1460 * device_power_down() now. Otherwise, drivers for 1459 * device_power_down() now. Otherwise, drivers for
@@ -1464,8 +1463,9 @@ int kernel_kexec(void)
1464 */ 1463 */
1465 error = device_power_down(PMSG_FREEZE); 1464 error = device_power_down(PMSG_FREEZE);
1466 if (error) 1465 if (error)
1467 goto Enable_irqs; 1466 goto Unlock_pm;
1468 1467
1468 local_irq_disable();
1469 /* Suspend system devices */ 1469 /* Suspend system devices */
1470 error = sysdev_suspend(PMSG_FREEZE); 1470 error = sysdev_suspend(PMSG_FREEZE);
1471 if (error) 1471 if (error)
@@ -1484,9 +1484,9 @@ int kernel_kexec(void)
1484 if (kexec_image->preserve_context) { 1484 if (kexec_image->preserve_context) {
1485 sysdev_resume(); 1485 sysdev_resume();
1486 Power_up_devices: 1486 Power_up_devices:
1487 device_power_up(PMSG_RESTORE);
1488 Enable_irqs:
1489 local_irq_enable(); 1487 local_irq_enable();
1488 device_power_up(PMSG_RESTORE);
1489 Unlock_pm:
1490 device_pm_unlock(); 1490 device_pm_unlock();
1491 enable_nonboot_cpus(); 1491 enable_nonboot_cpus();
1492 Resume_devices: 1492 Resume_devices:
diff --git a/kernel/power/disk.c b/kernel/power/disk.c
index 4a4a206b1979..320bb0949bdf 100644
--- a/kernel/power/disk.c
+++ b/kernel/power/disk.c
@@ -214,7 +214,7 @@ static int create_image(int platform_mode)
214 return error; 214 return error;
215 215
216 device_pm_lock(); 216 device_pm_lock();
217 local_irq_disable(); 217
218 /* At this point, device_suspend() has been called, but *not* 218 /* At this point, device_suspend() has been called, but *not*
219 * device_power_down(). We *must* call device_power_down() now. 219 * device_power_down(). We *must* call device_power_down() now.
220 * Otherwise, drivers for some devices (e.g. interrupt controllers) 220 * Otherwise, drivers for some devices (e.g. interrupt controllers)
@@ -225,8 +225,11 @@ static int create_image(int platform_mode)
225 if (error) { 225 if (error) {
226 printk(KERN_ERR "PM: Some devices failed to power down, " 226 printk(KERN_ERR "PM: Some devices failed to power down, "
227 "aborting hibernation\n"); 227 "aborting hibernation\n");
228 goto Enable_irqs; 228 goto Unlock;
229 } 229 }
230
231 local_irq_disable();
232
230 sysdev_suspend(PMSG_FREEZE); 233 sysdev_suspend(PMSG_FREEZE);
231 if (error) { 234 if (error) {
232 printk(KERN_ERR "PM: Some devices failed to power down, " 235 printk(KERN_ERR "PM: Some devices failed to power down, "
@@ -252,12 +255,16 @@ static int create_image(int platform_mode)
252 /* NOTE: device_power_up() is just a resume() for devices 255 /* NOTE: device_power_up() is just a resume() for devices
253 * that suspended with irqs off ... no overall powerup. 256 * that suspended with irqs off ... no overall powerup.
254 */ 257 */
258
255 Power_up_devices: 259 Power_up_devices:
260 local_irq_enable();
261
256 device_power_up(in_suspend ? 262 device_power_up(in_suspend ?
257 (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE); 263 (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE);
258 Enable_irqs: 264
259 local_irq_enable(); 265 Unlock:
260 device_pm_unlock(); 266 device_pm_unlock();
267
261 return error; 268 return error;
262} 269}
263 270
@@ -336,13 +343,16 @@ static int resume_target_kernel(void)
336 int error; 343 int error;
337 344
338 device_pm_lock(); 345 device_pm_lock();
339 local_irq_disable(); 346
340 error = device_power_down(PMSG_QUIESCE); 347 error = device_power_down(PMSG_QUIESCE);
341 if (error) { 348 if (error) {
342 printk(KERN_ERR "PM: Some devices failed to power down, " 349 printk(KERN_ERR "PM: Some devices failed to power down, "
343 "aborting resume\n"); 350 "aborting resume\n");
344 goto Enable_irqs; 351 goto Unlock;
345 } 352 }
353
354 local_irq_disable();
355
346 sysdev_suspend(PMSG_QUIESCE); 356 sysdev_suspend(PMSG_QUIESCE);
347 /* We'll ignore saved state, but this gets preempt count (etc) right */ 357 /* We'll ignore saved state, but this gets preempt count (etc) right */
348 save_processor_state(); 358 save_processor_state();
@@ -366,11 +376,16 @@ static int resume_target_kernel(void)
366 swsusp_free(); 376 swsusp_free();
367 restore_processor_state(); 377 restore_processor_state();
368 touch_softlockup_watchdog(); 378 touch_softlockup_watchdog();
379
369 sysdev_resume(); 380 sysdev_resume();
370 device_power_up(PMSG_RECOVER); 381
371 Enable_irqs:
372 local_irq_enable(); 382 local_irq_enable();
383
384 device_power_up(PMSG_RECOVER);
385
386 Unlock:
373 device_pm_unlock(); 387 device_pm_unlock();
388
374 return error; 389 return error;
375} 390}
376 391
@@ -447,15 +462,16 @@ int hibernation_platform_enter(void)
447 goto Finish; 462 goto Finish;
448 463
449 device_pm_lock(); 464 device_pm_lock();
450 local_irq_disable(); 465
451 error = device_power_down(PMSG_HIBERNATE); 466 error = device_power_down(PMSG_HIBERNATE);
452 if (!error) { 467 if (!error) {
468 local_irq_disable();
453 sysdev_suspend(PMSG_HIBERNATE); 469 sysdev_suspend(PMSG_HIBERNATE);
454 hibernation_ops->enter(); 470 hibernation_ops->enter();
455 /* We should never get here */ 471 /* We should never get here */
456 while (1); 472 while (1);
457 } 473 }
458 local_irq_enable(); 474
459 device_pm_unlock(); 475 device_pm_unlock();
460 476
461 /* 477 /*
@@ -464,12 +480,15 @@ int hibernation_platform_enter(void)
464 */ 480 */
465 Finish: 481 Finish:
466 hibernation_ops->finish(); 482 hibernation_ops->finish();
483
467 Resume_devices: 484 Resume_devices:
468 entering_platform_hibernation = false; 485 entering_platform_hibernation = false;
469 device_resume(PMSG_RESTORE); 486 device_resume(PMSG_RESTORE);
470 resume_console(); 487 resume_console();
488
471 Close: 489 Close:
472 hibernation_ops->end(); 490 hibernation_ops->end();
491
473 return error; 492 return error;
474} 493}
475 494
diff --git a/kernel/power/main.c b/kernel/power/main.c
index c9632f841f64..f0a466736c01 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -287,17 +287,19 @@ void __attribute__ ((weak)) arch_suspend_enable_irqs(void)
287 */ 287 */
288static int suspend_enter(suspend_state_t state) 288static int suspend_enter(suspend_state_t state)
289{ 289{
290 int error = 0; 290 int error;
291 291
292 device_pm_lock(); 292 device_pm_lock();
293 arch_suspend_disable_irqs();
294 BUG_ON(!irqs_disabled());
295 293
296 if ((error = device_power_down(PMSG_SUSPEND))) { 294 error = device_power_down(PMSG_SUSPEND);
295 if (error) {
297 printk(KERN_ERR "PM: Some devices failed to power down\n"); 296 printk(KERN_ERR "PM: Some devices failed to power down\n");
298 goto Done; 297 goto Done;
299 } 298 }
300 299
300 arch_suspend_disable_irqs();
301 BUG_ON(!irqs_disabled());
302
301 error = sysdev_suspend(PMSG_SUSPEND); 303 error = sysdev_suspend(PMSG_SUSPEND);
302 if (!error) { 304 if (!error) {
303 if (!suspend_test(TEST_CORE)) 305 if (!suspend_test(TEST_CORE))
@@ -305,11 +307,14 @@ static int suspend_enter(suspend_state_t state)
305 sysdev_resume(); 307 sysdev_resume();
306 } 308 }
307 309
308 device_power_up(PMSG_RESUME);
309 Done:
310 arch_suspend_enable_irqs(); 310 arch_suspend_enable_irqs();
311 BUG_ON(irqs_disabled()); 311 BUG_ON(irqs_disabled());
312
313 device_power_up(PMSG_RESUME);
314
315 Done:
312 device_pm_unlock(); 316 device_pm_unlock();
317
313 return error; 318 return error;
314} 319}
315 320