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:
Mika Westerberg 2022-09-05 11:02:29 +03:00 committed by Bjorn Helgaas
parent 49ad31e9d7
commit d1caf229c7
1 changed files with 113 additions and 113 deletions

View File

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