diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-14 12:29:05 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-14 12:29:05 -0500 |
commit | d73b388459b1ee2e80f8ff9c1916d75640d7d920 (patch) | |
tree | 3e4061226f817c5728009f0bcc1d810d0c4a7b37 /drivers/pci | |
parent | 5957e33d6aec266659a71cfabcf7cf2c593ad0d2 (diff) | |
parent | 0f953bf6b4efa0daddb7c418130a9bd3ee97f7ed (diff) |
Merge branch 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6
* 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6:
PCI/PM: Report wakeup events before resuming devices
PCI/PM: Use pm_wakeup_event() directly for reporting wakeup events
PCI: sysfs: Update ROM to include default owner write access
x86/PCI: make Broadcom CNB20LE driver EMBEDDED and EXPERIMENTAL
x86/PCI: don't use native Broadcom CNB20LE driver when ACPI is available
PCI/ACPI: Request _OSC control once for each root bridge (v3)
PCI: enable pci=bfsort by default on future Dell systems
PCI/PCIe: Clear Root PME Status bits early during system resume
PCI: pci-stub: ignore zero-length id parameters
x86/PCI: irq and pci_ids patch for Intel Patsburg
PCI: Skip id checking if no id is passed
PCI: fix __pci_device_probe kernel-doc warning
PCI: make pci_restore_state return void
PCI: Disable ASPM if BIOS asks us to
PCI: Add mask bit definition for MSI-X table
PCI: MSI: Move MSI-X entry definition to pci_regs.h
Fix up trivial conflicts in drivers/net/{skge.c,sky2.c} that had in the
meantime been converted to not use legacy PCI power management, and thus
no longer use pci_restore_state() at all (and that caused trivial
conflicts with the "make pci_restore_state return void" patch)
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/msi.c | 5 | ||||
-rw-r--r-- | drivers/pci/msi.h | 6 | ||||
-rw-r--r-- | drivers/pci/pci-acpi.c | 3 | ||||
-rw-r--r-- | drivers/pci/pci-driver.c | 5 | ||||
-rw-r--r-- | drivers/pci/pci-stub.c | 7 | ||||
-rw-r--r-- | drivers/pci/pci-sysfs.c | 2 | ||||
-rw-r--r-- | drivers/pci/pci.c | 25 | ||||
-rw-r--r-- | drivers/pci/pci.h | 14 | ||||
-rw-r--r-- | drivers/pci/pcie/aer/aerdrv.c | 1 | ||||
-rw-r--r-- | drivers/pci/pcie/aer/aerdrv.h | 3 | ||||
-rw-r--r-- | drivers/pci/pcie/aspm.c | 21 | ||||
-rw-r--r-- | drivers/pci/pcie/pme.c | 31 | ||||
-rw-r--r-- | drivers/pci/pcie/portdrv.h | 5 | ||||
-rw-r--r-- | drivers/pci/pcie/portdrv_acpi.c | 23 | ||||
-rw-r--r-- | drivers/pci/pcie/portdrv_core.c | 25 | ||||
-rw-r--r-- | drivers/pci/pcie/portdrv_pci.c | 37 |
16 files changed, 102 insertions, 111 deletions
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 7c24dcef2989..44b0aeee83e5 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
@@ -168,8 +168,9 @@ static u32 __msix_mask_irq(struct msi_desc *desc, u32 flag) | |||
168 | u32 mask_bits = desc->masked; | 168 | u32 mask_bits = desc->masked; |
169 | unsigned offset = desc->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + | 169 | unsigned offset = desc->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + |
170 | PCI_MSIX_ENTRY_VECTOR_CTRL; | 170 | PCI_MSIX_ENTRY_VECTOR_CTRL; |
171 | mask_bits &= ~1; | 171 | mask_bits &= ~PCI_MSIX_ENTRY_CTRL_MASKBIT; |
172 | mask_bits |= flag; | 172 | if (flag) |
173 | mask_bits |= PCI_MSIX_ENTRY_CTRL_MASKBIT; | ||
173 | writel(mask_bits, desc->mask_base + offset); | 174 | writel(mask_bits, desc->mask_base + offset); |
174 | 175 | ||
175 | return mask_bits; | 176 | return mask_bits; |
diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h index feff3bee6fe5..65c42f80f23e 100644 --- a/drivers/pci/msi.h +++ b/drivers/pci/msi.h | |||
@@ -6,12 +6,6 @@ | |||
6 | #ifndef MSI_H | 6 | #ifndef MSI_H |
7 | #define MSI_H | 7 | #define MSI_H |
8 | 8 | ||
9 | #define PCI_MSIX_ENTRY_SIZE 16 | ||
10 | #define PCI_MSIX_ENTRY_LOWER_ADDR 0 | ||
11 | #define PCI_MSIX_ENTRY_UPPER_ADDR 4 | ||
12 | #define PCI_MSIX_ENTRY_DATA 8 | ||
13 | #define PCI_MSIX_ENTRY_VECTOR_CTRL 12 | ||
14 | |||
15 | #define msi_control_reg(base) (base + PCI_MSI_FLAGS) | 9 | #define msi_control_reg(base) (base + PCI_MSI_FLAGS) |
16 | #define msi_lower_address_reg(base) (base + PCI_MSI_ADDRESS_LO) | 10 | #define msi_lower_address_reg(base) (base + PCI_MSI_ADDRESS_LO) |
17 | #define msi_upper_address_reg(base) (base + PCI_MSI_ADDRESS_HI) | 11 | #define msi_upper_address_reg(base) (base + PCI_MSI_ADDRESS_HI) |
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 24e19c594e57..6fe0772e0e7d 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c | |||
@@ -46,9 +46,9 @@ static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context) | |||
46 | struct pci_dev *pci_dev = context; | 46 | struct pci_dev *pci_dev = context; |
47 | 47 | ||
48 | if (event == ACPI_NOTIFY_DEVICE_WAKE && pci_dev) { | 48 | if (event == ACPI_NOTIFY_DEVICE_WAKE && pci_dev) { |
49 | pci_wakeup_event(pci_dev); | ||
49 | pci_check_pme_status(pci_dev); | 50 | pci_check_pme_status(pci_dev); |
50 | pm_runtime_resume(&pci_dev->dev); | 51 | pm_runtime_resume(&pci_dev->dev); |
51 | pci_wakeup_event(pci_dev); | ||
52 | if (pci_dev->subordinate) | 52 | if (pci_dev->subordinate) |
53 | pci_pme_wakeup_bus(pci_dev->subordinate); | 53 | pci_pme_wakeup_bus(pci_dev->subordinate); |
54 | } | 54 | } |
@@ -399,6 +399,7 @@ static int __init acpi_pci_init(void) | |||
399 | 399 | ||
400 | if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) { | 400 | if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) { |
401 | printk(KERN_INFO"ACPI FADT declares the system doesn't support PCIe ASPM, so disable it\n"); | 401 | printk(KERN_INFO"ACPI FADT declares the system doesn't support PCIe ASPM, so disable it\n"); |
402 | pcie_clear_aspm(); | ||
402 | pcie_no_aspm(); | 403 | pcie_no_aspm(); |
403 | } | 404 | } |
404 | 405 | ||
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 8a6f797de8e5..88246dd46452 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
@@ -338,7 +338,7 @@ static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev, | |||
338 | } | 338 | } |
339 | 339 | ||
340 | /** | 340 | /** |
341 | * __pci_device_probe() | 341 | * __pci_device_probe - check if a driver wants to claim a specific PCI device |
342 | * @drv: driver to call to check if it wants the PCI device | 342 | * @drv: driver to call to check if it wants the PCI device |
343 | * @pci_dev: PCI device being probed | 343 | * @pci_dev: PCI device being probed |
344 | * | 344 | * |
@@ -449,7 +449,8 @@ static int pci_restore_standard_config(struct pci_dev *pci_dev) | |||
449 | return error; | 449 | return error; |
450 | } | 450 | } |
451 | 451 | ||
452 | return pci_restore_state(pci_dev); | 452 | pci_restore_state(pci_dev); |
453 | return 0; | ||
453 | } | 454 | } |
454 | 455 | ||
455 | static void pci_pm_default_resume_early(struct pci_dev *pci_dev) | 456 | static void pci_pm_default_resume_early(struct pci_dev *pci_dev) |
diff --git a/drivers/pci/pci-stub.c b/drivers/pci/pci-stub.c index f7b68ca6cc98..775e933c2225 100644 --- a/drivers/pci/pci-stub.c +++ b/drivers/pci/pci-stub.c | |||
@@ -47,6 +47,10 @@ static int __init pci_stub_init(void) | |||
47 | if (rc) | 47 | if (rc) |
48 | return rc; | 48 | return rc; |
49 | 49 | ||
50 | /* no ids passed actually */ | ||
51 | if (ids[0] == '\0') | ||
52 | return 0; | ||
53 | |||
50 | /* add ids specified in the module parameter */ | 54 | /* add ids specified in the module parameter */ |
51 | p = ids; | 55 | p = ids; |
52 | while ((id = strsep(&p, ","))) { | 56 | while ((id = strsep(&p, ","))) { |
@@ -54,6 +58,9 @@ static int __init pci_stub_init(void) | |||
54 | subdevice = PCI_ANY_ID, class=0, class_mask=0; | 58 | subdevice = PCI_ANY_ID, class=0, class_mask=0; |
55 | int fields; | 59 | int fields; |
56 | 60 | ||
61 | if (!strlen(id)) | ||
62 | continue; | ||
63 | |||
57 | fields = sscanf(id, "%x:%x:%x:%x:%x:%x", | 64 | fields = sscanf(id, "%x:%x:%x:%x:%x:%x", |
58 | &vendor, &device, &subvendor, &subdevice, | 65 | &vendor, &device, &subvendor, &subdevice, |
59 | &class, &class_mask); | 66 | &class, &class_mask); |
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 63d5042f2079..8ecaac983923 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c | |||
@@ -1149,7 +1149,7 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev) | |||
1149 | sysfs_bin_attr_init(attr); | 1149 | sysfs_bin_attr_init(attr); |
1150 | attr->size = rom_size; | 1150 | attr->size = rom_size; |
1151 | attr->attr.name = "rom"; | 1151 | attr->attr.name = "rom"; |
1152 | attr->attr.mode = S_IRUSR; | 1152 | attr->attr.mode = S_IRUSR | S_IWUSR; |
1153 | attr->read = pci_read_rom; | 1153 | attr->read = pci_read_rom; |
1154 | attr->write = pci_write_rom; | 1154 | attr->write = pci_write_rom; |
1155 | retval = sysfs_create_bin_file(&pdev->dev.kobj, attr); | 1155 | retval = sysfs_create_bin_file(&pdev->dev.kobj, attr); |
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 710c8a29be0d..b714d787bddd 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -937,14 +937,13 @@ pci_save_state(struct pci_dev *dev) | |||
937 | * pci_restore_state - Restore the saved state of a PCI device | 937 | * pci_restore_state - Restore the saved state of a PCI device |
938 | * @dev: - PCI device that we're dealing with | 938 | * @dev: - PCI device that we're dealing with |
939 | */ | 939 | */ |
940 | int | 940 | void pci_restore_state(struct pci_dev *dev) |
941 | pci_restore_state(struct pci_dev *dev) | ||
942 | { | 941 | { |
943 | int i; | 942 | int i; |
944 | u32 val; | 943 | u32 val; |
945 | 944 | ||
946 | if (!dev->state_saved) | 945 | if (!dev->state_saved) |
947 | return 0; | 946 | return; |
948 | 947 | ||
949 | /* PCI Express register must be restored first */ | 948 | /* PCI Express register must be restored first */ |
950 | pci_restore_pcie_state(dev); | 949 | pci_restore_pcie_state(dev); |
@@ -968,8 +967,6 @@ pci_restore_state(struct pci_dev *dev) | |||
968 | pci_restore_iov_state(dev); | 967 | pci_restore_iov_state(dev); |
969 | 968 | ||
970 | dev->state_saved = false; | 969 | dev->state_saved = false; |
971 | |||
972 | return 0; | ||
973 | } | 970 | } |
974 | 971 | ||
975 | static int do_pci_enable_device(struct pci_dev *dev, int bars) | 972 | static int do_pci_enable_device(struct pci_dev *dev, int bars) |
@@ -1300,22 +1297,6 @@ bool pci_check_pme_status(struct pci_dev *dev) | |||
1300 | return ret; | 1297 | return ret; |
1301 | } | 1298 | } |
1302 | 1299 | ||
1303 | /* | ||
1304 | * Time to wait before the system can be put into a sleep state after reporting | ||
1305 | * a wakeup event signaled by a PCI device. | ||
1306 | */ | ||
1307 | #define PCI_WAKEUP_COOLDOWN 100 | ||
1308 | |||
1309 | /** | ||
1310 | * pci_wakeup_event - Report a wakeup event related to a given PCI device. | ||
1311 | * @dev: Device to report the wakeup event for. | ||
1312 | */ | ||
1313 | void pci_wakeup_event(struct pci_dev *dev) | ||
1314 | { | ||
1315 | if (device_may_wakeup(&dev->dev)) | ||
1316 | pm_wakeup_event(&dev->dev, PCI_WAKEUP_COOLDOWN); | ||
1317 | } | ||
1318 | |||
1319 | /** | 1300 | /** |
1320 | * pci_pme_wakeup - Wake up a PCI device if its PME Status bit is set. | 1301 | * pci_pme_wakeup - Wake up a PCI device if its PME Status bit is set. |
1321 | * @dev: Device to handle. | 1302 | * @dev: Device to handle. |
@@ -1327,8 +1308,8 @@ void pci_wakeup_event(struct pci_dev *dev) | |||
1327 | static int pci_pme_wakeup(struct pci_dev *dev, void *ign) | 1308 | static int pci_pme_wakeup(struct pci_dev *dev, void *ign) |
1328 | { | 1309 | { |
1329 | if (pci_check_pme_status(dev)) { | 1310 | if (pci_check_pme_status(dev)) { |
1330 | pm_request_resume(&dev->dev); | ||
1331 | pci_wakeup_event(dev); | 1311 | pci_wakeup_event(dev); |
1312 | pm_request_resume(&dev->dev); | ||
1332 | } | 1313 | } |
1333 | return 0; | 1314 | return 0; |
1334 | } | 1315 | } |
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 7d33f6673868..f69d6e0fda75 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
@@ -74,6 +74,12 @@ extern void pci_pm_init(struct pci_dev *dev); | |||
74 | extern void platform_pci_wakeup_init(struct pci_dev *dev); | 74 | extern void platform_pci_wakeup_init(struct pci_dev *dev); |
75 | extern void pci_allocate_cap_save_buffers(struct pci_dev *dev); | 75 | extern void pci_allocate_cap_save_buffers(struct pci_dev *dev); |
76 | 76 | ||
77 | static inline void pci_wakeup_event(struct pci_dev *dev) | ||
78 | { | ||
79 | /* Wait 100 ms before the system can be put into a sleep state. */ | ||
80 | pm_wakeup_event(&dev->dev, 100); | ||
81 | } | ||
82 | |||
77 | static inline bool pci_is_bridge(struct pci_dev *pci_dev) | 83 | static inline bool pci_is_bridge(struct pci_dev *pci_dev) |
78 | { | 84 | { |
79 | return !!(pci_dev->subordinate); | 85 | return !!(pci_dev->subordinate); |
@@ -140,14 +146,6 @@ static inline void pci_no_msi(void) { } | |||
140 | static inline void pci_msi_init_pci_dev(struct pci_dev *dev) { } | 146 | static inline void pci_msi_init_pci_dev(struct pci_dev *dev) { } |
141 | #endif | 147 | #endif |
142 | 148 | ||
143 | #ifdef CONFIG_PCIEAER | ||
144 | void pci_no_aer(void); | ||
145 | bool pci_aer_available(void); | ||
146 | #else | ||
147 | static inline void pci_no_aer(void) { } | ||
148 | static inline bool pci_aer_available(void) { return false; } | ||
149 | #endif | ||
150 | |||
151 | static inline int pci_no_d1d2(struct pci_dev *dev) | 149 | static inline int pci_no_d1d2(struct pci_dev *dev) |
152 | { | 150 | { |
153 | unsigned int parent_dstates = 0; | 151 | unsigned int parent_dstates = 0; |
diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c index 2b2b6508efde..58ad7917553c 100644 --- a/drivers/pci/pcie/aer/aerdrv.c +++ b/drivers/pci/pcie/aer/aerdrv.c | |||
@@ -17,6 +17,7 @@ | |||
17 | 17 | ||
18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
19 | #include <linux/pci.h> | 19 | #include <linux/pci.h> |
20 | #include <linux/pci-acpi.h> | ||
20 | #include <linux/sched.h> | 21 | #include <linux/sched.h> |
21 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
22 | #include <linux/errno.h> | 23 | #include <linux/errno.h> |
diff --git a/drivers/pci/pcie/aer/aerdrv.h b/drivers/pci/pcie/aer/aerdrv.h index 9656e3060412..80c11d131499 100644 --- a/drivers/pci/pcie/aer/aerdrv.h +++ b/drivers/pci/pcie/aer/aerdrv.h | |||
@@ -132,7 +132,6 @@ static inline int aer_osc_setup(struct pcie_device *pciedev) | |||
132 | 132 | ||
133 | #ifdef CONFIG_ACPI_APEI | 133 | #ifdef CONFIG_ACPI_APEI |
134 | extern int pcie_aer_get_firmware_first(struct pci_dev *pci_dev); | 134 | extern int pcie_aer_get_firmware_first(struct pci_dev *pci_dev); |
135 | extern bool aer_acpi_firmware_first(void); | ||
136 | #else | 135 | #else |
137 | static inline int pcie_aer_get_firmware_first(struct pci_dev *pci_dev) | 136 | static inline int pcie_aer_get_firmware_first(struct pci_dev *pci_dev) |
138 | { | 137 | { |
@@ -140,8 +139,6 @@ static inline int pcie_aer_get_firmware_first(struct pci_dev *pci_dev) | |||
140 | return pci_dev->__aer_firmware_first; | 139 | return pci_dev->__aer_firmware_first; |
141 | return 0; | 140 | return 0; |
142 | } | 141 | } |
143 | |||
144 | static inline bool aer_acpi_firmware_first(void) { return false; } | ||
145 | #endif | 142 | #endif |
146 | 143 | ||
147 | static inline void pcie_aer_force_firmware_first(struct pci_dev *pci_dev, | 144 | static inline void pcie_aer_force_firmware_first(struct pci_dev *pci_dev, |
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index 71222814c1ec..3188cd96b338 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c | |||
@@ -68,7 +68,7 @@ struct pcie_link_state { | |||
68 | struct aspm_latency acceptable[8]; | 68 | struct aspm_latency acceptable[8]; |
69 | }; | 69 | }; |
70 | 70 | ||
71 | static int aspm_disabled, aspm_force; | 71 | static int aspm_disabled, aspm_force, aspm_clear_state; |
72 | static DEFINE_MUTEX(aspm_lock); | 72 | static DEFINE_MUTEX(aspm_lock); |
73 | static LIST_HEAD(link_list); | 73 | static LIST_HEAD(link_list); |
74 | 74 | ||
@@ -139,7 +139,7 @@ static void pcie_set_clkpm(struct pcie_link_state *link, int enable) | |||
139 | { | 139 | { |
140 | /* Don't enable Clock PM if the link is not Clock PM capable */ | 140 | /* Don't enable Clock PM if the link is not Clock PM capable */ |
141 | if (!link->clkpm_capable && enable) | 141 | if (!link->clkpm_capable && enable) |
142 | return; | 142 | enable = 0; |
143 | /* Need nothing if the specified equals to current state */ | 143 | /* Need nothing if the specified equals to current state */ |
144 | if (link->clkpm_enabled == enable) | 144 | if (link->clkpm_enabled == enable) |
145 | return; | 145 | return; |
@@ -498,6 +498,10 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev) | |||
498 | struct pci_dev *child; | 498 | struct pci_dev *child; |
499 | int pos; | 499 | int pos; |
500 | u32 reg32; | 500 | u32 reg32; |
501 | |||
502 | if (aspm_clear_state) | ||
503 | return -EINVAL; | ||
504 | |||
501 | /* | 505 | /* |
502 | * Some functions in a slot might not all be PCIe functions, | 506 | * Some functions in a slot might not all be PCIe functions, |
503 | * very strange. Disable ASPM for the whole slot | 507 | * very strange. Disable ASPM for the whole slot |
@@ -563,12 +567,15 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev) | |||
563 | struct pcie_link_state *link; | 567 | struct pcie_link_state *link; |
564 | int blacklist = !!pcie_aspm_sanity_check(pdev); | 568 | int blacklist = !!pcie_aspm_sanity_check(pdev); |
565 | 569 | ||
566 | if (aspm_disabled || !pci_is_pcie(pdev) || pdev->link_state) | 570 | if (!pci_is_pcie(pdev) || pdev->link_state) |
567 | return; | 571 | return; |
568 | if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT && | 572 | if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT && |
569 | pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) | 573 | pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) |
570 | return; | 574 | return; |
571 | 575 | ||
576 | if (aspm_disabled && !aspm_clear_state) | ||
577 | return; | ||
578 | |||
572 | /* VIA has a strange chipset, root port is under a bridge */ | 579 | /* VIA has a strange chipset, root port is under a bridge */ |
573 | if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT && | 580 | if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT && |
574 | pdev->bus->self) | 581 | pdev->bus->self) |
@@ -641,7 +648,7 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev) | |||
641 | struct pci_dev *parent = pdev->bus->self; | 648 | struct pci_dev *parent = pdev->bus->self; |
642 | struct pcie_link_state *link, *root, *parent_link; | 649 | struct pcie_link_state *link, *root, *parent_link; |
643 | 650 | ||
644 | if (aspm_disabled || !pci_is_pcie(pdev) || | 651 | if ((aspm_disabled && !aspm_clear_state) || !pci_is_pcie(pdev) || |
645 | !parent || !parent->link_state) | 652 | !parent || !parent->link_state) |
646 | return; | 653 | return; |
647 | if ((parent->pcie_type != PCI_EXP_TYPE_ROOT_PORT) && | 654 | if ((parent->pcie_type != PCI_EXP_TYPE_ROOT_PORT) && |
@@ -899,6 +906,12 @@ static int __init pcie_aspm_disable(char *str) | |||
899 | 906 | ||
900 | __setup("pcie_aspm=", pcie_aspm_disable); | 907 | __setup("pcie_aspm=", pcie_aspm_disable); |
901 | 908 | ||
909 | void pcie_clear_aspm(void) | ||
910 | { | ||
911 | if (!aspm_force) | ||
912 | aspm_clear_state = 1; | ||
913 | } | ||
914 | |||
902 | void pcie_no_aspm(void) | 915 | void pcie_no_aspm(void) |
903 | { | 916 | { |
904 | if (!aspm_force) | 917 | if (!aspm_force) |
diff --git a/drivers/pci/pcie/pme.c b/drivers/pci/pcie/pme.c index 2f3c90407227..0057344a3fcb 100644 --- a/drivers/pci/pcie/pme.c +++ b/drivers/pci/pcie/pme.c | |||
@@ -26,9 +26,6 @@ | |||
26 | #include "../pci.h" | 26 | #include "../pci.h" |
27 | #include "portdrv.h" | 27 | #include "portdrv.h" |
28 | 28 | ||
29 | #define PCI_EXP_RTSTA_PME 0x10000 /* PME status */ | ||
30 | #define PCI_EXP_RTSTA_PENDING 0x20000 /* PME pending */ | ||
31 | |||
32 | /* | 29 | /* |
33 | * If this switch is set, MSI will not be used for PCIe PME signaling. This | 30 | * If this switch is set, MSI will not be used for PCIe PME signaling. This |
34 | * causes the PCIe port driver to use INTx interrupts only, but it turns out | 31 | * causes the PCIe port driver to use INTx interrupts only, but it turns out |
@@ -74,22 +71,6 @@ void pcie_pme_interrupt_enable(struct pci_dev *dev, bool enable) | |||
74 | } | 71 | } |
75 | 72 | ||
76 | /** | 73 | /** |
77 | * pcie_pme_clear_status - Clear root port PME interrupt status. | ||
78 | * @dev: PCIe root port or event collector. | ||
79 | */ | ||
80 | static void pcie_pme_clear_status(struct pci_dev *dev) | ||
81 | { | ||
82 | int rtsta_pos; | ||
83 | u32 rtsta; | ||
84 | |||
85 | rtsta_pos = pci_pcie_cap(dev) + PCI_EXP_RTSTA; | ||
86 | |||
87 | pci_read_config_dword(dev, rtsta_pos, &rtsta); | ||
88 | rtsta |= PCI_EXP_RTSTA_PME; | ||
89 | pci_write_config_dword(dev, rtsta_pos, rtsta); | ||
90 | } | ||
91 | |||
92 | /** | ||
93 | * pcie_pme_walk_bus - Scan a PCI bus for devices asserting PME#. | 74 | * pcie_pme_walk_bus - Scan a PCI bus for devices asserting PME#. |
94 | * @bus: PCI bus to scan. | 75 | * @bus: PCI bus to scan. |
95 | * | 76 | * |
@@ -103,8 +84,8 @@ static bool pcie_pme_walk_bus(struct pci_bus *bus) | |||
103 | list_for_each_entry(dev, &bus->devices, bus_list) { | 84 | list_for_each_entry(dev, &bus->devices, bus_list) { |
104 | /* Skip PCIe devices in case we started from a root port. */ | 85 | /* Skip PCIe devices in case we started from a root port. */ |
105 | if (!pci_is_pcie(dev) && pci_check_pme_status(dev)) { | 86 | if (!pci_is_pcie(dev) && pci_check_pme_status(dev)) { |
106 | pm_request_resume(&dev->dev); | ||
107 | pci_wakeup_event(dev); | 87 | pci_wakeup_event(dev); |
88 | pm_request_resume(&dev->dev); | ||
108 | ret = true; | 89 | ret = true; |
109 | } | 90 | } |
110 | 91 | ||
@@ -206,8 +187,8 @@ static void pcie_pme_handle_request(struct pci_dev *port, u16 req_id) | |||
206 | /* The device is there, but we have to check its PME status. */ | 187 | /* The device is there, but we have to check its PME status. */ |
207 | found = pci_check_pme_status(dev); | 188 | found = pci_check_pme_status(dev); |
208 | if (found) { | 189 | if (found) { |
209 | pm_request_resume(&dev->dev); | ||
210 | pci_wakeup_event(dev); | 190 | pci_wakeup_event(dev); |
191 | pm_request_resume(&dev->dev); | ||
211 | } | 192 | } |
212 | pci_dev_put(dev); | 193 | pci_dev_put(dev); |
213 | } else if (devfn) { | 194 | } else if (devfn) { |
@@ -253,7 +234,7 @@ static void pcie_pme_work_fn(struct work_struct *work) | |||
253 | * Clear PME status of the port. If there are other | 234 | * Clear PME status of the port. If there are other |
254 | * pending PMEs, the status will be set again. | 235 | * pending PMEs, the status will be set again. |
255 | */ | 236 | */ |
256 | pcie_pme_clear_status(port); | 237 | pcie_clear_root_pme_status(port); |
257 | 238 | ||
258 | spin_unlock_irq(&data->lock); | 239 | spin_unlock_irq(&data->lock); |
259 | pcie_pme_handle_request(port, rtsta & 0xffff); | 240 | pcie_pme_handle_request(port, rtsta & 0xffff); |
@@ -378,7 +359,7 @@ static int pcie_pme_probe(struct pcie_device *srv) | |||
378 | 359 | ||
379 | port = srv->port; | 360 | port = srv->port; |
380 | pcie_pme_interrupt_enable(port, false); | 361 | pcie_pme_interrupt_enable(port, false); |
381 | pcie_pme_clear_status(port); | 362 | pcie_clear_root_pme_status(port); |
382 | 363 | ||
383 | ret = request_irq(srv->irq, pcie_pme_irq, IRQF_SHARED, "PCIe PME", srv); | 364 | ret = request_irq(srv->irq, pcie_pme_irq, IRQF_SHARED, "PCIe PME", srv); |
384 | if (ret) { | 365 | if (ret) { |
@@ -402,7 +383,7 @@ static int pcie_pme_suspend(struct pcie_device *srv) | |||
402 | 383 | ||
403 | spin_lock_irq(&data->lock); | 384 | spin_lock_irq(&data->lock); |
404 | pcie_pme_interrupt_enable(port, false); | 385 | pcie_pme_interrupt_enable(port, false); |
405 | pcie_pme_clear_status(port); | 386 | pcie_clear_root_pme_status(port); |
406 | data->noirq = true; | 387 | data->noirq = true; |
407 | spin_unlock_irq(&data->lock); | 388 | spin_unlock_irq(&data->lock); |
408 | 389 | ||
@@ -422,7 +403,7 @@ static int pcie_pme_resume(struct pcie_device *srv) | |||
422 | 403 | ||
423 | spin_lock_irq(&data->lock); | 404 | spin_lock_irq(&data->lock); |
424 | data->noirq = false; | 405 | data->noirq = false; |
425 | pcie_pme_clear_status(port); | 406 | pcie_clear_root_pme_status(port); |
426 | pcie_pme_interrupt_enable(port, true); | 407 | pcie_pme_interrupt_enable(port, true); |
427 | spin_unlock_irq(&data->lock); | 408 | spin_unlock_irq(&data->lock); |
428 | 409 | ||
diff --git a/drivers/pci/pcie/portdrv.h b/drivers/pci/pcie/portdrv.h index 7b5aba0a3291..bd00a01aef14 100644 --- a/drivers/pci/pcie/portdrv.h +++ b/drivers/pci/pcie/portdrv.h | |||
@@ -20,9 +20,6 @@ | |||
20 | 20 | ||
21 | #define get_descriptor_id(type, service) (((type - 4) << 4) | service) | 21 | #define get_descriptor_id(type, service) (((type - 4) << 4) | service) |
22 | 22 | ||
23 | extern bool pcie_ports_disabled; | ||
24 | extern bool pcie_ports_auto; | ||
25 | |||
26 | extern struct bus_type pcie_port_bus_type; | 23 | extern struct bus_type pcie_port_bus_type; |
27 | extern int pcie_port_device_register(struct pci_dev *dev); | 24 | extern int pcie_port_device_register(struct pci_dev *dev); |
28 | #ifdef CONFIG_PM | 25 | #ifdef CONFIG_PM |
@@ -35,6 +32,8 @@ extern void pcie_port_bus_unregister(void); | |||
35 | 32 | ||
36 | struct pci_dev; | 33 | struct pci_dev; |
37 | 34 | ||
35 | extern void pcie_clear_root_pme_status(struct pci_dev *dev); | ||
36 | |||
38 | #ifdef CONFIG_PCIE_PME | 37 | #ifdef CONFIG_PCIE_PME |
39 | extern bool pcie_pme_msi_disabled; | 38 | extern bool pcie_pme_msi_disabled; |
40 | 39 | ||
diff --git a/drivers/pci/pcie/portdrv_acpi.c b/drivers/pci/pcie/portdrv_acpi.c index 5982b6a63b89..a86b56e5f2f2 100644 --- a/drivers/pci/pcie/portdrv_acpi.c +++ b/drivers/pci/pcie/portdrv_acpi.c | |||
@@ -33,7 +33,7 @@ | |||
33 | */ | 33 | */ |
34 | int pcie_port_acpi_setup(struct pci_dev *port, int *srv_mask) | 34 | int pcie_port_acpi_setup(struct pci_dev *port, int *srv_mask) |
35 | { | 35 | { |
36 | acpi_status status; | 36 | struct acpi_pci_root *root; |
37 | acpi_handle handle; | 37 | acpi_handle handle; |
38 | u32 flags; | 38 | u32 flags; |
39 | 39 | ||
@@ -44,26 +44,11 @@ int pcie_port_acpi_setup(struct pci_dev *port, int *srv_mask) | |||
44 | if (!handle) | 44 | if (!handle) |
45 | return -EINVAL; | 45 | return -EINVAL; |
46 | 46 | ||
47 | flags = OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL | 47 | root = acpi_pci_find_root(handle); |
48 | | OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | 48 | if (!root) |
49 | | OSC_PCI_EXPRESS_PME_CONTROL; | ||
50 | |||
51 | if (pci_aer_available()) { | ||
52 | if (aer_acpi_firmware_first()) | ||
53 | dev_dbg(&port->dev, "PCIe errors handled by BIOS.\n"); | ||
54 | else | ||
55 | flags |= OSC_PCI_EXPRESS_AER_CONTROL; | ||
56 | } | ||
57 | |||
58 | status = acpi_pci_osc_control_set(handle, &flags, | ||
59 | OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); | ||
60 | if (ACPI_FAILURE(status)) { | ||
61 | dev_dbg(&port->dev, "ACPI _OSC request failed (code %d)\n", | ||
62 | status); | ||
63 | return -ENODEV; | 49 | return -ENODEV; |
64 | } | ||
65 | 50 | ||
66 | dev_info(&port->dev, "ACPI _OSC control granted for 0x%02x\n", flags); | 51 | flags = root->osc_control_set; |
67 | 52 | ||
68 | *srv_mask = PCIE_PORT_SERVICE_VC; | 53 | *srv_mask = PCIE_PORT_SERVICE_VC; |
69 | if (flags & OSC_PCI_EXPRESS_NATIVE_HP_CONTROL) | 54 | if (flags & OSC_PCI_EXPRESS_NATIVE_HP_CONTROL) |
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index a9c222d79ebc..5130d0d22390 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c | |||
@@ -241,17 +241,17 @@ static int get_port_device_capability(struct pci_dev *dev) | |||
241 | int cap_mask; | 241 | int cap_mask; |
242 | int err; | 242 | int err; |
243 | 243 | ||
244 | if (pcie_ports_disabled) | ||
245 | return 0; | ||
246 | |||
244 | err = pcie_port_platform_notify(dev, &cap_mask); | 247 | err = pcie_port_platform_notify(dev, &cap_mask); |
245 | if (pcie_ports_auto) { | 248 | if (!pcie_ports_auto) { |
246 | if (err) { | ||
247 | pcie_no_aspm(); | ||
248 | return 0; | ||
249 | } | ||
250 | } else { | ||
251 | cap_mask = PCIE_PORT_SERVICE_PME | PCIE_PORT_SERVICE_HP | 249 | cap_mask = PCIE_PORT_SERVICE_PME | PCIE_PORT_SERVICE_HP |
252 | | PCIE_PORT_SERVICE_VC; | 250 | | PCIE_PORT_SERVICE_VC; |
253 | if (pci_aer_available()) | 251 | if (pci_aer_available()) |
254 | cap_mask |= PCIE_PORT_SERVICE_AER; | 252 | cap_mask |= PCIE_PORT_SERVICE_AER; |
253 | } else if (err) { | ||
254 | return 0; | ||
255 | } | 255 | } |
256 | 256 | ||
257 | pos = pci_pcie_cap(dev); | 257 | pos = pci_pcie_cap(dev); |
@@ -349,15 +349,18 @@ int pcie_port_device_register(struct pci_dev *dev) | |||
349 | int status, capabilities, i, nr_service; | 349 | int status, capabilities, i, nr_service; |
350 | int irqs[PCIE_PORT_DEVICE_MAXSERVICES]; | 350 | int irqs[PCIE_PORT_DEVICE_MAXSERVICES]; |
351 | 351 | ||
352 | /* Get and check PCI Express port services */ | ||
353 | capabilities = get_port_device_capability(dev); | ||
354 | if (!capabilities) | ||
355 | return -ENODEV; | ||
356 | |||
357 | /* Enable PCI Express port device */ | 352 | /* Enable PCI Express port device */ |
358 | status = pci_enable_device(dev); | 353 | status = pci_enable_device(dev); |
359 | if (status) | 354 | if (status) |
360 | return status; | 355 | return status; |
356 | |||
357 | /* Get and check PCI Express port services */ | ||
358 | capabilities = get_port_device_capability(dev); | ||
359 | if (!capabilities) { | ||
360 | pcie_no_aspm(); | ||
361 | return 0; | ||
362 | } | ||
363 | |||
361 | pci_set_master(dev); | 364 | pci_set_master(dev); |
362 | /* | 365 | /* |
363 | * Initialize service irqs. Don't use service devices that | 366 | * Initialize service irqs. Don't use service devices that |
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index f9033e190fb6..e0610bda1dea 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c | |||
@@ -57,6 +57,22 @@ __setup("pcie_ports=", pcie_port_setup); | |||
57 | 57 | ||
58 | /* global data */ | 58 | /* global data */ |
59 | 59 | ||
60 | /** | ||
61 | * pcie_clear_root_pme_status - Clear root port PME interrupt status. | ||
62 | * @dev: PCIe root port or event collector. | ||
63 | */ | ||
64 | void pcie_clear_root_pme_status(struct pci_dev *dev) | ||
65 | { | ||
66 | int rtsta_pos; | ||
67 | u32 rtsta; | ||
68 | |||
69 | rtsta_pos = pci_pcie_cap(dev) + PCI_EXP_RTSTA; | ||
70 | |||
71 | pci_read_config_dword(dev, rtsta_pos, &rtsta); | ||
72 | rtsta |= PCI_EXP_RTSTA_PME; | ||
73 | pci_write_config_dword(dev, rtsta_pos, rtsta); | ||
74 | } | ||
75 | |||
60 | static int pcie_portdrv_restore_config(struct pci_dev *dev) | 76 | static int pcie_portdrv_restore_config(struct pci_dev *dev) |
61 | { | 77 | { |
62 | int retval; | 78 | int retval; |
@@ -69,6 +85,20 @@ static int pcie_portdrv_restore_config(struct pci_dev *dev) | |||
69 | } | 85 | } |
70 | 86 | ||
71 | #ifdef CONFIG_PM | 87 | #ifdef CONFIG_PM |
88 | static int pcie_port_resume_noirq(struct device *dev) | ||
89 | { | ||
90 | struct pci_dev *pdev = to_pci_dev(dev); | ||
91 | |||
92 | /* | ||
93 | * Some BIOSes forget to clear Root PME Status bits after system wakeup | ||
94 | * which breaks ACPI-based runtime wakeup on PCI Express, so clear those | ||
95 | * bits now just in case (shouldn't hurt). | ||
96 | */ | ||
97 | if(pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT) | ||
98 | pcie_clear_root_pme_status(pdev); | ||
99 | return 0; | ||
100 | } | ||
101 | |||
72 | static const struct dev_pm_ops pcie_portdrv_pm_ops = { | 102 | static const struct dev_pm_ops pcie_portdrv_pm_ops = { |
73 | .suspend = pcie_port_device_suspend, | 103 | .suspend = pcie_port_device_suspend, |
74 | .resume = pcie_port_device_resume, | 104 | .resume = pcie_port_device_resume, |
@@ -76,6 +106,7 @@ static const struct dev_pm_ops pcie_portdrv_pm_ops = { | |||
76 | .thaw = pcie_port_device_resume, | 106 | .thaw = pcie_port_device_resume, |
77 | .poweroff = pcie_port_device_suspend, | 107 | .poweroff = pcie_port_device_suspend, |
78 | .restore = pcie_port_device_resume, | 108 | .restore = pcie_port_device_resume, |
109 | .resume_noirq = pcie_port_resume_noirq, | ||
79 | }; | 110 | }; |
80 | 111 | ||
81 | #define PCIE_PORTDRV_PM_OPS (&pcie_portdrv_pm_ops) | 112 | #define PCIE_PORTDRV_PM_OPS (&pcie_portdrv_pm_ops) |
@@ -327,10 +358,8 @@ static int __init pcie_portdrv_init(void) | |||
327 | { | 358 | { |
328 | int retval; | 359 | int retval; |
329 | 360 | ||
330 | if (pcie_ports_disabled) { | 361 | if (pcie_ports_disabled) |
331 | pcie_no_aspm(); | 362 | return pci_register_driver(&pcie_portdriver); |
332 | return -EACCES; | ||
333 | } | ||
334 | 363 | ||
335 | dmi_check_system(pcie_portdrv_dmi_table); | 364 | dmi_check_system(pcie_portdrv_dmi_table); |
336 | 365 | ||