mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 21:38:32 +08:00
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: Qiuxu Zhuo <qiuxu.zhuo@intel.com> Reported-by: Matthew Riley <mattdr@google.com> Acked-by: Aristeu Rozanski <aris@redhat.com> Signed-off-by: Tony Luck <tony.luck@intel.com> Link: https://lore.kernel.org/r/20200515210146.1337-1-tony.luck@intel.com
This commit is contained in:
parent
b2f9fb0d67
commit
1032095053
@ -161,7 +161,7 @@ static int i10nm_get_dimm_config(struct mem_ctl_info *mci)
|
||||
mtr, mcddrtcfg, imc->mc, i, j);
|
||||
|
||||
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);
|
||||
else if (IS_NVDIMM_PRESENT(mcddrtcfg, j))
|
||||
ndimms += skx_get_nvdimm_info(dimm, imc, i, j,
|
||||
|
@ -163,27 +163,23 @@ static const struct x86_cpu_id skx_cpuids[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(x86cpu, skx_cpuids);
|
||||
|
||||
#define SKX_GET_MTMTR(dev, reg) \
|
||||
pci_read_config_dword((dev), 0x87c, &(reg))
|
||||
|
||||
static bool skx_check_ecc(struct pci_dev *pdev)
|
||||
static bool skx_check_ecc(u32 mcmtr)
|
||||
{
|
||||
u32 mtmtr;
|
||||
|
||||
SKX_GET_MTMTR(pdev, mtmtr);
|
||||
|
||||
return !!GET_BITFIELD(mtmtr, 2, 2);
|
||||
return !!GET_BITFIELD(mcmtr, 2, 2);
|
||||
}
|
||||
|
||||
static int skx_get_dimm_config(struct mem_ctl_info *mci)
|
||||
{
|
||||
struct skx_pvt *pvt = mci->pvt_info;
|
||||
u32 mtr, mcmtr, amap, mcddrtcfg;
|
||||
struct skx_imc *imc = pvt->imc;
|
||||
u32 mtr, amap, mcddrtcfg;
|
||||
struct dimm_info *dimm;
|
||||
int i, j;
|
||||
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++) {
|
||||
ndimms = 0;
|
||||
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)
|
||||
pci_read_config_dword(imc->chan[i].cdev,
|
||||
0x80 + 4 * j, &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)) {
|
||||
ndimms += skx_get_nvdimm_info(dimm, imc, i, j,
|
||||
EDAC_MOD_STR);
|
||||
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);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
@ -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 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)
|
||||
{
|
||||
int banks = 16, ranks, rows, cols, npages;
|
||||
@ -324,8 +324,8 @@ int skx_get_dimm_info(u32 mtr, u32 amap, struct dimm_info *dimm,
|
||||
imc->mc, chan, dimmno, size, npages,
|
||||
banks, 1 << ranks, rows, cols);
|
||||
|
||||
imc->chan[chan].dimms[dimmno].close_pg = GET_BITFIELD(mtr, 0, 0);
|
||||
imc->chan[chan].dimms[dimmno].bank_xor_enable = GET_BITFIELD(mtr, 9, 9);
|
||||
imc->chan[chan].dimms[dimmno].close_pg = GET_BITFIELD(mcmtr, 0, 0);
|
||||
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].rowbits = rows;
|
||||
imc->chan[chan].dimms[dimmno].colbits = cols;
|
||||
|
@ -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_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);
|
||||
|
||||
int skx_get_nvdimm_info(struct dimm_info *dimm, struct skx_imc *imc,
|
||||
|
Loading…
Reference in New Issue
Block a user