diff options
author | Robert Mustacchi <rm@fingolfin.org> | 2022-10-12 16:47:27 +0000 |
---|---|---|
committer | Robert Mustacchi <rm@fingolfin.org> | 2022-10-19 20:16:19 +0000 |
commit | 89cd7a0dac26a375a2d8df0e6a5737eb57c6f224 (patch) | |
tree | 6d585d5558e0b7ea10062f61a967ce8630007e52 | |
parent | f23ed011dd1990f5b6b2d755feeaa7baf5a22caa (diff) | |
download | illumos-gate-89cd7a0dac26a375a2d8df0e6a5737eb57c6f224.tar.gz |
15056 Missing pcie cap leads to panic in pcie_fabric_feature_scan()
Reviewed by: Patrick Mooney <pmooney@pfmooney.com>
Reviewed by: Dan Cross <cross@oxidecomputer.com>
Approved by: Richard Lowe <richlowe@richlowe.net>
-rw-r--r-- | usr/src/uts/common/io/pciex/pcie.c | 20 |
1 files changed, 18 insertions, 2 deletions
diff --git a/usr/src/uts/common/io/pciex/pcie.c b/usr/src/uts/common/io/pciex/pcie.c index acf2e3880c..0f461da167 100644 --- a/usr/src/uts/common/io/pciex/pcie.c +++ b/usr/src/uts/common/io/pciex/pcie.c @@ -3585,6 +3585,21 @@ pcie_fabric_feature_scan(dev_info_t *dip, void *arg) fab->pfd_flags |= PCIE_FABRIC_F_COMPLEX; return (DDI_WALK_TERMINATE); } + + /* + * In a similar case, there is hardware out there which is a PCIe + * device, but does not advertise a PCIe capability. An example of this + * is the IDT Tsi382A which can hide its PCIe capability. If this is + * the case, we immediately terminate scanning and flag this as a + * 'complex' case which causes us to use guaranteed safe settings. + */ + if (bus_p->bus_pcie_off == 0) { + dev_err(dip, CE_WARN, "encountered PCIe device without PCIe " + "capability"); + fab->pfd_flags |= PCIE_FABRIC_F_COMPLEX; + return (DDI_WALK_TERMINATE); + } + rcdip = pcie_get_rc_dip(dip); /* @@ -3686,10 +3701,11 @@ pcie_fabric_feature_set(dev_info_t *dip, void *arg) /* * The missing bus_t sent us into the complex case previously. We still * need to make sure all devices have values we expect here and thus - * don't terminate like the above. + * don't terminate like the above. The same is true for the case where + * there is no PCIe capability. */ bus_p = PCIE_DIP2BUS(dip); - if (bus_p == NULL) { + if (bus_p == NULL || bus_p->bus_pcie_off == 0) { return (DDI_WALK_CONTINUE); } rcdip = pcie_get_rc_dip(dip); |