提交 432fad27 编写于 作者: Q Qiuxu Zhuo 提交者: Youquan Song

EDAC/i10nm: Add Intel Sapphire Rapids server support

mainline inclusion
from mainline-v5.11-rc1
commit 479f58dd
category: feature
bugzilla: https://gitee.com/openeuler/intel-kernel/issues/I5HAC1
CVE: NA

Intel_SIG: commit 479f58dd EDAC/i10nm: Add Intel Sapphire
Rapids server support.
Backport for add EDAC SPR suppporting.

--------------------------------

The Sapphire Rapids CPU model shares the same memory controller
architecture with Ice Lake server. There are some configurations
different from Ice Lake server as below:
- The device ID for configuration agent.
- The size for per channel memory-mapped I/O.
- The DDR5 memory support.
So add the above configurations and the Sapphire Rapids CPU model
ID for EDAC support.
Signed-off-by: NQiuxu Zhuo <qiuxu.zhuo@intel.com>
Signed-off-by: NTony Luck <tony.luck@intel.com>
Signed-off-by: NYouquan Song <youquan.song@intel.com>
上级 928722d8
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
#include "edac_module.h" #include "edac_module.h"
#include "skx_common.h" #include "skx_common.h"
#define I10NM_REVISION "v0.0.3" #define I10NM_REVISION "v0.0.4"
#define EDAC_MOD_STR "i10nm_edac" #define EDAC_MOD_STR "i10nm_edac"
/* Debug macros */ /* Debug macros */
...@@ -25,11 +25,13 @@ ...@@ -25,11 +25,13 @@
#define I10NM_GET_IMC_BAR(d, i, reg) \ #define I10NM_GET_IMC_BAR(d, i, reg) \
pci_read_config_dword((d)->uracu, 0xd8 + (i) * 4, &(reg)) pci_read_config_dword((d)->uracu, 0xd8 + (i) * 4, &(reg))
#define I10NM_GET_DIMMMTR(m, i, j) \ #define I10NM_GET_DIMMMTR(m, i, j) \
readl((m)->mbase + 0x2080c + (i) * 0x4000 + (j) * 4) readl((m)->mbase + 0x2080c + (i) * (m)->chan_mmio_sz + (j) * 4)
#define I10NM_GET_MCDDRTCFG(m, i) \ #define I10NM_GET_MCDDRTCFG(m, i) \
readl((m)->mbase + 0x20970 + (i) * 0x4000) readl((m)->mbase + 0x20970 + (i) * (m)->chan_mmio_sz)
#define I10NM_GET_MCMTR(m, i) \ #define I10NM_GET_MCMTR(m, i) \
readl((m)->mbase + 0x20ef8 + (i) * 0x4000) readl((m)->mbase + 0x20ef8 + (i) * (m)->chan_mmio_sz)
#define I10NM_GET_AMAP(m, i) \
readl((m)->mbase + 0x20814 + (i) * (m)->chan_mmio_sz)
#define I10NM_GET_SCK_MMIO_BASE(reg) (GET_BITFIELD(reg, 0, 28) << 23) #define I10NM_GET_SCK_MMIO_BASE(reg) (GET_BITFIELD(reg, 0, 28) << 23)
#define I10NM_GET_IMC_MMIO_OFFSET(reg) (GET_BITFIELD(reg, 0, 10) << 12) #define I10NM_GET_IMC_MMIO_OFFSET(reg) (GET_BITFIELD(reg, 0, 10) << 12)
...@@ -129,12 +131,22 @@ static struct res_config i10nm_cfg0 = { ...@@ -129,12 +131,22 @@ static struct res_config i10nm_cfg0 = {
.type = I10NM, .type = I10NM,
.decs_did = 0x3452, .decs_did = 0x3452,
.busno_cfg_offset = 0xcc, .busno_cfg_offset = 0xcc,
.ddr_chan_mmio_sz = 0x4000,
}; };
static struct res_config i10nm_cfg1 = { static struct res_config i10nm_cfg1 = {
.type = I10NM, .type = I10NM,
.decs_did = 0x3452, .decs_did = 0x3452,
.busno_cfg_offset = 0xd0, .busno_cfg_offset = 0xd0,
.ddr_chan_mmio_sz = 0x4000,
};
static struct res_config spr_cfg = {
.type = SPR,
.decs_did = 0x3252,
.busno_cfg_offset = 0xd0,
.ddr_chan_mmio_sz = 0x8000,
.support_ddr5 = true,
}; };
static const struct x86_cpu_id i10nm_cpuids[] = { static const struct x86_cpu_id i10nm_cpuids[] = {
...@@ -143,6 +155,7 @@ static const struct x86_cpu_id i10nm_cpuids[] = { ...@@ -143,6 +155,7 @@ static const struct x86_cpu_id i10nm_cpuids[] = {
X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(ICELAKE_X, X86_STEPPINGS(0x0, 0x3), &i10nm_cfg0), X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(ICELAKE_X, X86_STEPPINGS(0x0, 0x3), &i10nm_cfg0),
X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(ICELAKE_X, X86_STEPPINGS(0x4, 0xf), &i10nm_cfg1), X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(ICELAKE_X, X86_STEPPINGS(0x4, 0xf), &i10nm_cfg1),
X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(ICELAKE_D, X86_STEPPINGS(0x0, 0xf), &i10nm_cfg1), X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(ICELAKE_D, X86_STEPPINGS(0x0, 0xf), &i10nm_cfg1),
X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(SAPPHIRERAPIDS_X, X86_STEPPINGS(0x0, 0xf), &spr_cfg),
{} {}
}; };
MODULE_DEVICE_TABLE(x86cpu, i10nm_cpuids); MODULE_DEVICE_TABLE(x86cpu, i10nm_cpuids);
...@@ -157,12 +170,13 @@ static bool i10nm_check_ecc(struct skx_imc *imc, int chan) ...@@ -157,12 +170,13 @@ static bool i10nm_check_ecc(struct skx_imc *imc, int chan)
return !!GET_BITFIELD(mcmtr, 2, 2); return !!GET_BITFIELD(mcmtr, 2, 2);
} }
static int i10nm_get_dimm_config(struct mem_ctl_info *mci) static int i10nm_get_dimm_config(struct mem_ctl_info *mci,
struct res_config *cfg)
{ {
struct skx_pvt *pvt = mci->pvt_info; struct skx_pvt *pvt = mci->pvt_info;
struct skx_imc *imc = pvt->imc; struct skx_imc *imc = pvt->imc;
u32 mtr, amap, mcddrtcfg;
struct dimm_info *dimm; struct dimm_info *dimm;
u32 mtr, mcddrtcfg;
int i, j, ndimms; int i, j, ndimms;
for (i = 0; i < I10NM_NUM_CHANNELS; i++) { for (i = 0; i < I10NM_NUM_CHANNELS; i++) {
...@@ -171,6 +185,7 @@ static int i10nm_get_dimm_config(struct mem_ctl_info *mci) ...@@ -171,6 +185,7 @@ static int i10nm_get_dimm_config(struct mem_ctl_info *mci)
ndimms = 0; ndimms = 0;
mcddrtcfg = I10NM_GET_MCDDRTCFG(imc, i); mcddrtcfg = I10NM_GET_MCDDRTCFG(imc, i);
amap = I10NM_GET_AMAP(imc, i);
for (j = 0; j < I10NM_NUM_DIMMS; j++) { for (j = 0; j < I10NM_NUM_DIMMS; j++) {
dimm = edac_get_dimm(mci, i, j, 0); dimm = edac_get_dimm(mci, i, j, 0);
mtr = I10NM_GET_DIMMMTR(imc, i, j); mtr = I10NM_GET_DIMMMTR(imc, i, j);
...@@ -178,8 +193,8 @@ static int i10nm_get_dimm_config(struct mem_ctl_info *mci) ...@@ -178,8 +193,8 @@ 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, 0, dimm, ndimms += skx_get_dimm_info(mtr, 0, amap, dimm,
imc, i, j); imc, i, j, cfg);
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);
...@@ -306,10 +321,11 @@ static int __init i10nm_init(void) ...@@ -306,10 +321,11 @@ static int __init i10nm_init(void)
d->imc[i].lmc = i; d->imc[i].lmc = i;
d->imc[i].src_id = src_id; d->imc[i].src_id = src_id;
d->imc[i].node_id = node_id; d->imc[i].node_id = node_id;
d->imc[i].chan_mmio_sz = cfg->ddr_chan_mmio_sz;
rc = skx_register_mci(&d->imc[i], d->imc[i].mdev, rc = skx_register_mci(&d->imc[i], d->imc[i].mdev,
"Intel_10nm Socket", EDAC_MOD_STR, "Intel_10nm Socket", EDAC_MOD_STR,
i10nm_get_dimm_config); i10nm_get_dimm_config, cfg);
if (rc < 0) if (rc < 0)
goto fail; goto fail;
} }
......
...@@ -174,7 +174,7 @@ static bool skx_check_ecc(u32 mcmtr) ...@@ -174,7 +174,7 @@ static bool skx_check_ecc(u32 mcmtr)
return !!GET_BITFIELD(mcmtr, 2, 2); return !!GET_BITFIELD(mcmtr, 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 res_config *cfg)
{ {
struct skx_pvt *pvt = mci->pvt_info; struct skx_pvt *pvt = mci->pvt_info;
u32 mtr, mcmtr, amap, mcddrtcfg; u32 mtr, mcmtr, amap, mcddrtcfg;
...@@ -195,7 +195,7 @@ static int skx_get_dimm_config(struct mem_ctl_info *mci) ...@@ -195,7 +195,7 @@ 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, mcmtr, amap, dimm, imc, i, j); ndimms += skx_get_dimm_info(mtr, mcmtr, amap, dimm, imc, i, j, cfg);
} 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);
...@@ -705,7 +705,7 @@ static int __init skx_init(void) ...@@ -705,7 +705,7 @@ static int __init skx_init(void)
d->imc[i].node_id = node_id; d->imc[i].node_id = node_id;
rc = skx_register_mci(&d->imc[i], d->imc[i].chan[0].cdev, rc = skx_register_mci(&d->imc[i], d->imc[i].chan[0].cdev,
"Skylake Socket", EDAC_MOD_STR, "Skylake Socket", EDAC_MOD_STR,
skx_get_dimm_config); skx_get_dimm_config, cfg);
if (rc < 0) if (rc < 0)
goto fail; goto fail;
} }
......
...@@ -304,15 +304,25 @@ static int skx_get_dimm_attr(u32 reg, int lobit, int hibit, int add, ...@@ -304,15 +304,25 @@ static int skx_get_dimm_attr(u32 reg, int lobit, int hibit, int add,
#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 mcmtr, 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,
struct res_config *cfg)
{ {
int banks = 16, ranks, rows, cols, npages; int banks, ranks, rows, cols, npages;
enum mem_type mtype;
u64 size; u64 size;
ranks = numrank(mtr); ranks = numrank(mtr);
rows = numrow(mtr); rows = numrow(mtr);
cols = numcol(mtr); cols = numcol(mtr);
if (cfg->support_ddr5 && (amap & 0x8)) {
banks = 32;
mtype = MEM_DDR5;
} else {
banks = 16;
mtype = MEM_DDR4;
}
/* /*
* Compute size in 8-byte (2^3) words, then shift to MiB (2^20) * Compute size in 8-byte (2^3) words, then shift to MiB (2^20)
*/ */
...@@ -332,7 +342,7 @@ int skx_get_dimm_info(u32 mtr, u32 mcmtr, u32 amap, struct dimm_info *dimm, ...@@ -332,7 +342,7 @@ int skx_get_dimm_info(u32 mtr, u32 mcmtr, u32 amap, struct dimm_info *dimm,
dimm->nr_pages = npages; dimm->nr_pages = npages;
dimm->grain = 32; dimm->grain = 32;
dimm->dtype = get_width(mtr); dimm->dtype = get_width(mtr);
dimm->mtype = MEM_DDR4; dimm->mtype = mtype;
dimm->edac_mode = EDAC_SECDED; /* likely better than this */ dimm->edac_mode = EDAC_SECDED; /* likely better than this */
snprintf(dimm->label, sizeof(dimm->label), "CPU_SrcID#%u_MC#%u_Chan#%u_DIMM#%u", snprintf(dimm->label, sizeof(dimm->label), "CPU_SrcID#%u_MC#%u_Chan#%u_DIMM#%u",
imc->src_id, imc->lmc, chan, dimmno); imc->src_id, imc->lmc, chan, dimmno);
...@@ -390,7 +400,8 @@ int skx_get_nvdimm_info(struct dimm_info *dimm, struct skx_imc *imc, ...@@ -390,7 +400,8 @@ int skx_get_nvdimm_info(struct dimm_info *dimm, struct skx_imc *imc,
int skx_register_mci(struct skx_imc *imc, struct pci_dev *pdev, int skx_register_mci(struct skx_imc *imc, struct pci_dev *pdev,
const char *ctl_name, const char *mod_str, const char *ctl_name, const char *mod_str,
get_dimm_config_f get_dimm_config) get_dimm_config_f get_dimm_config,
struct res_config *cfg)
{ {
struct mem_ctl_info *mci; struct mem_ctl_info *mci;
struct edac_mc_layer layers[2]; struct edac_mc_layer layers[2];
...@@ -425,13 +436,15 @@ int skx_register_mci(struct skx_imc *imc, struct pci_dev *pdev, ...@@ -425,13 +436,15 @@ int skx_register_mci(struct skx_imc *imc, struct pci_dev *pdev,
} }
mci->mtype_cap = MEM_FLAG_DDR4 | MEM_FLAG_NVDIMM; mci->mtype_cap = MEM_FLAG_DDR4 | MEM_FLAG_NVDIMM;
if (cfg->support_ddr5)
mci->mtype_cap |= MEM_FLAG_DDR5;
mci->edac_ctl_cap = EDAC_FLAG_NONE; mci->edac_ctl_cap = EDAC_FLAG_NONE;
mci->edac_cap = EDAC_FLAG_NONE; mci->edac_cap = EDAC_FLAG_NONE;
mci->mod_name = mod_str; mci->mod_name = mod_str;
mci->dev_name = pci_name(pdev); mci->dev_name = pci_name(pdev);
mci->ctl_page_to_phys = NULL; mci->ctl_page_to_phys = NULL;
rc = get_dimm_config(mci); rc = get_dimm_config(mci, cfg);
if (rc < 0) if (rc < 0)
goto fail; goto fail;
......
...@@ -59,6 +59,7 @@ struct skx_dev { ...@@ -59,6 +59,7 @@ struct skx_dev {
struct mem_ctl_info *mci; struct mem_ctl_info *mci;
struct pci_dev *mdev; /* for i10nm CPU */ struct pci_dev *mdev; /* for i10nm CPU */
void __iomem *mbase; /* for i10nm CPU */ void __iomem *mbase; /* for i10nm CPU */
int chan_mmio_sz; /* for i10nm CPU */
u8 mc; /* system wide mc# */ u8 mc; /* system wide mc# */
u8 lmc; /* socket relative mc# */ u8 lmc; /* socket relative mc# */
u8 src_id, node_id; u8 src_id, node_id;
...@@ -82,7 +83,8 @@ struct skx_pvt { ...@@ -82,7 +83,8 @@ struct skx_pvt {
enum type { enum type {
SKX, SKX,
I10NM I10NM,
SPR
}; };
enum { enum {
...@@ -118,9 +120,13 @@ struct res_config { ...@@ -118,9 +120,13 @@ struct res_config {
unsigned int decs_did; unsigned int decs_did;
/* Default bus number configuration register offset */ /* Default bus number configuration register offset */
int busno_cfg_offset; int busno_cfg_offset;
/* Per DDR channel memory-mapped I/O size */
int ddr_chan_mmio_sz;
bool support_ddr5;
}; };
typedef int (*get_dimm_config_f)(struct mem_ctl_info *mci); typedef int (*get_dimm_config_f)(struct mem_ctl_info *mci,
struct res_config *cfg);
typedef bool (*skx_decode_f)(struct decoded_addr *res); typedef bool (*skx_decode_f)(struct decoded_addr *res);
typedef void (*skx_show_retry_log_f)(struct decoded_addr *res, char *msg, int len); typedef void (*skx_show_retry_log_f)(struct decoded_addr *res, char *msg, int len);
...@@ -136,14 +142,16 @@ int skx_get_all_bus_mappings(struct res_config *cfg, struct list_head **list); ...@@ -136,14 +142,16 @@ int skx_get_all_bus_mappings(struct res_config *cfg, struct list_head **list);
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 mcmtr, 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,
struct res_config *cfg);
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,
int chan, int dimmno, const char *mod_str); int chan, int dimmno, const char *mod_str);
int skx_register_mci(struct skx_imc *imc, struct pci_dev *pdev, int skx_register_mci(struct skx_imc *imc, struct pci_dev *pdev,
const char *ctl_name, const char *mod_str, const char *ctl_name, const char *mod_str,
get_dimm_config_f get_dimm_config); get_dimm_config_f get_dimm_config,
struct res_config *cfg);
int skx_mce_check_error(struct notifier_block *nb, unsigned long val, int skx_mce_check_error(struct notifier_block *nb, unsigned long val,
void *data); void *data);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册