Current realloc path would not shrink bridge resource through pbus_size_mem() checking with the old size.
That cause problem: when "required+optional" resource allocation fails, the cached bridge resource size will prevent "required" resource to get allocated smaller resource. Clear the old resource size for last try or third and later try. -v3: for last or third time and later. change reset_bridge_resource_size to static according to Fengguang. -v4: don't clear size for bridge's normal resources. Link: https://bugzilla.kernel.org/show_bug.cgi?id=81431 Tested-by: TJ <li...@iam.tj> Signed-off-by: Yinghai Lu <ying...@kernel.org> --- drivers/pci/setup-bus.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 3dc4ac9..d3a39b7 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -1738,6 +1738,17 @@ static enum enable_type pci_realloc_detect(struct pci_bus *bus, } #endif +static void reset_bridge_resource_size(struct pci_dev *dev, + struct resource *res) +{ + int idx = res - &dev->resource[0]; + + if (idx >= PCI_BRIDGE_RESOURCES && idx <= PCI_BRIDGE_RESOURCE_END) { + res->start = 0; + res->end = res->start - 1; + } +} + /* * first try will not touch pci bridge res * second and later try will clear small leaf bridge res @@ -1822,8 +1833,13 @@ again: res->start = fail_res->start; res->end = fail_res->end; res->flags = fail_res->flags; - if (fail_res->dev->subordinate) + if (fail_res->dev->subordinate) { res->flags = 0; + /* last or third times and later */ + if (tried_times + 1 == pci_try_num || + tried_times + 1 > 2) + reset_bridge_resource_size(fail_res->dev, res); + } } free_list(&fail_head); @@ -1897,8 +1913,11 @@ again: res->start = fail_res->start; res->end = fail_res->end; res->flags = fail_res->flags; - if (fail_res->dev->subordinate) + if (fail_res->dev->subordinate) { res->flags = 0; + /* last time */ + reset_bridge_resource_size(fail_res->dev, res); + } } free_list(&fail_head); -- 1.8.4.5