aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/pci-driver.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-02-13 03:44:22 -0500
committerIngo Molnar <mingo@elte.hu>2009-02-13 03:44:22 -0500
commitf8a6b2b9cee298a9663cbe38ce1eb5240987cb62 (patch)
treeb356490269c9e77d164dcc1477792b882fbb8bdb /drivers/pci/pci-driver.c
parentba1511bf7fbda452138e4096bf10d5a382710f4f (diff)
parent071a0bc2ceace31266836801510879407a3701fa (diff)
Merge branch 'linus' into x86/apic
Conflicts: arch/x86/kernel/acpi/boot.c arch/x86/mm/fault.c
Diffstat (limited to 'drivers/pci/pci-driver.c')
-rw-r--r--drivers/pci/pci-driver.c164
1 files changed, 105 insertions, 59 deletions
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index ab1d615425a8..93eac1423585 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -355,6 +355,8 @@ static int pci_legacy_suspend(struct device *dev, pm_message_t state)
355 int i = 0; 355 int i = 0;
356 356
357 if (drv && drv->suspend) { 357 if (drv && drv->suspend) {
358 pci_power_t prev = pci_dev->current_state;
359
358 pci_dev->state_saved = false; 360 pci_dev->state_saved = false;
359 361
360 i = drv->suspend(pci_dev, state); 362 i = drv->suspend(pci_dev, state);
@@ -365,12 +367,16 @@ static int pci_legacy_suspend(struct device *dev, pm_message_t state)
365 if (pci_dev->state_saved) 367 if (pci_dev->state_saved)
366 goto Fixup; 368 goto Fixup;
367 369
368 if (WARN_ON_ONCE(pci_dev->current_state != PCI_D0)) 370 if (pci_dev->current_state != PCI_D0
371 && pci_dev->current_state != PCI_UNKNOWN) {
372 WARN_ONCE(pci_dev->current_state != prev,
373 "PCI PM: Device state not saved by %pF\n",
374 drv->suspend);
369 goto Fixup; 375 goto Fixup;
376 }
370 } 377 }
371 378
372 pci_save_state(pci_dev); 379 pci_save_state(pci_dev);
373 pci_dev->state_saved = true;
374 /* 380 /*
375 * This is for compatibility with existing code with legacy PM support. 381 * This is for compatibility with existing code with legacy PM support.
376 */ 382 */
@@ -424,35 +430,20 @@ static void pci_pm_default_resume_noirq(struct pci_dev *pci_dev)
424 pci_fixup_device(pci_fixup_resume_early, pci_dev); 430 pci_fixup_device(pci_fixup_resume_early, pci_dev);
425} 431}
426 432
427static int pci_pm_default_resume(struct pci_dev *pci_dev) 433static void pci_pm_default_resume(struct pci_dev *pci_dev)
428{ 434{
429 pci_fixup_device(pci_fixup_resume, pci_dev); 435 pci_fixup_device(pci_fixup_resume, pci_dev);
430 436
431 if (!pci_is_bridge(pci_dev)) 437 if (!pci_is_bridge(pci_dev))
432 pci_enable_wake(pci_dev, PCI_D0, false); 438 pci_enable_wake(pci_dev, PCI_D0, false);
433
434 return pci_pm_reenable_device(pci_dev);
435}
436
437static void pci_pm_default_suspend_generic(struct pci_dev *pci_dev)
438{
439 /* If device is enabled at this point, disable it */
440 pci_disable_enabled_device(pci_dev);
441 /*
442 * Save state with interrupts enabled, because in principle the bus the
443 * device is on may be put into a low power state after this code runs.
444 */
445 pci_save_state(pci_dev);
446} 439}
447 440
448static void pci_pm_default_suspend(struct pci_dev *pci_dev) 441static void pci_pm_default_suspend(struct pci_dev *pci_dev)
449{ 442{
450 pci_pm_default_suspend_generic(pci_dev); 443 /* Disable non-bridge devices without PM support */
451
452 if (!pci_is_bridge(pci_dev)) 444 if (!pci_is_bridge(pci_dev))
453 pci_prepare_to_sleep(pci_dev); 445 pci_disable_enabled_device(pci_dev);
454 446 pci_save_state(pci_dev);
455 pci_fixup_device(pci_fixup_suspend, pci_dev);
456} 447}
457 448
458static bool pci_has_legacy_pm_support(struct pci_dev *pci_dev) 449static bool pci_has_legacy_pm_support(struct pci_dev *pci_dev)
@@ -497,21 +488,49 @@ static void pci_pm_complete(struct device *dev)
497static int pci_pm_suspend(struct device *dev) 488static int pci_pm_suspend(struct device *dev)
498{ 489{
499 struct pci_dev *pci_dev = to_pci_dev(dev); 490 struct pci_dev *pci_dev = to_pci_dev(dev);
500 struct device_driver *drv = dev->driver; 491 struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
501 int error = 0;
502 492
503 if (pci_has_legacy_pm_support(pci_dev)) 493 if (pci_has_legacy_pm_support(pci_dev))
504 return pci_legacy_suspend(dev, PMSG_SUSPEND); 494 return pci_legacy_suspend(dev, PMSG_SUSPEND);
505 495
506 if (drv && drv->pm && drv->pm->suspend) { 496 if (!pm) {
507 error = drv->pm->suspend(dev); 497 pci_pm_default_suspend(pci_dev);
508 suspend_report_result(drv->pm->suspend, error); 498 goto Fixup;
509 } 499 }
510 500
511 if (!error) 501 pci_dev->state_saved = false;
512 pci_pm_default_suspend(pci_dev);
513 502
514 return error; 503 if (pm->suspend) {
504 pci_power_t prev = pci_dev->current_state;
505 int error;
506
507 error = pm->suspend(dev);
508 suspend_report_result(pm->suspend, error);
509 if (error)
510 return error;
511
512 if (pci_dev->state_saved)
513 goto Fixup;
514
515 if (pci_dev->current_state != PCI_D0
516 && pci_dev->current_state != PCI_UNKNOWN) {
517 WARN_ONCE(pci_dev->current_state != prev,
518 "PCI PM: State of device not saved by %pF\n",
519 pm->suspend);
520 goto Fixup;
521 }
522 }
523
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:
531 pci_fixup_device(pci_fixup_suspend, pci_dev);
532
533 return 0;
515} 534}
516 535
517static int pci_pm_suspend_noirq(struct device *dev) 536static int pci_pm_suspend_noirq(struct device *dev)
@@ -554,7 +573,7 @@ static int pci_pm_resume_noirq(struct device *dev)
554static int pci_pm_resume(struct device *dev) 573static int pci_pm_resume(struct device *dev)
555{ 574{
556 struct pci_dev *pci_dev = to_pci_dev(dev); 575 struct pci_dev *pci_dev = to_pci_dev(dev);
557 struct device_driver *drv = dev->driver; 576 struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
558 int error = 0; 577 int error = 0;
559 578
560 /* 579 /*
@@ -567,12 +586,16 @@ static int pci_pm_resume(struct device *dev)
567 if (pci_has_legacy_pm_support(pci_dev)) 586 if (pci_has_legacy_pm_support(pci_dev))
568 return pci_legacy_resume(dev); 587 return pci_legacy_resume(dev);
569 588
570 error = pci_pm_default_resume(pci_dev); 589 pci_pm_default_resume(pci_dev);
571 590
572 if (!error && drv && drv->pm && drv->pm->resume) 591 if (pm) {
573 error = drv->pm->resume(dev); 592 if (pm->resume)
593 error = pm->resume(dev);
594 } else {
595 pci_pm_reenable_device(pci_dev);
596 }
574 597
575 return error; 598 return 0;
576} 599}
577 600
578#else /* !CONFIG_SUSPEND */ 601#else /* !CONFIG_SUSPEND */
@@ -589,21 +612,31 @@ static int pci_pm_resume(struct device *dev)
589static int pci_pm_freeze(struct device *dev) 612static int pci_pm_freeze(struct device *dev)
590{ 613{
591 struct pci_dev *pci_dev = to_pci_dev(dev); 614 struct pci_dev *pci_dev = to_pci_dev(dev);
592 struct device_driver *drv = dev->driver; 615 struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
593 int error = 0;
594 616
595 if (pci_has_legacy_pm_support(pci_dev)) 617 if (pci_has_legacy_pm_support(pci_dev))
596 return pci_legacy_suspend(dev, PMSG_FREEZE); 618 return pci_legacy_suspend(dev, PMSG_FREEZE);
597 619
598 if (drv && drv->pm && drv->pm->freeze) { 620 if (!pm) {
599 error = drv->pm->freeze(dev); 621 pci_pm_default_suspend(pci_dev);
600 suspend_report_result(drv->pm->freeze, error); 622 return 0;
601 } 623 }
602 624
603 if (!error) 625 pci_dev->state_saved = false;
604 pci_pm_default_suspend_generic(pci_dev);
605 626
606 return error; 627 if (pm->freeze) {
628 int error;
629
630 error = pm->freeze(dev);
631 suspend_report_result(pm->freeze, error);
632 if (error)
633 return error;
634 }
635
636 if (!pci_dev->state_saved)
637 pci_save_state(pci_dev);
638
639 return 0;
607} 640}
608 641
609static int pci_pm_freeze_noirq(struct device *dev) 642static int pci_pm_freeze_noirq(struct device *dev)
@@ -646,16 +679,18 @@ static int pci_pm_thaw_noirq(struct device *dev)
646static int pci_pm_thaw(struct device *dev) 679static int pci_pm_thaw(struct device *dev)
647{ 680{
648 struct pci_dev *pci_dev = to_pci_dev(dev); 681 struct pci_dev *pci_dev = to_pci_dev(dev);
649 struct device_driver *drv = dev->driver; 682 struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
650 int error = 0; 683 int error = 0;
651 684
652 if (pci_has_legacy_pm_support(pci_dev)) 685 if (pci_has_legacy_pm_support(pci_dev))
653 return pci_legacy_resume(dev); 686 return pci_legacy_resume(dev);
654 687
655 pci_pm_reenable_device(pci_dev); 688 if (pm) {
656 689 if (pm->thaw)
657 if (drv && drv->pm && drv->pm->thaw) 690 error = pm->thaw(dev);
658 error = drv->pm->thaw(dev); 691 } else {
692 pci_pm_reenable_device(pci_dev);
693 }
659 694
660 return error; 695 return error;
661} 696}
@@ -663,22 +698,29 @@ static int pci_pm_thaw(struct device *dev)
663static int pci_pm_poweroff(struct device *dev) 698static int pci_pm_poweroff(struct device *dev)
664{ 699{
665 struct pci_dev *pci_dev = to_pci_dev(dev); 700 struct pci_dev *pci_dev = to_pci_dev(dev);
666 struct device_driver *drv = dev->driver; 701 struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
667 int error = 0; 702 int error = 0;
668 703
669 if (pci_has_legacy_pm_support(pci_dev)) 704 if (pci_has_legacy_pm_support(pci_dev))
670 return pci_legacy_suspend(dev, PMSG_HIBERNATE); 705 return pci_legacy_suspend(dev, PMSG_HIBERNATE);
671 706
672 if (!drv || !drv->pm) 707 if (!pm) {
673 return 0; 708 pci_pm_default_suspend(pci_dev);
709 goto Fixup;
710 }
711
712 pci_dev->state_saved = false;
674 713
675 if (drv->pm->poweroff) { 714 if (pm->poweroff) {
676 error = drv->pm->poweroff(dev); 715 error = pm->poweroff(dev);
677 suspend_report_result(drv->pm->poweroff, error); 716 suspend_report_result(pm->poweroff, error);
678 } 717 }
679 718
680 if (!error) 719 if (!pci_dev->state_saved && !pci_is_bridge(pci_dev))
681 pci_pm_default_suspend(pci_dev); 720 pci_prepare_to_sleep(pci_dev);
721
722 Fixup:
723 pci_fixup_device(pci_fixup_suspend, pci_dev);
682 724
683 return error; 725 return error;
684} 726}
@@ -719,7 +761,7 @@ static int pci_pm_restore_noirq(struct device *dev)
719static int pci_pm_restore(struct device *dev) 761static int pci_pm_restore(struct device *dev)
720{ 762{
721 struct pci_dev *pci_dev = to_pci_dev(dev); 763 struct pci_dev *pci_dev = to_pci_dev(dev);
722 struct device_driver *drv = dev->driver; 764 struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
723 int error = 0; 765 int error = 0;
724 766
725 /* 767 /*
@@ -732,10 +774,14 @@ static int pci_pm_restore(struct device *dev)
732 if (pci_has_legacy_pm_support(pci_dev)) 774 if (pci_has_legacy_pm_support(pci_dev))
733 return pci_legacy_resume(dev); 775 return pci_legacy_resume(dev);
734 776
735 error = pci_pm_default_resume(pci_dev); 777 pci_pm_default_resume(pci_dev);
736 778
737 if (!error && drv && drv->pm && drv->pm->restore) 779 if (pm) {
738 error = drv->pm->restore(dev); 780 if (pm->restore)
781 error = pm->restore(dev);
782 } else {
783 pci_pm_reenable_device(pci_dev);
784 }
739 785
740 return error; 786 return error;
741} 787}