diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2018-03-09 11:21:25 -0600 |
---|---|---|
committer | Bjorn Helgaas <helgaas@kernel.org> | 2018-03-30 17:26:54 -0500 |
commit | 02bfeb484230dfd073148a17253aeb1717ce769c (patch) | |
tree | 1f64c93fbef2833821d68d1fd9e714564c1460d8 /drivers/acpi/pci_root.c | |
parent | 168f3ae595d6a6cee8321633f29273a7dd4fc83e (diff) | |
download | lwn-02bfeb484230dfd073148a17253aeb1717ce769c.tar.gz lwn-02bfeb484230dfd073148a17253aeb1717ce769c.zip |
PCI/portdrv: Simplify PCIe feature permission checking
Some PCIe features (AER, DPC, hotplug, PME) can be managed by either the
platform firmware or the OS, so the host bridge driver may have to request
permission from the platform before using them. On ACPI systems, this is
done by negotiate_os_control() in acpi_pci_root_add().
The PCIe port driver later uses pcie_port_platform_notify() and
pcie_port_acpi_setup() to figure out whether it can use these features.
But all we need is a single bit for each service, so these interfaces are
needlessly complicated.
Simplify this by adding bits in the struct pci_host_bridge to show when the
OS has permission to use each feature:
+ unsigned int native_aer:1; /* OS may use PCIe AER */
+ unsigned int native_hotplug:1; /* OS may use PCIe hotplug */
+ unsigned int native_pme:1; /* OS may use PCIe PME */
These are set when we create a host bridge, and the host bridge driver can
clear the bits corresponding to any feature the platform doesn't want us to
use.
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi/pci_root.c')
-rw-r--r-- | drivers/acpi/pci_root.c | 13 |
1 files changed, 11 insertions, 2 deletions
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 6fc204a52493..63b2cb775324 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -871,6 +871,7 @@ struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root, struct acpi_device *device = root->device; int node = acpi_get_node(device->handle); struct pci_bus *bus; + struct pci_host_bridge *host_bridge; info->root = root; info->bridge = device; @@ -895,9 +896,17 @@ struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root, if (!bus) goto out_release_info; + host_bridge = to_pci_host_bridge(bus->bridge); + if (!(root->osc_control_set & OSC_PCI_EXPRESS_NATIVE_HP_CONTROL)) + host_bridge->native_hotplug = 0; + if (!(root->osc_control_set & OSC_PCI_EXPRESS_AER_CONTROL)) + host_bridge->native_aer = 0; + if (!(root->osc_control_set & OSC_PCI_EXPRESS_PME_CONTROL)) + host_bridge->native_pme = 0; + pci_scan_child_bus(bus); - pci_set_host_bridge_release(to_pci_host_bridge(bus->bridge), - acpi_pci_root_release_info, info); + pci_set_host_bridge_release(host_bridge, acpi_pci_root_release_info, + info); if (node != NUMA_NO_NODE) dev_printk(KERN_DEBUG, &bus->dev, "on NUMA node %d\n", node); return bus; |