aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-03-30 18:12:14 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-03-30 18:12:14 -0400
commit53d8f67082c9b86699dd88b7f9e667e245193f21 (patch)
tree0e888713ee7a1a53b05852839aeb724fabe80490
parent93c36ed8348934b462044d2d60ab345055318933 (diff)
parent8efb8c76fcdccf5050c0ea059dac392789baaff2 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/suspend-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/suspend-2.6: PCI PM: Make pci_prepare_to_sleep() disable wake-up if needed radeonfb: Use __pci_complete_power_transition() PCI PM: Introduce __pci_[start|complete]_power_transition() (rev. 2) PCI PM: Restore config spaces of all devices during early resume PCI PM: Make pci_set_power_state() handle devices with no PM support PCI PM: Put devices into low power states during late suspend (rev. 2) PCI PM: Move pci_restore_standard_config to pci-driver.c PCI PM: Use pci_set_power_state during early resume PCI PM: Consistently use variable name "error" for pm call return values kexec: Change kexec jump code ordering PM: Change hibernation code ordering PM: Change suspend code ordering PM: Rework handling of interrupts during suspend-resume PM: Introduce functions for suspending and resuming device interrupts
-rw-r--r--arch/x86/kernel/apm_32.c15
-rw-r--r--drivers/base/power/main.c20
-rw-r--r--drivers/base/sys.c8
-rw-r--r--drivers/pci/pci-driver.c177
-rw-r--r--drivers/pci/pci.c142
-rw-r--r--drivers/pci/pci.h1
-rw-r--r--drivers/video/aty/radeon_pm.c2
-rw-r--r--drivers/xen/manage.c16
-rw-r--r--include/linux/interrupt.h9
-rw-r--r--include/linux/irq.h1
-rw-r--r--include/linux/pci.h1
-rw-r--r--kernel/irq/Makefile1
-rw-r--r--kernel/irq/internals.h2
-rw-r--r--kernel/irq/manage.c31
-rw-r--r--kernel/irq/pm.c79
-rw-r--r--kernel/kexec.c19
-rw-r--r--kernel/power/disk.c138
-rw-r--r--kernel/power/main.c55
18 files changed, 461 insertions, 256 deletions
diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c
index 10033fe718e0..ac7783a67432 100644
--- a/arch/x86/kernel/apm_32.c
+++ b/arch/x86/kernel/apm_32.c
@@ -1190,8 +1190,10 @@ static int suspend(int vetoable)
1190 struct apm_user *as; 1190 struct apm_user *as;
1191 1191
1192 device_suspend(PMSG_SUSPEND); 1192 device_suspend(PMSG_SUSPEND);
1193 local_irq_disable(); 1193
1194 device_power_down(PMSG_SUSPEND); 1194 device_power_down(PMSG_SUSPEND);
1195
1196 local_irq_disable();
1195 sysdev_suspend(PMSG_SUSPEND); 1197 sysdev_suspend(PMSG_SUSPEND);
1196 1198
1197 local_irq_enable(); 1199 local_irq_enable();
@@ -1209,9 +1211,12 @@ static int suspend(int vetoable)
1209 if (err != APM_SUCCESS) 1211 if (err != APM_SUCCESS)
1210 apm_error("suspend", err); 1212 apm_error("suspend", err);
1211 err = (err == APM_SUCCESS) ? 0 : -EIO; 1213 err = (err == APM_SUCCESS) ? 0 : -EIO;
1214
1212 sysdev_resume(); 1215 sysdev_resume();
1213 device_power_up(PMSG_RESUME);
1214 local_irq_enable(); 1216 local_irq_enable();
1217
1218 device_power_up(PMSG_RESUME);
1219
1215 device_resume(PMSG_RESUME); 1220 device_resume(PMSG_RESUME);
1216 queue_event(APM_NORMAL_RESUME, NULL); 1221 queue_event(APM_NORMAL_RESUME, NULL);
1217 spin_lock(&user_list_lock); 1222 spin_lock(&user_list_lock);
@@ -1228,8 +1233,9 @@ static void standby(void)
1228{ 1233{
1229 int err; 1234 int err;
1230 1235
1231 local_irq_disable();
1232 device_power_down(PMSG_SUSPEND); 1236 device_power_down(PMSG_SUSPEND);
1237
1238 local_irq_disable();
1233 sysdev_suspend(PMSG_SUSPEND); 1239 sysdev_suspend(PMSG_SUSPEND);
1234 local_irq_enable(); 1240 local_irq_enable();
1235 1241
@@ -1239,8 +1245,9 @@ static void standby(void)
1239 1245
1240 local_irq_disable(); 1246 local_irq_disable();
1241 sysdev_resume(); 1247 sysdev_resume();
1242 device_power_up(PMSG_RESUME);
1243 local_irq_enable(); 1248 local_irq_enable();
1249
1250 device_power_up(PMSG_RESUME);
1244} 1251}
1245 1252
1246static apm_event_t get_event(void) 1253static apm_event_t get_event(void)
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index e255341682c8..69b4ddb7de3b 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -23,6 +23,7 @@
23#include <linux/pm.h> 23#include <linux/pm.h>
24#include <linux/resume-trace.h> 24#include <linux/resume-trace.h>
25#include <linux/rwsem.h> 25#include <linux/rwsem.h>
26#include <linux/interrupt.h>
26 27
27#include "../base.h" 28#include "../base.h"
28#include "power.h" 29#include "power.h"
@@ -349,7 +350,8 @@ static int resume_device_noirq(struct device *dev, pm_message_t state)
349 * Execute the appropriate "noirq resume" callback for all devices marked 350 * Execute the appropriate "noirq resume" callback for all devices marked
350 * as DPM_OFF_IRQ. 351 * as DPM_OFF_IRQ.
351 * 352 *
352 * Must be called with interrupts disabled and only one CPU running. 353 * Must be called under dpm_list_mtx. Device drivers should not receive
354 * interrupts while it's being executed.
353 */ 355 */
354static void dpm_power_up(pm_message_t state) 356static void dpm_power_up(pm_message_t state)
355{ 357{
@@ -370,14 +372,13 @@ static void dpm_power_up(pm_message_t state)
370 * device_power_up - Turn on all devices that need special attention. 372 * device_power_up - Turn on all devices that need special attention.
371 * @state: PM transition of the system being carried out. 373 * @state: PM transition of the system being carried out.
372 * 374 *
373 * Power on system devices, then devices that required we shut them down 375 * Call the "early" resume handlers and enable device drivers to receive
374 * with interrupts disabled. 376 * interrupts.
375 *
376 * Must be called with interrupts disabled.
377 */ 377 */
378void device_power_up(pm_message_t state) 378void device_power_up(pm_message_t state)
379{ 379{
380 dpm_power_up(state); 380 dpm_power_up(state);
381 resume_device_irqs();
381} 382}
382EXPORT_SYMBOL_GPL(device_power_up); 383EXPORT_SYMBOL_GPL(device_power_up);
383 384
@@ -602,16 +603,17 @@ static int suspend_device_noirq(struct device *dev, pm_message_t state)
602 * device_power_down - Shut down special devices. 603 * device_power_down - Shut down special devices.
603 * @state: PM transition of the system being carried out. 604 * @state: PM transition of the system being carried out.
604 * 605 *
605 * Power down devices that require interrupts to be disabled. 606 * Prevent device drivers from receiving interrupts and call the "late"
606 * Then power down system devices. 607 * suspend handlers.
607 * 608 *
608 * Must be called with interrupts disabled and only one CPU running. 609 * Must be called under dpm_list_mtx.
609 */ 610 */
610int device_power_down(pm_message_t state) 611int device_power_down(pm_message_t state)
611{ 612{
612 struct device *dev; 613 struct device *dev;
613 int error = 0; 614 int error = 0;
614 615
616 suspend_device_irqs();
615 list_for_each_entry_reverse(dev, &dpm_list, power.entry) { 617 list_for_each_entry_reverse(dev, &dpm_list, power.entry) {
616 error = suspend_device_noirq(dev, state); 618 error = suspend_device_noirq(dev, state);
617 if (error) { 619 if (error) {
@@ -621,7 +623,7 @@ int device_power_down(pm_message_t state)
621 dev->power.status = DPM_OFF_IRQ; 623 dev->power.status = DPM_OFF_IRQ;
622 } 624 }
623 if (error) 625 if (error)
624 dpm_power_up(resume_event(state)); 626 device_power_up(resume_event(state));
625 return error; 627 return error;
626} 628}
627EXPORT_SYMBOL_GPL(device_power_down); 629EXPORT_SYMBOL_GPL(device_power_down);
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
index cbd36cf59a0f..76ce75bad91e 100644
--- a/drivers/base/sys.c
+++ b/drivers/base/sys.c
@@ -22,6 +22,7 @@
22#include <linux/pm.h> 22#include <linux/pm.h>
23#include <linux/device.h> 23#include <linux/device.h>
24#include <linux/mutex.h> 24#include <linux/mutex.h>
25#include <linux/interrupt.h>
25 26
26#include "base.h" 27#include "base.h"
27 28
@@ -369,6 +370,13 @@ int sysdev_suspend(pm_message_t state)
369 struct sysdev_driver *drv, *err_drv; 370 struct sysdev_driver *drv, *err_drv;
370 int ret; 371 int ret;
371 372
373 pr_debug("Checking wake-up interrupts\n");
374
375 /* Return error code if there are any wake-up interrupts pending */
376 ret = check_wakeup_irqs();
377 if (ret)
378 return ret;
379
372 pr_debug("Suspending System Devices\n"); 380 pr_debug("Suspending System Devices\n");
373 381
374 list_for_each_entry_reverse(cls, &system_kset->list, kset.kobj.entry) { 382 list_for_each_entry_reverse(cls, &system_kset->list, kset.kobj.entry) {
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 93eac1423585..267de88551c9 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -352,53 +352,60 @@ static int pci_legacy_suspend(struct device *dev, pm_message_t state)
352{ 352{
353 struct pci_dev * pci_dev = to_pci_dev(dev); 353 struct pci_dev * pci_dev = to_pci_dev(dev);
354 struct pci_driver * drv = pci_dev->driver; 354 struct pci_driver * drv = pci_dev->driver;
355 int i = 0; 355
356 pci_dev->state_saved = false;
356 357
357 if (drv && drv->suspend) { 358 if (drv && drv->suspend) {
358 pci_power_t prev = pci_dev->current_state; 359 pci_power_t prev = pci_dev->current_state;
360 int error;
359 361
360 pci_dev->state_saved = false; 362 error = drv->suspend(pci_dev, state);
361 363 suspend_report_result(drv->suspend, error);
362 i = drv->suspend(pci_dev, state); 364 if (error)
363 suspend_report_result(drv->suspend, i); 365 return error;
364 if (i)
365 return i;
366
367 if (pci_dev->state_saved)
368 goto Fixup;
369 366
370 if (pci_dev->current_state != PCI_D0 367 if (!pci_dev->state_saved && pci_dev->current_state != PCI_D0
371 && pci_dev->current_state != PCI_UNKNOWN) { 368 && pci_dev->current_state != PCI_UNKNOWN) {
372 WARN_ONCE(pci_dev->current_state != prev, 369 WARN_ONCE(pci_dev->current_state != prev,
373 "PCI PM: Device state not saved by %pF\n", 370 "PCI PM: Device state not saved by %pF\n",
374 drv->suspend); 371 drv->suspend);
375 goto Fixup;
376 } 372 }
377 } 373 }
378 374
379 pci_save_state(pci_dev);
380 /*
381 * This is for compatibility with existing code with legacy PM support.
382 */
383 pci_pm_set_unknown_state(pci_dev);
384
385 Fixup:
386 pci_fixup_device(pci_fixup_suspend, pci_dev); 375 pci_fixup_device(pci_fixup_suspend, pci_dev);
387 376
388 return i; 377 return 0;
389} 378}
390 379
391static int pci_legacy_suspend_late(struct device *dev, pm_message_t state) 380static int pci_legacy_suspend_late(struct device *dev, pm_message_t state)
392{ 381{
393 struct pci_dev * pci_dev = to_pci_dev(dev); 382 struct pci_dev * pci_dev = to_pci_dev(dev);
394 struct pci_driver * drv = pci_dev->driver; 383 struct pci_driver * drv = pci_dev->driver;
395 int i = 0;
396 384
397 if (drv && drv->suspend_late) { 385 if (drv && drv->suspend_late) {
398 i = drv->suspend_late(pci_dev, state); 386 pci_power_t prev = pci_dev->current_state;
399 suspend_report_result(drv->suspend_late, i); 387 int error;
388
389 error = drv->suspend_late(pci_dev, state);
390 suspend_report_result(drv->suspend_late, error);
391 if (error)
392 return error;
393
394 if (!pci_dev->state_saved && pci_dev->current_state != PCI_D0
395 && pci_dev->current_state != PCI_UNKNOWN) {
396 WARN_ONCE(pci_dev->current_state != prev,
397 "PCI PM: Device state not saved by %pF\n",
398 drv->suspend_late);
399 return 0;
400 }
400 } 401 }
401 return i; 402
403 if (!pci_dev->state_saved)
404 pci_save_state(pci_dev);
405
406 pci_pm_set_unknown_state(pci_dev);
407
408 return 0;
402} 409}
403 410
404static int pci_legacy_resume_early(struct device *dev) 411static int pci_legacy_resume_early(struct device *dev)
@@ -423,6 +430,23 @@ static int pci_legacy_resume(struct device *dev)
423 430
424/* Auxiliary functions used by the new power management framework */ 431/* Auxiliary functions used by the new power management framework */
425 432
433/**
434 * pci_restore_standard_config - restore standard config registers of PCI device
435 * @pci_dev: PCI device to handle
436 */
437static int pci_restore_standard_config(struct pci_dev *pci_dev)
438{
439 pci_update_current_state(pci_dev, PCI_UNKNOWN);
440
441 if (pci_dev->current_state != PCI_D0) {
442 int error = pci_set_power_state(pci_dev, PCI_D0);
443 if (error)
444 return error;
445 }
446
447 return pci_dev->state_saved ? pci_restore_state(pci_dev) : 0;
448}
449
426static void pci_pm_default_resume_noirq(struct pci_dev *pci_dev) 450static void pci_pm_default_resume_noirq(struct pci_dev *pci_dev)
427{ 451{
428 pci_restore_standard_config(pci_dev); 452 pci_restore_standard_config(pci_dev);
@@ -443,7 +467,6 @@ static void pci_pm_default_suspend(struct pci_dev *pci_dev)
443 /* Disable non-bridge devices without PM support */ 467 /* Disable non-bridge devices without PM support */
444 if (!pci_is_bridge(pci_dev)) 468 if (!pci_is_bridge(pci_dev))
445 pci_disable_enabled_device(pci_dev); 469 pci_disable_enabled_device(pci_dev);
446 pci_save_state(pci_dev);
447} 470}
448 471
449static bool pci_has_legacy_pm_support(struct pci_dev *pci_dev) 472static bool pci_has_legacy_pm_support(struct pci_dev *pci_dev)
@@ -493,13 +516,13 @@ static int pci_pm_suspend(struct device *dev)
493 if (pci_has_legacy_pm_support(pci_dev)) 516 if (pci_has_legacy_pm_support(pci_dev))
494 return pci_legacy_suspend(dev, PMSG_SUSPEND); 517 return pci_legacy_suspend(dev, PMSG_SUSPEND);
495 518
519 pci_dev->state_saved = false;
520
496 if (!pm) { 521 if (!pm) {
497 pci_pm_default_suspend(pci_dev); 522 pci_pm_default_suspend(pci_dev);
498 goto Fixup; 523 goto Fixup;
499 } 524 }
500 525
501 pci_dev->state_saved = false;
502
503 if (pm->suspend) { 526 if (pm->suspend) {
504 pci_power_t prev = pci_dev->current_state; 527 pci_power_t prev = pci_dev->current_state;
505 int error; 528 int error;
@@ -509,24 +532,14 @@ static int pci_pm_suspend(struct device *dev)
509 if (error) 532 if (error)
510 return error; 533 return error;
511 534
512 if (pci_dev->state_saved) 535 if (!pci_dev->state_saved && pci_dev->current_state != PCI_D0
513 goto Fixup;
514
515 if (pci_dev->current_state != PCI_D0
516 && pci_dev->current_state != PCI_UNKNOWN) { 536 && pci_dev->current_state != PCI_UNKNOWN) {
517 WARN_ONCE(pci_dev->current_state != prev, 537 WARN_ONCE(pci_dev->current_state != prev,
518 "PCI PM: State of device not saved by %pF\n", 538 "PCI PM: State of device not saved by %pF\n",
519 pm->suspend); 539 pm->suspend);
520 goto Fixup;
521 } 540 }
522 } 541 }
523 542
524 if (!pci_dev->state_saved) {
525 pci_save_state(pci_dev);
526 if (!pci_is_bridge(pci_dev))
527 pci_prepare_to_sleep(pci_dev);
528 }
529
530 Fixup: 543 Fixup:
531 pci_fixup_device(pci_fixup_suspend, pci_dev); 544 pci_fixup_device(pci_fixup_suspend, pci_dev);
532 545
@@ -536,21 +549,43 @@ static int pci_pm_suspend(struct device *dev)
536static int pci_pm_suspend_noirq(struct device *dev) 549static int pci_pm_suspend_noirq(struct device *dev)
537{ 550{
538 struct pci_dev *pci_dev = to_pci_dev(dev); 551 struct pci_dev *pci_dev = to_pci_dev(dev);
539 struct device_driver *drv = dev->driver; 552 struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
540 int error = 0;
541 553
542 if (pci_has_legacy_pm_support(pci_dev)) 554 if (pci_has_legacy_pm_support(pci_dev))
543 return pci_legacy_suspend_late(dev, PMSG_SUSPEND); 555 return pci_legacy_suspend_late(dev, PMSG_SUSPEND);
544 556
545 if (drv && drv->pm && drv->pm->suspend_noirq) { 557 if (!pm) {
546 error = drv->pm->suspend_noirq(dev); 558 pci_save_state(pci_dev);
547 suspend_report_result(drv->pm->suspend_noirq, error); 559 return 0;
548 } 560 }
549 561
550 if (!error) 562 if (pm->suspend_noirq) {
551 pci_pm_set_unknown_state(pci_dev); 563 pci_power_t prev = pci_dev->current_state;
564 int error;
552 565
553 return error; 566 error = pm->suspend_noirq(dev);
567 suspend_report_result(pm->suspend_noirq, error);
568 if (error)
569 return error;
570
571 if (!pci_dev->state_saved && pci_dev->current_state != PCI_D0
572 && pci_dev->current_state != PCI_UNKNOWN) {
573 WARN_ONCE(pci_dev->current_state != prev,
574 "PCI PM: State of device not saved by %pF\n",
575 pm->suspend_noirq);
576 return 0;
577 }
578 }
579
580 if (!pci_dev->state_saved) {
581 pci_save_state(pci_dev);
582 if (!pci_is_bridge(pci_dev))
583 pci_prepare_to_sleep(pci_dev);
584 }
585
586 pci_pm_set_unknown_state(pci_dev);
587
588 return 0;
554} 589}
555 590
556static int pci_pm_resume_noirq(struct device *dev) 591static int pci_pm_resume_noirq(struct device *dev)
@@ -617,13 +652,13 @@ static int pci_pm_freeze(struct device *dev)
617 if (pci_has_legacy_pm_support(pci_dev)) 652 if (pci_has_legacy_pm_support(pci_dev))
618 return pci_legacy_suspend(dev, PMSG_FREEZE); 653 return pci_legacy_suspend(dev, PMSG_FREEZE);
619 654
655 pci_dev->state_saved = false;
656
620 if (!pm) { 657 if (!pm) {
621 pci_pm_default_suspend(pci_dev); 658 pci_pm_default_suspend(pci_dev);
622 return 0; 659 return 0;
623 } 660 }
624 661
625 pci_dev->state_saved = false;
626
627 if (pm->freeze) { 662 if (pm->freeze) {
628 int error; 663 int error;
629 664
@@ -633,9 +668,6 @@ static int pci_pm_freeze(struct device *dev)
633 return error; 668 return error;
634 } 669 }
635 670
636 if (!pci_dev->state_saved)
637 pci_save_state(pci_dev);
638
639 return 0; 671 return 0;
640} 672}
641 673
@@ -643,20 +675,25 @@ static int pci_pm_freeze_noirq(struct device *dev)
643{ 675{
644 struct pci_dev *pci_dev = to_pci_dev(dev); 676 struct pci_dev *pci_dev = to_pci_dev(dev);
645 struct device_driver *drv = dev->driver; 677 struct device_driver *drv = dev->driver;
646 int error = 0;
647 678
648 if (pci_has_legacy_pm_support(pci_dev)) 679 if (pci_has_legacy_pm_support(pci_dev))
649 return pci_legacy_suspend_late(dev, PMSG_FREEZE); 680 return pci_legacy_suspend_late(dev, PMSG_FREEZE);
650 681
651 if (drv && drv->pm && drv->pm->freeze_noirq) { 682 if (drv && drv->pm && drv->pm->freeze_noirq) {
683 int error;
684
652 error = drv->pm->freeze_noirq(dev); 685 error = drv->pm->freeze_noirq(dev);
653 suspend_report_result(drv->pm->freeze_noirq, error); 686 suspend_report_result(drv->pm->freeze_noirq, error);
687 if (error)
688 return error;
654 } 689 }
655 690
656 if (!error) 691 if (!pci_dev->state_saved)
657 pci_pm_set_unknown_state(pci_dev); 692 pci_save_state(pci_dev);
658 693
659 return error; 694 pci_pm_set_unknown_state(pci_dev);
695
696 return 0;
660} 697}
661 698
662static int pci_pm_thaw_noirq(struct device *dev) 699static int pci_pm_thaw_noirq(struct device *dev)
@@ -699,46 +736,56 @@ static int pci_pm_poweroff(struct device *dev)
699{ 736{
700 struct pci_dev *pci_dev = to_pci_dev(dev); 737 struct pci_dev *pci_dev = to_pci_dev(dev);
701 struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 738 struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
702 int error = 0;
703 739
704 if (pci_has_legacy_pm_support(pci_dev)) 740 if (pci_has_legacy_pm_support(pci_dev))
705 return pci_legacy_suspend(dev, PMSG_HIBERNATE); 741 return pci_legacy_suspend(dev, PMSG_HIBERNATE);
706 742
743 pci_dev->state_saved = false;
744
707 if (!pm) { 745 if (!pm) {
708 pci_pm_default_suspend(pci_dev); 746 pci_pm_default_suspend(pci_dev);
709 goto Fixup; 747 goto Fixup;
710 } 748 }
711 749
712 pci_dev->state_saved = false;
713
714 if (pm->poweroff) { 750 if (pm->poweroff) {
751 int error;
752
715 error = pm->poweroff(dev); 753 error = pm->poweroff(dev);
716 suspend_report_result(pm->poweroff, error); 754 suspend_report_result(pm->poweroff, error);
755 if (error)
756 return error;
717 } 757 }
718 758
719 if (!pci_dev->state_saved && !pci_is_bridge(pci_dev))
720 pci_prepare_to_sleep(pci_dev);
721
722 Fixup: 759 Fixup:
723 pci_fixup_device(pci_fixup_suspend, pci_dev); 760 pci_fixup_device(pci_fixup_suspend, pci_dev);
724 761
725 return error; 762 return 0;
726} 763}
727 764
728static int pci_pm_poweroff_noirq(struct device *dev) 765static int pci_pm_poweroff_noirq(struct device *dev)
729{ 766{
767 struct pci_dev *pci_dev = to_pci_dev(dev);
730 struct device_driver *drv = dev->driver; 768 struct device_driver *drv = dev->driver;
731 int error = 0;
732 769
733 if (pci_has_legacy_pm_support(to_pci_dev(dev))) 770 if (pci_has_legacy_pm_support(to_pci_dev(dev)))
734 return pci_legacy_suspend_late(dev, PMSG_HIBERNATE); 771 return pci_legacy_suspend_late(dev, PMSG_HIBERNATE);
735 772
736 if (drv && drv->pm && drv->pm->poweroff_noirq) { 773 if (!drv || !drv->pm)
774 return 0;
775
776 if (drv->pm->poweroff_noirq) {
777 int error;
778
737 error = drv->pm->poweroff_noirq(dev); 779 error = drv->pm->poweroff_noirq(dev);
738 suspend_report_result(drv->pm->poweroff_noirq, error); 780 suspend_report_result(drv->pm->poweroff_noirq, error);
781 if (error)
782 return error;
739 } 783 }
740 784
741 return error; 785 if (!pci_dev->state_saved && !pci_is_bridge(pci_dev))
786 pci_prepare_to_sleep(pci_dev);
787
788 return 0;
742} 789}
743 790
744static int pci_pm_restore_noirq(struct device *dev) 791static int pci_pm_restore_noirq(struct device *dev)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 6d6120007af4..0195066251e5 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -426,7 +426,6 @@ static inline int platform_pci_sleep_wake(struct pci_dev *dev, bool enable)
426 * given PCI device 426 * given PCI device
427 * @dev: PCI device to handle. 427 * @dev: PCI device to handle.
428 * @state: PCI power state (D0, D1, D2, D3hot) to put the device into. 428 * @state: PCI power state (D0, D1, D2, D3hot) to put the device into.
429 * @wait: If 'true', wait for the device to change its power state
430 * 429 *
431 * RETURN VALUE: 430 * RETURN VALUE:
432 * -EINVAL if the requested state is invalid. 431 * -EINVAL if the requested state is invalid.
@@ -435,12 +434,15 @@ static inline int platform_pci_sleep_wake(struct pci_dev *dev, bool enable)
435 * 0 if device already is in the requested state. 434 * 0 if device already is in the requested state.
436 * 0 if device's power state has been successfully changed. 435 * 0 if device's power state has been successfully changed.
437 */ 436 */
438static int 437static int pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state)
439pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state, bool wait)
440{ 438{
441 u16 pmcsr; 439 u16 pmcsr;
442 bool need_restore = false; 440 bool need_restore = false;
443 441
442 /* Check if we're already there */
443 if (dev->current_state == state)
444 return 0;
445
444 if (!dev->pm_cap) 446 if (!dev->pm_cap)
445 return -EIO; 447 return -EIO;
446 448
@@ -451,10 +453,7 @@ pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state, bool wait)
451 * Can enter D0 from any state, but if we can only go deeper 453 * Can enter D0 from any state, but if we can only go deeper
452 * to sleep if we're already in a low power state 454 * to sleep if we're already in a low power state
453 */ 455 */
454 if (dev->current_state == state) { 456 if (state != PCI_D0 && dev->current_state <= PCI_D3cold
455 /* we're already there */
456 return 0;
457 } else if (state != PCI_D0 && dev->current_state <= PCI_D3cold
458 && dev->current_state > state) { 457 && dev->current_state > state) {
459 dev_err(&dev->dev, "invalid power transition " 458 dev_err(&dev->dev, "invalid power transition "
460 "(from state %d to %d)\n", dev->current_state, state); 459 "(from state %d to %d)\n", dev->current_state, state);
@@ -481,10 +480,8 @@ pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state, bool wait)
481 break; 480 break;
482 case PCI_UNKNOWN: /* Boot-up */ 481 case PCI_UNKNOWN: /* Boot-up */
483 if ((pmcsr & PCI_PM_CTRL_STATE_MASK) == PCI_D3hot 482 if ((pmcsr & PCI_PM_CTRL_STATE_MASK) == PCI_D3hot
484 && !(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET)) { 483 && !(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET))
485 need_restore = true; 484 need_restore = true;
486 wait = true;
487 }
488 /* Fall-through: force to D0 */ 485 /* Fall-through: force to D0 */
489 default: 486 default:
490 pmcsr = 0; 487 pmcsr = 0;
@@ -494,9 +491,6 @@ pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state, bool wait)
494 /* enter specified state */ 491 /* enter specified state */
495 pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr); 492 pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr);
496 493
497 if (!wait)
498 return 0;
499
500 /* Mandatory power management transition delays */ 494 /* Mandatory power management transition delays */
501 /* see PCI PM 1.1 5.6.1 table 18 */ 495 /* see PCI PM 1.1 5.6.1 table 18 */
502 if (state == PCI_D3hot || dev->current_state == PCI_D3hot) 496 if (state == PCI_D3hot || dev->current_state == PCI_D3hot)
@@ -521,7 +515,7 @@ pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state, bool wait)
521 if (need_restore) 515 if (need_restore)
522 pci_restore_bars(dev); 516 pci_restore_bars(dev);
523 517
524 if (wait && dev->bus->self) 518 if (dev->bus->self)
525 pcie_aspm_pm_state_change(dev->bus->self); 519 pcie_aspm_pm_state_change(dev->bus->self);
526 520
527 return 0; 521 return 0;
@@ -546,6 +540,53 @@ void pci_update_current_state(struct pci_dev *dev, pci_power_t state)
546} 540}
547 541
548/** 542/**
543 * pci_platform_power_transition - Use platform to change device power state
544 * @dev: PCI device to handle.
545 * @state: State to put the device into.
546 */
547static int pci_platform_power_transition(struct pci_dev *dev, pci_power_t state)
548{
549 int error;
550
551 if (platform_pci_power_manageable(dev)) {
552 error = platform_pci_set_power_state(dev, state);
553 if (!error)
554 pci_update_current_state(dev, state);
555 } else {
556 error = -ENODEV;
557 /* Fall back to PCI_D0 if native PM is not supported */
558 pci_update_current_state(dev, PCI_D0);
559 }
560
561 return error;
562}
563
564/**
565 * __pci_start_power_transition - Start power transition of a PCI device
566 * @dev: PCI device to handle.
567 * @state: State to put the device into.
568 */
569static void __pci_start_power_transition(struct pci_dev *dev, pci_power_t state)
570{
571 if (state == PCI_D0)
572 pci_platform_power_transition(dev, PCI_D0);
573}
574
575/**
576 * __pci_complete_power_transition - Complete power transition of a PCI device
577 * @dev: PCI device to handle.
578 * @state: State to put the device into.
579 *
580 * This function should not be called directly by device drivers.
581 */
582int __pci_complete_power_transition(struct pci_dev *dev, pci_power_t state)
583{
584 return state > PCI_D0 ?
585 pci_platform_power_transition(dev, state) : -EINVAL;
586}
587EXPORT_SYMBOL_GPL(__pci_complete_power_transition);
588
589/**
549 * pci_set_power_state - Set the power state of a PCI device 590 * pci_set_power_state - Set the power state of a PCI device
550 * @dev: PCI device to handle. 591 * @dev: PCI device to handle.
551 * @state: PCI power state (D0, D1, D2, D3hot) to put the device into. 592 * @state: PCI power state (D0, D1, D2, D3hot) to put the device into.
@@ -577,30 +618,21 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state)
577 */ 618 */
578 return 0; 619 return 0;
579 620
580 if (state == PCI_D0 && platform_pci_power_manageable(dev)) { 621 /* Check if we're already there */
581 /* 622 if (dev->current_state == state)
582 * Allow the platform to change the state, for example via ACPI 623 return 0;
583 * _PR0, _PS0 and some such, but do not trust it. 624
584 */ 625 __pci_start_power_transition(dev, state);
585 int ret = platform_pci_set_power_state(dev, PCI_D0); 626
586 if (!ret)
587 pci_update_current_state(dev, PCI_D0);
588 }
589 /* This device is quirked not to be put into D3, so 627 /* This device is quirked not to be put into D3, so
590 don't put it in D3 */ 628 don't put it in D3 */
591 if (state == PCI_D3hot && (dev->dev_flags & PCI_DEV_FLAGS_NO_D3)) 629 if (state == PCI_D3hot && (dev->dev_flags & PCI_DEV_FLAGS_NO_D3))
592 return 0; 630 return 0;
593 631
594 error = pci_raw_set_power_state(dev, state, true); 632 error = pci_raw_set_power_state(dev, state);
595 633
596 if (state > PCI_D0 && platform_pci_power_manageable(dev)) { 634 if (!__pci_complete_power_transition(dev, state))
597 /* Allow the platform to finalize the transition */ 635 error = 0;
598 int ret = platform_pci_set_power_state(dev, state);
599 if (!ret) {
600 pci_update_current_state(dev, state);
601 error = 0;
602 }
603 }
604 636
605 return error; 637 return error;
606} 638}
@@ -1231,7 +1263,7 @@ int pci_prepare_to_sleep(struct pci_dev *dev)
1231 if (target_state == PCI_POWER_ERROR) 1263 if (target_state == PCI_POWER_ERROR)
1232 return -EIO; 1264 return -EIO;
1233 1265
1234 pci_enable_wake(dev, target_state, true); 1266 pci_enable_wake(dev, target_state, device_may_wakeup(&dev->dev));
1235 1267
1236 error = pci_set_power_state(dev, target_state); 1268 error = pci_set_power_state(dev, target_state);
1237 1269
@@ -1381,50 +1413,6 @@ void pci_allocate_cap_save_buffers(struct pci_dev *dev)
1381} 1413}
1382 1414
1383/** 1415/**
1384 * pci_restore_standard_config - restore standard config registers of PCI device
1385 * @dev: PCI device to handle
1386 *
1387 * This function assumes that the device's configuration space is accessible.
1388 * If the device needs to be powered up, the function will wait for it to
1389 * change the state.
1390 */
1391int pci_restore_standard_config(struct pci_dev *dev)
1392{
1393 pci_power_t prev_state;
1394 int error;
1395
1396 pci_update_current_state(dev, PCI_D0);
1397
1398 prev_state = dev->current_state;
1399 if (prev_state == PCI_D0)
1400 goto Restore;
1401
1402 error = pci_raw_set_power_state(dev, PCI_D0, false);
1403 if (error)
1404 return error;
1405
1406 /*
1407 * This assumes that we won't get a bus in B2 or B3 from the BIOS, but
1408 * we've made this assumption forever and it appears to be universally
1409 * satisfied.
1410 */
1411 switch(prev_state) {
1412 case PCI_D3cold:
1413 case PCI_D3hot:
1414 mdelay(pci_pm_d3_delay);
1415 break;
1416 case PCI_D2:
1417 udelay(PCI_PM_D2_DELAY);
1418 break;
1419 }
1420
1421 pci_update_current_state(dev, PCI_D0);
1422
1423 Restore:
1424 return dev->state_saved ? pci_restore_state(dev) : 0;
1425}
1426
1427/**
1428 * pci_enable_ari - enable ARI forwarding if hardware support it 1416 * pci_enable_ari - enable ARI forwarding if hardware support it
1429 * @dev: the PCI device 1417 * @dev: the PCI device
1430 */ 1418 */
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 07c0aa5275e6..149fff65891f 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -49,7 +49,6 @@ extern void pci_disable_enabled_device(struct pci_dev *dev);
49extern void pci_pm_init(struct pci_dev *dev); 49extern void pci_pm_init(struct pci_dev *dev);
50extern void platform_pci_wakeup_init(struct pci_dev *dev); 50extern void platform_pci_wakeup_init(struct pci_dev *dev);
51extern void pci_allocate_cap_save_buffers(struct pci_dev *dev); 51extern void pci_allocate_cap_save_buffers(struct pci_dev *dev);
52extern int pci_restore_standard_config(struct pci_dev *dev);
53 52
54static inline bool pci_is_bridge(struct pci_dev *pci_dev) 53static inline bool pci_is_bridge(struct pci_dev *pci_dev)
55{ 54{
diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c
index c6d7cc76516f..1de0c0032468 100644
--- a/drivers/video/aty/radeon_pm.c
+++ b/drivers/video/aty/radeon_pm.c
@@ -2582,7 +2582,7 @@ static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend)
2582 * calling pci_set_power_state() 2582 * calling pci_set_power_state()
2583 */ 2583 */
2584 radeonfb_whack_power_state(rinfo, PCI_D2); 2584 radeonfb_whack_power_state(rinfo, PCI_D2);
2585 pci_set_power_state(rinfo->pdev, PCI_D2); 2585 __pci_complete_power_transition(rinfo->pdev, PCI_D2);
2586 } else { 2586 } else {
2587 printk(KERN_DEBUG "radeonfb (%s): switching to D0 state...\n", 2587 printk(KERN_DEBUG "radeonfb (%s): switching to D0 state...\n",
2588 pci_name(rinfo->pdev)); 2588 pci_name(rinfo->pdev));
diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c
index 3ccd348d112d..0d61db1e7b49 100644
--- a/drivers/xen/manage.c
+++ b/drivers/xen/manage.c
@@ -39,12 +39,6 @@ static int xen_suspend(void *data)
39 39
40 BUG_ON(!irqs_disabled()); 40 BUG_ON(!irqs_disabled());
41 41
42 err = device_power_down(PMSG_SUSPEND);
43 if (err) {
44 printk(KERN_ERR "xen_suspend: device_power_down failed: %d\n",
45 err);
46 return err;
47 }
48 err = sysdev_suspend(PMSG_SUSPEND); 42 err = sysdev_suspend(PMSG_SUSPEND);
49 if (err) { 43 if (err) {
50 printk(KERN_ERR "xen_suspend: sysdev_suspend failed: %d\n", 44 printk(KERN_ERR "xen_suspend: sysdev_suspend failed: %d\n",
@@ -69,7 +63,6 @@ static int xen_suspend(void *data)
69 xen_mm_unpin_all(); 63 xen_mm_unpin_all();
70 64
71 sysdev_resume(); 65 sysdev_resume();
72 device_power_up(PMSG_RESUME);
73 66
74 if (!*cancelled) { 67 if (!*cancelled) {
75 xen_irq_resume(); 68 xen_irq_resume();
@@ -108,6 +101,12 @@ static void do_suspend(void)
108 /* XXX use normal device tree? */ 101 /* XXX use normal device tree? */
109 xenbus_suspend(); 102 xenbus_suspend();
110 103
104 err = device_power_down(PMSG_SUSPEND);
105 if (err) {
106 printk(KERN_ERR "device_power_down failed: %d\n", err);
107 goto resume_devices;
108 }
109
111 err = stop_machine(xen_suspend, &cancelled, cpumask_of(0)); 110 err = stop_machine(xen_suspend, &cancelled, cpumask_of(0));
112 if (err) { 111 if (err) {
113 printk(KERN_ERR "failed to start xen_suspend: %d\n", err); 112 printk(KERN_ERR "failed to start xen_suspend: %d\n", err);
@@ -120,6 +119,9 @@ static void do_suspend(void)
120 } else 119 } else
121 xenbus_suspend_cancel(); 120 xenbus_suspend_cancel();
122 121
122 device_power_up(PMSG_RESUME);
123
124resume_devices:
123 device_resume(PMSG_RESUME); 125 device_resume(PMSG_RESUME);
124 126
125 /* Make sure timer events get retriggered on all CPUs */ 127 /* Make sure timer events get retriggered on all CPUs */
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 0c9cb63e6895..c68bffd182bb 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -117,6 +117,15 @@ extern void disable_irq_nosync(unsigned int irq);
117extern void disable_irq(unsigned int irq); 117extern void disable_irq(unsigned int irq);
118extern void enable_irq(unsigned int irq); 118extern void enable_irq(unsigned int irq);
119 119
120/* The following three functions are for the core kernel use only. */
121extern void suspend_device_irqs(void);
122extern void resume_device_irqs(void);
123#ifdef CONFIG_PM_SLEEP
124extern int check_wakeup_irqs(void);
125#else
126static inline int check_wakeup_irqs(void) { return 0; }
127#endif
128
120#if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_HARDIRQS) 129#if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_HARDIRQS)
121 130
122extern cpumask_var_t irq_default_affinity; 131extern cpumask_var_t irq_default_affinity;
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 9c62fbe2ef30..974890b3c52f 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -67,6 +67,7 @@ typedef void (*irq_flow_handler_t)(unsigned int irq,
67#define IRQ_SPURIOUS_DISABLED 0x00800000 /* IRQ was disabled by the spurious trap */ 67#define IRQ_SPURIOUS_DISABLED 0x00800000 /* IRQ was disabled by the spurious trap */
68#define IRQ_MOVE_PCNTXT 0x01000000 /* IRQ migration from process context */ 68#define IRQ_MOVE_PCNTXT 0x01000000 /* IRQ migration from process context */
69#define IRQ_AFFINITY_SET 0x02000000 /* IRQ affinity was set from userspace*/ 69#define IRQ_AFFINITY_SET 0x02000000 /* IRQ affinity was set from userspace*/
70#define IRQ_SUSPENDED 0x04000000 /* IRQ has gone through suspend sequence */
70 71
71#ifdef CONFIG_IRQ_PER_CPU 72#ifdef CONFIG_IRQ_PER_CPU
72# define CHECK_IRQ_PER_CPU(var) ((var) & IRQ_PER_CPU) 73# define CHECK_IRQ_PER_CPU(var) ((var) & IRQ_PER_CPU)
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 7bd624bfdcfd..df3644132617 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -689,6 +689,7 @@ size_t pci_get_rom_size(struct pci_dev *pdev, void __iomem *rom, size_t size);
689/* Power management related routines */ 689/* Power management related routines */
690int pci_save_state(struct pci_dev *dev); 690int pci_save_state(struct pci_dev *dev);
691int pci_restore_state(struct pci_dev *dev); 691int pci_restore_state(struct pci_dev *dev);
692int __pci_complete_power_transition(struct pci_dev *dev, pci_power_t state);
692int pci_set_power_state(struct pci_dev *dev, pci_power_t state); 693int pci_set_power_state(struct pci_dev *dev, pci_power_t state);
693pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state); 694pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state);
694bool pci_pme_capable(struct pci_dev *dev, pci_power_t state); 695bool pci_pme_capable(struct pci_dev *dev, pci_power_t state);
diff --git a/kernel/irq/Makefile b/kernel/irq/Makefile
index 4dd5b1edac98..3394f8f52964 100644
--- a/kernel/irq/Makefile
+++ b/kernel/irq/Makefile
@@ -4,3 +4,4 @@ obj-$(CONFIG_GENERIC_IRQ_PROBE) += autoprobe.o
4obj-$(CONFIG_PROC_FS) += proc.o 4obj-$(CONFIG_PROC_FS) += proc.o
5obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o 5obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o
6obj-$(CONFIG_NUMA_MIGRATE_IRQ_DESC) += numa_migrate.o 6obj-$(CONFIG_NUMA_MIGRATE_IRQ_DESC) += numa_migrate.o
7obj-$(CONFIG_PM_SLEEP) += pm.o
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
index ee1aa9f8e8b9..01ce20eab38f 100644
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -12,6 +12,8 @@ extern void compat_irq_chip_set_default_handler(struct irq_desc *desc);
12 12
13extern int __irq_set_trigger(struct irq_desc *desc, unsigned int irq, 13extern int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
14 unsigned long flags); 14 unsigned long flags);
15extern void __disable_irq(struct irq_desc *desc, unsigned int irq, bool susp);
16extern void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume);
15 17
16extern struct lock_class_key irq_desc_lock_class; 18extern struct lock_class_key irq_desc_lock_class;
17extern void init_kstat_irqs(struct irq_desc *desc, int cpu, int nr); 19extern void init_kstat_irqs(struct irq_desc *desc, int cpu, int nr);
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 6458e99984c0..1516ab77355c 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -162,6 +162,20 @@ static inline int setup_affinity(unsigned int irq, struct irq_desc *desc)
162} 162}
163#endif 163#endif
164 164
165void __disable_irq(struct irq_desc *desc, unsigned int irq, bool suspend)
166{
167 if (suspend) {
168 if (!desc->action || (desc->action->flags & IRQF_TIMER))
169 return;
170 desc->status |= IRQ_SUSPENDED;
171 }
172
173 if (!desc->depth++) {
174 desc->status |= IRQ_DISABLED;
175 desc->chip->disable(irq);
176 }
177}
178
165/** 179/**
166 * disable_irq_nosync - disable an irq without waiting 180 * disable_irq_nosync - disable an irq without waiting
167 * @irq: Interrupt to disable 181 * @irq: Interrupt to disable
@@ -182,10 +196,7 @@ void disable_irq_nosync(unsigned int irq)
182 return; 196 return;
183 197
184 spin_lock_irqsave(&desc->lock, flags); 198 spin_lock_irqsave(&desc->lock, flags);
185 if (!desc->depth++) { 199 __disable_irq(desc, irq, false);
186 desc->status |= IRQ_DISABLED;
187 desc->chip->disable(irq);
188 }
189 spin_unlock_irqrestore(&desc->lock, flags); 200 spin_unlock_irqrestore(&desc->lock, flags);
190} 201}
191EXPORT_SYMBOL(disable_irq_nosync); 202EXPORT_SYMBOL(disable_irq_nosync);
@@ -215,15 +226,21 @@ void disable_irq(unsigned int irq)
215} 226}
216EXPORT_SYMBOL(disable_irq); 227EXPORT_SYMBOL(disable_irq);
217 228
218static void __enable_irq(struct irq_desc *desc, unsigned int irq) 229void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume)
219{ 230{
231 if (resume)
232 desc->status &= ~IRQ_SUSPENDED;
233
220 switch (desc->depth) { 234 switch (desc->depth) {
221 case 0: 235 case 0:
236 err_out:
222 WARN(1, KERN_WARNING "Unbalanced enable for IRQ %d\n", irq); 237 WARN(1, KERN_WARNING "Unbalanced enable for IRQ %d\n", irq);
223 break; 238 break;
224 case 1: { 239 case 1: {
225 unsigned int status = desc->status & ~IRQ_DISABLED; 240 unsigned int status = desc->status & ~IRQ_DISABLED;
226 241
242 if (desc->status & IRQ_SUSPENDED)
243 goto err_out;
227 /* Prevent probing on this irq: */ 244 /* Prevent probing on this irq: */
228 desc->status = status | IRQ_NOPROBE; 245 desc->status = status | IRQ_NOPROBE;
229 check_irq_resend(desc, irq); 246 check_irq_resend(desc, irq);
@@ -253,7 +270,7 @@ void enable_irq(unsigned int irq)
253 return; 270 return;
254 271
255 spin_lock_irqsave(&desc->lock, flags); 272 spin_lock_irqsave(&desc->lock, flags);
256 __enable_irq(desc, irq); 273 __enable_irq(desc, irq, false);
257 spin_unlock_irqrestore(&desc->lock, flags); 274 spin_unlock_irqrestore(&desc->lock, flags);
258} 275}
259EXPORT_SYMBOL(enable_irq); 276EXPORT_SYMBOL(enable_irq);
@@ -511,7 +528,7 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
511 */ 528 */
512 if (shared && (desc->status & IRQ_SPURIOUS_DISABLED)) { 529 if (shared && (desc->status & IRQ_SPURIOUS_DISABLED)) {
513 desc->status &= ~IRQ_SPURIOUS_DISABLED; 530 desc->status &= ~IRQ_SPURIOUS_DISABLED;
514 __enable_irq(desc, irq); 531 __enable_irq(desc, irq, false);
515 } 532 }
516 533
517 spin_unlock_irqrestore(&desc->lock, flags); 534 spin_unlock_irqrestore(&desc->lock, flags);
diff --git a/kernel/irq/pm.c b/kernel/irq/pm.c
new file mode 100644
index 000000000000..638d8bedec14
--- /dev/null
+++ b/kernel/irq/pm.c
@@ -0,0 +1,79 @@
1/*
2 * linux/kernel/irq/pm.c
3 *
4 * Copyright (C) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
5 *
6 * This file contains power management functions related to interrupts.
7 */
8
9#include <linux/irq.h>
10#include <linux/module.h>
11#include <linux/interrupt.h>
12
13#include "internals.h"
14
15/**
16 * suspend_device_irqs - disable all currently enabled interrupt lines
17 *
18 * During system-wide suspend or hibernation device interrupts need to be
19 * disabled at the chip level and this function is provided for this purpose.
20 * It disables all interrupt lines that are enabled at the moment and sets the
21 * IRQ_SUSPENDED flag for them.
22 */
23void suspend_device_irqs(void)
24{
25 struct irq_desc *desc;
26 int irq;
27
28 for_each_irq_desc(irq, desc) {
29 unsigned long flags;
30
31 spin_lock_irqsave(&desc->lock, flags);
32 __disable_irq(desc, irq, true);
33 spin_unlock_irqrestore(&desc->lock, flags);
34 }
35
36 for_each_irq_desc(irq, desc)
37 if (desc->status & IRQ_SUSPENDED)
38 synchronize_irq(irq);
39}
40EXPORT_SYMBOL_GPL(suspend_device_irqs);
41
42/**
43 * resume_device_irqs - enable interrupt lines disabled by suspend_device_irqs()
44 *
45 * Enable all interrupt lines previously disabled by suspend_device_irqs() that
46 * have the IRQ_SUSPENDED flag set.
47 */
48void resume_device_irqs(void)
49{
50 struct irq_desc *desc;
51 int irq;
52
53 for_each_irq_desc(irq, desc) {
54 unsigned long flags;
55
56 if (!(desc->status & IRQ_SUSPENDED))
57 continue;
58
59 spin_lock_irqsave(&desc->lock, flags);
60 __enable_irq(desc, irq, true);
61 spin_unlock_irqrestore(&desc->lock, flags);
62 }
63}
64EXPORT_SYMBOL_GPL(resume_device_irqs);
65
66/**
67 * check_wakeup_irqs - check if any wake-up interrupts are pending
68 */
69int check_wakeup_irqs(void)
70{
71 struct irq_desc *desc;
72 int irq;
73
74 for_each_irq_desc(irq, desc)
75 if ((desc->status & IRQ_WAKEUP) && (desc->status & IRQ_PENDING))
76 return -EBUSY;
77
78 return 0;
79}
diff --git a/kernel/kexec.c b/kernel/kexec.c
index c7fd6692939d..93eed85fe017 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -1450,11 +1450,7 @@ int kernel_kexec(void)
1450 error = device_suspend(PMSG_FREEZE); 1450 error = device_suspend(PMSG_FREEZE);
1451 if (error) 1451 if (error)
1452 goto Resume_console; 1452 goto Resume_console;
1453 error = disable_nonboot_cpus();
1454 if (error)
1455 goto Resume_devices;
1456 device_pm_lock(); 1453 device_pm_lock();
1457 local_irq_disable();
1458 /* At this point, device_suspend() has been called, 1454 /* At this point, device_suspend() has been called,
1459 * but *not* device_power_down(). We *must* 1455 * but *not* device_power_down(). We *must*
1460 * device_power_down() now. Otherwise, drivers for 1456 * device_power_down() now. Otherwise, drivers for
@@ -1464,12 +1460,15 @@ int kernel_kexec(void)
1464 */ 1460 */
1465 error = device_power_down(PMSG_FREEZE); 1461 error = device_power_down(PMSG_FREEZE);
1466 if (error) 1462 if (error)
1467 goto Enable_irqs; 1463 goto Resume_devices;
1468 1464 error = disable_nonboot_cpus();
1465 if (error)
1466 goto Enable_cpus;
1467 local_irq_disable();
1469 /* Suspend system devices */ 1468 /* Suspend system devices */
1470 error = sysdev_suspend(PMSG_FREEZE); 1469 error = sysdev_suspend(PMSG_FREEZE);
1471 if (error) 1470 if (error)
1472 goto Power_up_devices; 1471 goto Enable_irqs;
1473 } else 1472 } else
1474#endif 1473#endif
1475 { 1474 {
@@ -1483,13 +1482,13 @@ int kernel_kexec(void)
1483#ifdef CONFIG_KEXEC_JUMP 1482#ifdef CONFIG_KEXEC_JUMP
1484 if (kexec_image->preserve_context) { 1483 if (kexec_image->preserve_context) {
1485 sysdev_resume(); 1484 sysdev_resume();
1486 Power_up_devices:
1487 device_power_up(PMSG_RESTORE);
1488 Enable_irqs: 1485 Enable_irqs:
1489 local_irq_enable(); 1486 local_irq_enable();
1490 device_pm_unlock(); 1487 Enable_cpus:
1491 enable_nonboot_cpus(); 1488 enable_nonboot_cpus();
1489 device_power_up(PMSG_RESTORE);
1492 Resume_devices: 1490 Resume_devices:
1491 device_pm_unlock();
1493 device_resume(PMSG_RESTORE); 1492 device_resume(PMSG_RESTORE);
1494 Resume_console: 1493 Resume_console:
1495 resume_console(); 1494 resume_console();
diff --git a/kernel/power/disk.c b/kernel/power/disk.c
index 4a4a206b1979..e886d1332a10 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,13 +225,25 @@ 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 error = platform_pre_snapshot(platform_mode);
232 if (error || hibernation_test(TEST_PLATFORM))
233 goto Platform_finish;
234
235 error = disable_nonboot_cpus();
236 if (error || hibernation_test(TEST_CPUS)
237 || hibernation_testmode(HIBERNATION_TEST))
238 goto Enable_cpus;
239
240 local_irq_disable();
241
230 sysdev_suspend(PMSG_FREEZE); 242 sysdev_suspend(PMSG_FREEZE);
231 if (error) { 243 if (error) {
232 printk(KERN_ERR "PM: Some devices failed to power down, " 244 printk(KERN_ERR "PM: Some devices failed to power down, "
233 "aborting hibernation\n"); 245 "aborting hibernation\n");
234 goto Power_up_devices; 246 goto Enable_irqs;
235 } 247 }
236 248
237 if (hibernation_test(TEST_CORE)) 249 if (hibernation_test(TEST_CORE))
@@ -247,17 +259,28 @@ static int create_image(int platform_mode)
247 restore_processor_state(); 259 restore_processor_state();
248 if (!in_suspend) 260 if (!in_suspend)
249 platform_leave(platform_mode); 261 platform_leave(platform_mode);
262
250 Power_up: 263 Power_up:
251 sysdev_resume(); 264 sysdev_resume();
252 /* NOTE: device_power_up() is just a resume() for devices 265 /* NOTE: device_power_up() is just a resume() for devices
253 * that suspended with irqs off ... no overall powerup. 266 * that suspended with irqs off ... no overall powerup.
254 */ 267 */
255 Power_up_devices: 268
256 device_power_up(in_suspend ?
257 (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE);
258 Enable_irqs: 269 Enable_irqs:
259 local_irq_enable(); 270 local_irq_enable();
271
272 Enable_cpus:
273 enable_nonboot_cpus();
274
275 Platform_finish:
276 platform_finish(platform_mode);
277
278 device_power_up(in_suspend ?
279 (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE);
280
281 Unlock:
260 device_pm_unlock(); 282 device_pm_unlock();
283
261 return error; 284 return error;
262} 285}
263 286
@@ -291,25 +314,9 @@ int hibernation_snapshot(int platform_mode)
291 if (hibernation_test(TEST_DEVICES)) 314 if (hibernation_test(TEST_DEVICES))
292 goto Recover_platform; 315 goto Recover_platform;
293 316
294 error = platform_pre_snapshot(platform_mode); 317 error = create_image(platform_mode);
295 if (error || hibernation_test(TEST_PLATFORM)) 318 /* Control returns here after successful restore */
296 goto Finish;
297
298 error = disable_nonboot_cpus();
299 if (!error) {
300 if (hibernation_test(TEST_CPUS))
301 goto Enable_cpus;
302
303 if (hibernation_testmode(HIBERNATION_TEST))
304 goto Enable_cpus;
305 319
306 error = create_image(platform_mode);
307 /* Control returns here after successful restore */
308 }
309 Enable_cpus:
310 enable_nonboot_cpus();
311 Finish:
312 platform_finish(platform_mode);
313 Resume_devices: 320 Resume_devices:
314 device_resume(in_suspend ? 321 device_resume(in_suspend ?
315 (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE); 322 (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE);
@@ -331,19 +338,33 @@ int hibernation_snapshot(int platform_mode)
331 * kernel. 338 * kernel.
332 */ 339 */
333 340
334static int resume_target_kernel(void) 341static int resume_target_kernel(bool platform_mode)
335{ 342{
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 }
346 sysdev_suspend(PMSG_QUIESCE); 353
354 error = platform_pre_restore(platform_mode);
355 if (error)
356 goto Cleanup;
357
358 error = disable_nonboot_cpus();
359 if (error)
360 goto Enable_cpus;
361
362 local_irq_disable();
363
364 error = sysdev_suspend(PMSG_QUIESCE);
365 if (error)
366 goto Enable_irqs;
367
347 /* We'll ignore saved state, but this gets preempt count (etc) right */ 368 /* We'll ignore saved state, but this gets preempt count (etc) right */
348 save_processor_state(); 369 save_processor_state();
349 error = restore_highmem(); 370 error = restore_highmem();
@@ -366,11 +387,23 @@ static int resume_target_kernel(void)
366 swsusp_free(); 387 swsusp_free();
367 restore_processor_state(); 388 restore_processor_state();
368 touch_softlockup_watchdog(); 389 touch_softlockup_watchdog();
390
369 sysdev_resume(); 391 sysdev_resume();
370 device_power_up(PMSG_RECOVER); 392
371 Enable_irqs: 393 Enable_irqs:
372 local_irq_enable(); 394 local_irq_enable();
395
396 Enable_cpus:
397 enable_nonboot_cpus();
398
399 Cleanup:
400 platform_restore_cleanup(platform_mode);
401
402 device_power_up(PMSG_RECOVER);
403
404 Unlock:
373 device_pm_unlock(); 405 device_pm_unlock();
406
374 return error; 407 return error;
375} 408}
376 409
@@ -390,19 +423,10 @@ int hibernation_restore(int platform_mode)
390 pm_prepare_console(); 423 pm_prepare_console();
391 suspend_console(); 424 suspend_console();
392 error = device_suspend(PMSG_QUIESCE); 425 error = device_suspend(PMSG_QUIESCE);
393 if (error)
394 goto Finish;
395
396 error = platform_pre_restore(platform_mode);
397 if (!error) { 426 if (!error) {
398 error = disable_nonboot_cpus(); 427 error = resume_target_kernel(platform_mode);
399 if (!error) 428 device_resume(PMSG_RECOVER);
400 error = resume_target_kernel();
401 enable_nonboot_cpus();
402 } 429 }
403 platform_restore_cleanup(platform_mode);
404 device_resume(PMSG_RECOVER);
405 Finish:
406 resume_console(); 430 resume_console();
407 pm_restore_console(); 431 pm_restore_console();
408 return error; 432 return error;
@@ -438,38 +462,46 @@ int hibernation_platform_enter(void)
438 goto Resume_devices; 462 goto Resume_devices;
439 } 463 }
440 464
465 device_pm_lock();
466
467 error = device_power_down(PMSG_HIBERNATE);
468 if (error)
469 goto Unlock;
470
441 error = hibernation_ops->prepare(); 471 error = hibernation_ops->prepare();
442 if (error) 472 if (error)
443 goto Resume_devices; 473 goto Platofrm_finish;
444 474
445 error = disable_nonboot_cpus(); 475 error = disable_nonboot_cpus();
446 if (error) 476 if (error)
447 goto Finish; 477 goto Platofrm_finish;
448 478
449 device_pm_lock();
450 local_irq_disable(); 479 local_irq_disable();
451 error = device_power_down(PMSG_HIBERNATE); 480 sysdev_suspend(PMSG_HIBERNATE);
452 if (!error) { 481 hibernation_ops->enter();
453 sysdev_suspend(PMSG_HIBERNATE); 482 /* We should never get here */
454 hibernation_ops->enter(); 483 while (1);
455 /* We should never get here */
456 while (1);
457 }
458 local_irq_enable();
459 device_pm_unlock();
460 484
461 /* 485 /*
462 * We don't need to reenable the nonboot CPUs or resume consoles, since 486 * We don't need to reenable the nonboot CPUs or resume consoles, since
463 * the system is going to be halted anyway. 487 * the system is going to be halted anyway.
464 */ 488 */
465 Finish: 489 Platofrm_finish:
466 hibernation_ops->finish(); 490 hibernation_ops->finish();
491
492 device_power_up(PMSG_RESTORE);
493
494 Unlock:
495 device_pm_unlock();
496
467 Resume_devices: 497 Resume_devices:
468 entering_platform_hibernation = false; 498 entering_platform_hibernation = false;
469 device_resume(PMSG_RESTORE); 499 device_resume(PMSG_RESTORE);
470 resume_console(); 500 resume_console();
501
471 Close: 502 Close:
472 hibernation_ops->end(); 503 hibernation_ops->end();
504
473 return error; 505 return error;
474} 506}
475 507
diff --git a/kernel/power/main.c b/kernel/power/main.c
index c9632f841f64..f172f41858bb 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -287,17 +287,32 @@ 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 if (suspend_ops->prepare) {
301 error = suspend_ops->prepare();
302 if (error)
303 goto Power_up_devices;
304 }
305
306 if (suspend_test(TEST_PLATFORM))
307 goto Platfrom_finish;
308
309 error = disable_nonboot_cpus();
310 if (error || suspend_test(TEST_CPUS))
311 goto Enable_cpus;
312
313 arch_suspend_disable_irqs();
314 BUG_ON(!irqs_disabled());
315
301 error = sysdev_suspend(PMSG_SUSPEND); 316 error = sysdev_suspend(PMSG_SUSPEND);
302 if (!error) { 317 if (!error) {
303 if (!suspend_test(TEST_CORE)) 318 if (!suspend_test(TEST_CORE))
@@ -305,11 +320,22 @@ static int suspend_enter(suspend_state_t state)
305 sysdev_resume(); 320 sysdev_resume();
306 } 321 }
307 322
308 device_power_up(PMSG_RESUME);
309 Done:
310 arch_suspend_enable_irqs(); 323 arch_suspend_enable_irqs();
311 BUG_ON(irqs_disabled()); 324 BUG_ON(irqs_disabled());
325
326 Enable_cpus:
327 enable_nonboot_cpus();
328
329 Platfrom_finish:
330 if (suspend_ops->finish)
331 suspend_ops->finish();
332
333 Power_up_devices:
334 device_power_up(PMSG_RESUME);
335
336 Done:
312 device_pm_unlock(); 337 device_pm_unlock();
338
313 return error; 339 return error;
314} 340}
315 341
@@ -341,23 +367,8 @@ int suspend_devices_and_enter(suspend_state_t state)
341 if (suspend_test(TEST_DEVICES)) 367 if (suspend_test(TEST_DEVICES))
342 goto Recover_platform; 368 goto Recover_platform;
343 369
344 if (suspend_ops->prepare) { 370 suspend_enter(state);
345 error = suspend_ops->prepare();
346 if (error)
347 goto Resume_devices;
348 }
349
350 if (suspend_test(TEST_PLATFORM))
351 goto Finish;
352
353 error = disable_nonboot_cpus();
354 if (!error && !suspend_test(TEST_CPUS))
355 suspend_enter(state);
356 371
357 enable_nonboot_cpus();
358 Finish:
359 if (suspend_ops->finish)
360 suspend_ops->finish();
361 Resume_devices: 372 Resume_devices:
362 suspend_test_start(); 373 suspend_test_start();
363 device_resume(PMSG_RESUME); 374 device_resume(PMSG_RESUME);