PCI: Move pci_assign_unassigned_root_bus_resources()
We need to be able to call pci_bridge_distribute_available_resources() from this function so move it accordingly to avoid need for forward declaration. No functional impact. Link: https://lore.kernel.org/r/20220905080232.36087-4-mika.westerberg@linux.intel.com Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
This commit is contained in:
parent
49ad31e9d7
commit
d1caf229c7
|
@ -1745,119 +1745,6 @@ static enum enable_type pci_realloc_detect(struct pci_bus *bus,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
* First try will not touch PCI bridge res.
|
|
||||||
* Second and later try will clear small leaf bridge res.
|
|
||||||
* Will stop till to the max depth if can not find good one.
|
|
||||||
*/
|
|
||||||
void pci_assign_unassigned_root_bus_resources(struct pci_bus *bus)
|
|
||||||
{
|
|
||||||
LIST_HEAD(realloc_head);
|
|
||||||
/* List of resources that want additional resources */
|
|
||||||
struct list_head *add_list = NULL;
|
|
||||||
int tried_times = 0;
|
|
||||||
enum release_type rel_type = leaf_only;
|
|
||||||
LIST_HEAD(fail_head);
|
|
||||||
struct pci_dev_resource *fail_res;
|
|
||||||
int pci_try_num = 1;
|
|
||||||
enum enable_type enable_local;
|
|
||||||
|
|
||||||
/* Don't realloc if asked to do so */
|
|
||||||
enable_local = pci_realloc_detect(bus, pci_realloc_enable);
|
|
||||||
if (pci_realloc_enabled(enable_local)) {
|
|
||||||
int max_depth = pci_bus_get_depth(bus);
|
|
||||||
|
|
||||||
pci_try_num = max_depth + 1;
|
|
||||||
dev_info(&bus->dev, "max bus depth: %d pci_try_num: %d\n",
|
|
||||||
max_depth, pci_try_num);
|
|
||||||
}
|
|
||||||
|
|
||||||
again:
|
|
||||||
/*
|
|
||||||
* Last try will use add_list, otherwise will try good to have as must
|
|
||||||
* have, so can realloc parent bridge resource
|
|
||||||
*/
|
|
||||||
if (tried_times + 1 == pci_try_num)
|
|
||||||
add_list = &realloc_head;
|
|
||||||
/*
|
|
||||||
* Depth first, calculate sizes and alignments of all subordinate buses.
|
|
||||||
*/
|
|
||||||
__pci_bus_size_bridges(bus, add_list);
|
|
||||||
|
|
||||||
/* Depth last, allocate resources and update the hardware. */
|
|
||||||
__pci_bus_assign_resources(bus, add_list, &fail_head);
|
|
||||||
if (add_list)
|
|
||||||
BUG_ON(!list_empty(add_list));
|
|
||||||
tried_times++;
|
|
||||||
|
|
||||||
/* Any device complain? */
|
|
||||||
if (list_empty(&fail_head))
|
|
||||||
goto dump;
|
|
||||||
|
|
||||||
if (tried_times >= pci_try_num) {
|
|
||||||
if (enable_local == undefined)
|
|
||||||
dev_info(&bus->dev, "Some PCI device resources are unassigned, try booting with pci=realloc\n");
|
|
||||||
else if (enable_local == auto_enabled)
|
|
||||||
dev_info(&bus->dev, "Automatically enabled pci realloc, if you have problem, try booting with pci=realloc=off\n");
|
|
||||||
|
|
||||||
free_list(&fail_head);
|
|
||||||
goto dump;
|
|
||||||
}
|
|
||||||
|
|
||||||
dev_info(&bus->dev, "No. %d try to assign unassigned res\n",
|
|
||||||
tried_times + 1);
|
|
||||||
|
|
||||||
/* Third times and later will not check if it is leaf */
|
|
||||||
if ((tried_times + 1) > 2)
|
|
||||||
rel_type = whole_subtree;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Try to release leaf bridge's resources that doesn't fit resource of
|
|
||||||
* child device under that bridge.
|
|
||||||
*/
|
|
||||||
list_for_each_entry(fail_res, &fail_head, list)
|
|
||||||
pci_bus_release_bridge_resources(fail_res->dev->bus,
|
|
||||||
fail_res->flags & PCI_RES_TYPE_MASK,
|
|
||||||
rel_type);
|
|
||||||
|
|
||||||
/* Restore size and flags */
|
|
||||||
list_for_each_entry(fail_res, &fail_head, list) {
|
|
||||||
struct resource *res = fail_res->res;
|
|
||||||
int idx;
|
|
||||||
|
|
||||||
res->start = fail_res->start;
|
|
||||||
res->end = fail_res->end;
|
|
||||||
res->flags = fail_res->flags;
|
|
||||||
|
|
||||||
if (pci_is_bridge(fail_res->dev)) {
|
|
||||||
idx = res - &fail_res->dev->resource[0];
|
|
||||||
if (idx >= PCI_BRIDGE_RESOURCES &&
|
|
||||||
idx <= PCI_BRIDGE_RESOURCE_END)
|
|
||||||
res->flags = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free_list(&fail_head);
|
|
||||||
|
|
||||||
goto again;
|
|
||||||
|
|
||||||
dump:
|
|
||||||
/* Dump the resource on buses */
|
|
||||||
pci_bus_dump_resources(bus);
|
|
||||||
}
|
|
||||||
|
|
||||||
void __init pci_assign_unassigned_resources(void)
|
|
||||||
{
|
|
||||||
struct pci_bus *root_bus;
|
|
||||||
|
|
||||||
list_for_each_entry(root_bus, &pci_root_buses, node) {
|
|
||||||
pci_assign_unassigned_root_bus_resources(root_bus);
|
|
||||||
|
|
||||||
/* Make sure the root bridge has a companion ACPI device */
|
|
||||||
if (ACPI_HANDLE(root_bus->bridge))
|
|
||||||
acpi_ioapic_add(ACPI_HANDLE(root_bus->bridge));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void adjust_bridge_window(struct pci_dev *bridge, struct resource *res,
|
static void adjust_bridge_window(struct pci_dev *bridge, struct resource *res,
|
||||||
struct list_head *add_list,
|
struct list_head *add_list,
|
||||||
resource_size_t new_size)
|
resource_size_t new_size)
|
||||||
|
@ -2047,6 +1934,119 @@ static void pci_bridge_distribute_available_resources(struct pci_dev *bridge,
|
||||||
available_mmio_pref);
|
available_mmio_pref);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First try will not touch PCI bridge res.
|
||||||
|
* Second and later try will clear small leaf bridge res.
|
||||||
|
* Will stop till to the max depth if can not find good one.
|
||||||
|
*/
|
||||||
|
void pci_assign_unassigned_root_bus_resources(struct pci_bus *bus)
|
||||||
|
{
|
||||||
|
LIST_HEAD(realloc_head);
|
||||||
|
/* List of resources that want additional resources */
|
||||||
|
struct list_head *add_list = NULL;
|
||||||
|
int tried_times = 0;
|
||||||
|
enum release_type rel_type = leaf_only;
|
||||||
|
LIST_HEAD(fail_head);
|
||||||
|
struct pci_dev_resource *fail_res;
|
||||||
|
int pci_try_num = 1;
|
||||||
|
enum enable_type enable_local;
|
||||||
|
|
||||||
|
/* Don't realloc if asked to do so */
|
||||||
|
enable_local = pci_realloc_detect(bus, pci_realloc_enable);
|
||||||
|
if (pci_realloc_enabled(enable_local)) {
|
||||||
|
int max_depth = pci_bus_get_depth(bus);
|
||||||
|
|
||||||
|
pci_try_num = max_depth + 1;
|
||||||
|
dev_info(&bus->dev, "max bus depth: %d pci_try_num: %d\n",
|
||||||
|
max_depth, pci_try_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
again:
|
||||||
|
/*
|
||||||
|
* Last try will use add_list, otherwise will try good to have as must
|
||||||
|
* have, so can realloc parent bridge resource
|
||||||
|
*/
|
||||||
|
if (tried_times + 1 == pci_try_num)
|
||||||
|
add_list = &realloc_head;
|
||||||
|
/*
|
||||||
|
* Depth first, calculate sizes and alignments of all subordinate buses.
|
||||||
|
*/
|
||||||
|
__pci_bus_size_bridges(bus, add_list);
|
||||||
|
|
||||||
|
/* Depth last, allocate resources and update the hardware. */
|
||||||
|
__pci_bus_assign_resources(bus, add_list, &fail_head);
|
||||||
|
if (add_list)
|
||||||
|
BUG_ON(!list_empty(add_list));
|
||||||
|
tried_times++;
|
||||||
|
|
||||||
|
/* Any device complain? */
|
||||||
|
if (list_empty(&fail_head))
|
||||||
|
goto dump;
|
||||||
|
|
||||||
|
if (tried_times >= pci_try_num) {
|
||||||
|
if (enable_local == undefined)
|
||||||
|
dev_info(&bus->dev, "Some PCI device resources are unassigned, try booting with pci=realloc\n");
|
||||||
|
else if (enable_local == auto_enabled)
|
||||||
|
dev_info(&bus->dev, "Automatically enabled pci realloc, if you have problem, try booting with pci=realloc=off\n");
|
||||||
|
|
||||||
|
free_list(&fail_head);
|
||||||
|
goto dump;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev_info(&bus->dev, "No. %d try to assign unassigned res\n",
|
||||||
|
tried_times + 1);
|
||||||
|
|
||||||
|
/* Third times and later will not check if it is leaf */
|
||||||
|
if ((tried_times + 1) > 2)
|
||||||
|
rel_type = whole_subtree;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Try to release leaf bridge's resources that doesn't fit resource of
|
||||||
|
* child device under that bridge.
|
||||||
|
*/
|
||||||
|
list_for_each_entry(fail_res, &fail_head, list)
|
||||||
|
pci_bus_release_bridge_resources(fail_res->dev->bus,
|
||||||
|
fail_res->flags & PCI_RES_TYPE_MASK,
|
||||||
|
rel_type);
|
||||||
|
|
||||||
|
/* Restore size and flags */
|
||||||
|
list_for_each_entry(fail_res, &fail_head, list) {
|
||||||
|
struct resource *res = fail_res->res;
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
res->start = fail_res->start;
|
||||||
|
res->end = fail_res->end;
|
||||||
|
res->flags = fail_res->flags;
|
||||||
|
|
||||||
|
if (pci_is_bridge(fail_res->dev)) {
|
||||||
|
idx = res - &fail_res->dev->resource[0];
|
||||||
|
if (idx >= PCI_BRIDGE_RESOURCES &&
|
||||||
|
idx <= PCI_BRIDGE_RESOURCE_END)
|
||||||
|
res->flags = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free_list(&fail_head);
|
||||||
|
|
||||||
|
goto again;
|
||||||
|
|
||||||
|
dump:
|
||||||
|
/* Dump the resource on buses */
|
||||||
|
pci_bus_dump_resources(bus);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __init pci_assign_unassigned_resources(void)
|
||||||
|
{
|
||||||
|
struct pci_bus *root_bus;
|
||||||
|
|
||||||
|
list_for_each_entry(root_bus, &pci_root_buses, node) {
|
||||||
|
pci_assign_unassigned_root_bus_resources(root_bus);
|
||||||
|
|
||||||
|
/* Make sure the root bridge has a companion ACPI device */
|
||||||
|
if (ACPI_HANDLE(root_bus->bridge))
|
||||||
|
acpi_ioapic_add(ACPI_HANDLE(root_bus->bridge));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge)
|
void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge)
|
||||||
{
|
{
|
||||||
struct pci_bus *parent = bridge->subordinate;
|
struct pci_bus *parent = bridge->subordinate;
|
||||||
|
|
Loading…
Reference in New Issue