Commit 10320950 authored by Qiuxu Zhuo's avatar Qiuxu Zhuo Committed by Tony Luck

EDAC/skx: Use the mcmtr register to retrieve close_pg/bank_xor_enable

The skx_edac driver wrongly uses the mtr register to retrieve two fields
close_pg and bank_xor_enable. Fix it by using the correct mcmtr register
to get the two fields.

Cc: <stable@vger.kernel.org>
Signed-off-by: default avatarQiuxu Zhuo <qiuxu.zhuo@intel.com>
Reported-by: default avatarMatthew Riley <mattdr@google.com>
Acked-by: default avatarAristeu Rozanski <aris@redhat.com>
Signed-off-by: default avatarTony Luck <tony.luck@intel.com>
Link: https://lore.kernel.org/r/20200515210146.1337-1-tony.luck@intel.com
parent b2f9fb0d
...@@ -161,7 +161,7 @@ static int i10nm_get_dimm_config(struct mem_ctl_info *mci) ...@@ -161,7 +161,7 @@ static int i10nm_get_dimm_config(struct mem_ctl_info *mci)
mtr, mcddrtcfg, imc->mc, i, j); mtr, mcddrtcfg, imc->mc, i, j);
if (IS_DIMM_PRESENT(mtr)) if (IS_DIMM_PRESENT(mtr))
ndimms += skx_get_dimm_info(mtr, 0, dimm, ndimms += skx_get_dimm_info(mtr, 0, 0, dimm,
imc, i, j); imc, i, j);
else if (IS_NVDIMM_PRESENT(mcddrtcfg, j)) else if (IS_NVDIMM_PRESENT(mcddrtcfg, j))
ndimms += skx_get_nvdimm_info(dimm, imc, i, j, ndimms += skx_get_nvdimm_info(dimm, imc, i, j,
......
...@@ -163,27 +163,23 @@ static const struct x86_cpu_id skx_cpuids[] = { ...@@ -163,27 +163,23 @@ static const struct x86_cpu_id skx_cpuids[] = {
}; };
MODULE_DEVICE_TABLE(x86cpu, skx_cpuids); MODULE_DEVICE_TABLE(x86cpu, skx_cpuids);
#define SKX_GET_MTMTR(dev, reg) \ static bool skx_check_ecc(u32 mcmtr)
pci_read_config_dword((dev), 0x87c, &(reg))
static bool skx_check_ecc(struct pci_dev *pdev)
{ {
u32 mtmtr; return !!GET_BITFIELD(mcmtr, 2, 2);
SKX_GET_MTMTR(pdev, mtmtr);
return !!GET_BITFIELD(mtmtr, 2, 2);
} }
static int skx_get_dimm_config(struct mem_ctl_info *mci) static int skx_get_dimm_config(struct mem_ctl_info *mci)
{ {
struct skx_pvt *pvt = mci->pvt_info; struct skx_pvt *pvt = mci->pvt_info;
u32 mtr, mcmtr, amap, mcddrtcfg;
struct skx_imc *imc = pvt->imc; struct skx_imc *imc = pvt->imc;
u32 mtr, amap, mcddrtcfg;
struct dimm_info *dimm; struct dimm_info *dimm;
int i, j; int i, j;
int ndimms; int ndimms;
/* Only the mcmtr on the first channel is effective */
pci_read_config_dword(imc->chan[0].cdev, 0x87c, &mcmtr);
for (i = 0; i < SKX_NUM_CHANNELS; i++) { for (i = 0; i < SKX_NUM_CHANNELS; i++) {
ndimms = 0; ndimms = 0;
pci_read_config_dword(imc->chan[i].cdev, 0x8C, &amap); pci_read_config_dword(imc->chan[i].cdev, 0x8C, &amap);
...@@ -193,14 +189,14 @@ static int skx_get_dimm_config(struct mem_ctl_info *mci) ...@@ -193,14 +189,14 @@ static int skx_get_dimm_config(struct mem_ctl_info *mci)
pci_read_config_dword(imc->chan[i].cdev, pci_read_config_dword(imc->chan[i].cdev,
0x80 + 4 * j, &mtr); 0x80 + 4 * j, &mtr);
if (IS_DIMM_PRESENT(mtr)) { if (IS_DIMM_PRESENT(mtr)) {
ndimms += skx_get_dimm_info(mtr, amap, dimm, imc, i, j); ndimms += skx_get_dimm_info(mtr, mcmtr, amap, dimm, imc, i, j);
} else if (IS_NVDIMM_PRESENT(mcddrtcfg, j)) { } else if (IS_NVDIMM_PRESENT(mcddrtcfg, j)) {
ndimms += skx_get_nvdimm_info(dimm, imc, i, j, ndimms += skx_get_nvdimm_info(dimm, imc, i, j,
EDAC_MOD_STR); EDAC_MOD_STR);
nvdimm_count++; nvdimm_count++;
} }
} }
if (ndimms && !skx_check_ecc(imc->chan[0].cdev)) { if (ndimms && !skx_check_ecc(mcmtr)) {
skx_printk(KERN_ERR, "ECC is disabled on imc %d\n", imc->mc); skx_printk(KERN_ERR, "ECC is disabled on imc %d\n", imc->mc);
return -ENODEV; return -ENODEV;
} }
......
...@@ -304,7 +304,7 @@ static int skx_get_dimm_attr(u32 reg, int lobit, int hibit, int add, ...@@ -304,7 +304,7 @@ static int skx_get_dimm_attr(u32 reg, int lobit, int hibit, int add,
#define numrow(reg) skx_get_dimm_attr(reg, 2, 4, 12, 1, 6, "rows") #define numrow(reg) skx_get_dimm_attr(reg, 2, 4, 12, 1, 6, "rows")
#define numcol(reg) skx_get_dimm_attr(reg, 0, 1, 10, 0, 2, "cols") #define numcol(reg) skx_get_dimm_attr(reg, 0, 1, 10, 0, 2, "cols")
int skx_get_dimm_info(u32 mtr, u32 amap, struct dimm_info *dimm, int skx_get_dimm_info(u32 mtr, u32 mcmtr, u32 amap, struct dimm_info *dimm,
struct skx_imc *imc, int chan, int dimmno) struct skx_imc *imc, int chan, int dimmno)
{ {
int banks = 16, ranks, rows, cols, npages; int banks = 16, ranks, rows, cols, npages;
...@@ -324,8 +324,8 @@ int skx_get_dimm_info(u32 mtr, u32 amap, struct dimm_info *dimm, ...@@ -324,8 +324,8 @@ int skx_get_dimm_info(u32 mtr, u32 amap, struct dimm_info *dimm,
imc->mc, chan, dimmno, size, npages, imc->mc, chan, dimmno, size, npages,
banks, 1 << ranks, rows, cols); banks, 1 << ranks, rows, cols);
imc->chan[chan].dimms[dimmno].close_pg = GET_BITFIELD(mtr, 0, 0); imc->chan[chan].dimms[dimmno].close_pg = GET_BITFIELD(mcmtr, 0, 0);
imc->chan[chan].dimms[dimmno].bank_xor_enable = GET_BITFIELD(mtr, 9, 9); imc->chan[chan].dimms[dimmno].bank_xor_enable = GET_BITFIELD(mcmtr, 9, 9);
imc->chan[chan].dimms[dimmno].fine_grain_bank = GET_BITFIELD(amap, 0, 0); imc->chan[chan].dimms[dimmno].fine_grain_bank = GET_BITFIELD(amap, 0, 0);
imc->chan[chan].dimms[dimmno].rowbits = rows; imc->chan[chan].dimms[dimmno].rowbits = rows;
imc->chan[chan].dimms[dimmno].colbits = cols; imc->chan[chan].dimms[dimmno].colbits = cols;
......
...@@ -128,7 +128,7 @@ int skx_get_all_bus_mappings(unsigned int did, int off, enum type, ...@@ -128,7 +128,7 @@ int skx_get_all_bus_mappings(unsigned int did, int off, enum type,
int skx_get_hi_lo(unsigned int did, int off[], u64 *tolm, u64 *tohm); int skx_get_hi_lo(unsigned int did, int off[], u64 *tolm, u64 *tohm);
int skx_get_dimm_info(u32 mtr, u32 amap, struct dimm_info *dimm, int skx_get_dimm_info(u32 mtr, u32 mcmtr, u32 amap, struct dimm_info *dimm,
struct skx_imc *imc, int chan, int dimmno); struct skx_imc *imc, int chan, int dimmno);
int skx_get_nvdimm_info(struct dimm_info *dimm, struct skx_imc *imc, int skx_get_nvdimm_info(struct dimm_info *dimm, struct skx_imc *imc,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment