aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Noever <andreas.noever@gmail.com>2014-06-03 16:04:09 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-06-19 17:08:41 -0400
commit7d2a01b87f1682fde87461864e6682031bfaa0a9 (patch)
tree071da51f78bd9b2091ea9663be6d0dde4069492e
parent3364f0c12795713e89ae1209081c60d64bfb4ca1 (diff)
PCI: Add pci_fixup_suspend_late quirk pass
Add pci_fixup_suspend_late as a new pci_fixup_pass. The pass is called from suspend_noirq and poweroff_noirq. Using the same pass for suspend and hibernate is consistent with resume_early which is called by resume_noirq and restore_noirq. The new quirk pass is required for Thunderbolt support on Apple hardware. Signed-off-by: Andreas Noever <andreas.noever@gmail.com> Acked-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/pci/pci-driver.c18
-rw-r--r--drivers/pci/quirks.c7
-rw-r--r--include/asm-generic/vmlinux.lds.h3
-rw-r--r--include/linux/pci.h12
4 files changed, 35 insertions, 5 deletions
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 3f8e3dbcaa7c..d04c5adafc16 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -582,7 +582,7 @@ static int pci_legacy_suspend_late(struct device *dev, pm_message_t state)
582 WARN_ONCE(pci_dev->current_state != prev, 582 WARN_ONCE(pci_dev->current_state != prev,
583 "PCI PM: Device state not saved by %pF\n", 583 "PCI PM: Device state not saved by %pF\n",
584 drv->suspend_late); 584 drv->suspend_late);
585 return 0; 585 goto Fixup;
586 } 586 }
587 } 587 }
588 588
@@ -591,6 +591,9 @@ static int pci_legacy_suspend_late(struct device *dev, pm_message_t state)
591 591
592 pci_pm_set_unknown_state(pci_dev); 592 pci_pm_set_unknown_state(pci_dev);
593 593
594Fixup:
595 pci_fixup_device(pci_fixup_suspend_late, pci_dev);
596
594 return 0; 597 return 0;
595} 598}
596 599
@@ -734,7 +737,7 @@ static int pci_pm_suspend_noirq(struct device *dev)
734 737
735 if (!pm) { 738 if (!pm) {
736 pci_save_state(pci_dev); 739 pci_save_state(pci_dev);
737 return 0; 740 goto Fixup;
738 } 741 }
739 742
740 if (pm->suspend_noirq) { 743 if (pm->suspend_noirq) {
@@ -751,7 +754,7 @@ static int pci_pm_suspend_noirq(struct device *dev)
751 WARN_ONCE(pci_dev->current_state != prev, 754 WARN_ONCE(pci_dev->current_state != prev,
752 "PCI PM: State of device not saved by %pF\n", 755 "PCI PM: State of device not saved by %pF\n",
753 pm->suspend_noirq); 756 pm->suspend_noirq);
754 return 0; 757 goto Fixup;
755 } 758 }
756 } 759 }
757 760
@@ -775,6 +778,9 @@ static int pci_pm_suspend_noirq(struct device *dev)
775 if (pci_dev->class == PCI_CLASS_SERIAL_USB_EHCI) 778 if (pci_dev->class == PCI_CLASS_SERIAL_USB_EHCI)
776 pci_write_config_word(pci_dev, PCI_COMMAND, 0); 779 pci_write_config_word(pci_dev, PCI_COMMAND, 0);
777 780
781Fixup:
782 pci_fixup_device(pci_fixup_suspend_late, pci_dev);
783
778 return 0; 784 return 0;
779} 785}
780 786
@@ -999,8 +1005,10 @@ static int pci_pm_poweroff_noirq(struct device *dev)
999 if (pci_has_legacy_pm_support(to_pci_dev(dev))) 1005 if (pci_has_legacy_pm_support(to_pci_dev(dev)))
1000 return pci_legacy_suspend_late(dev, PMSG_HIBERNATE); 1006 return pci_legacy_suspend_late(dev, PMSG_HIBERNATE);
1001 1007
1002 if (!drv || !drv->pm) 1008 if (!drv || !drv->pm) {
1009 pci_fixup_device(pci_fixup_suspend_late, pci_dev);
1003 return 0; 1010 return 0;
1011 }
1004 1012
1005 if (drv->pm->poweroff_noirq) { 1013 if (drv->pm->poweroff_noirq) {
1006 int error; 1014 int error;
@@ -1021,6 +1029,8 @@ static int pci_pm_poweroff_noirq(struct device *dev)
1021 if (pci_dev->class == PCI_CLASS_SERIAL_USB_EHCI) 1029 if (pci_dev->class == PCI_CLASS_SERIAL_USB_EHCI)
1022 pci_write_config_word(pci_dev, PCI_COMMAND, 0); 1030 pci_write_config_word(pci_dev, PCI_COMMAND, 0);
1023 1031
1032 pci_fixup_device(pci_fixup_suspend_late, pci_dev);
1033
1024 if (pcibios_pm_ops.poweroff_noirq) 1034 if (pcibios_pm_ops.poweroff_noirq)
1025 return pcibios_pm_ops.poweroff_noirq(dev); 1035 return pcibios_pm_ops.poweroff_noirq(dev);
1026 1036
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index d0f69269eb6c..03266af20d5f 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -3018,6 +3018,8 @@ extern struct pci_fixup __start_pci_fixups_resume_early[];
3018extern struct pci_fixup __end_pci_fixups_resume_early[]; 3018extern struct pci_fixup __end_pci_fixups_resume_early[];
3019extern struct pci_fixup __start_pci_fixups_suspend[]; 3019extern struct pci_fixup __start_pci_fixups_suspend[];
3020extern struct pci_fixup __end_pci_fixups_suspend[]; 3020extern struct pci_fixup __end_pci_fixups_suspend[];
3021extern struct pci_fixup __start_pci_fixups_suspend_late[];
3022extern struct pci_fixup __end_pci_fixups_suspend_late[];
3021 3023
3022static bool pci_apply_fixup_final_quirks; 3024static bool pci_apply_fixup_final_quirks;
3023 3025
@@ -3063,6 +3065,11 @@ void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev)
3063 end = __end_pci_fixups_suspend; 3065 end = __end_pci_fixups_suspend;
3064 break; 3066 break;
3065 3067
3068 case pci_fixup_suspend_late:
3069 start = __start_pci_fixups_suspend_late;
3070 end = __end_pci_fixups_suspend_late;
3071 break;
3072
3066 default: 3073 default:
3067 /* stupid compiler warning, you would think with an enum... */ 3074 /* stupid compiler warning, you would think with an enum... */
3068 return; 3075 return;
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 471ba48c7ae4..47cd98656f9d 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -268,6 +268,9 @@
268 VMLINUX_SYMBOL(__start_pci_fixups_suspend) = .; \ 268 VMLINUX_SYMBOL(__start_pci_fixups_suspend) = .; \
269 *(.pci_fixup_suspend) \ 269 *(.pci_fixup_suspend) \
270 VMLINUX_SYMBOL(__end_pci_fixups_suspend) = .; \ 270 VMLINUX_SYMBOL(__end_pci_fixups_suspend) = .; \
271 VMLINUX_SYMBOL(__start_pci_fixups_suspend_late) = .; \
272 *(.pci_fixup_suspend_late) \
273 VMLINUX_SYMBOL(__end_pci_fixups_suspend_late) = .; \
271 } \ 274 } \
272 \ 275 \
273 /* Built-in firmware blobs */ \ 276 /* Built-in firmware blobs */ \
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 466bcd111d85..295d3a9d8ffe 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1477,8 +1477,9 @@ enum pci_fixup_pass {
1477 pci_fixup_final, /* Final phase of device fixups */ 1477 pci_fixup_final, /* Final phase of device fixups */
1478 pci_fixup_enable, /* pci_enable_device() time */ 1478 pci_fixup_enable, /* pci_enable_device() time */
1479 pci_fixup_resume, /* pci_device_resume() */ 1479 pci_fixup_resume, /* pci_device_resume() */
1480 pci_fixup_suspend, /* pci_device_suspend */ 1480 pci_fixup_suspend, /* pci_device_suspend() */
1481 pci_fixup_resume_early, /* pci_device_resume_early() */ 1481 pci_fixup_resume_early, /* pci_device_resume_early() */
1482 pci_fixup_suspend_late, /* pci_device_suspend_late() */
1482}; 1483};
1483 1484
1484/* Anonymous variables would be nice... */ 1485/* Anonymous variables would be nice... */
@@ -1519,6 +1520,11 @@ enum pci_fixup_pass {
1519 DECLARE_PCI_FIXUP_SECTION(.pci_fixup_suspend, \ 1520 DECLARE_PCI_FIXUP_SECTION(.pci_fixup_suspend, \
1520 suspend##hook, vendor, device, class, \ 1521 suspend##hook, vendor, device, class, \
1521 class_shift, hook) 1522 class_shift, hook)
1523#define DECLARE_PCI_FIXUP_CLASS_SUSPEND_LATE(vendor, device, class, \
1524 class_shift, hook) \
1525 DECLARE_PCI_FIXUP_SECTION(.pci_fixup_suspend_late, \
1526 suspend_late##hook, vendor, device, \
1527 class, class_shift, hook)
1522 1528
1523#define DECLARE_PCI_FIXUP_EARLY(vendor, device, hook) \ 1529#define DECLARE_PCI_FIXUP_EARLY(vendor, device, hook) \
1524 DECLARE_PCI_FIXUP_SECTION(.pci_fixup_early, \ 1530 DECLARE_PCI_FIXUP_SECTION(.pci_fixup_early, \
@@ -1544,6 +1550,10 @@ enum pci_fixup_pass {
1544 DECLARE_PCI_FIXUP_SECTION(.pci_fixup_suspend, \ 1550 DECLARE_PCI_FIXUP_SECTION(.pci_fixup_suspend, \
1545 suspend##hook, vendor, device, \ 1551 suspend##hook, vendor, device, \
1546 PCI_ANY_ID, 0, hook) 1552 PCI_ANY_ID, 0, hook)
1553#define DECLARE_PCI_FIXUP_SUSPEND_LATE(vendor, device, hook) \
1554 DECLARE_PCI_FIXUP_SECTION(.pci_fixup_suspend_late, \
1555 suspend_late##hook, vendor, device, \
1556 PCI_ANY_ID, 0, hook)
1547 1557
1548#ifdef CONFIG_PCI_QUIRKS 1558#ifdef CONFIG_PCI_QUIRKS
1549void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev); 1559void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev);