aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/PCI/pci.txt12
-rw-r--r--drivers/acpi/pci_root.c19
-rw-r--r--drivers/pci/host-bridge.c6
-rw-r--r--drivers/pci/pci-acpi.c83
-rw-r--r--drivers/pci/pci-label.c11
-rw-r--r--drivers/pci/pci.c11
-rw-r--r--drivers/pci/pci.h2
-rw-r--r--drivers/pci/pcie/aspm.c18
-rw-r--r--drivers/pci/quirks.c2
-rw-r--r--include/linux/pci-acpi.h5
-rw-r--r--include/linux/pci-aspm.h4
-rw-r--r--include/linux/pci.h1
12 files changed, 118 insertions, 56 deletions
diff --git a/Documentation/PCI/pci.txt b/Documentation/PCI/pci.txt
index 9518006f6675..123881f62219 100644
--- a/Documentation/PCI/pci.txt
+++ b/Documentation/PCI/pci.txt
@@ -564,14 +564,14 @@ to be handled by platform and generic code, not individual drivers.
5648. Vendor and device identifications 5648. Vendor and device identifications
565~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 565~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
566 566
567One is not required to add new device ids to include/linux/pci_ids.h. 567Do not add new device or vendor IDs to include/linux/pci_ids.h unless they
568Please add PCI_VENDOR_ID_xxx for vendors and a hex constant for device ids. 568are shared across multiple drivers. You can add private definitions in
569your driver if they're helpful, or just use plain hex constants.
569 570
570PCI_VENDOR_ID_xxx constants are re-used. The device ids are arbitrary 571The device IDs are arbitrary hex numbers (vendor controlled) and normally used
571hex numbers (vendor controlled) and normally used only in a single 572only in a single location, the pci_device_id table.
572location, the pci_device_id table.
573 573
574Please DO submit new vendor/device ids to pciids.sourceforge.net project. 574Please DO submit new vendor/device IDs to http://pciids.sourceforge.net/.
575 575
576 576
577 577
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 68a5f712cd19..1b5569c092c6 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -423,8 +423,7 @@ out:
423} 423}
424EXPORT_SYMBOL(acpi_pci_osc_control_set); 424EXPORT_SYMBOL(acpi_pci_osc_control_set);
425 425
426static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm, 426static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm)
427 int *clear_aspm)
428{ 427{
429 u32 support, control, requested; 428 u32 support, control, requested;
430 acpi_status status; 429 acpi_status status;
@@ -495,10 +494,12 @@ static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm,
495 decode_osc_control(root, "OS now controls", control); 494 decode_osc_control(root, "OS now controls", control);
496 if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) { 495 if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) {
497 /* 496 /*
498 * We have ASPM control, but the FADT indicates 497 * We have ASPM control, but the FADT indicates that
499 * that it's unsupported. Clear it. 498 * it's unsupported. Leave existing configuration
499 * intact and prevent the OS from touching it.
500 */ 500 */
501 *clear_aspm = 1; 501 dev_info(&device->dev, "FADT indicates ASPM is unsupported, using BIOS configuration\n");
502 *no_aspm = 1;
502 } 503 }
503 } else { 504 } else {
504 decode_osc_control(root, "OS requested", requested); 505 decode_osc_control(root, "OS requested", requested);
@@ -525,7 +526,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
525 int result; 526 int result;
526 struct acpi_pci_root *root; 527 struct acpi_pci_root *root;
527 acpi_handle handle = device->handle; 528 acpi_handle handle = device->handle;
528 int no_aspm = 0, clear_aspm = 0; 529 int no_aspm = 0;
529 bool hotadd = system_state != SYSTEM_BOOTING; 530 bool hotadd = system_state != SYSTEM_BOOTING;
530 531
531 root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL); 532 root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
@@ -584,7 +585,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
584 585
585 root->mcfg_addr = acpi_pci_root_get_mcfg_addr(handle); 586 root->mcfg_addr = acpi_pci_root_get_mcfg_addr(handle);
586 587
587 negotiate_os_control(root, &no_aspm, &clear_aspm); 588 negotiate_os_control(root, &no_aspm);
588 589
589 /* 590 /*
590 * TBD: Need PCI interface for enumeration/configuration of roots. 591 * TBD: Need PCI interface for enumeration/configuration of roots.
@@ -607,10 +608,6 @@ static int acpi_pci_root_add(struct acpi_device *device,
607 goto remove_dmar; 608 goto remove_dmar;
608 } 609 }
609 610
610 if (clear_aspm) {
611 dev_info(&device->dev, "Disabling ASPM (FADT indicates it is unsupported)\n");
612 pcie_clear_aspm(root->bus);
613 }
614 if (no_aspm) 611 if (no_aspm)
615 pcie_no_aspm(); 612 pcie_no_aspm();
616 613
diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
index 3e5bbf9e8889..5f4a2e04c8d7 100644
--- a/drivers/pci/host-bridge.c
+++ b/drivers/pci/host-bridge.c
@@ -16,7 +16,7 @@ static struct pci_bus *find_pci_root_bus(struct pci_bus *bus)
16 return bus; 16 return bus;
17} 17}
18 18
19static struct pci_host_bridge *find_pci_host_bridge(struct pci_bus *bus) 19struct pci_host_bridge *pci_find_host_bridge(struct pci_bus *bus)
20{ 20{
21 struct pci_bus *root_bus = find_pci_root_bus(bus); 21 struct pci_bus *root_bus = find_pci_root_bus(bus);
22 22
@@ -48,7 +48,7 @@ void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
48void pcibios_resource_to_bus(struct pci_bus *bus, struct pci_bus_region *region, 48void pcibios_resource_to_bus(struct pci_bus *bus, struct pci_bus_region *region,
49 struct resource *res) 49 struct resource *res)
50{ 50{
51 struct pci_host_bridge *bridge = find_pci_host_bridge(bus); 51 struct pci_host_bridge *bridge = pci_find_host_bridge(bus);
52 struct resource_entry *window; 52 struct resource_entry *window;
53 resource_size_t offset = 0; 53 resource_size_t offset = 0;
54 54
@@ -73,7 +73,7 @@ static bool region_contains(struct pci_bus_region *region1,
73void pcibios_bus_to_resource(struct pci_bus *bus, struct resource *res, 73void pcibios_bus_to_resource(struct pci_bus *bus, struct resource *res,
74 struct pci_bus_region *region) 74 struct pci_bus_region *region)
75{ 75{
76 struct pci_host_bridge *bridge = find_pci_host_bridge(bus); 76 struct pci_host_bridge *bridge = pci_find_host_bridge(bus);
77 struct resource_entry *window; 77 struct resource_entry *window;
78 resource_size_t offset = 0; 78 resource_size_t offset = 0;
79 79
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 489063987325..5eba74716900 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -18,6 +18,15 @@
18#include <linux/pm_qos.h> 18#include <linux/pm_qos.h>
19#include "pci.h" 19#include "pci.h"
20 20
21/*
22 * The UUID is defined in the PCI Firmware Specification available here:
23 * https://www.pcisig.com/members/downloads/pcifw_r3_1_13Dec10.pdf
24 */
25const u8 pci_acpi_dsm_uuid[] = {
26 0xd0, 0x37, 0xc9, 0xe5, 0x53, 0x35, 0x7a, 0x4d,
27 0x91, 0x17, 0xea, 0x4d, 0x19, 0xc3, 0x43, 0x4d
28};
29
21phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle) 30phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle)
22{ 31{
23 acpi_status status = AE_NOT_EXIST; 32 acpi_status status = AE_NOT_EXIST;
@@ -528,11 +537,32 @@ static struct pci_platform_pm_ops acpi_pci_platform_pm = {
528 537
529void acpi_pci_add_bus(struct pci_bus *bus) 538void acpi_pci_add_bus(struct pci_bus *bus)
530{ 539{
540 union acpi_object *obj;
541 struct pci_host_bridge *bridge;
542
531 if (acpi_pci_disabled || !bus->bridge) 543 if (acpi_pci_disabled || !bus->bridge)
532 return; 544 return;
533 545
534 acpi_pci_slot_enumerate(bus); 546 acpi_pci_slot_enumerate(bus);
535 acpiphp_enumerate_slots(bus); 547 acpiphp_enumerate_slots(bus);
548
549 /*
550 * For a host bridge, check its _DSM for function 8 and if
551 * that is available, mark it in pci_host_bridge.
552 */
553 if (!pci_is_root_bus(bus))
554 return;
555
556 obj = acpi_evaluate_dsm(ACPI_HANDLE(bus->bridge), pci_acpi_dsm_uuid, 3,
557 RESET_DELAY_DSM, NULL);
558 if (!obj)
559 return;
560
561 if (obj->type == ACPI_TYPE_INTEGER && obj->integer.value == 1) {
562 bridge = pci_find_host_bridge(bus);
563 bridge->ignore_reset_delay = 1;
564 }
565 ACPI_FREE(obj);
536} 566}
537 567
538void acpi_pci_remove_bus(struct pci_bus *bus) 568void acpi_pci_remove_bus(struct pci_bus *bus)
@@ -558,6 +588,57 @@ static struct acpi_device *acpi_pci_find_companion(struct device *dev)
558 check_children); 588 check_children);
559} 589}
560 590
591/**
592 * pci_acpi_optimize_delay - optimize PCI D3 and D3cold delay from ACPI
593 * @pdev: the PCI device whose delay is to be updated
594 * @adev: the companion ACPI device of this PCI device
595 *
596 * Update the d3_delay and d3cold_delay of a PCI device from the ACPI _DSM
597 * control method of either the device itself or the PCI host bridge.
598 *
599 * Function 8, "Reset Delay," applies to the entire hierarchy below a PCI
600 * host bridge. If it returns one, the OS may assume that all devices in
601 * the hierarchy have already completed power-on reset delays.
602 *
603 * Function 9, "Device Readiness Durations," applies only to the object
604 * where it is located. It returns delay durations required after various
605 * events if the device requires less time than the spec requires. Delays
606 * from this function take precedence over the Reset Delay function.
607 *
608 * These _DSM functions are defined by the draft ECN of January 28, 2014,
609 * titled "ACPI additions for FW latency optimizations."
610 */
611static void pci_acpi_optimize_delay(struct pci_dev *pdev,
612 acpi_handle handle)
613{
614 struct pci_host_bridge *bridge = pci_find_host_bridge(pdev->bus);
615 int value;
616 union acpi_object *obj, *elements;
617
618 if (bridge->ignore_reset_delay)
619 pdev->d3cold_delay = 0;
620
621 obj = acpi_evaluate_dsm(handle, pci_acpi_dsm_uuid, 3,
622 FUNCTION_DELAY_DSM, NULL);
623 if (!obj)
624 return;
625
626 if (obj->type == ACPI_TYPE_PACKAGE && obj->package.count == 5) {
627 elements = obj->package.elements;
628 if (elements[0].type == ACPI_TYPE_INTEGER) {
629 value = (int)elements[0].integer.value / 1000;
630 if (value < PCI_PM_D3COLD_WAIT)
631 pdev->d3cold_delay = value;
632 }
633 if (elements[3].type == ACPI_TYPE_INTEGER) {
634 value = (int)elements[3].integer.value / 1000;
635 if (value < PCI_PM_D3_WAIT)
636 pdev->d3_delay = value;
637 }
638 }
639 ACPI_FREE(obj);
640}
641
561static void pci_acpi_setup(struct device *dev) 642static void pci_acpi_setup(struct device *dev)
562{ 643{
563 struct pci_dev *pci_dev = to_pci_dev(dev); 644 struct pci_dev *pci_dev = to_pci_dev(dev);
@@ -566,6 +647,8 @@ static void pci_acpi_setup(struct device *dev)
566 if (!adev) 647 if (!adev)
567 return; 648 return;
568 649
650 pci_acpi_optimize_delay(pci_dev, adev->handle);
651
569 pci_acpi_add_pm_notifier(adev, pci_dev); 652 pci_acpi_add_pm_notifier(adev, pci_dev);
570 if (!adev->wakeup.flags.valid) 653 if (!adev->wakeup.flags.valid)
571 return; 654 return;
diff --git a/drivers/pci/pci-label.c b/drivers/pci/pci-label.c
index 2ab1b47c7651..024b5c179348 100644
--- a/drivers/pci/pci-label.c
+++ b/drivers/pci/pci-label.c
@@ -31,8 +31,6 @@
31#include <linux/pci-acpi.h> 31#include <linux/pci-acpi.h>
32#include "pci.h" 32#include "pci.h"
33 33
34#define DEVICE_LABEL_DSM 0x07
35
36#ifdef CONFIG_DMI 34#ifdef CONFIG_DMI
37enum smbios_attr_enum { 35enum smbios_attr_enum {
38 SMBIOS_ATTR_NONE = 0, 36 SMBIOS_ATTR_NONE = 0,
@@ -148,11 +146,6 @@ static inline void pci_remove_smbiosname_file(struct pci_dev *pdev)
148#endif 146#endif
149 147
150#ifdef CONFIG_ACPI 148#ifdef CONFIG_ACPI
151static const char device_label_dsm_uuid[] = {
152 0xD0, 0x37, 0xC9, 0xE5, 0x53, 0x35, 0x7A, 0x4D,
153 0x91, 0x17, 0xEA, 0x4D, 0x19, 0xC3, 0x43, 0x4D
154};
155
156enum acpi_attr_enum { 149enum acpi_attr_enum {
157 ACPI_ATTR_LABEL_SHOW, 150 ACPI_ATTR_LABEL_SHOW,
158 ACPI_ATTR_INDEX_SHOW, 151 ACPI_ATTR_INDEX_SHOW,
@@ -179,7 +172,7 @@ static int dsm_get_label(struct device *dev, char *buf,
179 if (!handle) 172 if (!handle)
180 return -1; 173 return -1;
181 174
182 obj = acpi_evaluate_dsm(handle, device_label_dsm_uuid, 0x2, 175 obj = acpi_evaluate_dsm(handle, pci_acpi_dsm_uuid, 0x2,
183 DEVICE_LABEL_DSM, NULL); 176 DEVICE_LABEL_DSM, NULL);
184 if (!obj) 177 if (!obj)
185 return -1; 178 return -1;
@@ -219,7 +212,7 @@ static bool device_has_dsm(struct device *dev)
219 if (!handle) 212 if (!handle)
220 return false; 213 return false;
221 214
222 return !!acpi_check_dsm(handle, device_label_dsm_uuid, 0x2, 215 return !!acpi_check_dsm(handle, pci_acpi_dsm_uuid, 0x2,
223 1 << DEVICE_LABEL_DSM); 216 1 << DEVICE_LABEL_DSM);
224} 217}
225 218
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 061fdce8f8e1..acc4b6ef78c4 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -146,19 +146,22 @@ static int __pci_find_next_cap_ttl(struct pci_bus *bus, unsigned int devfn,
146 u8 pos, int cap, int *ttl) 146 u8 pos, int cap, int *ttl)
147{ 147{
148 u8 id; 148 u8 id;
149 u16 ent;
150
151 pci_bus_read_config_byte(bus, devfn, pos, &pos);
149 152
150 while ((*ttl)--) { 153 while ((*ttl)--) {
151 pci_bus_read_config_byte(bus, devfn, pos, &pos);
152 if (pos < 0x40) 154 if (pos < 0x40)
153 break; 155 break;
154 pos &= ~3; 156 pos &= ~3;
155 pci_bus_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_ID, 157 pci_bus_read_config_word(bus, devfn, pos, &ent);
156 &id); 158
159 id = ent & 0xff;
157 if (id == 0xff) 160 if (id == 0xff)
158 break; 161 break;
159 if (id == cap) 162 if (id == cap)
160 return pos; 163 return pos;
161 pos += PCI_CAP_LIST_NEXT; 164 pos = (ent >> 8);
162 } 165 }
163 return 0; 166 return 0;
164} 167}
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 4091f82239cd..d72f849174a4 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -321,4 +321,6 @@ static inline int pci_dev_specific_reset(struct pci_dev *dev, int probe)
321} 321}
322#endif 322#endif
323 323
324struct pci_host_bridge *pci_find_host_bridge(struct pci_bus *bus);
325
324#endif /* DRIVERS_PCI_H */ 326#endif /* DRIVERS_PCI_H */
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index 820740a22e94..7d4fcdc512aa 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -782,24 +782,6 @@ void pci_disable_link_state(struct pci_dev *pdev, int state)
782} 782}
783EXPORT_SYMBOL(pci_disable_link_state); 783EXPORT_SYMBOL(pci_disable_link_state);
784 784
785void pcie_clear_aspm(struct pci_bus *bus)
786{
787 struct pci_dev *child;
788
789 if (aspm_force)
790 return;
791
792 /*
793 * Clear any ASPM setup that the firmware has carried out on this bus
794 */
795 list_for_each_entry(child, &bus->devices, bus_list) {
796 __pci_disable_link_state(child, PCIE_LINK_STATE_L0S |
797 PCIE_LINK_STATE_L1 |
798 PCIE_LINK_STATE_CLKPM,
799 false, true);
800 }
801}
802
803static int pcie_aspm_set_policy(const char *val, struct kernel_param *kp) 785static int pcie_aspm_set_policy(const char *val, struct kernel_param *kp)
804{ 786{
805 int i; 787 int i;
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 1bde3972e318..c6dc1dfd25d5 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -3182,7 +3182,7 @@ static void quirk_apple_wait_for_thunderbolt(struct pci_dev *dev)
3182 || nhi->subsystem_vendor != 0x2222 3182 || nhi->subsystem_vendor != 0x2222
3183 || nhi->subsystem_device != 0x1111) 3183 || nhi->subsystem_device != 0x1111)
3184 goto out; 3184 goto out;
3185 dev_info(&dev->dev, "quirk: wating for thunderbolt to reestablish pci tunnels...\n"); 3185 dev_info(&dev->dev, "quirk: waiting for thunderbolt to reestablish PCI tunnels...\n");
3186 device_pm_wait_for_dev(&dev->dev, &nhi->dev); 3186 device_pm_wait_for_dev(&dev->dev, &nhi->dev);
3187out: 3187out:
3188 pci_dev_put(nhi); 3188 pci_dev_put(nhi);
diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
index 24c7728ca681..a965efa52152 100644
--- a/include/linux/pci-acpi.h
+++ b/include/linux/pci-acpi.h
@@ -77,6 +77,11 @@ static inline void acpiphp_remove_slots(struct pci_bus *bus) { }
77static inline void acpiphp_check_host_bridge(struct acpi_device *adev) { } 77static inline void acpiphp_check_host_bridge(struct acpi_device *adev) { }
78#endif 78#endif
79 79
80extern const u8 pci_acpi_dsm_uuid[];
81#define DEVICE_LABEL_DSM 0x07
82#define RESET_DELAY_DSM 0x08
83#define FUNCTION_DELAY_DSM 0x09
84
80#else /* CONFIG_ACPI */ 85#else /* CONFIG_ACPI */
81static inline void acpi_pci_add_bus(struct pci_bus *bus) { } 86static inline void acpi_pci_add_bus(struct pci_bus *bus) { }
82static inline void acpi_pci_remove_bus(struct pci_bus *bus) { } 87static inline void acpi_pci_remove_bus(struct pci_bus *bus) { }
diff --git a/include/linux/pci-aspm.h b/include/linux/pci-aspm.h
index 8af4610c2e41..207c561fb40e 100644
--- a/include/linux/pci-aspm.h
+++ b/include/linux/pci-aspm.h
@@ -29,7 +29,6 @@ void pcie_aspm_pm_state_change(struct pci_dev *pdev);
29void pcie_aspm_powersave_config_link(struct pci_dev *pdev); 29void pcie_aspm_powersave_config_link(struct pci_dev *pdev);
30void pci_disable_link_state(struct pci_dev *pdev, int state); 30void pci_disable_link_state(struct pci_dev *pdev, int state);
31void pci_disable_link_state_locked(struct pci_dev *pdev, int state); 31void pci_disable_link_state_locked(struct pci_dev *pdev, int state);
32void pcie_clear_aspm(struct pci_bus *bus);
33void pcie_no_aspm(void); 32void pcie_no_aspm(void);
34#else 33#else
35static inline void pcie_aspm_init_link_state(struct pci_dev *pdev) 34static inline void pcie_aspm_init_link_state(struct pci_dev *pdev)
@@ -47,9 +46,6 @@ static inline void pcie_aspm_powersave_config_link(struct pci_dev *pdev)
47static inline void pci_disable_link_state(struct pci_dev *pdev, int state) 46static inline void pci_disable_link_state(struct pci_dev *pdev, int state)
48{ 47{
49} 48}
50static inline void pcie_clear_aspm(struct pci_bus *bus)
51{
52}
53static inline void pcie_no_aspm(void) 49static inline void pcie_no_aspm(void)
54{ 50{
55} 51}
diff --git a/include/linux/pci.h b/include/linux/pci.h
index a379513bddef..e63112fb55be 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -406,6 +406,7 @@ struct pci_host_bridge {
406 struct list_head windows; /* resource_entry */ 406 struct list_head windows; /* resource_entry */
407 void (*release_fn)(struct pci_host_bridge *); 407 void (*release_fn)(struct pci_host_bridge *);
408 void *release_data; 408 void *release_data;
409 unsigned int ignore_reset_delay:1; /* for entire hierarchy */
409}; 410};
410 411
411#define to_pci_host_bridge(n) container_of(n, struct pci_host_bridge, dev) 412#define to_pci_host_bridge(n) container_of(n, struct pci_host_bridge, dev)