pci_find_cap_method(): limit number of iterations for finding a capability

Powered down device might return 0xff of extended config registers
reads, causing loop.

PR:	283815
Reviewed by:	imp
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
Differential revision:	https://reviews.freebsd.org/D48348
This commit is contained in:
Konstantin Belousov
2025-01-07 01:29:18 +02:00
parent e6d40f9011
commit 6ba2c036a0
+5 -2
View File
@@ -1519,6 +1519,7 @@ pci_find_cap_method(device_t dev, device_t child, int capability,
pcicfgregs *cfg = &dinfo->cfg;
uint32_t status;
uint8_t ptr;
int cnt;
/*
* Check the CAP_LIST bit of the PCI status register first.
@@ -1545,9 +1546,11 @@ pci_find_cap_method(device_t dev, device_t child, int capability,
ptr = pci_read_config(child, ptr, 1);
/*
* Traverse the capabilities list.
* Traverse the capabilities list. Limit by total theoretical
* maximum number of caps: capability needs at least id and
* next registers, and any type X header cannot contain caps.
*/
while (ptr != 0) {
for (cnt = 0; ptr != 0 && cnt < (PCIE_REGMAX - 0x40) / 2; cnt++) {
if (pci_read_config(child, ptr + PCICAP_ID, 1) == capability) {
if (capreg != NULL)
*capreg = ptr;