Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5352a44a authored by Mika Westerberg's avatar Mika Westerberg Committed by Bjorn Helgaas
Browse files

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: default avatarBjorn Helgaas <bhelgaas@google.com>
Signed-off-by: default avatarMika Westerberg <mika.westerberg@linux.intel.com>
[bhelgaas: remove NULL pointer check]
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
Reviewed-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 9310f0dc
Loading
Loading
Loading
Loading
+14 −12
Original line number Diff line number Diff line
@@ -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;
}

/**
+0 −2
Original line number Diff line number Diff line
@@ -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)
+2 −0
Original line number Diff line number Diff line
@@ -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
+2 −2
Original line number Diff line number Diff line
@@ -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