Message ID | 20221114115953.40236-2-mika.westerberg@linux.intel.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Bjorn Helgaas |
Headers | show |
Series | [v2,1/2] PCI: Take multifunction devices into account when distributing resources | expand |
On Mon, 14 Nov 2022 13:59:53 +0200 Mika Westerberg <mika.westerberg@linux.intel.com> wrote: > This reverts commit 5632e2beaf9d5dda694c0572684dea783d8a9492. > > Now that pci_bridge_distribute_available_resources() takes multifunction > devices int account we can revert this revert to fix the original issue. into account Looks fine to me, but I never really figured out the original logic properly so will leave it to others to give tags on this one. > > Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> > --- > drivers/pci/setup-bus.c | 62 ++++++++++++++++++++++++++++++++++++++++- > 1 file changed, 61 insertions(+), 1 deletion(-) > > diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c > index f3f39aa82dda..dfa490da728d 100644 > --- a/drivers/pci/setup-bus.c > +++ b/drivers/pci/setup-bus.c > @@ -1768,7 +1768,10 @@ static void adjust_bridge_window(struct pci_dev *bridge, struct resource *res, > } > > res->end = res->start + new_size - 1; > - remove_from_list(add_list, res); > + > + /* If the resource is part of the add_list remove it now */ > + if (add_list) > + remove_from_list(add_list, res); > } > > static void pci_bus_distribute_available_resources(struct pci_bus *bus, > @@ -1971,6 +1974,8 @@ static void pci_bridge_distribute_available_resources(struct pci_dev *bridge, > if (!bridge->is_hotplug_bridge) > return; > > + pci_dbg(bridge, "distributing available resources\n"); > + > /* Take the initial extra resources from the hotplug port */ > available_io = bridge->resource[PCI_BRIDGE_IO_WINDOW]; > available_mmio = bridge->resource[PCI_BRIDGE_MEM_WINDOW]; > @@ -1982,6 +1987,59 @@ static void pci_bridge_distribute_available_resources(struct pci_dev *bridge, > available_mmio_pref); > } > > +static bool pci_bridge_resources_not_assigned(struct pci_dev *dev) > +{ > + const struct resource *r; > + > + /* > + * Check the child device's resources and if they are not yet > + * assigned it means we are configuring them (not the boot > + * firmware) so we should be able to extend the upstream > + * bridge's (that's the hotplug downstream PCIe port) resources > + * in the same way we do with the normal hotplug case. > + */ > + r = &dev->resource[PCI_BRIDGE_IO_WINDOW]; > + if (!r->flags || !(r->flags & IORESOURCE_STARTALIGN)) > + return false; > + r = &dev->resource[PCI_BRIDGE_MEM_WINDOW]; > + if (!r->flags || !(r->flags & IORESOURCE_STARTALIGN)) > + return false; > + r = &dev->resource[PCI_BRIDGE_PREF_MEM_WINDOW]; > + if (!r->flags || !(r->flags & IORESOURCE_STARTALIGN)) > + return false; > + > + return true; > +} > + > +static void pci_root_bus_distribute_available_resources(struct pci_bus *bus, > + struct list_head *add_list) > +{ > + struct pci_dev *dev, *bridge = bus->self; > + > + for_each_pci_bridge(dev, bus) { > + struct pci_bus *b; > + > + b = dev->subordinate; > + if (!b) > + continue; > + > + /* > + * Need to check "bridge" here too because it is NULL > + * in case of root bus. > + */ > + if (bridge && pci_bridge_resources_not_assigned(dev)) { > + pci_bridge_distribute_available_resources(bridge, add_list); > + /* > + * There is only PCIe upstream port on the bus > + * so we don't need to go futher. > + */ > + return; > + } > + > + pci_root_bus_distribute_available_resources(b, add_list); > + } > +} > + > /* > * First try will not touch PCI bridge res. > * Second and later try will clear small leaf bridge res. > @@ -2021,6 +2079,8 @@ void pci_assign_unassigned_root_bus_resources(struct pci_bus *bus) > */ > __pci_bus_size_bridges(bus, add_list); > > + pci_root_bus_distribute_available_resources(bus, add_list); > + > /* Depth last, allocate resources and update the hardware. */ > __pci_bus_assign_resources(bus, add_list, &fail_head); > if (add_list)
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index f3f39aa82dda..dfa490da728d 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -1768,7 +1768,10 @@ static void adjust_bridge_window(struct pci_dev *bridge, struct resource *res, } res->end = res->start + new_size - 1; - remove_from_list(add_list, res); + + /* If the resource is part of the add_list remove it now */ + if (add_list) + remove_from_list(add_list, res); } static void pci_bus_distribute_available_resources(struct pci_bus *bus, @@ -1971,6 +1974,8 @@ static void pci_bridge_distribute_available_resources(struct pci_dev *bridge, if (!bridge->is_hotplug_bridge) return; + pci_dbg(bridge, "distributing available resources\n"); + /* Take the initial extra resources from the hotplug port */ available_io = bridge->resource[PCI_BRIDGE_IO_WINDOW]; available_mmio = bridge->resource[PCI_BRIDGE_MEM_WINDOW]; @@ -1982,6 +1987,59 @@ static void pci_bridge_distribute_available_resources(struct pci_dev *bridge, available_mmio_pref); } +static bool pci_bridge_resources_not_assigned(struct pci_dev *dev) +{ + const struct resource *r; + + /* + * Check the child device's resources and if they are not yet + * assigned it means we are configuring them (not the boot + * firmware) so we should be able to extend the upstream + * bridge's (that's the hotplug downstream PCIe port) resources + * in the same way we do with the normal hotplug case. + */ + r = &dev->resource[PCI_BRIDGE_IO_WINDOW]; + if (!r->flags || !(r->flags & IORESOURCE_STARTALIGN)) + return false; + r = &dev->resource[PCI_BRIDGE_MEM_WINDOW]; + if (!r->flags || !(r->flags & IORESOURCE_STARTALIGN)) + return false; + r = &dev->resource[PCI_BRIDGE_PREF_MEM_WINDOW]; + if (!r->flags || !(r->flags & IORESOURCE_STARTALIGN)) + return false; + + return true; +} + +static void pci_root_bus_distribute_available_resources(struct pci_bus *bus, + struct list_head *add_list) +{ + struct pci_dev *dev, *bridge = bus->self; + + for_each_pci_bridge(dev, bus) { + struct pci_bus *b; + + b = dev->subordinate; + if (!b) + continue; + + /* + * Need to check "bridge" here too because it is NULL + * in case of root bus. + */ + if (bridge && pci_bridge_resources_not_assigned(dev)) { + pci_bridge_distribute_available_resources(bridge, add_list); + /* + * There is only PCIe upstream port on the bus + * so we don't need to go futher. + */ + return; + } + + pci_root_bus_distribute_available_resources(b, add_list); + } +} + /* * First try will not touch PCI bridge res. * Second and later try will clear small leaf bridge res. @@ -2021,6 +2079,8 @@ void pci_assign_unassigned_root_bus_resources(struct pci_bus *bus) */ __pci_bus_size_bridges(bus, add_list); + pci_root_bus_distribute_available_resources(bus, add_list); + /* Depth last, allocate resources and update the hardware. */ __pci_bus_assign_resources(bus, add_list, &fail_head); if (add_list)
This reverts commit 5632e2beaf9d5dda694c0572684dea783d8a9492. Now that pci_bridge_distribute_available_resources() takes multifunction devices int account we can revert this revert to fix the original issue. Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> --- drivers/pci/setup-bus.c | 62 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-)