summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2019-07-12 17:08:28 -0500
committerBjorn Helgaas <bhelgaas@google.com>2019-07-12 17:08:28 -0500
commit8c6af6f04252110b3e4c2ff1614a4518d5208383 (patch)
tree2c8c4cbeca0d6bbb71a98de26342a05f9a41803a /drivers
parent3306e99edf70e9f7f9839c0c680136f098ebb1ed (diff)
parent6a381ea694c9da31ba8741c42a7f1b206c156841 (diff)
downloadlinux-8c6af6f04252110b3e4c2ff1614a4518d5208383.tar.bz2
Merge branch 'pci/resource'
- Evaluate ACPI "PCI Boot Configuration"_DSM (Benjamin Herrenschmidt) - Don't auto-realloc if we're preserving firmware config (Benjamin Herrenschmidt) - Allow arm64 to reallocate resources if necessary (Benjamin Herrenschmidt) - Preserve firmware config on arm64 when desired (Benjamin Herrenschmidt) - Simplify resource distribution to hotplug bridges (Nicholas Johnson) * pci/resource: PCI: Skip resource distribution when no hotplug bridges PCI: Simplify pci_bus_distribute_available_resources() arm64: PCI: Preserve firmware configuration when desired arm64: PCI: Allow resource reallocation if necessary PCI: Don't auto-realloc if we're preserving firmware config PCI/ACPI: Evaluate PCI Boot Configuration _DSM
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/pci_root.c12
-rw-r--r--drivers/pci/setup-bus.c60
2 files changed, 45 insertions, 27 deletions
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index c36781a9b493..0d57f817ef1e 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -894,6 +894,7 @@ struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root,
int node = acpi_get_node(device->handle);
struct pci_bus *bus;
struct pci_host_bridge *host_bridge;
+ union acpi_object *obj;
info->root = root;
info->bridge = device;
@@ -930,6 +931,17 @@ struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root,
if (!(root->osc_control_set & OSC_PCI_EXPRESS_LTR_CONTROL))
host_bridge->native_ltr = 0;
+ /*
+ * Evaluate the "PCI Boot Configuration" _DSM Function. If it
+ * exists and returns 0, we must preserve any PCI resource
+ * assignments made by firmware for this host bridge.
+ */
+ obj = acpi_evaluate_dsm(ACPI_HANDLE(bus->bridge), &pci_acpi_dsm_guid, 1,
+ IGNORE_PCI_BOOT_CONFIG_DSM, NULL);
+ if (obj && obj->type == ACPI_TYPE_INTEGER && obj->integer.value == 0)
+ host_bridge->preserve_config = 1;
+ ACPI_FREE(obj);
+
pci_scan_child_bus(bus);
pci_set_host_bridge_release(host_bridge, acpi_pci_root_release_info,
info);
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 0cdd5ff389de..79b1fa6519be 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -1684,10 +1684,15 @@ static enum enable_type pci_realloc_detect(struct pci_bus *bus,
enum enable_type enable_local)
{
bool unassigned = false;
+ struct pci_host_bridge *host;
if (enable_local != undefined)
return enable_local;
+ host = pci_find_host_bridge(bus);
+ if (host->preserve_config)
+ return auto_disabled;
+
pci_walk_bus(bus, iov_resources_unassigned, &unassigned);
if (unassigned)
return auto_enabled;
@@ -1861,16 +1866,6 @@ static void pci_bus_distribute_available_resources(struct pci_bus *bus,
available_mmio_pref);
/*
- * Calculate the total amount of extra resource space we can
- * pass to bridges below this one. This is basically the
- * extra space reduced by the minimal required space for the
- * non-hotplug bridges.
- */
- remaining_io = available_io;
- remaining_mmio = available_mmio;
- remaining_mmio_pref = available_mmio_pref;
-
- /*
* Calculate how many hotplug bridges and normal bridges there
* are on this bus. We will distribute the additional available
* resources between hotplug bridges.
@@ -1882,6 +1877,34 @@ static void pci_bus_distribute_available_resources(struct pci_bus *bus,
normal_bridges++;
}
+ /*
+ * There is only one bridge on the bus so it gets all available
+ * resources which it can then distribute to the possible hotplug
+ * bridges below.
+ */
+ if (hotplug_bridges + normal_bridges == 1) {
+ dev = list_first_entry(&bus->devices, struct pci_dev, bus_list);
+ if (dev->subordinate) {
+ pci_bus_distribute_available_resources(dev->subordinate,
+ add_list, available_io, available_mmio,
+ available_mmio_pref);
+ }
+ return;
+ }
+
+ if (hotplug_bridges == 0)
+ return;
+
+ /*
+ * Calculate the total amount of extra resource space we can
+ * pass to bridges below this one. This is basically the
+ * extra space reduced by the minimal required space for the
+ * non-hotplug bridges.
+ */
+ remaining_io = available_io;
+ remaining_mmio = available_mmio;
+ remaining_mmio_pref = available_mmio_pref;
+
for_each_pci_bridge(dev, bus) {
const struct resource *res;
@@ -1906,21 +1929,6 @@ static void pci_bus_distribute_available_resources(struct pci_bus *bus,
}
/*
- * There is only one bridge on the bus so it gets all available
- * resources which it can then distribute to the possible hotplug
- * bridges below.
- */
- if (hotplug_bridges + normal_bridges == 1) {
- dev = list_first_entry(&bus->devices, struct pci_dev, bus_list);
- if (dev->subordinate) {
- pci_bus_distribute_available_resources(dev->subordinate,
- add_list, available_io, available_mmio,
- available_mmio_pref);
- }
- return;
- }
-
- /*
* Go over devices on this bus and distribute the remaining
* resource space between hotplug bridges.
*/
@@ -1936,8 +1944,6 @@ static void pci_bus_distribute_available_resources(struct pci_bus *bus,
* Distribute available extra resources equally between
* hotplug-capable downstream ports taking alignment into
* account.
- *
- * Here hotplug_bridges is always != 0.
*/
align = pci_resource_alignment(bridge, io_res);
io = div64_ul(available_io, hotplug_bridges);