From 7d91603476b740ff8f4c917d71ee5884ab39cb60 Mon Sep 17 00:00:00 2001 From: Robert Mustacchi Date: Thu, 9 Jul 2020 18:33:59 -0700 Subject: 12966 imc driver blew up on missing channel Reviewed by: Andy Fiddaman Reviewed by: Igor Kozhukhov Reviewed by: Paul Winder Approved by: Dan McDonald --- usr/src/uts/i86pc/io/imc/imc.c | 39 +++++++++++++++++++++++++++++++++++++++ usr/src/uts/i86pc/io/imc/imc.h | 5 +++-- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/usr/src/uts/i86pc/io/imc/imc.c b/usr/src/uts/i86pc/io/imc/imc.c index 25ba86061b..e1dbfbfc2e 100644 --- a/usr/src/uts/i86pc/io/imc/imc.c +++ b/usr/src/uts/i86pc/io/imc/imc.c @@ -931,6 +931,40 @@ imc_fixup_stubs(imc_t *imc) } } +/* + * In the wild we've hit a few odd cases where not all devices are exposed that + * we might expect by firmware. In particular we've seen and validate the + * following cases: + * + * o We don't find all of the channel devices that we expect, e.g. we have the + * stubs for channels 1-3, but not 0. That has been seen on an Intel S2600CW + * with an E5-2630v3. + */ +static boolean_t +imc_validate_stubs(imc_t *imc) +{ + for (uint_t sock = 0; sock < imc->imc_nsockets; sock++) { + imc_socket_t *socket = &imc->imc_sockets[sock]; + + for (uint_t mc = 0; mc < socket->isock_nimc; mc++) { + imc_mc_t *mcp = &socket->isock_imcs[mc]; + + for (uint_t chan = 0; chan < mcp->icn_nchannels; + chan++) { + if (mcp->icn_channels[chan].ich_desc == NULL) { + dev_err(imc->imc_dip, CE_WARN, + "!missing device for socket %u/" + "imc %u/channel %u", sock, mc, + chan); + return (B_FALSE); + } + } + } + } + + return (B_TRUE); +} + /* * Attempt to map all of the discovered sockets to the corresponding APIC based * socket. We do these mappings by getting the node id of the socket and @@ -2194,6 +2228,11 @@ imc_attach_complete(void *arg) goto done; } + if (!imc_validate_stubs(imc)) { + imc->imc_flags |= IMC_F_VALIDATE_FAILED; + goto done; + } + imc_fixup_stubs(imc); imc_map_sockets(imc); diff --git a/usr/src/uts/i86pc/io/imc/imc.h b/usr/src/uts/i86pc/io/imc/imc.h index 7d07be20af..5f3def4930 100644 --- a/usr/src/uts/i86pc/io/imc/imc.h +++ b/usr/src/uts/i86pc/io/imc/imc.h @@ -500,12 +500,13 @@ typedef enum { IMC_F_SCAN_COMPLETE = (1 << 2), IMC_F_ATTACH_DISPATCHED = (1 << 3), IMC_F_ATTACH_COMPLETE = (1 << 4), - IMC_F_MCREG_FAILED = (1 << 5) + IMC_F_MCREG_FAILED = (1 << 5), + IMC_F_VALIDATE_FAILED = (1 << 6) } imc_flags_t; #define IMC_F_ALL_FLAGS (IMC_F_UNSUP_PLATFORM | IMC_F_SCAN_DISPATCHED | \ IMC_F_SCAN_COMPLETE | IMC_F_ATTACH_DISPATCHED | IMC_F_ATTACH_COMPLETE | \ - IMC_F_MCREG_FAILED) + IMC_F_MCREG_FAILED | IMC_F_VALIDATE_FAILED) typedef enum imc_dimm_type { IMC_DIMM_UNKNOWN, -- cgit v1.2.3