pci_pci: Support growing bus ranges in bus_adjust_resource for NEW_PCIB

This is the same underlying problem as 2624598064, just for bus ranges
rather than windows. SiFive's HiFive Unmatched has the following
topology:

  Root Port <---> Bridge <---> Bridge <-+-> Bridge <---> (Unused)
   (pcib0)        (pcib1)      (pcib2)  |   (pcib3)
                                        +-> Bridge <---> xHCI
                                        |   (pcib4)
                                        +-> Bridge <---> M.2 E-key
                                        |   (pcib5)
                                        +-> Bridge <---> M.2 M-key
                                        |   (pcib6)
                                        +-> Bridge <---> x16 slot
                                            (pcib7)

If a device is plugged into the x16 slot that itself has a bridge, such
as many graphics cards, we currently fail to allocate a bus number for
its child bus (and so pcib_attach_child skips adding a child bus for
further enumeration) as, when the new child bridge attaches, it attempts
to allocate a bus number from its parent (pcib7) which in turn attempts
to grow its own bus range by calling bus_adjust_resource on its own
parent (pcib2) whose bus rman cannot accommodate the request and needs
to itself be extended by calling its own parent (pcib1). Note that
pcib3-7 do not face the same issue when they attach since pcib1 ends up
managing bus numbers 1-255 from the beginning and so never needs to grow
its own range.

Reviewed by:	jhb, mav
MFC after:	1 week
Differential Revision:	https://reviews.freebsd.org/D32011
This commit is contained in:
Jessica Clarke 2021-10-03 19:35:26 +01:00
parent 2404f03fca
commit 31776afdc7

View File

@ -2364,7 +2364,20 @@ pcib_adjust_resource(device_t bus, device_t child, int type, struct resource *r,
start, end));
#ifdef PCI_RES_BUS
if (type != PCI_RES_BUS)
if (type == PCI_RES_BUS) {
/*
* If our bus range isn't big enough to grow the sub-allocation
* then we need to grow our bus range. Any request that would
* require us to decrease the start of our own bus range is
* invalid, we can only extend the end; ignore such requests
* and let rman_adjust_resource fail below.
*/
if (start >= sc->bus.sec && end > sc->bus.sub) {
error = pcib_grow_subbus(&sc->bus, end);
if (error != 0)
return (error);
}
} else
#endif
{
/*