diff options
author | Tim Wawrzynczak <twawrzynczak@chromium.org> | 2021-09-16 20:18:16 -0600 |
---|---|---|
committer | Felix Held <felix-coreboot@felixheld.de> | 2022-02-10 12:48:00 +0000 |
commit | 3d121ae1a16751d55006c9b907a283f03c639197 (patch) | |
tree | 9fd9479168b1eab48326024959a5dc192413c764 /src/device | |
parent | 49be1a93467e6bd1bd61ec7889c0a6f24e824288 (diff) |
device: Add pciexp_find_next_extended_cap function
Some PCIe devices have extended capability lists that contain
multiples instances of the same capability. This patch provides a
function similar to pciexp_find_extended_cap that can be used to
search through multiple instances of the same capability by returning
the offset of the next extended capability of the given type following
the passed-in offset. The base functionality of searching for a given
capability from an offset is extracted to a local helper function and
both pciexp_find_extended_cap and pciexp_find_next_extended_cap use
this helper.
Change-Id: Ie68dc26012ba57650484c4f2ff53cc694a5347aa
Signed-off-by: Tim Wawrzynczak <twawrzynczak@chromium.org>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/57784
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Karthik Ramasubramanian <kramasub@google.com>
Reviewed-by: Nick Vaccaro <nvaccaro@google.com>
Diffstat (limited to 'src/device')
-rw-r--r-- | src/device/pciexp_device.c | 32 |
1 files changed, 21 insertions, 11 deletions
diff --git a/src/device/pciexp_device.c b/src/device/pciexp_device.c index e0b3544874..c52530196d 100644 --- a/src/device/pciexp_device.c +++ b/src/device/pciexp_device.c @@ -8,29 +8,39 @@ #include <device/pci_ops.h> #include <device/pciexp.h> -unsigned int pciexp_find_extended_cap(const struct device *dev, unsigned int cap) +static unsigned int pciexp_get_ext_cap_offset(const struct device *dev, unsigned int cap, + unsigned int offset) { - unsigned int this_cap_offset, next_cap_offset; - unsigned int this_cap, cafe; - - this_cap_offset = PCIE_EXT_CAP_OFFSET; + unsigned int this_cap_offset = offset; + unsigned int next_cap_offset, this_cap, cafe; do { this_cap = pci_read_config32(dev, this_cap_offset); - next_cap_offset = this_cap >> 20; - this_cap &= 0xffff; cafe = pci_read_config32(dev, this_cap_offset + 4); - cafe &= 0xffff; - if (this_cap == cap) + if ((this_cap & 0xffff) == cap) { return this_cap_offset; - else if (cafe == cap) + } else if ((cafe & 0xffff) == cap) { return this_cap_offset + 4; - else + } else { + next_cap_offset = this_cap >> 20; this_cap_offset = next_cap_offset; + } } while (next_cap_offset != 0); return 0; } +unsigned int pciexp_find_next_extended_cap(const struct device *dev, unsigned int cap, + unsigned int pos) +{ + const unsigned int next_cap_offset = pci_read_config32(dev, pos) >> 20; + return pciexp_get_ext_cap_offset(dev, cap, next_cap_offset); +} + +unsigned int pciexp_find_extended_cap(const struct device *dev, unsigned int cap) +{ + return pciexp_get_ext_cap_offset(dev, cap, PCIE_EXT_CAP_OFFSET); +} + /* * Re-train a PCIe link */ |