summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Mustacchi <rm@fingolfin.org>2020-07-09 18:33:59 -0700
committerRobert Mustacchi <rm@fingolfin.org>2020-07-21 15:50:52 -0700
commit7d91603476b740ff8f4c917d71ee5884ab39cb60 (patch)
treec02be81031cbbc3869a0d974925ff4dbc242ee2f
parent777a71cfc7f5d1d0c739d58698fe598f2cdb6f2d (diff)
downloadillumos-joyent-7d91603476b740ff8f4c917d71ee5884ab39cb60.tar.gz
12966 imc driver blew up on missing channel
Reviewed by: Andy Fiddaman <andy@omniosce.org> Reviewed by: Igor Kozhukhov <igor@dilos.org> Reviewed by: Paul Winder <paul@winder.uk.net> Approved by: Dan McDonald <danmcd@joyent.com>
-rw-r--r--usr/src/uts/i86pc/io/imc/imc.c39
-rw-r--r--usr/src/uts/i86pc/io/imc/imc.h5
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
@@ -932,6 +932,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
* adjusting it to make sure that no home agent is present in it. We use the
@@ -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,