diff --git a/drivers/edac/ie31200_edac.c b/drivers/edac/ie31200_edac.c index 71061ab5fa91..865a2f838317 100644 --- a/drivers/edac/ie31200_edac.c +++ b/drivers/edac/ie31200_edac.c @@ -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),