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
This commit is contained in:
Bjorn Helgaas 2019-07-12 17:08:28 -05:00
commit 8c6af6f042
5 changed files with 62 additions and 32 deletions

View file

@ -168,6 +168,7 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
struct acpi_pci_generic_root_info *ri;
struct pci_bus *bus, *child;
struct acpi_pci_root_ops *root_ops;
struct pci_host_bridge *host;
ri = kzalloc(sizeof(*ri), GFP_KERNEL);
if (!ri)
@ -193,8 +194,16 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
if (!bus)
return NULL;
pci_bus_size_bridges(bus);
pci_bus_assign_resources(bus);
/* If we must preserve the resource configuration, claim now */
host = pci_find_host_bridge(bus);
if (host->preserve_config)
pci_bus_claim_resources(bus);
/*
* Assign whatever was left unassigned. If we didn't claim above,
* this will reassign everything.
*/
pci_assign_unassigned_root_bus_resources(bus);
list_for_each_entry(child, &bus->children, node)
pcie_bus_configure_settings(child);

View file

@ -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);

View file

@ -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;
@ -1860,16 +1865,6 @@ static void pci_bus_distribute_available_resources(struct pci_bus *bus,
extend_bridge_window(bridge, mmio_pref_res, add_list,
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
@ -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;
@ -1905,21 +1928,6 @@ static void pci_bus_distribute_available_resources(struct pci_bus *bus,
remaining_mmio_pref -= resource_size(res);
}
/*
* 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);

View file

@ -107,9 +107,10 @@ static inline void acpiphp_check_host_bridge(struct acpi_device *adev) { }
#endif
extern const guid_t pci_acpi_dsm_guid;
#define DEVICE_LABEL_DSM 0x07
#define RESET_DELAY_DSM 0x08
#define FUNCTION_DELAY_DSM 0x09
#define IGNORE_PCI_BOOT_CONFIG_DSM 0x05
#define DEVICE_LABEL_DSM 0x07
#define RESET_DELAY_DSM 0x08
#define FUNCTION_DELAY_DSM 0x09
#else /* CONFIG_ACPI */
static inline void acpi_pci_add_bus(struct pci_bus *bus) { }

View file

@ -508,6 +508,8 @@ struct pci_host_bridge {
unsigned int native_shpc_hotplug:1; /* OS may use SHPC hotplug */
unsigned int native_pme:1; /* OS may use PCIe PME */
unsigned int native_ltr:1; /* OS may use PCIe LTR */
unsigned int preserve_config:1; /* Preserve FW resource setup */
/* Resource alignment requirements */
resource_size_t (*align_resource)(struct pci_dev *dev,
const struct resource *res,