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>
This commit is contained in:
parent
a43380e3d5
commit
513d359dad
|
@ -6,6 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <acpi/acpi.h>
|
#include <acpi/acpi.h>
|
||||||
|
#include <assert.h>
|
||||||
#include <device/pci_ops.h>
|
#include <device/pci_ops.h>
|
||||||
#include <bootmode.h>
|
#include <bootmode.h>
|
||||||
#include <console/console.h>
|
#include <console/console.h>
|
||||||
|
@ -1298,6 +1299,29 @@ unsigned int pci_match_simple_dev(struct device *dev, pci_devfn_t sdev)
|
||||||
dev->path.pci.devfn == PCI_DEV2DEVFN(sdev);
|
dev->path.pci.devfn == PCI_DEV2DEVFN(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
|
* 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
|
* initialization logic is still performed as if it were. This is useful when
|
||||||
|
|
|
@ -97,6 +97,7 @@ void pci_dev_set_subsystem(struct device *dev, unsigned int vendor,
|
||||||
unsigned int device);
|
unsigned int device);
|
||||||
void pci_dev_init(struct device *dev);
|
void pci_dev_init(struct device *dev);
|
||||||
unsigned int pci_match_simple_dev(struct device *dev, pci_devfn_t sdev);
|
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);
|
const char *pin_to_str(int pin);
|
||||||
int get_pci_irq_pins(struct device *dev, struct device **parent_bdg);
|
int get_pci_irq_pins(struct device *dev, struct device **parent_bdg);
|
||||||
|
|
Loading…
Reference in New Issue