Hung-Te Lin has submitted this change. ( https://review.coreboot.org/c/coreboot/+/56788 )
Change subject: device/pci_device.c: Scan only one device for PCIe ......................................................................
device/pci_device.c: Scan only one device for PCIe
Only scan one device if it's a PCIe downstream port.
A PCIe downstream port normally leads to a link with only device 0 on it. As an optimization, scan only for device 0 in that case.
Signed-off-by: Jianjun Wang jianjun.wang@mediatek.com Change-Id: Id184d03b33e1742b18efb3f11aa9b2f81fa03806 Reviewed-on: https://review.coreboot.org/c/coreboot/+/56788 Tested-by: build bot (Jenkins) no-reply@coreboot.org Reviewed-by: Yu-Ping Wu yupingso@google.com --- M src/device/pci_device.c M src/include/device/pci_def.h M src/include/device/pciexp.h 3 files changed, 36 insertions(+), 0 deletions(-)
Approvals: build bot (Jenkins): Verified Yu-Ping Wu: Looks good to me, approved
diff --git a/src/device/pci_device.c b/src/device/pci_device.c index 4b5e73b..1075ef7 100644 --- a/src/device/pci_device.c +++ b/src/device/pci_device.c @@ -1204,6 +1204,30 @@ }
/** + * A PCIe Downstream Port normally leads to a Link with only Device 0 on it + * (PCIe spec r5.0, sec 7.3.1). As an optimization, scan only for Device 0 in + * that situation. + * + * @param bus Pointer to the bus structure. + */ +static bool pci_bus_only_one_child(struct bus *bus) +{ + struct device *bridge = bus->dev; + u16 pcie_pos, pcie_flags_reg; + int pcie_type; + + pcie_pos = pci_find_capability(bridge, PCI_CAP_ID_PCIE); + if (!pcie_pos) + return false; + + pcie_flags_reg = pci_read_config16(bridge, pcie_pos + PCI_EXP_FLAGS); + + pcie_type = (pcie_flags_reg & PCI_EXP_FLAGS_TYPE) >> 4; + + return pciexp_is_downstream_port(pcie_type); +} + +/** * Scan a PCI bus. * * Determine the existence of devices and bridges on a PCI bus. If there are @@ -1232,6 +1256,9 @@
post_code(0x24);
+ if (pci_bus_only_one_child(bus)) + max_devfn = MIN(max_devfn, 0x07); + /* * Probe all devices/functions on this bus with some optimization for * non-existence and single function devices. diff --git a/src/include/device/pci_def.h b/src/include/device/pci_def.h index 22a5390..0611436 100644 --- a/src/include/device/pci_def.h +++ b/src/include/device/pci_def.h @@ -385,6 +385,7 @@ #define PCI_EXP_TYPE_UPSTREAM 0x5 /* Upstream Port */ #define PCI_EXP_TYPE_DOWNSTREAM 0x6 /* Downstream Port */ #define PCI_EXP_TYPE_PCI_BRIDGE 0x7 /* PCI/PCI-X Bridge */ +#define PCI_EXP_TYPE_PCIE_BRIDGE 0x8 /* PCI/PCI-X to PCIe Bridge */ #define PCI_EXP_FLAGS_SLOT 0x0100 /* Slot implemented */ #define PCI_EXP_FLAGS_IRQ 0x3e00 /* Interrupt message number */ #define PCI_EXP_DEVCAP 4 /* Device capabilities */ diff --git a/src/include/device/pciexp.h b/src/include/device/pciexp.h index 014fcb1..fbc769e 100644 --- a/src/include/device/pciexp.h +++ b/src/include/device/pciexp.h @@ -31,4 +31,12 @@ extern struct device_operations default_pciexp_hotplug_ops_bus;
unsigned int pciexp_find_extended_cap(struct device *dev, unsigned int cap); + +static inline bool pciexp_is_downstream_port(int type) +{ + return type == PCI_EXP_TYPE_ROOT_PORT || + type == PCI_EXP_TYPE_DOWNSTREAM || + type == PCI_EXP_TYPE_PCIE_BRIDGE; +} + #endif /* DEVICE_PCIEXP_H */