summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBill XIE <persmule@hardenedlinux.org>2022-08-02 22:55:51 +0800
committerMartin L Roth <gaumless@gmail.com>2022-08-07 19:41:38 +0000
commit513d359dad3a99c13846f4e97b372ec98d245695 (patch)
tree7cbd42b71dde4c9908bd69058e816bd685f9beab
parenta43380e3d5637b5d2e23b001a5c2519696a21c5d (diff)
downloadcoreboot-513d359dad3a99c13846f4e97b372ec98d245695.tar.gz
coreboot-513d359dad3a99c13846f4e97b372ec98d245695.tar.bz2
coreboot-513d359dad3a99c13846f4e97b372ec98d245695.zip
pci_device: Add a function to find PCI capability ID recursively
Some PCI capabilities should only be enabled if it is available not only on a device, but also all bridge upstream of it. Checking only the device and the bridge just above it may not be enough. Signed-off-by: Bill XIE <persmule@hardenedlinux.org> Change-Id: I1237d3b4b86dd0ae5eb586e3c3c407362e6ca291 Reviewed-on: https://review.coreboot.org/c/coreboot/+/66383 Reviewed-by: Arthur Heymans <arthur@aheymans.xyz> Reviewed-by: Lean Sheng Tan <sheng.tan@9elements.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
-rw-r--r--src/device/pci_device.c24
-rw-r--r--src/include/device/pci.h1
2 files changed, 25 insertions, 0 deletions
diff --git a/src/device/pci_device.c b/src/device/pci_device.c
index fda088b0206c..44c47a75486a 100644
--- a/src/device/pci_device.c
+++ b/src/device/pci_device.c
@@ -6,6 +6,7 @@
*/
#include <acpi/acpi.h>
+#include <assert.h>
#include <device/pci_ops.h>
#include <bootmode.h>
#include <console/console.h>
@@ -1299,6 +1300,29 @@ unsigned int pci_match_simple_dev(struct device *dev, pci_devfn_t sdev)
}
/**
+ * Test whether a capability is available along the whole path from the given
+ * device to the host bridge.
+ *
+ * @param dev Pointer to the device structure.
+ * @param cap PCI_CAP_LIST_ID of the PCI capability we're looking for.
+ * @return The next matching capability of the given device, if it is available
+ * along the whole path, or zero if not.
+ */
+uint16_t pci_find_cap_recursive(const struct device *dev, uint16_t cap)
+{
+ assert(dev->bus);
+ uint16_t pos = pci_find_capability(dev, cap);
+ const struct device *bridge = dev->bus->dev;
+ while (bridge && (bridge->path.type == DEVICE_PATH_PCI)) {
+ assert(bridge->bus);
+ if (!pci_find_capability(bridge, cap))
+ return 0;
+ bridge = bridge->bus->dev;
+ }
+ return pos;
+}
+
+/**
* PCI devices that are marked as "hidden" do not get probed. However, the same
* initialization logic is still performed as if it were. This is useful when
* devices would like to be described in the devicetree.cb file, and/or present
diff --git a/src/include/device/pci.h b/src/include/device/pci.h
index f2e250631e45..f28f319d8cc6 100644
--- a/src/include/device/pci.h
+++ b/src/include/device/pci.h
@@ -97,6 +97,7 @@ void pci_dev_set_subsystem(struct device *dev, unsigned int vendor,
unsigned int device);
void pci_dev_init(struct device *dev);
unsigned int pci_match_simple_dev(struct device *dev, pci_devfn_t sdev);
+uint16_t pci_find_cap_recursive(const struct device *dev, uint16_t cap);
const char *pin_to_str(int pin);
int get_pci_irq_pins(struct device *dev, struct device **parent_bdg);