ecc/memtemp/e5: Prepare for E5 v3 support
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Sun, 8 Feb 2015 13:49:48 +0000 (21:49 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Wed, 11 Feb 2015 02:14:55 +0000 (10:14 +0800)
sys/dev/misc/ecc/e5_imc_reg.h [new file with mode: 0644]
sys/dev/misc/ecc/e5_imc_var.h [new file with mode: 0644]
sys/dev/misc/ecc/ecc_e5.c
sys/dev/misc/ecc/ecc_e5_reg.h [deleted file]
sys/dev/powermng/memtemp/memtemp_e5.c

diff --git a/sys/dev/misc/ecc/e5_imc_reg.h b/sys/dev/misc/ecc/e5_imc_reg.h
new file mode 100644 (file)
index 0000000..db6eb76
--- /dev/null
@@ -0,0 +1,186 @@
+#ifndef _E5_IMC_REG_H_
+#define _E5_IMC_REG_H_
+
+#ifndef _SYS_BITOPS_H_
+#include <sys/bitops.h>
+#endif
+
+/*
+ * E5 v2/v3 supports 4 channels, each channels could have 3 DIMMs.
+ * However each channel could only support 8 ranks, e.g. 3 quad-
+ * rank DIMMs can _not_ be installed.
+ *
+ * E5 v2 only has IMC0, which has 4 channels (channel 0~3).
+ *
+ * E5 v3 has two configuration:
+ * - IMC0, which has 4 channels (channel 0~3).
+ * - IMC0, which has 2 channels (channel 0~1) and IMC1, which has
+ *   2 channels (channel 2~3).
+ */ 
+
+#define PCI_E5_IMC_VID_ID                      0x8086
+#define PCI_E5_IMC_CHN_MAX                     4       /* max chans/sock */
+#define PCI_E5_IMC_CHN_DIMM_MAX                        3       /* max dimms/chan */
+#define PCI_E5_IMC_ERROR_RANK_MAX              8
+
+/*
+ * UBOX0
+ */
+/* E5 v2 */
+#define PCISLOT_E5V2_UBOX0                     11
+#define PCIFUNC_E5V2_UBOX0                     0
+#define PCI_E5V2_UBOX0_DID_ID                  0x0e1e
+/* E5 v3 */
+#define PCISLOT_E5V3_UBOX0                     16
+#define PCIFUNC_E5V3_UBOX0                     5
+#define PCI_E5V3_UBOX0_DID_ID                  0x2f1e
+/* UBOX0 regs */
+#define PCI_E5_UBOX0_CPUNODEID                 0x40
+#define PCI_E5_UBOX0_CPUNODEID_LCLNODEID       __BITS(0, 2) /* local socket */
+
+/*
+ * IMC main (aka CPGC)
+ */
+/* E5 v2 */
+#define PCISLOT_E5V2_IMC0_CPGC                 15
+#define PCIFUNC_E5V2_IMC0_CPGC                 0
+#define PCI_E5V2_IMC0_CPGC_DID_ID              0x0ea8
+/* E5 v3 */
+#define PCISLOT_E5V3_IMC0_CPGC                 19
+#define PCIFUNC_E5V3_IMC0_CPGC                 0
+#define PCI_E5V3_IMC0_CPGC_DID_ID              0x2fa8
+#define PCISLOT_E5V3_IMC1_CPGC                 22
+#define PCIFUNC_E5V3_IMC1_CPGC                 0
+#define PCI_E5V3_IMC1_CPGC_DID_ID              0x2f68
+/* CPGC regs */
+#define PCI_E5_IMC_CPGC_MCMTR                  0x7c
+#define PCI_E5V2_IMC_CPGC_MCMTR_CHN_DISABLE(c) __BIT(16 + (c))
+#define PCI_E5V3_IMC_CPGC_MCMTR_CHN_DISABLE(c) __BIT(18 + (c))
+#define PCI_E5V3_IMC_CPGC_MCMTR_DDR4           __BIT(14)
+#define PCI_E5_IMC_CPGC_MCMTR_IMC_MODE         __BITS(12, 13)
+#define PCI_E5_IMC_CPGC_MCMTR_IMC_MODE_DDR3    0       /* v3 native DDR */
+#define PCI_E5_IMC_CPGC_MCMTR_ECC_EN           __BIT(2)
+
+/*
+ * Channel Target Address Decoder, per-channel
+ */
+/* E5 v2 */
+#define PCISLOT_E5V2_IMC0_CTAD                 15
+#define PCIFUNC_E5V2_IMC0_CTAD(c)              (2 + (c))
+#define PCI_E5V2_IMC0_CTAD_DID_ID(c)           (0x0eaa + (c))
+/* E5 v3 */
+#define PCISLOT_E5V3_IMC0_CTAD                 19
+#define PCIFUNC_E5V3_IMC0_CTAD(c)              (2 + (c))
+#define PCI_E5V3_IMC0_CTAD_DID_ID(c)           (0x2faa + (c))
+#define PCISLOT_E5V3_IMC1_CTAD                 22
+#define PCIFUNC_E5V3_IMC1_CTAD(c)              (2 + (c))
+#define PCI_E5V3_IMC1_CTAD_DID_ID(c)           (0x2f6a + (c))
+/* CTAD regs */
+#define PCI_E5_IMC_CTAD_DIMMMTR(dimm)          (0x80 + ((dimm) * 4))
+#define PCI_E5V3_IMC_CTAD_DIMMMTR_DDR4         __BIT(20)
+#define PCI_E5_IMC_CTAD_DIMMMTR_RANK_DISABLE(r)        __BIT(16 + (r))
+#define PCI_E5_IMC_CTAD_DIMMMTR_RANK_DISABLE_ALL __BITS(16, 19)
+#define PCI_E5_IMC_CTAD_DIMMMTR_DIMM_POP       __BIT(14)
+#define PCI_E5_IMC_CTAD_DIMMMTR_RANK_CNT       __BITS(12, 13)
+#define PCI_E5_IMC_CTAD_DIMMMTR_RANK_CNT_SR    0
+#define PCI_E5_IMC_CTAD_DIMMMTR_RANK_CNT_DR    1
+#define PCI_E5_IMC_CTAD_DIMMMTR_RANK_CNT_QR    2
+#define PCI_E5V3_IMC_CTAD_DIMMMTR_RANK_CNT_8R  3
+#define PCI_E5_IMC_CTAD_DIMMMTR_DDR3_WIDTH     __BITS(7, 8)
+#define PCI_E5_IMC_CTAD_DIMMMTR_DDR3_WIDTH_4   0
+#define PCI_E5_IMC_CTAD_DIMMMTR_DDR3_WIDTH_8   1
+#define PCI_E5_IMC_CTAD_DIMMMTR_DDR3_WIDTH_16  2
+#define PCI_E5_IMC_CTAD_DIMMMTR_DDR3_WIDTH_RSVD        3
+#define PCI_E5_IMC_CTAD_DIMMMTR_DDR3_DNSTY     __BITS(5, 6)
+#define PCI_E5_IMC_CTAD_DIMMMTR_DDR3_DNSTY_1G  0       /* v3 reserved */
+#define PCI_E5_IMC_CTAD_DIMMMTR_DDR3_DNSTY_2G  1
+#define PCI_E5_IMC_CTAD_DIMMMTR_DDR3_DNSTY_4G  2
+#define PCI_E5_IMC_CTAD_DIMMMTR_DDR3_DNSTY_8G  3
+
+/*
+ * ERROR, per-channel
+ */
+/* E5 v2 */
+#define PCISLOT_E5V2_IMC0_ERROR_CHN0           16
+#define PCIFUNC_E5V2_IMC0_ERROR_CHN0           2
+#define PCI_E5V2_IMC0_ERROR_CHN0_DID_ID                0x0eb2
+#define PCISLOT_E5V2_IMC0_ERROR_CHN1           16
+#define PCIFUNC_E5V2_IMC0_ERROR_CHN1           3
+#define PCI_E5V2_IMC0_ERROR_CHN1_DID_ID                0x0eb3
+#define PCISLOT_E5V2_IMC0_ERROR_CHN2           16
+#define PCIFUNC_E5V2_IMC0_ERROR_CHN2           6
+#define PCI_E5V2_IMC0_ERROR_CHN2_DID_ID                0x0eb6
+#define PCISLOT_E5V2_IMC0_ERROR_CHN3           16
+#define PCIFUNC_E5V2_IMC0_ERROR_CHN3           7
+#define PCI_E5V2_IMC0_ERROR_CHN3_DID_ID                0x0eb7
+/* E5 v3 */
+#define PCISLOT_E5V3_IMC0_ERROR_CHN0           20
+#define PCIFUNC_E5V3_IMC0_ERROR_CHN0           2
+#define PCI_E5V3_IMC0_ERROR_CHN0_DID_ID                0x2fb6
+#define PCISLOT_E5V3_IMC0_ERROR_CHN1           20
+#define PCIFUNC_E5V3_IMC0_ERROR_CHN1           3
+#define PCI_E5V3_IMC0_ERROR_CHN1_DID_ID                0x2fb7
+#define PCISLOT_E5V3_IMC0_ERROR_CHN2           21
+#define PCIFUNC_E5V3_IMC0_ERROR_CHN2           2
+#define PCI_E5V3_IMC0_ERROR_CHN2_DID_ID                0x2fb2
+#define PCISLOT_E5V3_IMC0_ERROR_CHN3           21
+#define PCIFUNC_E5V3_IMC0_ERROR_CHN3           3
+#define PCI_E5V3_IMC0_ERROR_CHN3_DID_ID                0x2fb3
+#define PCISLOT_E5V3_IMC1_ERROR_CHN0           23
+#define PCIFUNC_E5V3_IMC1_ERROR_CHN0           2
+#define PCI_E5V3_IMC1_ERROR_CHN0_DID_ID                0x2fd6
+#define PCISLOT_E5V3_IMC1_ERROR_CHN1           23
+#define PCIFUNC_E5V3_IMC1_ERROR_CHN1           3
+#define PCI_E5V3_IMC1_ERROR_CHN1_DID_ID                0x2fd7
+/* ERROR regs */
+#define PCI_E5_IMC_ERROR_COR_ERR_CNT(i)                (0x104 + ((i) * 4))
+#define PCI_E5_IMC_ERROR_COR_ERR_CNT_HI_OVFL   __BIT(31)
+#define PCI_E5_IMC_ERROR_COR_ERR_CNT_HI                __BITS(16, 30)
+#define PCI_E5_IMC_ERROR_COR_ERR_CNT_LO_OVFL   __BIT(15)
+#define PCI_E5_IMC_ERROR_COR_ERR_CNT_LO                __BITS(0, 14)
+#define PCI_E5_IMC_ERROR_COR_ERR_TH(i)         (0x11c + ((i) * 4))
+#define PCI_E5_IMC_ERROR_COR_ERR_TH_HI         __BITS(16, 30)
+#define PCI_E5_IMC_ERROR_COR_ERR_TH_LO         __BITS(0, 14)
+#define PCI_E5_IMC_ERROR_COR_ERR_STAT          0x134
+#define PCI_E5_IMC_ERROR_COR_ERR_STAT_RANKS    __BITS(0, 7)
+
+/*
+ * Thermal, per-channel
+ */
+/* E5 v2 */
+#define PCISLOT_E5V2_IMC0_THERMAL_CHN0         16
+#define PCIFUNC_E5V2_IMC0_THERMAL_CHN0         0
+#define PCI_E5V2_IMC0_THERMAL_CHN0_DID_ID      0x0eb0
+#define PCISLOT_E5V2_IMC0_THERMAL_CHN1         16
+#define PCIFUNC_E5V2_IMC0_THERMAL_CHN1         1
+#define PCI_E5V2_IMC0_THERMAL_CHN1_DID_ID      0x0eb1
+#define PCISLOT_E5V2_IMC0_THERMAL_CHN2         16
+#define PCIFUNC_E5V2_IMC0_THERMAL_CHN2         4
+#define PCI_E5V2_IMC0_THERMAL_CHN2_DID_ID      0x0eb4
+#define PCISLOT_E5V2_IMC0_THERMAL_CHN3         16
+#define PCIFUNC_E5V2_IMC0_THERMAL_CHN3         5
+#define PCI_E5V2_IMC0_THERMAL_CHN3_DID_ID      0x0eb5
+/* E5 v3 */
+#define PCISLOT_E5V3_IMC0_THERMAL_CHN0         20
+#define PCIFUNC_E5V3_IMC0_THERMAL_CHN0         0
+#define PCI_E5V3_IMC0_THERMAL_CHN0_DID_ID      0x2fb4
+#define PCISLOT_E5V3_IMC0_THERMAL_CHN1         20
+#define PCIFUNC_E5V3_IMC0_THERMAL_CHN1         1
+#define PCI_E5V3_IMC0_THERMAL_CHN1_DID_ID      0x2fb5
+#define PCISLOT_E5V3_IMC0_THERMAL_CHN2         21
+#define PCIFUNC_E5V3_IMC0_THERMAL_CHN2         0
+#define PCI_E5V3_IMC0_THERMAL_CHN2_DID_ID      0x2fb0
+#define PCISLOT_E5V3_IMC0_THERMAL_CHN3         21
+#define PCIFUNC_E5V3_IMC0_THERMAL_CHN3         1
+#define PCI_E5V3_IMC0_THERMAL_CHN3_DID_ID      0x2fb1
+#define PCISLOT_E5V3_IMC1_THERMAL_CHN0         23
+#define PCIFUNC_E5V3_IMC1_THERMAL_CHN0         0
+#define PCI_E5V3_IMC1_THERMAL_CHN0_DID_ID      0x2fd4
+#define PCISLOT_E5V3_IMC1_THERMAL_CHN1         23
+#define PCIFUNC_E5V3_IMC1_THERMAL_CHN1         1
+#define PCI_E5V3_IMC1_THERMAL_CHN1_DID_ID      0x2fd5
+/* Thermal regs */
+#define PCI_E5_IMC_THERMAL_DIMMTEMPSTAT(dimm)  (0x150 + ((dimm) * 4))
+#define PCI_E5_IMC_THERMAL_DIMMTEMPSTAT_TEMP   __BITS(0, 7)
+
+#endif /* !_E5_IMC_REG_H_ */
diff --git a/sys/dev/misc/ecc/e5_imc_var.h b/sys/dev/misc/ecc/e5_imc_var.h
new file mode 100644 (file)
index 0000000..dface69
--- /dev/null
@@ -0,0 +1,111 @@
+#ifndef _E5_IMC_VAR_H_
+#define _E5_IMC_VAR_H_
+
+#define E5_IMC_CHAN_VER2       2       /* E5 v2 */
+#define E5_IMC_CHAN_VER3       3       /* E5 v3 */
+
+struct e5_imc_chan {
+       uint16_t        did;
+       int             slot;
+       int             func;
+       const char      *desc;
+
+       int             chan_ext;       /* external channel */
+       int             chan;
+       int             ver;
+
+       int             ubox_slot;
+       int             ubox_func;
+       uint16_t        ubox_did;
+
+       int             cpgc_slot;
+       int             cpgc_func;
+       uint16_t        cpgc_did;
+       uint32_t        cpgc_chandis;
+
+       int             ctad_slot;
+       int             ctad_func;
+       uint16_t        ctad_did;
+};
+
+#define E5_IMC_CHAN_END        \
+       { 0, 0, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+
+#define E5_IMC_CHAN_FIELDS(v, imc, c, c_ext)                   \
+       .chan_ext       = c_ext,                                \
+       .chan           = c,                                    \
+       .ver            = E5_IMC_CHAN_VER##v,                   \
+                                                               \
+       .ubox_slot      = PCISLOT_E5V##v##_UBOX0,               \
+       .ubox_func      = PCIFUNC_E5V##v##_UBOX0,               \
+       .ubox_did       = PCI_E5V##v##_UBOX0_DID_ID,            \
+                                                               \
+       .cpgc_slot      = PCISLOT_E5V##v##_IMC##imc##_CPGC,     \
+       .cpgc_func      = PCIFUNC_E5V##v##_IMC##imc##_CPGC,     \
+       .cpgc_did       = PCI_E5V##v##_IMC##imc##_CPGC_DID_ID,  \
+       .cpgc_chandis   = PCI_E5V##v##_IMC_CPGC_MCMTR_CHN_DISABLE(c), \
+                                                               \
+       .ctad_slot      = PCISLOT_E5V##v##_IMC##imc##_CTAD,     \
+       .ctad_func      = PCIFUNC_E5V##v##_IMC##imc##_CTAD(c),  \
+       .ctad_did       = PCI_E5V##v##_IMC##imc##_CTAD_DID_ID(c) \
+
+#define UBOX_READ(dev, c, ofs, w)                      \
+       pcib_read_config((dev), pci_get_bus((dev)),     \
+           (c)->ubox_slot, (c)->ubox_func, (ofs), (w))
+#define UBOX_READ_2(dev, c, ofs)       UBOX_READ((dev), (c), (ofs), 2)
+#define UBOX_READ_4(dev, c, ofs)       UBOX_READ((dev), (c), (ofs), 4)
+
+#define IMC_CPGC_READ(dev, c, ofs, w)                  \
+       pcib_read_config((dev), pci_get_bus((dev)),     \
+           (c)->cpgc_slot, (c)->cpgc_func, (ofs), (w))
+#define IMC_CPGC_READ_2(dev, c, ofs)   IMC_CPGC_READ((dev), (c), (ofs), 2)
+#define IMC_CPGC_READ_4(dev, c, ofs)   IMC_CPGC_READ((dev), (c), (ofs), 4)
+
+#define IMC_CTAD_READ(dev, c, ofs, w)                  \
+       pcib_read_config((dev), pci_get_bus((dev)),     \
+           (c)->ctad_slot, (c)->ctad_func, (ofs), (w))
+#define IMC_CTAD_READ_2(dev, c, ofs)   IMC_CTAD_READ((dev), (c), (ofs), 2)
+#define IMC_CTAD_READ_4(dev, c, ofs)   IMC_CTAD_READ((dev), (c), (ofs), 4)
+
+static __inline int
+e5_imc_node_probe(device_t dev, const struct e5_imc_chan *c)
+{
+       int node, dimm;
+       uint32_t val;
+
+       /* Check CPGC vid/did */
+       if (IMC_CPGC_READ_2(dev, c, PCIR_VENDOR) != PCI_E5_IMC_VID_ID ||
+           IMC_CPGC_READ_2(dev, c, PCIR_DEVICE) != c->cpgc_did)
+               return -1;
+
+       /* Is this channel disabled */
+       val = IMC_CPGC_READ_4(dev, c, PCI_E5_IMC_CPGC_MCMTR);
+       if (val & c->cpgc_chandis)
+               return -1;
+
+       /* Check CTAD vid/did */
+       if (IMC_CTAD_READ_2(dev, c, PCIR_VENDOR) != PCI_E5_IMC_VID_ID ||
+           IMC_CTAD_READ_2(dev, c, PCIR_DEVICE) != c->ctad_did)
+               return -1;
+
+       /* Are there any DIMMs populated? */
+       for (dimm = 0; dimm < PCI_E5_IMC_CHN_DIMM_MAX; ++dimm) {
+               val = IMC_CTAD_READ_4(dev, c, PCI_E5_IMC_CTAD_DIMMMTR(dimm));
+               if (val & PCI_E5_IMC_CTAD_DIMMMTR_DIMM_POP)
+                       break;
+       }
+       if (dimm == PCI_E5_IMC_CHN_DIMM_MAX)
+               return -1;
+
+       /* Check UBOX vid/did */
+       if (UBOX_READ_2(dev, c, PCIR_VENDOR) != PCI_E5_IMC_VID_ID ||
+           UBOX_READ_2(dev, c, PCIR_DEVICE) != c->ubox_did)
+               return -1;
+
+       val = UBOX_READ_4(dev, c, PCI_E5_UBOX0_CPUNODEID);
+       node = __SHIFTOUT(val, PCI_E5_UBOX0_CPUNODEID_LCLNODEID);
+
+       return node;
+}
+
+#endif /* !_E5_IMC_VAR_H_ */
index ee4c44d..6149181 100644 (file)
 
 #include "pcib_if.h"
 
-#include <dev/misc/ecc/ecc_e5_reg.h>
-
-#define UBOX_READ(dev, ofs, w)                         \
-       pcib_read_config((dev), pci_get_bus((dev)),     \
-           PCISLOT_E5_UBOX0, PCIFUNC_E5_UBOX0, (ofs), w)
-#define UBOX_READ_2(dev, ofs)          UBOX_READ((dev), (ofs), 2)
-#define UBOX_READ_4(dev, ofs)          UBOX_READ((dev), (ofs), 4)
-
-#define IMC_CPGC_READ(dev, ofs, w)                     \
-       pcib_read_config((dev), pci_get_bus((dev)),     \
-           PCISLOT_E5_IMC_CPGC, PCIFUNC_E5_IMC_CPGC, (ofs), w)
-#define IMC_CPGC_READ_2(dev, ofs)      IMC_CPGC_READ((dev), (ofs), 2)
-#define IMC_CPGC_READ_4(dev, ofs)      IMC_CPGC_READ((dev), (ofs), 4)
-
-#define IMC_CTAD_READ(dev, c, ofs, w)                  \
-       pcib_read_config((dev), pci_get_bus((dev)),     \
-           PCISLOT_E5_IMC_CTAD, PCIFUNC_E5_IMC_CTAD((c)), (ofs), w)
-#define IMC_CTAD_READ_2(dev, c, ofs)   IMC_CTAD_READ((dev), (c), (ofs), 2)
-#define IMC_CTAD_READ_4(dev, c, ofs)   IMC_CTAD_READ((dev), (c), (ofs), 4)
-
-struct ecc_e5_type {
-       uint16_t        did;
-       int             slot;
-       int             func;
-       int             chan;
-       const char      *desc;
-};
+#include <dev/misc/ecc/e5_imc_reg.h>
+#include <dev/misc/ecc/e5_imc_var.h>
 
 struct ecc_e5_rank {
        int             rank_dimm;      /* owner dimm */
@@ -82,7 +57,7 @@ struct ecc_e5_rank {
 
 struct ecc_e5_softc {
        device_t                ecc_dev;
-       int                     ecc_chan;
+       const struct e5_imc_chan *ecc_chan;
        int                     ecc_node;
        int                     ecc_rank_cnt;
        struct ecc_e5_rank      ecc_rank[PCI_E5_IMC_ERROR_RANK_MAX];
@@ -99,28 +74,31 @@ static void ecc_e5_shutdown(device_t);
 
 static void    ecc_e5_callout(void *);
 
-#define ECC_E5_TYPE_V2(c) \
-{ \
-       .did    = PCI_E5_IMC_ERROR_CHN##c##_DID_ID, \
-       .slot   = PCISLOT_E5_IMC_ERROR, \
-       .func   = PCIFUNC_E5_IMC_ERROR_CHN##c, \
-       .chan   = c, \
-       .desc   = "Intel E5 v2 ECC" \
+#define ECC_E5_CHAN(v, imc, c, c_ext)                          \
+{                                                              \
+       .did            = PCI_E5V##v##_IMC##imc##_ERROR_CHN##c##_DID_ID, \
+       .slot           = PCISLOT_E5V##v##_IMC##imc##_ERROR_CHN##c, \
+       .func           = PCIFUNC_E5V##v##_IMC##imc##_ERROR_CHN##c, \
+       .desc           = "Intel E5 v" #v " ECC",               \
+                                                               \
+       E5_IMC_CHAN_FIELDS(v, imc, c, c_ext)                    \
 }
 
-#define ECC_E5_TYPE_END                { 0, 0, 0, 0, NULL }
+#define ECC_E5_CHAN_V2(c)      ECC_E5_CHAN(2, 0, c, c)
+#define ECC_E5_CHAN_END                E5_IMC_CHAN_END
 
-static const struct ecc_e5_type ecc_types[] = {
-       ECC_E5_TYPE_V2(0),
-       ECC_E5_TYPE_V2(1),
-       ECC_E5_TYPE_V2(2),
-       ECC_E5_TYPE_V2(3),
+static const struct e5_imc_chan ecc_e5_chans[] = {
+       ECC_E5_CHAN_V2(0),
+       ECC_E5_CHAN_V2(1),
+       ECC_E5_CHAN_V2(2),
+       ECC_E5_CHAN_V2(3),
 
-       ECC_E5_TYPE_END
+       ECC_E5_CHAN_END
 };
 
-#undef ECC_E5_TYPE_V2
-#undef ECC_E5_TYPE_END
+#undef ECC_E5_CHAN_END
+#undef ECC_E5_CHAN_V2
+#undef ECC_E5_CHAN
 
 static device_method_t ecc_e5_methods[] = {
        /* Device interface */
@@ -145,69 +123,33 @@ MODULE_DEPEND(ecc_e5, pci, 1, 1, 1);
 static int
 ecc_e5_probe(device_t dev)
 {
-       const struct ecc_e5_type *t;
+       const struct e5_imc_chan *c;
        uint16_t vid, did;
        int slot, func;
 
        vid = pci_get_vendor(dev);
-       if (vid != PCI_E5_VID_ID)
+       if (vid != PCI_E5_IMC_VID_ID)
                return ENXIO;
 
        did = pci_get_device(dev);
        slot = pci_get_slot(dev);
        func = pci_get_function(dev);
 
-       for (t = ecc_types; t->desc != NULL; ++t) {
-               if (t->did == did && t->slot == slot && t->func == func) {
+       for (c = ecc_e5_chans; c->desc != NULL; ++c) {
+               if (c->did == did && c->slot == slot && c->func == func) {
                        struct ecc_e5_softc *sc = device_get_softc(dev);
                        char desc[32];
-                       uint32_t val;
-                       int node, dimm;
-
-                       /* Check CPGC vid/did */
-                       if (IMC_CPGC_READ_2(dev, PCIR_VENDOR) !=
-                           PCI_E5_VID_ID ||
-                           IMC_CPGC_READ_2(dev, PCIR_DEVICE) !=
-                           PCI_E5_IMC_CPGC_DID_ID)
-                               break;
-
-                       /* Is this channel disabled */
-                       val = IMC_CPGC_READ_4(dev, PCI_E5_IMC_CPGC_MCMTR);
-                       if (val & PCI_E5_IMC_CPGC_MCMTR_CHN_DISABLE(t->chan))
-                               break;
-
-                       /* Check CTAD vid/did */
-                       if (IMC_CTAD_READ_2(dev, t->chan, PCIR_VENDOR) !=
-                           PCI_E5_VID_ID ||
-                           IMC_CTAD_READ_2(dev, t->chan, PCIR_DEVICE) !=
-                           PCI_E5_IMC_CTAD_DID_ID(t->chan))
-                               break;
+                       int node;
 
-                       /* Are there any DIMMs populated? */
-                       for (dimm = 0; dimm < PCI_E5_IMC_DIMM_MAX; ++dimm) {
-                               val = IMC_CTAD_READ_4(dev, t->chan,
-                                   PCI_E5_IMC_CTAD_DIMMMTR(dimm));
-                               if (val & PCI_E5_IMC_CTAD_DIMMMTR_DIMM_POP)
-                                       break;
-                       }
-                       if (dimm == PCI_E5_IMC_DIMM_MAX)
+                       node = e5_imc_node_probe(dev, c);
+                       if (node < 0)
                                break;
 
-                       /* Check UBOX vid/did */
-                       if (UBOX_READ_2(dev, PCIR_VENDOR) != PCI_E5_VID_ID ||
-                           UBOX_READ_2(dev, PCIR_DEVICE) !=
-                           PCI_E5_UBOX0_DID_ID)
-                               break;
-
-                       val = UBOX_READ_4(dev, PCI_E5_UBOX0_CPUNODEID);
-                       node = __SHIFTOUT(val,
-                           PCI_E5_UBOX0_CPUNODEID_LCLNODEID);
-
                        ksnprintf(desc, sizeof(desc), "%s node%d channel%d",
-                           t->desc, node, t->chan);
+                           c->desc, node, c->chan_ext);
                        device_set_desc_copy(dev, desc);
 
-                       sc->ecc_chan = t->chan;
+                       sc->ecc_chan = c;
                        sc->ecc_node = node;
                        return 0;
                }
@@ -225,15 +167,23 @@ ecc_e5_attach(device_t dev)
        callout_init_mp(&sc->ecc_callout);
        sc->ecc_dev = dev;
 
-       mcmtr = IMC_CPGC_READ_4(sc->ecc_dev, PCI_E5_IMC_CPGC_MCMTR);
+       mcmtr = IMC_CPGC_READ_4(sc->ecc_dev, sc->ecc_chan,
+           PCI_E5_IMC_CPGC_MCMTR);
        if (bootverbose) {
+               if (sc->ecc_chan->ver == E5_IMC_CHAN_VER3 &&
+                   (mcmtr & PCI_E5V3_IMC_CPGC_MCMTR_DDR4))
+                       ecc_printf(sc, "DDR4 ");
                if (__SHIFTOUT(mcmtr, PCI_E5_IMC_CPGC_MCMTR_IMC_MODE) ==
-                   PCI_E5_IMC_CPGC_MCMTR_IMC_MODE_DDR3)
-                       ecc_printf(sc, "native DDR3\n");
+                   PCI_E5_IMC_CPGC_MCMTR_IMC_MODE_DDR3) {
+                       ecc_printf(sc, "native %s",
+                           sc->ecc_chan->ver == E5_IMC_CHAN_VER2 ?
+                           "DDR3" : "DDR");
+               }
+               kprintf("\n");
        }
 
        rank = 0;
-       for (dimm = 0; dimm < PCI_E5_IMC_DIMM_MAX; ++dimm) {
+       for (dimm = 0; dimm < PCI_E5_IMC_CHN_DIMM_MAX; ++dimm) {
                const char *width;
                uint32_t dimmmtr;
                int rank_cnt, r;
@@ -257,6 +207,12 @@ ecc_e5_attach(device_t dev)
                case PCI_E5_IMC_CTAD_DIMMMTR_RANK_CNT_QR:
                        rank_cnt = 4;
                        break;
+               case PCI_E5V3_IMC_CTAD_DIMMMTR_RANK_CNT_8R:
+                       if (sc->ecc_chan->ver >= E5_IMC_CHAN_VER3) {
+                               rank_cnt = 8;
+                               break;
+                       }
+                       /* FALL THROUGH */
                default:
                        ecc_printf(sc, "unknown rank count 0x%x\n", val);
                        return ENXIO;
@@ -280,9 +236,6 @@ ecc_e5_attach(device_t dev)
 
                val = __SHIFTOUT(dimmmtr, PCI_E5_IMC_CTAD_DIMMMTR_DDR3_DNSTY);
                switch (val) {
-               case PCI_E5_IMC_CTAD_DIMMMTR_DDR3_DNSTY_1G:
-                       density = 1;
-                       break;
                case PCI_E5_IMC_CTAD_DIMMMTR_DDR3_DNSTY_2G:
                        density = 2;
                        break;
@@ -292,6 +245,12 @@ ecc_e5_attach(device_t dev)
                case PCI_E5_IMC_CTAD_DIMMMTR_DDR3_DNSTY_8G:
                        density = 8;
                        break;
+               case PCI_E5_IMC_CTAD_DIMMMTR_DDR3_DNSTY_1G:
+                       if (sc->ecc_chan->ver < E5_IMC_CHAN_VER3) {
+                               density = 1;
+                               break;
+                       }
+                       /* FALL THROUGH */
                default:
                        ecc_printf(sc, "unknown ddr3 density 0x%x\n", val);
                        return ENXIO;
@@ -335,7 +294,7 @@ ecc_e5_attach(device_t dev)
                        if (rank & 1)
                                mask = PCI_E5_IMC_ERROR_COR_ERR_TH_HI;
                        else
-                               mask = PCI_E5_IMC_ERROR_COR_ERR_TH_HI;
+                               mask = PCI_E5_IMC_ERROR_COR_ERR_TH_LO;
 
                        thr = pci_read_config(sc->ecc_dev, ofs, 4);
                        ecc_printf(sc, "DIMM%d rank%d, "
@@ -378,7 +337,7 @@ ecc_e5_callout(void *xsc)
                        err = pci_read_config(sc->ecc_dev, ofs, 4);
                        ecc_printf(sc, "node%d channel%d DIMM%d rank%d, "
                            "too many errors %d",
-                           sc->ecc_node, sc->ecc_chan,
+                           sc->ecc_node, sc->ecc_chan->chan_ext,
                            rk->rank_dimm, rk->rank_dimm_rank,
                            __SHIFTOUT(err, mask));
                }
diff --git a/sys/dev/misc/ecc/ecc_e5_reg.h b/sys/dev/misc/ecc/ecc_e5_reg.h
deleted file mode 100644 (file)
index aae381c..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-#ifndef _ECC_E5_REG_H_
-#define _ECC_E5_REG_H_
-
-#ifndef _SYS_BITOPS_H_
-#include <sys/bitops.h>
-#endif
-
-#define PCI_E5_VID_ID                          0x8086
-#define PCI_E5_IMC_CHN_MAX                     4
-#define PCI_E5_IMC_DIMM_MAX                    3
-#define PCI_E5_IMC_ERROR_RANK_MAX              8
-
-#define PCISLOT_E5_UBOX0                       11
-#define PCIFUNC_E5_UBOX0                       0
-#define PCI_E5_UBOX0_DID_ID                    0x0e1e
-#define PCI_E5_UBOX0_CPUNODEID                 0x40
-#define PCI_E5_UBOX0_CPUNODEID_LCLNODEID       __BITS(0, 2) /* local socket */
-
-#define PCISLOT_E5_IMC_CPGC                    15
-#define PCIFUNC_E5_IMC_CPGC                    0
-#define PCI_E5_IMC_CPGC_DID_ID                 0x0ea8
-#define PCI_E5_IMC_CPGC_MCMTR                  0x7c
-#define PCI_E5_IMC_CPGC_MCMTR_CHN_DISABLE(c)   __BIT(16 + (c))
-#define PCI_E5_IMC_CPGC_MCMTR_IMC_MODE         __BITS(12, 13)
-#define PCI_E5_IMC_CPGC_MCMTR_IMC_MODE_DDR3    0
-#define PCI_E5_IMC_CPGC_MCMTR_ECC_EN           __BIT(2)
-
-/* Channel Target Address Decoder, per-channel */
-#define PCISLOT_E5_IMC_CTAD                    15
-#define PCIFUNC_E5_IMC_CTAD(c)                 (2 + (c))
-#define PCI_E5_IMC_CTAD_DID_ID(c)              (0x0eaa + (c))
-#define PCI_E5_IMC_CTAD_DIMMMTR(dimm)          (0x80 + ((dimm) * 4))
-#define PCI_E5_IMC_CTAD_DIMMMTR_RANK_DISABLE(r)        __BIT(16 + (r))
-#define PCI_E5_IMC_CTAD_DIMMMTR_RANK_DISABLE_ALL __BITS(16, 19)
-#define PCI_E5_IMC_CTAD_DIMMMTR_DIMM_POP       __BIT(14)
-#define PCI_E5_IMC_CTAD_DIMMMTR_RANK_CNT       __BITS(12, 13)
-#define PCI_E5_IMC_CTAD_DIMMMTR_RANK_CNT_SR    0
-#define PCI_E5_IMC_CTAD_DIMMMTR_RANK_CNT_DR    1
-#define PCI_E5_IMC_CTAD_DIMMMTR_RANK_CNT_QR    2
-#define PCI_E5_IMC_CTAD_DIMMMTR_RANK_CNT_RSVD  3
-#define PCI_E5_IMC_CTAD_DIMMMTR_DDR3_WIDTH     __BITS(7, 8)
-#define PCI_E5_IMC_CTAD_DIMMMTR_DDR3_WIDTH_4   0
-#define PCI_E5_IMC_CTAD_DIMMMTR_DDR3_WIDTH_8   1
-#define PCI_E5_IMC_CTAD_DIMMMTR_DDR3_WIDTH_16  2
-#define PCI_E5_IMC_CTAD_DIMMMTR_DDR3_WIDTH_RSVD        3
-#define PCI_E5_IMC_CTAD_DIMMMTR_DDR3_DNSTY     __BITS(5, 6)
-#define PCI_E5_IMC_CTAD_DIMMMTR_DDR3_DNSTY_1G  0
-#define PCI_E5_IMC_CTAD_DIMMMTR_DDR3_DNSTY_2G  1
-#define PCI_E5_IMC_CTAD_DIMMMTR_DDR3_DNSTY_4G  2
-#define PCI_E5_IMC_CTAD_DIMMMTR_DDR3_DNSTY_8G  3
-
-/* ERROR, per-channel */
-#define PCISLOT_E5_IMC_ERROR                   16
-#define PCIFUNC_E5_IMC_ERROR_CHN0              2
-#define PCIFUNC_E5_IMC_ERROR_CHN1              3
-#define PCIFUNC_E5_IMC_ERROR_CHN2              6
-#define PCIFUNC_E5_IMC_ERROR_CHN3              7
-#define PCI_E5_IMC_ERROR_CHN0_DID_ID           0x0eb2
-#define PCI_E5_IMC_ERROR_CHN1_DID_ID           0x0eb3
-#define PCI_E5_IMC_ERROR_CHN2_DID_ID           0x0eb6
-#define PCI_E5_IMC_ERROR_CHN3_DID_ID           0x0eb7
-#define PCI_E5_IMC_ERROR_COR_ERR_CNT(i)                (0x104 + ((i) * 4))
-#define PCI_E5_IMC_ERROR_COR_ERR_CNT_HI_OVFL   __BIT(31)
-#define PCI_E5_IMC_ERROR_COR_ERR_CNT_HI                __BITS(16, 30)
-#define PCI_E5_IMC_ERROR_COR_ERR_CNT_LO_OVFL   __BIT(15)
-#define PCI_E5_IMC_ERROR_COR_ERR_CNT_LO                __BITS(0, 14)
-#define PCI_E5_IMC_ERROR_COR_ERR_TH(i)         (0x11c + ((i) * 4))
-#define PCI_E5_IMC_ERROR_COR_ERR_TH_HI         __BITS(16, 30)
-#define PCI_E5_IMC_ERROR_COR_ERR_TH_LO         __BITS(0, 14)
-#define PCI_E5_IMC_ERROR_COR_ERR_STAT          0x134
-#define PCI_E5_IMC_ERROR_COR_ERR_STAT_RANKS    __BITS(0, 7)
-
-/* Thermal, per-channel */
-#define PCISLOT_E5_IMC_THERMAL                 16
-#define PCIFUNC_E5_IMC_THERMAL_CHN0            0
-#define PCIFUNC_E5_IMC_THERMAL_CHN1            1
-#define PCIFUNC_E5_IMC_THERMAL_CHN2            4
-#define PCIFUNC_E5_IMC_THERMAL_CHN3            5
-#define PCI_E5_IMC_THERMAL_CHN0_DID_ID         0x0eb0
-#define PCI_E5_IMC_THERMAL_CHN1_DID_ID         0x0eb1
-#define PCI_E5_IMC_THERMAL_CHN2_DID_ID         0x0eb4
-#define PCI_E5_IMC_THERMAL_CHN3_DID_ID         0x0eb5
-#define PCI_E5_IMC_THERMAL_DIMMTEMPSTAT(dimm)  (0x150 + ((dimm) * 4))
-#define PCI_E5_IMC_THERMAL_DIMMTEMPSTAT_TEMP   __BITS(0, 7)
-
-#endif /* !_ECC_E5_REG_H_ */
index 54927bd..8480868 100644 (file)
 
 #include "pcib_if.h"
 
-#include <dev/misc/ecc/ecc_e5_reg.h>
-
-#define UBOX_READ(dev, ofs, w)                         \
-       pcib_read_config((dev), pci_get_bus((dev)),     \
-           PCISLOT_E5_UBOX0, PCIFUNC_E5_UBOX0, (ofs), w)
-#define UBOX_READ_2(dev, ofs)          UBOX_READ((dev), (ofs), 2)
-#define UBOX_READ_4(dev, ofs)          UBOX_READ((dev), (ofs), 4)
-
-#define IMC_CPGC_READ(dev, ofs, w)                     \
-       pcib_read_config((dev), pci_get_bus((dev)),     \
-           PCISLOT_E5_IMC_CPGC, PCIFUNC_E5_IMC_CPGC, (ofs), w)
-#define IMC_CPGC_READ_2(dev, ofs)      IMC_CPGC_READ((dev), (ofs), 2)
-#define IMC_CPGC_READ_4(dev, ofs)      IMC_CPGC_READ((dev), (ofs), 4)
-
-#define IMC_CTAD_READ(dev, c, ofs, w)                  \
-       pcib_read_config((dev), pci_get_bus((dev)),     \
-           PCISLOT_E5_IMC_CTAD, PCIFUNC_E5_IMC_CTAD((c)), (ofs), w)
-#define IMC_CTAD_READ_2(dev, c, ofs)   IMC_CTAD_READ((dev), (c), (ofs), 2)
-#define IMC_CTAD_READ_4(dev, c, ofs)   IMC_CTAD_READ((dev), (c), (ofs), 4)
-
-struct memtemp_e5_type {
-       uint16_t        did;
-       int             slot;
-       int             func;
-       int             chan;
-       const char      *desc;
-};
+#include <dev/misc/ecc/e5_imc_reg.h>
+#include <dev/misc/ecc/e5_imc_var.h>
 
 struct memtemp_e5_softc;
 
 struct memtemp_e5_dimm {
-       TAILQ_ENTRY(memtemp_e5_dimm) dimm_link;
-       struct ksensordev       dimm_sensordev;
-       struct ksensor          dimm_sensor;
-       struct memtemp_e5_softc *dimm_parent;
-       int                     dimm_id;
-       int                     dimm_extid;
+       TAILQ_ENTRY(memtemp_e5_dimm)    dimm_link;
+       struct ksensordev               dimm_sensordev;
+       struct ksensor                  dimm_sensor;
+       struct memtemp_e5_softc         *dimm_parent;
+       int                             dimm_id;
+       int                             dimm_extid;
 };
 
 struct memtemp_e5_softc {
-       device_t                temp_dev;
-       int                     temp_chan;
-       int                     temp_node;
-       TAILQ_HEAD(, memtemp_e5_dimm) temp_dimm;
+       device_t                        temp_dev;
+       const struct e5_imc_chan        *temp_chan;
+       int                             temp_node;
+       TAILQ_HEAD(, memtemp_e5_dimm)   temp_dimm;
 };
 
 static int     memtemp_e5_probe(device_t);
@@ -101,28 +76,31 @@ static int memtemp_e5_detach(device_t);
 
 static void    memtemp_e5_sensor_task(void *);
 
-#define MEMTEMP_E5_TYPE_V2(c) \
-{ \
-       .did    = PCI_E5_IMC_THERMAL_CHN##c##_DID_ID, \
-       .slot   = PCISLOT_E5_IMC_THERMAL, \
-       .func   = PCIFUNC_E5_IMC_THERMAL_CHN##c, \
-       .chan   = c, \
-       .desc   = "Intel E5 v2 memory thermal sensor" \
+#define MEMTEMP_E5_CHAN(v, imc, c, c_ext)                      \
+{                                                              \
+       .did            = PCI_E5V##v##_IMC##imc##_THERMAL_CHN##c##_DID_ID, \
+       .slot           = PCISLOT_E5V##v##_IMC##imc##_THERMAL_CHN##c, \
+       .func           = PCIFUNC_E5V##v##_IMC##imc##_THERMAL_CHN##c, \
+       .desc           = "Intel E5 v" #v " memory thermal sensor", \
+                                                               \
+       E5_IMC_CHAN_FIELDS(v, imc, c, c_ext)                    \
 }
 
-#define MEMTEMP_E5_TYPE_END            { 0, 0, 0, 0, NULL }
+#define MEMTEMP_E5_CHAN_V2(c)  MEMTEMP_E5_CHAN(2, 0, c, c)
+#define MEMTEMP_E5_CHAN_END    E5_IMC_CHAN_END
 
-static const struct memtemp_e5_type memtemp_types[] = {
-       MEMTEMP_E5_TYPE_V2(0),
-       MEMTEMP_E5_TYPE_V2(1),
-       MEMTEMP_E5_TYPE_V2(2),
-       MEMTEMP_E5_TYPE_V2(3),
+static const struct e5_imc_chan memtemp_e5_chans[] = {
+       MEMTEMP_E5_CHAN_V2(0),
+       MEMTEMP_E5_CHAN_V2(1),
+       MEMTEMP_E5_CHAN_V2(2),
+       MEMTEMP_E5_CHAN_V2(3),
 
-       MEMTEMP_E5_TYPE_END
+       MEMTEMP_E5_CHAN_END
 };
 
-#undef MEMTEMP_E5_TYPE_V2
-#undef MEMTEMP_E5_TYPE_END
+#undef MEMTEMP_E5_CHAN_END
+#undef MEMTEMP_E5_CHAN_V2
+#undef MEMTEMP_E5_CHAN
 
 static device_method_t memtemp_e5_methods[] = {
        /* Device interface */
@@ -147,69 +125,33 @@ MODULE_DEPEND(memtemp_e5, pci, 1, 1, 1);
 static int
 memtemp_e5_probe(device_t dev)
 {
-       const struct memtemp_e5_type *t;
+       const struct e5_imc_chan *c;
        uint16_t vid, did;
        int slot, func;
 
        vid = pci_get_vendor(dev);
-       if (vid != PCI_E5_VID_ID)
+       if (vid != PCI_E5_IMC_VID_ID)
                return ENXIO;
 
        did = pci_get_device(dev);
        slot = pci_get_slot(dev);
        func = pci_get_function(dev);
 
-       for (t = memtemp_types; t->desc != NULL; ++t) {
-               if (t->did == did && t->slot == slot && t->func == func) {
+       for (c = memtemp_e5_chans; c->desc != NULL; ++c) {
+               if (c->did == did && c->slot == slot && c->func == func) {
                        struct memtemp_e5_softc *sc = device_get_softc(dev);
                        char desc[128];
-                       uint32_t val;
-                       int node, dimm;
-
-                       /* Check CPGC vid/did */
-                       if (IMC_CPGC_READ_2(dev, PCIR_VENDOR) !=
-                           PCI_E5_VID_ID ||
-                           IMC_CPGC_READ_2(dev, PCIR_DEVICE) !=
-                           PCI_E5_IMC_CPGC_DID_ID)
-                               break;
+                       int node;
 
-                       /* Is this channel disabled */
-                       val = IMC_CPGC_READ_4(dev, PCI_E5_IMC_CPGC_MCMTR);
-                       if (val & PCI_E5_IMC_CPGC_MCMTR_CHN_DISABLE(t->chan))
+                       node = e5_imc_node_probe(dev, c);
+                       if (node < 0)
                                break;
 
-                       /* Check CTAD vid/did */
-                       if (IMC_CTAD_READ_2(dev, t->chan, PCIR_VENDOR) !=
-                           PCI_E5_VID_ID ||
-                           IMC_CTAD_READ_2(dev, t->chan, PCIR_DEVICE) !=
-                           PCI_E5_IMC_CTAD_DID_ID(t->chan))
-                               break;
-
-                       /* Are there any DIMMs populated? */
-                       for (dimm = 0; dimm < PCI_E5_IMC_DIMM_MAX; ++dimm) {
-                               val = IMC_CTAD_READ_4(dev, t->chan,
-                                   PCI_E5_IMC_CTAD_DIMMMTR(dimm));
-                               if (val & PCI_E5_IMC_CTAD_DIMMMTR_DIMM_POP)
-                                       break;
-                       }
-                       if (dimm == PCI_E5_IMC_DIMM_MAX)
-                               break;
-
-                       /* Check UBOX vid/did */
-                       if (UBOX_READ_2(dev, PCIR_VENDOR) != PCI_E5_VID_ID ||
-                           UBOX_READ_2(dev, PCIR_DEVICE) !=
-                           PCI_E5_UBOX0_DID_ID)
-                               break;
-
-                       val = UBOX_READ_4(dev, PCI_E5_UBOX0_CPUNODEID);
-                       node = __SHIFTOUT(val,
-                           PCI_E5_UBOX0_CPUNODEID_LCLNODEID);
-
                        ksnprintf(desc, sizeof(desc), "%s node%d channel%d",
-                           t->desc, node, t->chan);
+                           c->desc, node, c->chan_ext);
                        device_set_desc_copy(dev, desc);
 
-                       sc->temp_chan = t->chan;
+                       sc->temp_chan = c;
                        sc->temp_node = node;
 
                        return 0;
@@ -227,7 +169,7 @@ memtemp_e5_attach(device_t dev)
        sc->temp_dev = dev;
        TAILQ_INIT(&sc->temp_dimm);
 
-       for (dimm = 0; dimm < PCI_E5_IMC_DIMM_MAX; ++dimm) {
+       for (dimm = 0; dimm < PCI_E5_IMC_CHN_DIMM_MAX; ++dimm) {
                struct memtemp_e5_dimm *dimm_sc;
                uint32_t dimmmtr;
 
@@ -242,8 +184,8 @@ memtemp_e5_attach(device_t dev)
                dimm_sc->dimm_id = dimm;
                dimm_sc->dimm_parent = sc;
                dimm_sc->dimm_extid =
-                   (sc->temp_node * PCI_E5_IMC_CHN_MAX * PCI_E5_IMC_DIMM_MAX) +
-                   (sc->temp_chan * PCI_E5_IMC_DIMM_MAX) + dimm;
+               (sc->temp_node * PCI_E5_IMC_CHN_MAX * PCI_E5_IMC_CHN_DIMM_MAX) +
+               (sc->temp_chan->chan_ext * PCI_E5_IMC_CHN_DIMM_MAX) + dimm;
 
                ksnprintf(dimm_sc->dimm_sensordev.xname,
                    sizeof(dimm_sc->dimm_sensordev.xname),