@@ -84,16 +84,6 @@
#define PCI_DEVICE_ID_INTEL_IE31200_HB_CFL_9 0x3ec6
#define PCI_DEVICE_ID_INTEL_IE31200_HB_CFL_10 0x3eca
-/* Test if HB is for Skylake or later. */
-#define DEVICE_ID_SKYLAKE_OR_LATER(did) \
- (((did) == PCI_DEVICE_ID_INTEL_IE31200_HB_8) || \
- ((did) == PCI_DEVICE_ID_INTEL_IE31200_HB_9) || \
- ((did) == PCI_DEVICE_ID_INTEL_IE31200_HB_10) || \
- ((did) == PCI_DEVICE_ID_INTEL_IE31200_HB_11) || \
- ((did) == PCI_DEVICE_ID_INTEL_IE31200_HB_12) || \
- (((did) & PCI_DEVICE_ID_INTEL_IE31200_HB_CFL_MASK) == \
- PCI_DEVICE_ID_INTEL_IE31200_HB_CFL_MASK))
-
#define IE31200_RANKS_PER_CHANNEL 4
#define IE31200_DIMMS_PER_CHANNEL 2
#define IE31200_CHANNELS 2
@@ -118,10 +108,6 @@
#define IE31200_CAPID0_DDPCD BIT(6)
#define IE31200_CAPID0_ECC BIT(1)
-/* Skylake reports 1GB increments, everything else is 256MB */
-#define IE31200_PAGES(n, skl) \
- (n << (28 + (2 * skl) - PAGE_SHIFT))
-
/* Non-constant mask variant of FIELD_GET() */
#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
@@ -141,6 +127,7 @@ struct res_config {
u64 reg_eccerrlog_rank_mask;
u64 reg_eccerrlog_syndrome_mask;
/* DIMM characteristics register */
+ u64 reg_mad_dimm_size_granularity;
u64 reg_mad_dimm_offset[IE31200_CHANNELS];
u32 reg_mad_dimm_size_mask[IE31200_DIMMS_PER_CHANNEL];
u32 reg_mad_dimm_rank_mask[IE31200_DIMMS_PER_CHANNEL];
@@ -175,9 +162,9 @@ static const struct ie31200_dev_info ie31200_devs[] = {
};
struct dimm_data {
- u8 size; /* in multiples of 256MB, except Skylake is 1GB */
- u8 dual_rank : 1,
- x16_width : 2; /* 0 means x8 width */
+ u64 size; /* in bytes */
+ u8 ranks;
+ enum dev_type dtype;
};
static int how_many_channels(struct pci_dev *pdev)
@@ -340,26 +327,20 @@ static void __iomem *ie31200_map_mchbar(struct pci_dev *pdev, struct res_config
static void populate_dimm_info(struct dimm_data *dd, u32 addr_decode, int dimm,
struct res_config *cfg)
{
- dd->size = field_get(cfg->reg_mad_dimm_size_mask[dimm], addr_decode);
- dd->dual_rank = field_get(cfg->reg_mad_dimm_rank_mask[dimm], addr_decode);
- dd->x16_width = field_get(cfg->reg_mad_dimm_width_mask[dimm], addr_decode);
+ dd->size = field_get(cfg->reg_mad_dimm_size_mask[dimm], addr_decode) * cfg->reg_mad_dimm_size_granularity;
+ dd->ranks = field_get(cfg->reg_mad_dimm_rank_mask[dimm], addr_decode) + 1;
+ dd->dtype = field_get(cfg->reg_mad_dimm_width_mask[dimm], addr_decode) + DEV_X8;
}
static int ie31200_probe1(struct pci_dev *pdev, struct res_config *cfg)
{
- int i, j, ret;
+ int i, j, k, ret;
struct mem_ctl_info *mci = NULL;
struct edac_mc_layer layers[2];
void __iomem *window;
struct ie31200_priv *priv;
u32 addr_decode[IE31200_CHANNELS];
- /*
- * Kaby Lake, Coffee Lake seem to work like Skylake. Please re-visit
- * this logic when adding new CPU support.
- */
- bool skl = DEVICE_ID_SKYLAKE_OR_LATER(pdev->device);
-
edac_dbg(0, "MC:\n");
if (!ecc_capable(pdev)) {
@@ -419,32 +400,25 @@ static int ie31200_probe1(struct pci_dev *pdev, struct res_config *cfg)
unsigned long nr_pages;
populate_dimm_info(&dimm_info, addr_decode[j], i, cfg);
- edac_dbg(0, "size: 0x%x, rank: %d, width: %d\n",
- dimm_info.size,
- dimm_info.dual_rank,
- dimm_info.x16_width);
+ edac_dbg(0, "channel: %d, dimm: %d, size: %lld MiB, ranks: %d, DRAM chip type: %d\n",
+ j, i, dimm_info.size >> 20,
+ dimm_info.ranks,
+ dimm_info.dtype);
- nr_pages = IE31200_PAGES(dimm_info.size, skl);
+ nr_pages = MiB_TO_PAGES(dimm_info.size >> 20);
if (nr_pages == 0)
continue;
- if (dimm_info.dual_rank) {
- nr_pages = nr_pages / 2;
- dimm = edac_get_dimm(mci, (i * 2) + 1, j, 0);
+ nr_pages = nr_pages / dimm_info.ranks;
+ for (k = 0; k < dimm_info.ranks; k++) {
+ dimm = edac_get_dimm(mci, (i * dimm_info.ranks) + k, j, 0);
dimm->nr_pages = nr_pages;
edac_dbg(0, "set nr pages: 0x%lx\n", nr_pages);
dimm->grain = 8; /* just a guess */
dimm->mtype = cfg->mtype;
- dimm->dtype = DEV_UNKNOWN;
+ dimm->dtype = dimm_info.dtype;
dimm->edac_mode = EDAC_UNKNOWN;
}
- dimm = edac_get_dimm(mci, i * 2, j, 0);
- dimm->nr_pages = nr_pages;
- edac_dbg(0, "set nr pages: 0x%lx\n", nr_pages);
- dimm->grain = 8; /* same guess */
- dimm->mtype = cfg->mtype;
- dimm->dtype = DEV_UNKNOWN;
- dimm->edac_mode = EDAC_UNKNOWN;
}
}
@@ -510,6 +484,7 @@ static struct res_config snb_cfg = {
.reg_eccerrlog_ue_mask = BIT_ULL(1),
.reg_eccerrlog_rank_mask = GENMASK_ULL(28, 27),
.reg_eccerrlog_syndrome_mask = GENMASK_ULL(23, 16),
+ .reg_mad_dimm_size_granularity = BIT_ULL(28),
.reg_mad_dimm_offset[0] = 0x5004,
.reg_mad_dimm_offset[1] = 0x5008,
.reg_mad_dimm_size_mask[0] = GENMASK(7, 0),
@@ -530,6 +505,7 @@ static struct res_config skl_cfg = {
.reg_eccerrlog_ue_mask = BIT_ULL(1),
.reg_eccerrlog_rank_mask = GENMASK_ULL(28, 27),
.reg_eccerrlog_syndrome_mask = GENMASK_ULL(23, 16),
+ .reg_mad_dimm_size_granularity = BIT_ULL(30),
.reg_mad_dimm_offset[0] = 0x500c,
.reg_mad_dimm_offset[1] = 0x5010,
.reg_mad_dimm_size_mask[0] = GENMASK(5, 0),