From 89cd7a0dac26a375a2d8df0e6a5737eb57c6f224 Mon Sep 17 00:00:00 2001 From: Robert Mustacchi Date: Wed, 12 Oct 2022 16:47:27 +0000 Subject: 15056 Missing pcie cap leads to panic in pcie_fabric_feature_scan() Reviewed by: Patrick Mooney Reviewed by: Dan Cross Approved by: Richard Lowe --- usr/src/uts/common/io/pciex/pcie.c | 20 ++++++++++++++++++-- 1 file 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); -- cgit v1.2.3