diff options
author | Mika Westerberg <mika.westerberg@linux.intel.com> | 2018-05-23 17:24:08 -0500 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2018-06-02 00:18:28 -0500 |
commit | 5352a44a561d708f1a975a90f5ce16a054fe265c (patch) | |
tree | ce141dc89652f25a3288ea4069563ee9b9b18f41 | |
parent | 9310f0dc1c6430ca9e370a8341bea9f5dc85f40b (diff) | |
download | linux-5352a44a561d708f1a975a90f5ce16a054fe265c.tar.gz linux-5352a44a561d708f1a975a90f5ce16a054fe265c.tar.bz2 linux-5352a44a561d708f1a975a90f5ce16a054fe265c.zip |
PCI: pciehp: Make pciehp_is_native() stricter
Previously pciehp_is_native() returned true for any PCI device in a
hierarchy where _OSC says we can use pciehp. This is incorrect because
bridges without PCI_EXP_SLTCAP_HPC capability should be managed by acpiphp
instead.
Improve pciehp_is_native() to return true only when PCI_EXP_SLTCAP_HPC is
set and the pciehp driver is present. In any other case return false
to let acpiphp handle those.
Suggested-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
[bhelgaas: remove NULL pointer check]
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r-- | drivers/pci/pci-acpi.c | 26 | ||||
-rw-r--r-- | drivers/pci/pcie/portdrv.h | 2 | ||||
-rw-r--r-- | include/linux/pci.h | 2 | ||||
-rw-r--r-- | include/linux/pci_hotplug.h | 4 |
4 files changed, 18 insertions, 16 deletions
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 1abdbf267c19..52b8434d4d6e 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -370,26 +370,28 @@ EXPORT_SYMBOL_GPL(pci_get_hp_params); /** * pciehp_is_native - Check whether a hotplug port is handled by the OS - * @pdev: Hotplug port to check + * @bridge: Hotplug port to check * - * Walk up from @pdev to the host bridge, obtain its cached _OSC Control Field - * and return the value of the "PCI Express Native Hot Plug control" bit. - * On failure to obtain the _OSC Control Field return %false. + * Returns true if the given @bridge is handled by the native PCIe hotplug + * driver. */ -bool pciehp_is_native(struct pci_dev *pdev) +bool pciehp_is_native(struct pci_dev *bridge) { - struct acpi_pci_root *root; - acpi_handle handle; + const struct pci_host_bridge *host; + u32 slot_cap; - handle = acpi_find_root_bridge_handle(pdev); - if (!handle) + if (!IS_ENABLED(CONFIG_HOTPLUG_PCI_PCIE)) return false; - root = acpi_pci_find_root(handle); - if (!root) + pcie_capability_read_dword(bridge, PCI_EXP_SLTCAP, &slot_cap); + if (!(slot_cap & PCI_EXP_SLTCAP_HPC)) return false; - return root->osc_control_set & OSC_PCI_EXPRESS_NATIVE_HP_CONTROL; + if (pcie_ports_native) + return true; + + host = pci_find_host_bridge(bridge->bus); + return host->native_pcie_hotplug; } /** diff --git a/drivers/pci/pcie/portdrv.h b/drivers/pci/pcie/portdrv.h index d0c6783dbfe3..aa542dc10d23 100644 --- a/drivers/pci/pcie/portdrv.h +++ b/drivers/pci/pcie/portdrv.h @@ -11,8 +11,6 @@ #include <linux/compiler.h> -extern bool pcie_ports_native; - /* Service Type */ #define PCIE_PORT_SERVICE_PME_SHIFT 0 /* Power Management Event */ #define PCIE_PORT_SERVICE_PME (1 << PCIE_PORT_SERVICE_PME_SHIFT) diff --git a/include/linux/pci.h b/include/linux/pci.h index 30ec7e86af55..3f009003706a 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1454,8 +1454,10 @@ static inline int pci_irqd_intx_xlate(struct irq_domain *d, #ifdef CONFIG_PCIEPORTBUS extern bool pcie_ports_disabled; +extern bool pcie_ports_native; #else #define pcie_ports_disabled true +#define pcie_ports_native false #endif #ifdef CONFIG_PCIEASPM diff --git a/include/linux/pci_hotplug.h b/include/linux/pci_hotplug.h index 26213024e81b..3f32575d1ce8 100644 --- a/include/linux/pci_hotplug.h +++ b/include/linux/pci_hotplug.h @@ -162,7 +162,7 @@ struct hotplug_params { #ifdef CONFIG_ACPI #include <linux/acpi.h> int pci_get_hp_params(struct pci_dev *dev, struct hotplug_params *hpp); -bool pciehp_is_native(struct pci_dev *pdev); +bool pciehp_is_native(struct pci_dev *bridge); int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags); int acpi_pci_check_ejectable(struct pci_bus *pbus, acpi_handle handle); int acpi_pci_detect_ejectable(acpi_handle handle); @@ -172,6 +172,6 @@ static inline int pci_get_hp_params(struct pci_dev *dev, { return -ENODEV; } -static inline bool pciehp_is_native(struct pci_dev *pdev) { return true; } +static inline bool pciehp_is_native(struct pci_dev *bridge) { return true; } #endif #endif |