aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/pci-driver.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/pci-driver.c')
-rw-r--r--drivers/pci/pci-driver.c116
1 files changed, 75 insertions, 41 deletions
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 750ee79c178f..2e76945a1cd8 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -318,7 +318,7 @@ static void pci_device_shutdown(struct device *dev)
318 * Default "suspend" method for devices that have no driver provided suspend, 318 * Default "suspend" method for devices that have no driver provided suspend,
319 * or not even a driver at all (second part). 319 * or not even a driver at all (second part).
320 */ 320 */
321static void pci_default_pm_suspend_late(struct pci_dev *pci_dev) 321static void pci_pm_set_unknown_state(struct pci_dev *pci_dev)
322{ 322{
323 /* 323 /*
324 * mark its power state as "unknown", since we don't know if 324 * mark its power state as "unknown", since we don't know if
@@ -332,7 +332,7 @@ static void pci_default_pm_suspend_late(struct pci_dev *pci_dev)
332 * Default "resume" method for devices that have no driver provided resume, 332 * Default "resume" method for devices that have no driver provided resume,
333 * or not even a driver at all (second part). 333 * or not even a driver at all (second part).
334 */ 334 */
335static int pci_default_pm_resume_late(struct pci_dev *pci_dev) 335static int pci_pm_reenable_device(struct pci_dev *pci_dev)
336{ 336{
337 int retval; 337 int retval;
338 338
@@ -363,7 +363,7 @@ static int pci_legacy_suspend(struct device *dev, pm_message_t state)
363 * This is for compatibility with existing code with legacy PM 363 * This is for compatibility with existing code with legacy PM
364 * support. 364 * support.
365 */ 365 */
366 pci_default_pm_suspend_late(pci_dev); 366 pci_pm_set_unknown_state(pci_dev);
367 } 367 }
368 return i; 368 return i;
369} 369}
@@ -392,7 +392,7 @@ static int pci_legacy_resume(struct device *dev)
392 } else { 392 } else {
393 /* restore the PCI config space */ 393 /* restore the PCI config space */
394 pci_restore_state(pci_dev); 394 pci_restore_state(pci_dev);
395 error = pci_default_pm_resume_late(pci_dev); 395 error = pci_pm_reenable_device(pci_dev);
396 } 396 }
397 return error; 397 return error;
398} 398}
@@ -459,7 +459,7 @@ static int pci_pm_default_resume(struct pci_dev *pci_dev)
459 if (!pci_is_bridge(pci_dev)) 459 if (!pci_is_bridge(pci_dev))
460 pci_enable_wake(pci_dev, PCI_D0, false); 460 pci_enable_wake(pci_dev, PCI_D0, false);
461 461
462 return pci_default_pm_resume_late(pci_dev); 462 return pci_pm_reenable_device(pci_dev);
463} 463}
464 464
465static void pci_pm_default_suspend_generic(struct pci_dev *pci_dev) 465static void pci_pm_default_suspend_generic(struct pci_dev *pci_dev)
@@ -484,9 +484,17 @@ static void pci_pm_default_suspend(struct pci_dev *pci_dev)
484static bool pci_has_legacy_pm_support(struct pci_dev *pci_dev) 484static bool pci_has_legacy_pm_support(struct pci_dev *pci_dev)
485{ 485{
486 struct pci_driver *drv = pci_dev->driver; 486 struct pci_driver *drv = pci_dev->driver;
487 487 bool ret = drv && (drv->suspend || drv->suspend_late || drv->resume
488 return drv && (drv->suspend || drv->suspend_late || drv->resume
489 || drv->resume_early); 488 || drv->resume_early);
489
490 /*
491 * Legacy PM support is used by default, so warn if the new framework is
492 * supported as well. Drivers are supposed to support either the
493 * former, or the latter, but not both at the same time.
494 */
495 WARN_ON(ret && drv->driver.pm);
496
497 return ret;
490} 498}
491 499
492/* New power management framework */ 500/* New power management framework */
@@ -518,17 +526,21 @@ static int pci_pm_suspend(struct device *dev)
518 struct device_driver *drv = dev->driver; 526 struct device_driver *drv = dev->driver;
519 int error = 0; 527 int error = 0;
520 528
529 if (pci_has_legacy_pm_support(pci_dev)) {
530 error = pci_legacy_suspend(dev, PMSG_SUSPEND);
531 goto Exit;
532 }
533
521 if (drv && drv->pm) { 534 if (drv && drv->pm) {
522 if (drv->pm->suspend) { 535 if (drv->pm->suspend) {
523 error = drv->pm->suspend(dev); 536 error = drv->pm->suspend(dev);
524 suspend_report_result(drv->pm->suspend, error); 537 suspend_report_result(drv->pm->suspend, error);
525 } 538 }
526 } else if (pci_has_legacy_pm_support(pci_dev)) {
527 error = pci_legacy_suspend(dev, PMSG_SUSPEND);
528 } else { 539 } else {
529 pci_pm_default_suspend(pci_dev); 540 pci_pm_default_suspend(pci_dev);
530 } 541 }
531 542
543 Exit:
532 pci_fixup_device(pci_fixup_suspend, pci_dev); 544 pci_fixup_device(pci_fixup_suspend, pci_dev);
533 545
534 return error; 546 return error;
@@ -540,15 +552,16 @@ static int pci_pm_suspend_noirq(struct device *dev)
540 struct device_driver *drv = dev->driver; 552 struct device_driver *drv = dev->driver;
541 int error = 0; 553 int error = 0;
542 554
555 if (pci_has_legacy_pm_support(pci_dev))
556 return pci_legacy_suspend_late(dev, PMSG_SUSPEND);
557
543 if (drv && drv->pm) { 558 if (drv && drv->pm) {
544 if (drv->pm->suspend_noirq) { 559 if (drv->pm->suspend_noirq) {
545 error = drv->pm->suspend_noirq(dev); 560 error = drv->pm->suspend_noirq(dev);
546 suspend_report_result(drv->pm->suspend_noirq, error); 561 suspend_report_result(drv->pm->suspend_noirq, error);
547 } 562 }
548 } else if (pci_has_legacy_pm_support(pci_dev)) {
549 error = pci_legacy_suspend_late(dev, PMSG_SUSPEND);
550 } else { 563 } else {
551 pci_default_pm_suspend_late(pci_dev); 564 pci_pm_set_unknown_state(pci_dev);
552 } 565 }
553 566
554 return error; 567 return error;
@@ -560,14 +573,16 @@ static int pci_pm_resume(struct device *dev)
560 struct device_driver *drv = dev->driver; 573 struct device_driver *drv = dev->driver;
561 int error = 0; 574 int error = 0;
562 575
576 if (pci_has_legacy_pm_support(pci_dev)) {
577 pci_fixup_device(pci_fixup_resume, pci_dev);
578 return pci_legacy_resume(dev);
579 }
580
563 if (drv && drv->pm) { 581 if (drv && drv->pm) {
564 pci_fixup_device(pci_fixup_resume, pci_dev); 582 pci_fixup_device(pci_fixup_resume, pci_dev);
565 583
566 if (drv->pm->resume) 584 if (drv->pm->resume)
567 error = drv->pm->resume(dev); 585 error = drv->pm->resume(dev);
568 } else if (pci_has_legacy_pm_support(pci_dev)) {
569 pci_fixup_device(pci_fixup_resume, pci_dev);
570 error = pci_legacy_resume(dev);
571 } else { 586 } else {
572 error = pci_pm_default_resume(pci_dev); 587 error = pci_pm_default_resume(pci_dev);
573 } 588 }
@@ -581,14 +596,16 @@ static int pci_pm_resume_noirq(struct device *dev)
581 struct device_driver *drv = dev->driver; 596 struct device_driver *drv = dev->driver;
582 int error = 0; 597 int error = 0;
583 598
599 if (pci_has_legacy_pm_support(pci_dev)) {
600 pci_fixup_device(pci_fixup_resume_early, pci_dev);
601 return pci_legacy_resume_early(dev);
602 }
603
584 if (drv && drv->pm) { 604 if (drv && drv->pm) {
585 pci_fixup_device(pci_fixup_resume_early, pci_dev); 605 pci_fixup_device(pci_fixup_resume_early, pci_dev);
586 606
587 if (drv->pm->resume_noirq) 607 if (drv->pm->resume_noirq)
588 error = drv->pm->resume_noirq(dev); 608 error = drv->pm->resume_noirq(dev);
589 } else if (pci_has_legacy_pm_support(pci_dev)) {
590 pci_fixup_device(pci_fixup_resume_early, pci_dev);
591 error = pci_legacy_resume_early(dev);
592 } else { 609 } else {
593 pci_pm_default_resume_noirq(pci_dev); 610 pci_pm_default_resume_noirq(pci_dev);
594 } 611 }
@@ -613,14 +630,17 @@ static int pci_pm_freeze(struct device *dev)
613 struct device_driver *drv = dev->driver; 630 struct device_driver *drv = dev->driver;
614 int error = 0; 631 int error = 0;
615 632
633 if (pci_has_legacy_pm_support(pci_dev)) {
634 error = pci_legacy_suspend(dev, PMSG_FREEZE);
635 pci_fixup_device(pci_fixup_suspend, pci_dev);
636 return error;
637 }
638
616 if (drv && drv->pm) { 639 if (drv && drv->pm) {
617 if (drv->pm->freeze) { 640 if (drv->pm->freeze) {
618 error = drv->pm->freeze(dev); 641 error = drv->pm->freeze(dev);
619 suspend_report_result(drv->pm->freeze, error); 642 suspend_report_result(drv->pm->freeze, error);
620 } 643 }
621 } else if (pci_has_legacy_pm_support(pci_dev)) {
622 error = pci_legacy_suspend(dev, PMSG_FREEZE);
623 pci_fixup_device(pci_fixup_suspend, pci_dev);
624 } else { 644 } else {
625 pci_pm_default_suspend_generic(pci_dev); 645 pci_pm_default_suspend_generic(pci_dev);
626 } 646 }
@@ -634,15 +654,16 @@ static int pci_pm_freeze_noirq(struct device *dev)
634 struct device_driver *drv = dev->driver; 654 struct device_driver *drv = dev->driver;
635 int error = 0; 655 int error = 0;
636 656
657 if (pci_has_legacy_pm_support(pci_dev))
658 return pci_legacy_suspend_late(dev, PMSG_FREEZE);
659
637 if (drv && drv->pm) { 660 if (drv && drv->pm) {
638 if (drv->pm->freeze_noirq) { 661 if (drv->pm->freeze_noirq) {
639 error = drv->pm->freeze_noirq(dev); 662 error = drv->pm->freeze_noirq(dev);
640 suspend_report_result(drv->pm->freeze_noirq, error); 663 suspend_report_result(drv->pm->freeze_noirq, error);
641 } 664 }
642 } else if (pci_has_legacy_pm_support(pci_dev)) {
643 error = pci_legacy_suspend_late(dev, PMSG_FREEZE);
644 } else { 665 } else {
645 pci_default_pm_suspend_late(pci_dev); 666 pci_pm_set_unknown_state(pci_dev);
646 } 667 }
647 668
648 return error; 669 return error;
@@ -654,14 +675,16 @@ static int pci_pm_thaw(struct device *dev)
654 struct device_driver *drv = dev->driver; 675 struct device_driver *drv = dev->driver;
655 int error = 0; 676 int error = 0;
656 677
678 if (pci_has_legacy_pm_support(pci_dev)) {
679 pci_fixup_device(pci_fixup_resume, pci_dev);
680 return pci_legacy_resume(dev);
681 }
682
657 if (drv && drv->pm) { 683 if (drv && drv->pm) {
658 if (drv->pm->thaw) 684 if (drv->pm->thaw)
659 error = drv->pm->thaw(dev); 685 error = drv->pm->thaw(dev);
660 } else if (pci_has_legacy_pm_support(pci_dev)) {
661 pci_fixup_device(pci_fixup_resume, pci_dev);
662 error = pci_legacy_resume(dev);
663 } else { 686 } else {
664 pci_default_pm_resume_late(pci_dev); 687 pci_pm_reenable_device(pci_dev);
665 } 688 }
666 689
667 return error; 690 return error;
@@ -673,12 +696,14 @@ static int pci_pm_thaw_noirq(struct device *dev)
673 struct device_driver *drv = dev->driver; 696 struct device_driver *drv = dev->driver;
674 int error = 0; 697 int error = 0;
675 698
699 if (pci_has_legacy_pm_support(pci_dev)) {
700 pci_fixup_device(pci_fixup_resume_early, to_pci_dev(dev));
701 return pci_legacy_resume_early(dev);
702 }
703
676 if (drv && drv->pm) { 704 if (drv && drv->pm) {
677 if (drv->pm->thaw_noirq) 705 if (drv->pm->thaw_noirq)
678 error = drv->pm->thaw_noirq(dev); 706 error = drv->pm->thaw_noirq(dev);
679 } else if (pci_has_legacy_pm_support(pci_dev)) {
680 pci_fixup_device(pci_fixup_resume_early, to_pci_dev(dev));
681 error = pci_legacy_resume_early(dev);
682 } else { 707 } else {
683 pci_update_current_state(pci_dev, PCI_D0); 708 pci_update_current_state(pci_dev, PCI_D0);
684 } 709 }
@@ -692,17 +717,21 @@ static int pci_pm_poweroff(struct device *dev)
692 struct device_driver *drv = dev->driver; 717 struct device_driver *drv = dev->driver;
693 int error = 0; 718 int error = 0;
694 719
720 if (pci_has_legacy_pm_support(pci_dev)) {
721 error = pci_legacy_suspend(dev, PMSG_HIBERNATE);
722 goto Exit;
723 }
724
695 if (drv && drv->pm) { 725 if (drv && drv->pm) {
696 if (drv->pm->poweroff) { 726 if (drv->pm->poweroff) {
697 error = drv->pm->poweroff(dev); 727 error = drv->pm->poweroff(dev);
698 suspend_report_result(drv->pm->poweroff, error); 728 suspend_report_result(drv->pm->poweroff, error);
699 } 729 }
700 } else if (pci_has_legacy_pm_support(pci_dev)) {
701 error = pci_legacy_suspend(dev, PMSG_HIBERNATE);
702 } else { 730 } else {
703 pci_pm_default_suspend(pci_dev); 731 pci_pm_default_suspend(pci_dev);
704 } 732 }
705 733
734 Exit:
706 pci_fixup_device(pci_fixup_suspend, pci_dev); 735 pci_fixup_device(pci_fixup_suspend, pci_dev);
707 736
708 return error; 737 return error;
@@ -713,13 +742,14 @@ static int pci_pm_poweroff_noirq(struct device *dev)
713 struct device_driver *drv = dev->driver; 742 struct device_driver *drv = dev->driver;
714 int error = 0; 743 int error = 0;
715 744
745 if (pci_has_legacy_pm_support(to_pci_dev(dev)))
746 return pci_legacy_suspend_late(dev, PMSG_HIBERNATE);
747
716 if (drv && drv->pm) { 748 if (drv && drv->pm) {
717 if (drv->pm->poweroff_noirq) { 749 if (drv->pm->poweroff_noirq) {
718 error = drv->pm->poweroff_noirq(dev); 750 error = drv->pm->poweroff_noirq(dev);
719 suspend_report_result(drv->pm->poweroff_noirq, error); 751 suspend_report_result(drv->pm->poweroff_noirq, error);
720 } 752 }
721 } else if (pci_has_legacy_pm_support(to_pci_dev(dev))) {
722 error = pci_legacy_suspend_late(dev, PMSG_HIBERNATE);
723 } 753 }
724 754
725 return error; 755 return error;
@@ -731,14 +761,16 @@ static int pci_pm_restore(struct device *dev)
731 struct device_driver *drv = dev->driver; 761 struct device_driver *drv = dev->driver;
732 int error = 0; 762 int error = 0;
733 763
764 if (pci_has_legacy_pm_support(pci_dev)) {
765 pci_fixup_device(pci_fixup_resume, pci_dev);
766 return pci_legacy_resume(dev);
767 }
768
734 if (drv && drv->pm) { 769 if (drv && drv->pm) {
735 pci_fixup_device(pci_fixup_resume, pci_dev); 770 pci_fixup_device(pci_fixup_resume, pci_dev);
736 771
737 if (drv->pm->restore) 772 if (drv->pm->restore)
738 error = drv->pm->restore(dev); 773 error = drv->pm->restore(dev);
739 } else if (pci_has_legacy_pm_support(pci_dev)) {
740 pci_fixup_device(pci_fixup_resume, pci_dev);
741 error = pci_legacy_resume(dev);
742 } else { 774 } else {
743 error = pci_pm_default_resume(pci_dev); 775 error = pci_pm_default_resume(pci_dev);
744 } 776 }
@@ -752,14 +784,16 @@ static int pci_pm_restore_noirq(struct device *dev)
752 struct device_driver *drv = dev->driver; 784 struct device_driver *drv = dev->driver;
753 int error = 0; 785 int error = 0;
754 786
787 if (pci_has_legacy_pm_support(pci_dev)) {
788 pci_fixup_device(pci_fixup_resume_early, pci_dev);
789 return pci_legacy_resume_early(dev);
790 }
791
755 if (drv && drv->pm) { 792 if (drv && drv->pm) {
756 pci_fixup_device(pci_fixup_resume_early, pci_dev); 793 pci_fixup_device(pci_fixup_resume_early, pci_dev);
757 794
758 if (drv->pm->restore_noirq) 795 if (drv->pm->restore_noirq)
759 error = drv->pm->restore_noirq(dev); 796 error = drv->pm->restore_noirq(dev);
760 } else if (pci_has_legacy_pm_support(pci_dev)) {
761 pci_fixup_device(pci_fixup_resume_early, pci_dev);
762 error = pci_legacy_resume_early(dev);
763 } else { 797 } else {
764 pci_pm_default_resume_noirq(pci_dev); 798 pci_pm_default_resume_noirq(pci_dev);
765 } 799 }