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:
commit
8c6af6f042
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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) { }
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user