Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

PCI/ACPI: Request _OSC control once for each root bridge (v3)

Move the evaluation of acpi_pci_osc_control_set() (to request control of
PCI Express native features) into acpi_pci_root_add() to avoid calling
it many times for the same root complex with the same arguments.
Additionally, check if all of the requisite _OSC support bits are set
before calling acpi_pci_osc_control_set() for a given root complex.

References: https://bugzilla.kernel.org/show_bug.cgi?id=20232
Reported-by: Ozan Caglayan <ozan@pardus.org.tr>
Tested-by: Ozan Caglayan <ozan@pardus.org.tr>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>

authored by

Rafael J. Wysocki and committed by
Jesse Barnes
415e12b2 6e8af08d

+72 -46
+9 -13
drivers/acpi/apei/hest.c
··· 195 195 196 196 __setup("hest_disable", setup_hest_disable); 197 197 198 - static int __init hest_init(void) 198 + void __init acpi_hest_init(void) 199 199 { 200 200 acpi_status status; 201 201 int rc = -ENODEV; 202 202 unsigned int ghes_count = 0; 203 203 204 204 if (acpi_disabled) 205 - goto err; 205 + return; 206 206 207 207 if (hest_disable) { 208 - pr_info(HEST_PFX "HEST tabling parsing is disabled.\n"); 209 - goto err; 208 + pr_info(HEST_PFX "Table parsing disabled.\n"); 209 + return; 210 210 } 211 211 212 212 status = acpi_get_table(ACPI_SIG_HEST, 0, 213 213 (struct acpi_table_header **)&hest_tab); 214 214 if (status == AE_NOT_FOUND) { 215 - pr_info(HEST_PFX "Table is not found!\n"); 215 + pr_info(HEST_PFX "Table not found.\n"); 216 216 goto err; 217 217 } else if (ACPI_FAILURE(status)) { 218 218 const char *msg = acpi_format_exception(status); ··· 226 226 goto err; 227 227 228 228 rc = hest_ghes_dev_register(ghes_count); 229 - if (rc) 230 - goto err; 229 + if (!rc) { 230 + pr_info(HEST_PFX "Table parsing has been initialized.\n"); 231 + return; 232 + } 231 233 232 - pr_info(HEST_PFX "HEST table parsing is initialized.\n"); 233 - 234 - return 0; 235 234 err: 236 235 hest_disable = 1; 237 - return rc; 238 236 } 239 - 240 - subsys_initcall(hest_init);
+35
drivers/acpi/pci_root.c
··· 36 36 #include <linux/slab.h> 37 37 #include <acpi/acpi_bus.h> 38 38 #include <acpi/acpi_drivers.h> 39 + #include <acpi/apei.h> 39 40 40 41 #define PREFIX "ACPI: " 41 42 ··· 47 46 static int acpi_pci_root_add(struct acpi_device *device); 48 47 static int acpi_pci_root_remove(struct acpi_device *device, int type); 49 48 static int acpi_pci_root_start(struct acpi_device *device); 49 + 50 + #define ACPI_PCIE_REQ_SUPPORT (OSC_EXT_PCI_CONFIG_SUPPORT \ 51 + | OSC_ACTIVE_STATE_PWR_SUPPORT \ 52 + | OSC_CLOCK_PWR_CAPABILITY_SUPPORT \ 53 + | OSC_MSI_SUPPORT) 50 54 51 55 static const struct acpi_device_id root_device_ids[] = { 52 56 {"PNP0A03", 0}, ··· 572 566 if (flags != base_flags) 573 567 acpi_pci_osc_support(root, flags); 574 568 569 + if (!pcie_ports_disabled 570 + && (flags & ACPI_PCIE_REQ_SUPPORT) == ACPI_PCIE_REQ_SUPPORT) { 571 + flags = OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL 572 + | OSC_PCI_EXPRESS_NATIVE_HP_CONTROL 573 + | OSC_PCI_EXPRESS_PME_CONTROL; 574 + 575 + if (pci_aer_available()) { 576 + if (aer_acpi_firmware_first()) 577 + dev_dbg(root->bus->bridge, 578 + "PCIe errors handled by BIOS.\n"); 579 + else 580 + flags |= OSC_PCI_EXPRESS_AER_CONTROL; 581 + } 582 + 583 + dev_info(root->bus->bridge, 584 + "Requesting ACPI _OSC control (0x%02x)\n", flags); 585 + 586 + status = acpi_pci_osc_control_set(device->handle, &flags, 587 + OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); 588 + if (ACPI_SUCCESS(status)) 589 + dev_info(root->bus->bridge, 590 + "ACPI _OSC control (0x%02x) granted\n", flags); 591 + else 592 + dev_dbg(root->bus->bridge, 593 + "ACPI _OSC request failed (code %d)\n", status); 594 + } 595 + 575 596 pci_acpi_add_bus_pm_notifier(device, root->bus); 576 597 if (device->wakeup.flags.run_wake) 577 598 device_set_run_wake(root->bus->bridge, true); ··· 635 602 { 636 603 if (acpi_pci_disabled) 637 604 return 0; 605 + 606 + acpi_hest_init(); 638 607 639 608 pci_acpi_crs_quirks(); 640 609 if (acpi_bus_register_driver(&acpi_pci_root_driver) < 0)
-8
drivers/pci/pci.h
··· 140 140 static inline void pci_msi_init_pci_dev(struct pci_dev *dev) { } 141 141 #endif 142 142 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 143 static inline int pci_no_d1d2(struct pci_dev *dev) 152 144 { 153 145 unsigned int parent_dstates = 0;
+1
drivers/pci/pcie/aer/aerdrv.c
··· 17 17 18 18 #include <linux/module.h> 19 19 #include <linux/pci.h> 20 + #include <linux/pci-acpi.h> 20 21 #include <linux/sched.h> 21 22 #include <linux/kernel.h> 22 23 #include <linux/errno.h>
-3
drivers/pci/pcie/aer/aerdrv.h
··· 132 132 133 133 #ifdef CONFIG_ACPI_APEI 134 134 extern int pcie_aer_get_firmware_first(struct pci_dev *pci_dev); 135 - extern bool aer_acpi_firmware_first(void); 136 135 #else 137 136 static inline int pcie_aer_get_firmware_first(struct pci_dev *pci_dev) 138 137 { ··· 139 140 return pci_dev->__aer_firmware_first; 140 141 return 0; 141 142 } 142 - 143 - static inline bool aer_acpi_firmware_first(void) { return false; } 144 143 #endif 145 144 146 145 static inline void pcie_aer_force_firmware_first(struct pci_dev *pci_dev,
-3
drivers/pci/pcie/portdrv.h
··· 20 20 21 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 23 extern struct bus_type pcie_port_bus_type; 27 24 extern int pcie_port_device_register(struct pci_dev *dev); 28 25 #ifdef CONFIG_PM
+4 -19
drivers/pci/pcie/portdrv_acpi.c
··· 33 33 */ 34 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 37 acpi_handle handle; 38 38 u32 flags; 39 39 ··· 44 44 if (!handle) 45 45 return -EINVAL; 46 46 47 - flags = OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL 48 - | OSC_PCI_EXPRESS_NATIVE_HP_CONTROL 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); 47 + root = acpi_pci_find_root(handle); 48 + if (!root) 63 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 53 *srv_mask = PCIE_PORT_SERVICE_VC; 69 54 if (flags & OSC_PCI_EXPRESS_NATIVE_HP_CONTROL)
+6
include/acpi/apei.h
··· 19 19 extern int hest_disable; 20 20 extern int erst_disable; 21 21 22 + #ifdef CONFIG_ACPI_APEI 23 + void __init acpi_hest_init(void); 24 + #else 25 + static inline void acpi_hest_init(void) { return; } 26 + #endif 27 + 22 28 typedef int (*apei_hest_func_t)(struct acpi_hest_header *hest_hdr, void *data); 23 29 int apei_hest_parse(apei_hest_func_t func, void *data); 24 30
+6
include/linux/pci-acpi.h
··· 40 40 { return NULL; } 41 41 #endif 42 42 43 + #ifdef CONFIG_ACPI_APEI 44 + extern bool aer_acpi_firmware_first(void); 45 + #else 46 + static inline bool aer_acpi_firmware_first(void) { return false; } 47 + #endif 48 + 43 49 #endif /* _PCI_ACPI_H_ */
+11
include/linux/pci.h
··· 994 994 extern int pci_msi_enabled(void); 995 995 #endif 996 996 997 + extern bool pcie_ports_disabled; 998 + extern bool pcie_ports_auto; 999 + 997 1000 #ifndef CONFIG_PCIEASPM 998 1001 static inline int pcie_aspm_enabled(void) 999 1002 { ··· 1004 1001 } 1005 1002 #else 1006 1003 extern int pcie_aspm_enabled(void); 1004 + #endif 1005 + 1006 + #ifdef CONFIG_PCIEAER 1007 + void pci_no_aer(void); 1008 + bool pci_aer_available(void); 1009 + #else 1010 + static inline void pci_no_aer(void) { } 1011 + static inline bool pci_aer_available(void) { return false; } 1007 1012 #endif 1008 1013 1009 1014 #ifndef CONFIG_PCIE_ECRC