From 18caec20bfa56911b5d23811ae344ae8dc163ba9 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Wed, 24 May 2017 15:35:05 +0200 Subject: EDAC, altera: Constify irq_domain_ops struct irq_domain_ops is not modified, so it can be made const. Signed-off-by: Tobias Klauser Cc: Thor Thayer Cc: linux-edac Link: http://lkml.kernel.org/r/20170524133505.1233-1-tklauser@distanz.ch Signed-off-by: Borislav Petkov --- drivers/edac/altera_edac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c index 7717b094fabb..122637530b15 100644 --- a/drivers/edac/altera_edac.c +++ b/drivers/edac/altera_edac.c @@ -1839,7 +1839,7 @@ static int a10_eccmgr_irqdomain_map(struct irq_domain *d, unsigned int irq, return 0; } -static struct irq_domain_ops a10_eccmgr_ic_ops = { +static const struct irq_domain_ops a10_eccmgr_ic_ops = { .map = a10_eccmgr_irqdomain_map, .xlate = irq_domain_xlate_twocell, }; -- cgit v1.2.3 From 00cf50d90a99fac96644078f40c88a7ad43fb71c Mon Sep 17 00:00:00 2001 From: Qiuxu Zhuo Date: Tue, 23 May 2017 08:05:33 +0800 Subject: EDAC, sb_edac: Classify PCI-IDs by topology Each of the PCI device IDs belongs to a CPU socket, or to one of the integrated memory controllers. Provide an enum to specify the domain of each, and distinguish the resource number in each domain: the number of the PCI device IDs per integrated memory controller/socket, and the number of integrated memory controllers per socket. Signed-off-by: Qiuxu Zhuo Cc: linux-edac Link: http://lkml.kernel.org/r/20170523000533.87704-1-qiuxu.zhuo@intel.com [ Realign pci_dev_descr_knl members. ] Signed-off-by: Borislav Petkov --- drivers/edac/sb_edac.c | 235 +++++++++++++++++++++++++------------------------ 1 file changed, 121 insertions(+), 114 deletions(-) diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index ea21cb651b3c..fe4ffeaa623b 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -294,6 +294,12 @@ enum type { KNIGHTS_LANDING, }; +enum domain { + IMC0 = 0, + IMC1, + SOCK, +}; + struct sbridge_pvt; struct sbridge_info { enum type type; @@ -324,11 +330,14 @@ struct sbridge_channel { struct pci_id_descr { int dev_id; int optional; + enum domain dom; }; struct pci_id_table { const struct pci_id_descr *descr; - int n_devs; + int n_devs_per_imc; + int n_devs_per_sock; + int n_imcs_per_sock; enum type type; }; @@ -337,6 +346,7 @@ struct sbridge_dev { u8 bus, mc; u8 node_id, source_id; struct pci_dev **pdev; + enum domain dom; int n_devs; struct mem_ctl_info *mci; }; @@ -373,39 +383,42 @@ struct sbridge_pvt { struct knl_pvt knl; }; -#define PCI_DESCR(device_id, opt) \ +#define PCI_DESCR(device_id, opt, domain) \ .dev_id = (device_id), \ - .optional = opt + .optional = opt, \ + .dom = domain static const struct pci_id_descr pci_dev_descr_sbridge[] = { /* Processor Home Agent */ - { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0, 0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0, 0, IMC0) }, /* Memory controller */ - { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA, 0) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS, 0) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0, 0) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1, 0) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2, 0) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3, 0) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO, 1) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA, 0, IMC0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS, 0, IMC0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0, 0, IMC0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1, 0, IMC0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2, 0, IMC0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3, 0, IMC0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO, 1, SOCK) }, /* System Address Decoder */ - { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0, 0) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1, 0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0, 0, SOCK) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1, 0, SOCK) }, /* Broadcast Registers */ - { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_BR, 0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_BR, 0, SOCK) }, }; -#define PCI_ID_TABLE_ENTRY(A, T) { \ +#define PCI_ID_TABLE_ENTRY(A, N, M, T) { \ .descr = A, \ - .n_devs = ARRAY_SIZE(A), \ + .n_devs_per_imc = N, \ + .n_devs_per_sock = ARRAY_SIZE(A), \ + .n_imcs_per_sock = M, \ .type = T \ } static const struct pci_id_table pci_dev_descr_sbridge_table[] = { - PCI_ID_TABLE_ENTRY(pci_dev_descr_sbridge, SANDY_BRIDGE), + PCI_ID_TABLE_ENTRY(pci_dev_descr_sbridge, ARRAY_SIZE(pci_dev_descr_sbridge), 1, SANDY_BRIDGE), {0,} /* 0 terminated list. */ }; @@ -439,40 +452,39 @@ static const struct pci_id_table pci_dev_descr_sbridge_table[] = { static const struct pci_id_descr pci_dev_descr_ibridge[] = { /* Processor Home Agent */ - { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0, 0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0, 0, IMC0) }, /* Memory controller */ - { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA, 0) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS, 0) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0, 0) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD1, 0) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2, 0) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3, 0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA, 0, IMC0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS, 0, IMC0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0, 0, IMC0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD1, 0, IMC0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2, 0, IMC0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3, 0, IMC0) }, + + /* Optional, mode 2HA */ + { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1, 1, IMC1) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TA, 1, IMC1) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_RAS, 1, IMC1) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0, 1, IMC1) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1, 1, IMC1) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD2, 1, IMC1) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD3, 1, IMC1) }, + + { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_1HA_DDRIO0, 1, SOCK) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_2HA_DDRIO0, 1, SOCK) }, /* System Address Decoder */ - { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_SAD, 0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_SAD, 0, SOCK) }, /* Broadcast Registers */ - { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_BR0, 1) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_BR1, 0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_BR0, 1, SOCK) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_BR1, 0, SOCK) }, - /* Optional, mode 2HA */ - { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1, 1) }, -#if 0 - { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TA, 1) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_RAS, 1) }, -#endif - { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0, 1) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1, 1) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD2, 1) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD3, 1) }, - - { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_1HA_DDRIO0, 1) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_2HA_DDRIO0, 1) }, }; static const struct pci_id_table pci_dev_descr_ibridge_table[] = { - PCI_ID_TABLE_ENTRY(pci_dev_descr_ibridge, IVY_BRIDGE), + PCI_ID_TABLE_ENTRY(pci_dev_descr_ibridge, 12, 2, IVY_BRIDGE), {0,} /* 0 terminated list. */ }; @@ -498,9 +510,9 @@ static const struct pci_id_table pci_dev_descr_ibridge_table[] = { #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0 0x2fa0 #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1 0x2f60 #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA 0x2fa8 -#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_THERMAL 0x2f71 +#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TM 0x2f71 #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA 0x2f68 -#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_THERMAL 0x2f79 +#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TM 0x2f79 #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD0 0x2ffc #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD1 0x2ffd #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD0 0x2faa @@ -517,35 +529,33 @@ static const struct pci_id_table pci_dev_descr_ibridge_table[] = { #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO3 0x2fbb static const struct pci_id_descr pci_dev_descr_haswell[] = { /* first item must be the HA */ - { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0, 0) }, - - { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD0, 0) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD1, 0) }, - - { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1, 1) }, - - { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA, 0) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_THERMAL, 0) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD0, 0) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD1, 0) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD2, 1) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD3, 1) }, - - { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0, 1) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO1, 1) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO2, 1) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO3, 1) }, - - { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA, 1) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_THERMAL, 1) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD0, 1) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD1, 1) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD2, 1) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD3, 1) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0, 0, IMC0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1, 1, IMC1) }, + + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA, 0, IMC0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TM, 0, IMC0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD0, 0, IMC0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD1, 0, IMC0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD2, 1, IMC0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD3, 1, IMC0) }, + + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA, 1, IMC1) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TM, 1, IMC1) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD0, 1, IMC1) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD1, 1, IMC1) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD2, 1, IMC1) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD3, 1, IMC1) }, + + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD0, 0, SOCK) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD1, 0, SOCK) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0, 1, SOCK) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO1, 1, SOCK) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO2, 1, SOCK) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO3, 1, SOCK) }, }; static const struct pci_id_table pci_dev_descr_haswell_table[] = { - PCI_ID_TABLE_ENTRY(pci_dev_descr_haswell, HASWELL), + PCI_ID_TABLE_ENTRY(pci_dev_descr_haswell, 13, 2, HASWELL), {0,} /* 0 terminated list. */ }; @@ -559,7 +569,7 @@ static const struct pci_id_table pci_dev_descr_haswell_table[] = { /* Memory controller, TAD tables, error injection - 2-8-0, 2-9-0 (2 of these) */ #define PCI_DEVICE_ID_INTEL_KNL_IMC_MC 0x7840 /* DRAM channel stuff; bank addrs, dimmmtr, etc.. 2-8-2 - 2-9-4 (6 of these) */ -#define PCI_DEVICE_ID_INTEL_KNL_IMC_CHANNEL 0x7843 +#define PCI_DEVICE_ID_INTEL_KNL_IMC_CHAN 0x7843 /* kdrwdbu TAD limits/offsets, MCMTR - 2-10-1, 2-11-1 (2 of these) */ #define PCI_DEVICE_ID_INTEL_KNL_IMC_TA 0x7844 /* CHA broadcast registers, dram rules - 1-29-0 (1 of these) */ @@ -579,17 +589,17 @@ static const struct pci_id_table pci_dev_descr_haswell_table[] = { */ static const struct pci_id_descr pci_dev_descr_knl[] = { - [0] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_SAD0, 0) }, - [1] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_SAD1, 0) }, - [2 ... 3] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_MC, 0)}, - [4 ... 41] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_CHA, 0) }, - [42 ... 47] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_CHANNEL, 0) }, - [48] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_TA, 0) }, - [49] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_TOLHM, 0) }, + [0 ... 1] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_MC, 0, IMC0)}, + [2 ... 7] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_CHAN, 0, IMC0) }, + [8] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_TA, 0, IMC0) }, + [9] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_TOLHM, 0, IMC0) }, + [10] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_SAD0, 0, SOCK) }, + [11] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_SAD1, 0, SOCK) }, + [12 ... 49] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_CHA, 0, SOCK) }, }; static const struct pci_id_table pci_dev_descr_knl_table[] = { - PCI_ID_TABLE_ENTRY(pci_dev_descr_knl, KNIGHTS_LANDING), + PCI_ID_TABLE_ENTRY(pci_dev_descr_knl, ARRAY_SIZE(pci_dev_descr_knl), 1, KNIGHTS_LANDING), {0,} }; @@ -615,9 +625,9 @@ static const struct pci_id_table pci_dev_descr_knl_table[] = { #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0 0x6fa0 #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1 0x6f60 #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA 0x6fa8 -#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_THERMAL 0x6f71 +#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TM 0x6f71 #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TA 0x6f68 -#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_THERMAL 0x6f79 +#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TM 0x6f79 #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD0 0x6ffc #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD1 0x6ffd #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD0 0x6faa @@ -632,32 +642,30 @@ static const struct pci_id_table pci_dev_descr_knl_table[] = { static const struct pci_id_descr pci_dev_descr_broadwell[] = { /* first item must be the HA */ - { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0, 0) }, - - { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD0, 0) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD1, 0) }, - - { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1, 1) }, - - { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA, 0) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_THERMAL, 0) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD0, 0) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD1, 0) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD2, 1) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD3, 1) }, - - { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_DDRIO0, 1) }, - - { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TA, 1) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_THERMAL, 1) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD0, 1) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD1, 1) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD2, 1) }, - { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD3, 1) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0, 0, IMC0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1, 1, IMC1) }, + + { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA, 0, IMC0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TM, 0, IMC0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD0, 0, IMC0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD1, 0, IMC0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD2, 1, IMC0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD3, 1, IMC0) }, + + { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TA, 1, IMC1) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TM, 1, IMC1) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD0, 1, IMC1) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD1, 1, IMC1) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD2, 1, IMC1) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD3, 1, IMC1) }, + + { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD0, 0, SOCK) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD1, 0, SOCK) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_DDRIO0, 1, SOCK) }, }; static const struct pci_id_table pci_dev_descr_broadwell_table[] = { - PCI_ID_TABLE_ENTRY(pci_dev_descr_broadwell, BROADWELL), + PCI_ID_TABLE_ENTRY(pci_dev_descr_broadwell, 10, 2, BROADWELL), {0,} /* 0 terminated list. */ }; @@ -730,8 +738,7 @@ static struct sbridge_dev *get_sbridge_dev(u8 bus, int multi_bus) return NULL; } -static struct sbridge_dev *alloc_sbridge_dev(u8 bus, - const struct pci_id_table *table) +static struct sbridge_dev *alloc_sbridge_dev(u8 bus, enum domain dom, const struct pci_id_table *table) { struct sbridge_dev *sbridge_dev; @@ -739,15 +746,15 @@ static struct sbridge_dev *alloc_sbridge_dev(u8 bus, if (!sbridge_dev) return NULL; - sbridge_dev->pdev = kzalloc(sizeof(*sbridge_dev->pdev) * table->n_devs, - GFP_KERNEL); + sbridge_dev->pdev = kcalloc(table->n_devs_per_sock, sizeof(*sbridge_dev->pdev), GFP_KERNEL); if (!sbridge_dev->pdev) { kfree(sbridge_dev); return NULL; } sbridge_dev->bus = bus; - sbridge_dev->n_devs = table->n_devs; + sbridge_dev->dom = dom; + sbridge_dev->n_devs = table->n_devs_per_sock; list_add_tail(&sbridge_dev->list, &sbridge_edac_list); return sbridge_dev; @@ -2313,7 +2320,7 @@ static int sbridge_get_onedevice(struct pci_dev **prev, sbridge_dev = get_sbridge_dev(bus, multi_bus); if (!sbridge_dev) { - sbridge_dev = alloc_sbridge_dev(bus, table); + sbridge_dev = alloc_sbridge_dev(bus, dev_descr->dom, table); if (!sbridge_dev) { pci_dev_put(pdev); return -ENOMEM; @@ -2374,7 +2381,7 @@ static int sbridge_get_all_devices(u8 *num_mc, if (table->type == KNIGHTS_LANDING) allow_dups = multi_bus = 1; while (table && table->descr) { - for (i = 0; i < table->n_devs; i++) { + for (i = 0; i < table->n_devs_per_sock; i++) { if (!allow_dups || i == 0 || table->descr[i].dev_id != table->descr[i-1].dev_id) { @@ -2385,7 +2392,7 @@ static int sbridge_get_all_devices(u8 *num_mc, table, i, multi_bus); if (rc < 0) { if (i == 0) { - i = table->n_devs; + i = table->n_devs_per_sock; break; } sbridge_put_all_devices(); @@ -2598,7 +2605,7 @@ static int haswell_mci_bind_devs(struct mem_ctl_info *mci, case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA: pvt->pci_ta = pdev; break; - case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_THERMAL: + case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TM: pvt->pci_ras = pdev; break; case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD0: @@ -2695,7 +2702,7 @@ static int broadwell_mci_bind_devs(struct mem_ctl_info *mci, case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA: pvt->pci_ta = pdev; break; - case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_THERMAL: + case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TM: pvt->pci_ras = pdev; break; case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD0: @@ -2812,7 +2819,7 @@ static int knl_mci_bind_devs(struct mem_ctl_info *mci, pvt->knl.pci_cha[devidx] = pdev; break; - case PCI_DEVICE_ID_INTEL_KNL_IMC_CHANNEL: + case PCI_DEVICE_ID_INTEL_KNL_IMC_CHAN: devidx = -1; /* -- cgit v1.2.3 From 7fd562b75d7752ed50c61d65f27b558cd93a359b Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Tue, 23 May 2017 08:06:03 +0800 Subject: EDAC, sb_edac: Don't use "Socket#" in the memory controller name EDAC assigns logical memory controller numbers in the order that we find memory controllers, which depends on which PCI bus they are on. Some systems end up with MC0 on socket0, others (e.g Haswell) have MC0 on socket3. All this is made more confusing for users because we use the string "Socket" while generating names for memory controllers, but the number that we attach there is the memory controller number. E.g. EDAC MC0: Giving out device to module sbridge_edac.c controller Haswell Socket#0: DEV 0000:ff:12.0 (INTERRUPT) Change the names to say "SrcID#%d" (where the number we use is read from the h/w associated with the memory controller instead of some logical number internal to the EDAC driver). New message: EDAC MC0: Giving out device to module sbridge_edac.c controller Haswell SrcID#3: DEV 0000:ff:12.0 (INTERRUPT) Reported-by: Andrey Korolyov Reported-by: Patrick Geary Signed-off-by: Tony Luck Cc: linux-edac Link: http://lkml.kernel.org/r/20170523000603.87748-1-qiuxu.zhuo@intel.com Signed-off-by: Borislav Petkov --- drivers/edac/sb_edac.c | 54 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index fe4ffeaa623b..1990978e7963 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -1594,6 +1594,23 @@ static int knl_get_dimm_capacity(struct sbridge_pvt *pvt, u64 *mc_sizes) return 0; } +static void get_source_id(struct mem_ctl_info *mci) +{ + struct sbridge_pvt *pvt = mci->pvt_info; + u32 reg; + + if (pvt->info.type == HASWELL || pvt->info.type == BROADWELL || + pvt->info.type == KNIGHTS_LANDING) + pci_read_config_dword(pvt->pci_sad1, SAD_TARGET, ®); + else + pci_read_config_dword(pvt->pci_br0, SAD_TARGET, ®); + + if (pvt->info.type == KNIGHTS_LANDING) + pvt->sbridge_dev->source_id = SOURCE_ID_KNL(reg); + else + pvt->sbridge_dev->source_id = SOURCE_ID(reg); +} + static int get_dimm_config(struct mem_ctl_info *mci) { struct sbridge_pvt *pvt = mci->pvt_info; @@ -1611,17 +1628,6 @@ static int get_dimm_config(struct mem_ctl_info *mci) pci_read_config_dword(pvt->pci_ha0, HASWELL_HASYSDEFEATURE2, ®); pvt->is_chan_hash = GET_BITFIELD(reg, 21, 21); } - if (pvt->info.type == HASWELL || pvt->info.type == BROADWELL || - pvt->info.type == KNIGHTS_LANDING) - pci_read_config_dword(pvt->pci_sad1, SAD_TARGET, ®); - else - pci_read_config_dword(pvt->pci_br0, SAD_TARGET, ®); - - if (pvt->info.type == KNIGHTS_LANDING) - pvt->sbridge_dev->source_id = SOURCE_ID_KNL(reg); - else - pvt->sbridge_dev->source_id = SOURCE_ID(reg); - pvt->sbridge_dev->node_id = pvt->info.get_node_id(pvt); edac_dbg(0, "mc#%d: Node ID: %d, source ID: %d\n", pvt->sbridge_dev->mc, @@ -3222,12 +3228,14 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list); pvt->info.interleave_pkg = ibridge_interleave_pkg; pvt->info.get_width = ibridge_get_width; - mci->ctl_name = kasprintf(GFP_KERNEL, "Ivy Bridge Socket#%d", mci->mc_idx); /* Store pci devices at mci for faster access */ rc = ibridge_mci_bind_devs(mci, sbridge_dev); if (unlikely(rc < 0)) goto fail0; + get_source_id(mci); + mci->ctl_name = kasprintf(GFP_KERNEL, "Ivy Bridge SrcID#%d", + pvt->sbridge_dev->source_id); break; case SANDY_BRIDGE: pvt->info.rankcfgr = SB_RANK_CFG_A; @@ -3245,12 +3253,14 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) pvt->info.max_interleave = ARRAY_SIZE(sbridge_interleave_list); pvt->info.interleave_pkg = sbridge_interleave_pkg; pvt->info.get_width = sbridge_get_width; - mci->ctl_name = kasprintf(GFP_KERNEL, "Sandy Bridge Socket#%d", mci->mc_idx); /* Store pci devices at mci for faster access */ rc = sbridge_mci_bind_devs(mci, sbridge_dev); if (unlikely(rc < 0)) goto fail0; + get_source_id(mci); + mci->ctl_name = kasprintf(GFP_KERNEL, "Sandy Bridge SrcID#%d", + pvt->sbridge_dev->source_id); break; case HASWELL: /* rankcfgr isn't used */ @@ -3268,12 +3278,14 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list); pvt->info.interleave_pkg = ibridge_interleave_pkg; pvt->info.get_width = ibridge_get_width; - mci->ctl_name = kasprintf(GFP_KERNEL, "Haswell Socket#%d", mci->mc_idx); /* Store pci devices at mci for faster access */ rc = haswell_mci_bind_devs(mci, sbridge_dev); if (unlikely(rc < 0)) goto fail0; + get_source_id(mci); + mci->ctl_name = kasprintf(GFP_KERNEL, "Haswell SrcID#%d", + pvt->sbridge_dev->source_id); break; case BROADWELL: /* rankcfgr isn't used */ @@ -3291,12 +3303,14 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list); pvt->info.interleave_pkg = ibridge_interleave_pkg; pvt->info.get_width = broadwell_get_width; - mci->ctl_name = kasprintf(GFP_KERNEL, "Broadwell Socket#%d", mci->mc_idx); /* Store pci devices at mci for faster access */ rc = broadwell_mci_bind_devs(mci, sbridge_dev); if (unlikely(rc < 0)) goto fail0; + get_source_id(mci); + mci->ctl_name = kasprintf(GFP_KERNEL, "Broadwell SrcID#%d", + pvt->sbridge_dev->source_id); break; case KNIGHTS_LANDING: /* pvt->info.rankcfgr == ??? */ @@ -3314,12 +3328,13 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) pvt->info.max_interleave = ARRAY_SIZE(knl_interleave_list); pvt->info.interleave_pkg = ibridge_interleave_pkg; pvt->info.get_width = knl_get_width; - mci->ctl_name = kasprintf(GFP_KERNEL, - "Knights Landing Socket#%d", mci->mc_idx); rc = knl_mci_bind_devs(mci, sbridge_dev); if (unlikely(rc < 0)) goto fail0; + get_source_id(mci); + mci->ctl_name = kasprintf(GFP_KERNEL, "Knights Landing SrcID#%d", + pvt->sbridge_dev->source_id); break; } @@ -3334,13 +3349,14 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) if (unlikely(edac_mc_add_mc(mci))) { edac_dbg(0, "MC: failed edac_mc_add_mc()\n"); rc = -EINVAL; - goto fail0; + goto fail; } return 0; -fail0: +fail: kfree(mci->ctl_name); +fail0: edac_mc_free(mci); sbridge_dev->mci = NULL; return rc; -- cgit v1.2.3 From e2f747b1f42a2f6b0cf5416be1684c1b94a42f0f Mon Sep 17 00:00:00 2001 From: Qiuxu Zhuo Date: Tue, 23 May 2017 08:07:31 +0800 Subject: EDAC, sb_edac: Assign EDAC memory controller per h/w controller Tony pointed out: "currently the driver pretends there is one big 8-channel memory controller per socket instead of 2 4-channel controllers. This is fine with all memory controller populated with symmetrical DIMM configurations, but runs into difficulties on asymmetrical setups". Restructure the driver to assign an EDAC memory controller to each real h/w memory controller to resolve the issue. Signed-off-by: Qiuxu Zhuo Cc: linux-edac Link: http://lkml.kernel.org/r/20170523000731.87793-1-qiuxu.zhuo@intel.com [ Break some lines at convenient points. ] Signed-off-by: Borislav Petkov --- drivers/edac/sb_edac.c | 168 ++++++++++++++++++++++++------------------------- 1 file changed, 84 insertions(+), 84 deletions(-) diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index 1990978e7963..2c2c7ed9d886 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -348,6 +348,7 @@ struct sbridge_dev { struct pci_dev **pdev; enum domain dom; int n_devs; + int i_devs; struct mem_ctl_info *mci; }; @@ -362,11 +363,12 @@ struct knl_pvt { }; struct sbridge_pvt { - struct pci_dev *pci_ta, *pci_ddrio, *pci_ras; + /* Devices per socket */ + struct pci_dev *pci_ddrio; struct pci_dev *pci_sad0, *pci_sad1; - struct pci_dev *pci_ha0, *pci_ha1; struct pci_dev *pci_br0, *pci_br1; - struct pci_dev *pci_ha1_ta; + /* Devices per memory controller */ + struct pci_dev *pci_ha, *pci_ta, *pci_ras; struct pci_dev *pci_tad[NUM_CHANNELS]; struct sbridge_dev *sbridge_dev; @@ -717,7 +719,8 @@ static inline int numcol(u32 mtr) return 1 << cols; } -static struct sbridge_dev *get_sbridge_dev(u8 bus, int multi_bus) +static struct sbridge_dev *get_sbridge_dev(u8 bus, enum domain dom, int multi_bus, + struct sbridge_dev *prev) { struct sbridge_dev *sbridge_dev; @@ -730,15 +733,19 @@ static struct sbridge_dev *get_sbridge_dev(u8 bus, int multi_bus) struct sbridge_dev, list); } - list_for_each_entry(sbridge_dev, &sbridge_edac_list, list) { - if (sbridge_dev->bus == bus) + sbridge_dev = list_entry(prev ? prev->list.next + : sbridge_edac_list.next, struct sbridge_dev, list); + + list_for_each_entry_from(sbridge_dev, &sbridge_edac_list, list) { + if (sbridge_dev->bus == bus && (dom == SOCK || dom == sbridge_dev->dom)) return sbridge_dev; } return NULL; } -static struct sbridge_dev *alloc_sbridge_dev(u8 bus, enum domain dom, const struct pci_id_table *table) +static struct sbridge_dev *alloc_sbridge_dev(u8 bus, enum domain dom, + const struct pci_id_table *table) { struct sbridge_dev *sbridge_dev; @@ -746,7 +753,9 @@ static struct sbridge_dev *alloc_sbridge_dev(u8 bus, enum domain dom, const stru if (!sbridge_dev) return NULL; - sbridge_dev->pdev = kcalloc(table->n_devs_per_sock, sizeof(*sbridge_dev->pdev), GFP_KERNEL); + sbridge_dev->pdev = kcalloc(table->n_devs_per_imc, + sizeof(*sbridge_dev->pdev), + GFP_KERNEL); if (!sbridge_dev->pdev) { kfree(sbridge_dev); return NULL; @@ -754,7 +763,7 @@ static struct sbridge_dev *alloc_sbridge_dev(u8 bus, enum domain dom, const stru sbridge_dev->bus = bus; sbridge_dev->dom = dom; - sbridge_dev->n_devs = table->n_devs_per_sock; + sbridge_dev->n_devs = table->n_devs_per_imc; list_add_tail(&sbridge_dev->list, &sbridge_edac_list); return sbridge_dev; @@ -1625,7 +1634,7 @@ static int get_dimm_config(struct mem_ctl_info *mci) u64 knl_mc_sizes[KNL_MAX_CHANNELS]; if (pvt->info.type == HASWELL || pvt->info.type == BROADWELL) { - pci_read_config_dword(pvt->pci_ha0, HASWELL_HASYSDEFEATURE2, ®); + pci_read_config_dword(pvt->pci_ha, HASWELL_HASYSDEFEATURE2, ®); pvt->is_chan_hash = GET_BITFIELD(reg, 21, 21); } pvt->sbridge_dev->node_id = pvt->info.get_node_id(pvt); @@ -1730,7 +1739,7 @@ static int get_dimm_config(struct mem_ctl_info *mci) npages = MiB_TO_PAGES(size); edac_dbg(0, "mc#%d: ha %d channel %d, dimm %d, %lld Mb (%d pages) bank: %d, rank: %d, row: %#x, col: %#x\n", - pvt->sbridge_dev->mc, i/4, i%4, j, + pvt->sbridge_dev->mc, pvt->sbridge_dev->dom, i, j, size, npages, banks, ranks, rows, cols); @@ -1740,8 +1749,8 @@ static int get_dimm_config(struct mem_ctl_info *mci) dimm->mtype = mtype; dimm->edac_mode = mode; snprintf(dimm->label, sizeof(dimm->label), - "CPU_SrcID#%u_Ha#%u_Chan#%u_DIMM#%u", - pvt->sbridge_dev->source_id, i/4, i%4, j); + "CPU_SrcID#%u_Ha#%u_Chan#%u_DIMM#%u", + pvt->sbridge_dev->source_id, pvt->sbridge_dev->dom, i, j); } } } @@ -1829,8 +1838,7 @@ static void get_memory_layout(const struct mem_ctl_info *mci) */ prv = 0; for (n_tads = 0; n_tads < MAX_TAD; n_tads++) { - pci_read_config_dword(pvt->pci_ha0, tad_dram_rule[n_tads], - ®); + pci_read_config_dword(pvt->pci_ha, tad_dram_rule[n_tads], ®); limit = TAD_LIMIT(reg); if (limit <= prv) break; @@ -1912,12 +1920,12 @@ static void get_memory_layout(const struct mem_ctl_info *mci) } } -static struct mem_ctl_info *get_mci_for_node_id(u8 node_id) +static struct mem_ctl_info *get_mci_for_node_id(u8 node_id, u8 ha) { struct sbridge_dev *sbridge_dev; list_for_each_entry(sbridge_dev, &sbridge_edac_list, list) { - if (sbridge_dev->node_id == node_id) + if (sbridge_dev->node_id == node_id && sbridge_dev->dom == ha) return sbridge_dev->mci; } return NULL; @@ -1938,7 +1946,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci, int interleave_mode, shiftup = 0; unsigned sad_interleave[pvt->info.max_interleave]; u32 reg, dram_rule; - u8 ch_way, sck_way, pkg, sad_ha = 0, ch_add = 0; + u8 ch_way, sck_way, pkg, sad_ha = 0; u32 tad_offset; u32 rir_way; u32 mb, gb; @@ -2051,13 +2059,10 @@ static int get_memory_error_data(struct mem_ctl_info *mci, pkg = sad_pkg(pvt->info.interleave_pkg, reg, idx); *socket = sad_pkg_socket(pkg); sad_ha = sad_pkg_ha(pkg); - if (sad_ha) - ch_add = 4; if (a7mode) { /* MCChanShiftUpEnable */ - pci_read_config_dword(pvt->pci_ha0, - HASWELL_HASYSDEFEATURE2, ®); + pci_read_config_dword(pvt->pci_ha, HASWELL_HASYSDEFEATURE2, ®); shiftup = GET_BITFIELD(reg, 22, 22); } @@ -2069,8 +2074,6 @@ static int get_memory_error_data(struct mem_ctl_info *mci, pkg = sad_pkg(pvt->info.interleave_pkg, reg, idx); *socket = sad_pkg_socket(pkg); sad_ha = sad_pkg_ha(pkg); - if (sad_ha) - ch_add = 4; edac_dbg(0, "SAD interleave package: %d = CPU socket %d, HA %d\n", idx, *socket, sad_ha); } @@ -2081,7 +2084,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci, * Move to the proper node structure, in order to access the * right PCI registers */ - new_mci = get_mci_for_node_id(*socket); + new_mci = get_mci_for_node_id(*socket, sad_ha); if (!new_mci) { sprintf(msg, "Struct for socket #%u wasn't initialized", *socket); @@ -2094,14 +2097,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci, * Step 2) Get memory channel */ prv = 0; - if (pvt->info.type == SANDY_BRIDGE) - pci_ha = pvt->pci_ha0; - else { - if (sad_ha) - pci_ha = pvt->pci_ha1; - else - pci_ha = pvt->pci_ha0; - } + pci_ha = pvt->pci_ha; for (n_tads = 0; n_tads < MAX_TAD; n_tads++) { pci_read_config_dword(pci_ha, tad_dram_rule[n_tads], ®); limit = TAD_LIMIT(reg); @@ -2152,9 +2148,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci, } *channel_mask = 1 << base_ch; - pci_read_config_dword(pvt->pci_tad[ch_add + base_ch], - tad_ch_nilv_offset[n_tads], - &tad_offset); + pci_read_config_dword(pvt->pci_tad[base_ch], tad_ch_nilv_offset[n_tads], &tad_offset); if (pvt->is_mirrored) { *channel_mask |= 1 << ((base_ch + 2) % 4); @@ -2205,9 +2199,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci, * Step 3) Decode rank */ for (n_rir = 0; n_rir < MAX_RIR_RANGES; n_rir++) { - pci_read_config_dword(pvt->pci_tad[ch_add + base_ch], - rir_way_limit[n_rir], - ®); + pci_read_config_dword(pvt->pci_tad[base_ch], rir_way_limit[n_rir], ®); if (!IS_RIR_VALID(reg)) continue; @@ -2235,9 +2227,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci, idx = (ch_addr >> 13); /* FIXME: Datasheet says to shift by 15 */ idx %= 1 << rir_way; - pci_read_config_dword(pvt->pci_tad[ch_add + base_ch], - rir_offset[n_rir][idx], - ®); + pci_read_config_dword(pvt->pci_tad[base_ch], rir_offset[n_rir][idx], ®); *rank = RIR_RNK_TGT(pvt->info.type, reg); edac_dbg(0, "RIR#%d: channel address 0x%08Lx < 0x%08Lx, RIR interleave %d, index %d\n", @@ -2290,10 +2280,11 @@ static int sbridge_get_onedevice(struct pci_dev **prev, const unsigned devno, const int multi_bus) { - struct sbridge_dev *sbridge_dev; + struct sbridge_dev *sbridge_dev = NULL; const struct pci_id_descr *dev_descr = &table->descr[devno]; struct pci_dev *pdev = NULL; u8 bus = 0; + int i = 0; sbridge_printk(KERN_DEBUG, "Seeking for: PCI ID %04x:%04x\n", @@ -2324,7 +2315,8 @@ static int sbridge_get_onedevice(struct pci_dev **prev, } bus = pdev->bus->number; - sbridge_dev = get_sbridge_dev(bus, multi_bus); +next_imc: + sbridge_dev = get_sbridge_dev(bus, dev_descr->dom, multi_bus, sbridge_dev); if (!sbridge_dev) { sbridge_dev = alloc_sbridge_dev(bus, dev_descr->dom, table); if (!sbridge_dev) { @@ -2334,7 +2326,7 @@ static int sbridge_get_onedevice(struct pci_dev **prev, (*num_mc)++; } - if (sbridge_dev->pdev[devno]) { + if (sbridge_dev->pdev[sbridge_dev->i_devs]) { sbridge_printk(KERN_ERR, "Duplicated device for %04x:%04x\n", PCI_VENDOR_ID_INTEL, dev_descr->dev_id); @@ -2342,7 +2334,14 @@ static int sbridge_get_onedevice(struct pci_dev **prev, return -ENODEV; } - sbridge_dev->pdev[devno] = pdev; + sbridge_dev->pdev[sbridge_dev->i_devs++] = pdev; + + /* pdev belongs to more than one IMC, do extra gets */ + if (++i > 1) + pci_dev_get(pdev); + + if (dev_descr->dom == SOCK && i < table->n_imcs_per_sock) + goto next_imc; /* Be sure that the device is enabled */ if (unlikely(pci_enable_device(pdev) < 0)) { @@ -2436,7 +2435,7 @@ static int sbridge_mci_bind_devs(struct mem_ctl_info *mci, pvt->pci_br0 = pdev; break; case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0: - pvt->pci_ha0 = pdev; + pvt->pci_ha = pdev; break; case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA: pvt->pci_ta = pdev; @@ -2468,7 +2467,7 @@ static int sbridge_mci_bind_devs(struct mem_ctl_info *mci, } /* Check if everything were registered */ - if (!pvt->pci_sad0 || !pvt->pci_sad1 || !pvt->pci_ha0 || + if (!pvt->pci_sad0 || !pvt->pci_sad1 || !pvt->pci_ha || !pvt->pci_ras || !pvt->pci_ta) goto enodev; @@ -2501,11 +2500,13 @@ static int ibridge_mci_bind_devs(struct mem_ctl_info *mci, switch (pdev->device) { case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0: - pvt->pci_ha0 = pdev; + pvt->pci_ha = pdev; break; case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA: + case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TA: pvt->pci_ta = pdev; case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS: + case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_RAS: pvt->pci_ras = pdev; break; case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0: @@ -2534,14 +2535,14 @@ static int ibridge_mci_bind_devs(struct mem_ctl_info *mci, pvt->pci_br1 = pdev; break; case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1: - pvt->pci_ha1 = pdev; + pvt->pci_ha = pdev; break; case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0: case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1: case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD2: case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD3: { - int id = pdev->device - PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0 + 4; + int id = pdev->device - PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0; pvt->pci_tad[id] = pdev; saw_chan_mask |= 1 << id; } @@ -2557,13 +2558,12 @@ static int ibridge_mci_bind_devs(struct mem_ctl_info *mci, } /* Check if everything were registered */ - if (!pvt->pci_sad0 || !pvt->pci_ha0 || !pvt->pci_br0 || + if (!pvt->pci_sad0 || !pvt->pci_ha || !pvt->pci_br0 || !pvt->pci_br1 || !pvt->pci_ras || !pvt->pci_ta) goto enodev; - if (saw_chan_mask != 0x0f && /* -EN */ - saw_chan_mask != 0x33 && /* -EP */ - saw_chan_mask != 0xff) /* -EX */ + if (saw_chan_mask != 0x0f && /* -EN/-EX */ + saw_chan_mask != 0x03) /* -EP */ goto enodev; return 0; @@ -2606,12 +2606,13 @@ static int haswell_mci_bind_devs(struct mem_ctl_info *mci, pvt->pci_sad1 = pdev; break; case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0: - pvt->pci_ha0 = pdev; + pvt->pci_ha = pdev; break; case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA: pvt->pci_ta = pdev; break; case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TM: + case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TM: pvt->pci_ras = pdev; break; case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD0: @@ -2630,7 +2631,7 @@ static int haswell_mci_bind_devs(struct mem_ctl_info *mci, case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD2: case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD3: { - int id = pdev->device - PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD0 + 4; + int id = pdev->device - PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD0; pvt->pci_tad[id] = pdev; saw_chan_mask |= 1 << id; @@ -2644,10 +2645,10 @@ static int haswell_mci_bind_devs(struct mem_ctl_info *mci, pvt->pci_ddrio = pdev; break; case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1: - pvt->pci_ha1 = pdev; + pvt->pci_ha = pdev; break; case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA: - pvt->pci_ha1_ta = pdev; + pvt->pci_ta = pdev; break; default: break; @@ -2660,13 +2661,12 @@ static int haswell_mci_bind_devs(struct mem_ctl_info *mci, } /* Check if everything were registered */ - if (!pvt->pci_sad0 || !pvt->pci_ha0 || !pvt->pci_sad1 || + if (!pvt->pci_sad0 || !pvt->pci_ha || !pvt->pci_sad1 || !pvt->pci_ras || !pvt->pci_ta || !pvt->info.pci_vtd) goto enodev; - if (saw_chan_mask != 0x0f && /* -EN */ - saw_chan_mask != 0x33 && /* -EP */ - saw_chan_mask != 0xff) /* -EX */ + if (saw_chan_mask != 0x0f && /* -EN/-EX */ + saw_chan_mask != 0x03) /* -EP */ goto enodev; return 0; @@ -2703,12 +2703,13 @@ static int broadwell_mci_bind_devs(struct mem_ctl_info *mci, pvt->pci_sad1 = pdev; break; case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0: - pvt->pci_ha0 = pdev; + pvt->pci_ha = pdev; break; case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA: pvt->pci_ta = pdev; break; case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TM: + case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TM: pvt->pci_ras = pdev; break; case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD0: @@ -2726,7 +2727,7 @@ static int broadwell_mci_bind_devs(struct mem_ctl_info *mci, case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD2: case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD3: { - int id = pdev->device - PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD0 + 4; + int id = pdev->device - PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD0; pvt->pci_tad[id] = pdev; saw_chan_mask |= 1 << id; } @@ -2735,10 +2736,10 @@ static int broadwell_mci_bind_devs(struct mem_ctl_info *mci, pvt->pci_ddrio = pdev; break; case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1: - pvt->pci_ha1 = pdev; + pvt->pci_ha = pdev; break; case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TA: - pvt->pci_ha1_ta = pdev; + pvt->pci_ta = pdev; break; default: break; @@ -2751,13 +2752,12 @@ static int broadwell_mci_bind_devs(struct mem_ctl_info *mci, } /* Check if everything were registered */ - if (!pvt->pci_sad0 || !pvt->pci_ha0 || !pvt->pci_sad1 || + if (!pvt->pci_sad0 || !pvt->pci_ha || !pvt->pci_sad1 || !pvt->pci_ras || !pvt->pci_ta || !pvt->info.pci_vtd) goto enodev; - if (saw_chan_mask != 0x0f && /* -EN */ - saw_chan_mask != 0x33 && /* -EP */ - saw_chan_mask != 0xff) /* -EX */ + if (saw_chan_mask != 0x0f && /* -EN/-EX */ + saw_chan_mask != 0x03) /* -EP */ goto enodev; return 0; @@ -3019,7 +3019,7 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci, if (rc < 0) goto err_parsing; - new_mci = get_mci_for_node_id(socket); + new_mci = get_mci_for_node_id(socket, ha); if (!new_mci) { strcpy(msg, "Error: socket got corrupted!"); goto err_parsing; @@ -3066,7 +3066,7 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci, /* Call the helper to output message */ edac_mc_handle_error(tp_event, mci, core_err_cnt, m->addr >> PAGE_SHIFT, m->addr & ~PAGE_MASK, 0, - 4*ha+channel, dimm, -1, + channel, dimm, -1, optype, msg); return; err_parsing: @@ -3091,7 +3091,7 @@ static int sbridge_mce_check_error(struct notifier_block *nb, unsigned long val, if (edac_get_report_status() == EDAC_REPORTING_DISABLED) return NOTIFY_DONE; - mci = get_mci_for_node_id(mce->socketid); + mci = get_mci_for_node_id(mce->socketid, IMC0); if (!mci) return NOTIFY_DONE; pvt = mci->pvt_info; @@ -3234,8 +3234,8 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) if (unlikely(rc < 0)) goto fail0; get_source_id(mci); - mci->ctl_name = kasprintf(GFP_KERNEL, "Ivy Bridge SrcID#%d", - pvt->sbridge_dev->source_id); + mci->ctl_name = kasprintf(GFP_KERNEL, "Ivy Bridge SrcID#%d_Ha#%d", + pvt->sbridge_dev->source_id, pvt->sbridge_dev->dom); break; case SANDY_BRIDGE: pvt->info.rankcfgr = SB_RANK_CFG_A; @@ -3259,8 +3259,8 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) if (unlikely(rc < 0)) goto fail0; get_source_id(mci); - mci->ctl_name = kasprintf(GFP_KERNEL, "Sandy Bridge SrcID#%d", - pvt->sbridge_dev->source_id); + mci->ctl_name = kasprintf(GFP_KERNEL, "Sandy Bridge SrcID#%d_Ha#%d", + pvt->sbridge_dev->source_id, pvt->sbridge_dev->dom); break; case HASWELL: /* rankcfgr isn't used */ @@ -3284,8 +3284,8 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) if (unlikely(rc < 0)) goto fail0; get_source_id(mci); - mci->ctl_name = kasprintf(GFP_KERNEL, "Haswell SrcID#%d", - pvt->sbridge_dev->source_id); + mci->ctl_name = kasprintf(GFP_KERNEL, "Haswell SrcID#%d_Ha#%d", + pvt->sbridge_dev->source_id, pvt->sbridge_dev->dom); break; case BROADWELL: /* rankcfgr isn't used */ @@ -3309,8 +3309,8 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) if (unlikely(rc < 0)) goto fail0; get_source_id(mci); - mci->ctl_name = kasprintf(GFP_KERNEL, "Broadwell SrcID#%d", - pvt->sbridge_dev->source_id); + mci->ctl_name = kasprintf(GFP_KERNEL, "Broadwell SrcID#%d_Ha#%d", + pvt->sbridge_dev->source_id, pvt->sbridge_dev->dom); break; case KNIGHTS_LANDING: /* pvt->info.rankcfgr == ??? */ @@ -3333,8 +3333,8 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) if (unlikely(rc < 0)) goto fail0; get_source_id(mci); - mci->ctl_name = kasprintf(GFP_KERNEL, "Knights Landing SrcID#%d", - pvt->sbridge_dev->source_id); + mci->ctl_name = kasprintf(GFP_KERNEL, "Knights Landing SrcID#%d_Ha#%d", + pvt->sbridge_dev->source_id, pvt->sbridge_dev->dom); break; } -- cgit v1.2.3 From 199389acd95b8a8858e98244b72ea2970bc482ff Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Thu, 25 May 2017 13:00:05 +0200 Subject: EDAC, sb_edac: Fix mod_name It is called "sb_edac.c" now. Signed-off-by: Borislav Petkov --- drivers/edac/sb_edac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index 2c2c7ed9d886..903ca1f98361 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -3205,7 +3205,7 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) MEM_FLAG_DDR4 : MEM_FLAG_DDR3; mci->edac_ctl_cap = EDAC_FLAG_NONE; mci->edac_cap = EDAC_FLAG_NONE; - mci->mod_name = "sbridge_edac.c"; + mci->mod_name = "sb_edac.c"; mci->mod_ver = SBRIDGE_REVISION; mci->dev_name = pci_name(pdev); mci->ctl_page_to_phys = NULL; -- cgit v1.2.3 From 6696522957a192130dc42d80ea34796ec7ba0c2b Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Thu, 25 May 2017 13:20:28 +0200 Subject: EDAC, sb_edac: Carve out dimm-populating loop ... to slim down get_dimm_config(). No functionality change. Signed-off-by: Borislav Petkov --- drivers/edac/sb_edac.c | 124 ++++++++++++++++++++++++++----------------------- 1 file changed, 66 insertions(+), 58 deletions(-) diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index 903ca1f98361..fad5c79741d2 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -1620,66 +1620,17 @@ static void get_source_id(struct mem_ctl_info *mci) pvt->sbridge_dev->source_id = SOURCE_ID(reg); } -static int get_dimm_config(struct mem_ctl_info *mci) +static void __populate_dimms(struct mem_ctl_info *mci, + u64 knl_mc_sizes[KNL_MAX_CHANNELS], + enum edac_type mode) { struct sbridge_pvt *pvt = mci->pvt_info; + int channels = pvt->info.type == KNIGHTS_LANDING ? KNL_MAX_CHANNELS + : NUM_CHANNELS; + unsigned int i, j, banks, ranks, rows, cols, npages; struct dimm_info *dimm; - unsigned i, j, banks, ranks, rows, cols, npages; - u64 size; - u32 reg; - enum edac_type mode; enum mem_type mtype; - int channels = pvt->info.type == KNIGHTS_LANDING ? - KNL_MAX_CHANNELS : NUM_CHANNELS; - u64 knl_mc_sizes[KNL_MAX_CHANNELS]; - - if (pvt->info.type == HASWELL || pvt->info.type == BROADWELL) { - pci_read_config_dword(pvt->pci_ha, HASWELL_HASYSDEFEATURE2, ®); - pvt->is_chan_hash = GET_BITFIELD(reg, 21, 21); - } - pvt->sbridge_dev->node_id = pvt->info.get_node_id(pvt); - edac_dbg(0, "mc#%d: Node ID: %d, source ID: %d\n", - pvt->sbridge_dev->mc, - pvt->sbridge_dev->node_id, - pvt->sbridge_dev->source_id); - - /* KNL doesn't support mirroring or lockstep, - * and is always closed page - */ - if (pvt->info.type == KNIGHTS_LANDING) { - mode = EDAC_S4ECD4ED; - pvt->is_mirrored = false; - - if (knl_get_dimm_capacity(pvt, knl_mc_sizes) != 0) - return -1; - } else { - pci_read_config_dword(pvt->pci_ras, RASENABLES, ®); - if (IS_MIRROR_ENABLED(reg)) { - edac_dbg(0, "Memory mirror is enabled\n"); - pvt->is_mirrored = true; - } else { - edac_dbg(0, "Memory mirror is disabled\n"); - pvt->is_mirrored = false; - } - - pci_read_config_dword(pvt->pci_ta, MCMTR, &pvt->info.mcmtr); - if (IS_LOCKSTEP_ENABLED(pvt->info.mcmtr)) { - edac_dbg(0, "Lockstep is enabled\n"); - mode = EDAC_S8ECD8ED; - pvt->is_lockstep = true; - } else { - edac_dbg(0, "Lockstep is disabled\n"); - mode = EDAC_S4ECD4ED; - pvt->is_lockstep = false; - } - if (IS_CLOSE_PG(pvt->info.mcmtr)) { - edac_dbg(0, "address map is on closed page mode\n"); - pvt->is_close_pg = true; - } else { - edac_dbg(0, "address map is on open page mode\n"); - pvt->is_close_pg = false; - } - } + u64 size; mtype = pvt->info.get_memory_type(pvt); if (mtype == MEM_RDDR3 || mtype == MEM_RDDR4) @@ -1710,8 +1661,7 @@ static int get_dimm_config(struct mem_ctl_info *mci) } for (j = 0; j < max_dimms_per_channel; j++) { - dimm = EDAC_DIMM_PTR(mci->layers, mci->dimms, mci->n_layers, - i, j, 0); + dimm = EDAC_DIMM_PTR(mci->layers, mci->dimms, mci->n_layers, i, j, 0); if (pvt->info.type == KNIGHTS_LANDING) { pci_read_config_dword(pvt->knl.pci_channel[i], knl_mtr_reg, &mtr); @@ -1754,6 +1704,64 @@ static int get_dimm_config(struct mem_ctl_info *mci) } } } +} + +static int get_dimm_config(struct mem_ctl_info *mci) +{ + struct sbridge_pvt *pvt = mci->pvt_info; + u64 knl_mc_sizes[KNL_MAX_CHANNELS]; + enum edac_type mode; + u32 reg; + + if (pvt->info.type == HASWELL || pvt->info.type == BROADWELL) { + pci_read_config_dword(pvt->pci_ha, HASWELL_HASYSDEFEATURE2, ®); + pvt->is_chan_hash = GET_BITFIELD(reg, 21, 21); + } + pvt->sbridge_dev->node_id = pvt->info.get_node_id(pvt); + edac_dbg(0, "mc#%d: Node ID: %d, source ID: %d\n", + pvt->sbridge_dev->mc, + pvt->sbridge_dev->node_id, + pvt->sbridge_dev->source_id); + + /* KNL doesn't support mirroring or lockstep, + * and is always closed page + */ + if (pvt->info.type == KNIGHTS_LANDING) { + mode = EDAC_S4ECD4ED; + pvt->is_mirrored = false; + + if (knl_get_dimm_capacity(pvt, knl_mc_sizes) != 0) + return -1; + } else { + pci_read_config_dword(pvt->pci_ras, RASENABLES, ®); + if (IS_MIRROR_ENABLED(reg)) { + edac_dbg(0, "Memory mirror is enabled\n"); + pvt->is_mirrored = true; + } else { + edac_dbg(0, "Memory mirror is disabled\n"); + pvt->is_mirrored = false; + } + + pci_read_config_dword(pvt->pci_ta, MCMTR, &pvt->info.mcmtr); + if (IS_LOCKSTEP_ENABLED(pvt->info.mcmtr)) { + edac_dbg(0, "Lockstep is enabled\n"); + mode = EDAC_S8ECD8ED; + pvt->is_lockstep = true; + } else { + edac_dbg(0, "Lockstep is disabled\n"); + mode = EDAC_S4ECD4ED; + pvt->is_lockstep = false; + } + if (IS_CLOSE_PG(pvt->info.mcmtr)) { + edac_dbg(0, "address map is on closed page mode\n"); + pvt->is_close_pg = true; + } else { + edac_dbg(0, "address map is on open page mode\n"); + pvt->is_close_pg = false; + } + } + + __populate_dimms(mci, knl_mc_sizes, mode); return 0; } -- cgit v1.2.3 From 3286d3eb906cbac832884dda8ce2fdc7acb17a65 Mon Sep 17 00:00:00 2001 From: Qiuxu Zhuo Date: Tue, 23 May 2017 08:08:34 +0800 Subject: EDAC, sb_edac: Drop NUM_CHANNELS from 8 back to 4 We don't need this quirk anymore now that the EDAC memory controller representation matches the hardware. Signed-off-by: Qiuxu Zhuo Cc: linux-edac Link: http://lkml.kernel.org/r/20170523000834.87881-1-qiuxu.zhuo@intel.com [ Commit message. ] Signed-off-by: Borislav Petkov --- drivers/edac/sb_edac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index fad5c79741d2..b9564f767269 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -279,7 +279,7 @@ static const u32 correrrthrsld[] = { * sbridge structs */ -#define NUM_CHANNELS 8 /* 2MC per socket, four chan per MC */ +#define NUM_CHANNELS 4 /* Max channels per MC */ #define MAX_DIMMS 3 /* Max DIMMS per channel */ #define KNL_MAX_CHAS 38 /* KNL max num. of Cache Home Agents */ #define KNL_MAX_CHANNELS 6 /* KNL max num. of PCI channels */ -- cgit v1.2.3 From 4d475dde79b561bbd843d7deb7100f9e75596487 Mon Sep 17 00:00:00 2001 From: Qiuxu Zhuo Date: Thu, 25 May 2017 14:46:53 +0200 Subject: EDAC, sb_edac: Check if ECC enabled when at least one DIMM is present This is based on previous work by Patrick Geary, see Link. Additional cleanups ontop: - Remove the code to read MCMTR from pci_ha1_ta and CHN_TO_HA macro, now that TA0 and TA1 are unified. - Remove get_pdev_same_bus(), since in get_dimm_config() the variable "pvt->pci_ta" for KNL is also ready, we can simply use pci_read_config_dword(pvt->pci_ta, KNL_MCMTR, &pvt->info.mcmtr) to read MCMTR. Signed-off-by: Qiuxu Zhuo Cc: linux-edac Link: https://lkml.kernel.org/r/57884350.1030401@supermicro.com Link: http://lkml.kernel.org/r/20170523000910.87925-1-qiuxu.zhuo@intel.com [ Make __populate_dimms() return int. ] Signed-off-by: Borislav Petkov --- drivers/edac/sb_edac.c | 103 +++++++++---------------------------------------- 1 file changed, 18 insertions(+), 85 deletions(-) diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index b9564f767269..30eb91011ac9 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -1060,79 +1060,6 @@ static int haswell_chan_hash(int idx, u64 addr) return idx; } -/**************************************************************************** - Memory check routines - ****************************************************************************/ -static struct pci_dev *get_pdev_same_bus(u8 bus, u32 id) -{ - struct pci_dev *pdev = NULL; - - do { - pdev = pci_get_device(PCI_VENDOR_ID_INTEL, id, pdev); - if (pdev && pdev->bus->number == bus) - break; - } while (pdev); - - return pdev; -} - -/** - * check_if_ecc_is_active() - Checks if ECC is active - * @bus: Device bus - * @type: Memory controller type - * returns: 0 in case ECC is active, -ENODEV if it can't be determined or - * disabled - */ -static int check_if_ecc_is_active(const u8 bus, enum type type) -{ - struct pci_dev *pdev = NULL; - u32 mcmtr, id; - - switch (type) { - case IVY_BRIDGE: - id = PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA; - break; - case HASWELL: - id = PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA; - break; - case SANDY_BRIDGE: - id = PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA; - break; - case BROADWELL: - id = PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA; - break; - case KNIGHTS_LANDING: - /* - * KNL doesn't group things by bus the same way - * SB/IB/Haswell does. - */ - id = PCI_DEVICE_ID_INTEL_KNL_IMC_TA; - break; - default: - return -ENODEV; - } - - if (type != KNIGHTS_LANDING) - pdev = get_pdev_same_bus(bus, id); - else - pdev = pci_get_device(PCI_VENDOR_ID_INTEL, id, 0); - - if (!pdev) { - sbridge_printk(KERN_ERR, "Couldn't find PCI device " - "%04x:%04x! on bus %02d\n", - PCI_VENDOR_ID_INTEL, id, bus); - return -ENODEV; - } - - pci_read_config_dword(pdev, - type == KNIGHTS_LANDING ? KNL_MCMTR : MCMTR, &mcmtr); - if (!IS_ECC_ENABLED(mcmtr)) { - sbridge_printk(KERN_ERR, "ECC is disabled. Aborting\n"); - return -ENODEV; - } - return 0; -} - /* Low bits of TAD limit, and some metadata. */ static const u32 knl_tad_dram_limit_lo[] = { 0x400, 0x500, 0x600, 0x700, @@ -1620,9 +1547,9 @@ static void get_source_id(struct mem_ctl_info *mci) pvt->sbridge_dev->source_id = SOURCE_ID(reg); } -static void __populate_dimms(struct mem_ctl_info *mci, - u64 knl_mc_sizes[KNL_MAX_CHANNELS], - enum edac_type mode) +static int __populate_dimms(struct mem_ctl_info *mci, + u64 knl_mc_sizes[KNL_MAX_CHANNELS], + enum edac_type mode) { struct sbridge_pvt *pvt = mci->pvt_info; int channels = pvt->info.type == KNIGHTS_LANDING ? KNL_MAX_CHANNELS @@ -1671,6 +1598,12 @@ static void __populate_dimms(struct mem_ctl_info *mci, } edac_dbg(4, "Channel #%d MTR%d = %x\n", i, j, mtr); if (IS_DIMM_PRESENT(mtr)) { + if (!IS_ECC_ENABLED(pvt->info.mcmtr)) { + sbridge_printk(KERN_ERR, "CPU SrcID #%d, Ha #%d, Channel #%d has DIMMs, but ECC is disabled\n", + pvt->sbridge_dev->source_id, + pvt->sbridge_dev->dom, i); + return -ENODEV; + } pvt->channel[i].dimms++; ranks = numrank(pvt->info.type, mtr); @@ -1704,6 +1637,8 @@ static void __populate_dimms(struct mem_ctl_info *mci, } } } + + return 0; } static int get_dimm_config(struct mem_ctl_info *mci) @@ -1732,6 +1667,7 @@ static int get_dimm_config(struct mem_ctl_info *mci) if (knl_get_dimm_capacity(pvt, knl_mc_sizes) != 0) return -1; + pci_read_config_dword(pvt->pci_ta, KNL_MCMTR, &pvt->info.mcmtr); } else { pci_read_config_dword(pvt->pci_ras, RASENABLES, ®); if (IS_MIRROR_ENABLED(reg)) { @@ -1761,9 +1697,7 @@ static int get_dimm_config(struct mem_ctl_info *mci) } } - __populate_dimms(mci, knl_mc_sizes, mode); - - return 0; + return __populate_dimms(mci, knl_mc_sizes, mode); } static void get_memory_layout(const struct mem_ctl_info *mci) @@ -3180,11 +3114,6 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) struct pci_dev *pdev = sbridge_dev->pdev[0]; int rc; - /* Check the number of active and not disabled channels */ - rc = check_if_ecc_is_active(sbridge_dev->bus, type); - if (unlikely(rc < 0)) - return rc; - /* allocate a new MC control structure */ layers[0].type = EDAC_MC_LAYER_CHANNEL; layers[0].size = type == KNIGHTS_LANDING ? @@ -3347,7 +3276,11 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) } /* Get dimm basic config and the memory layout */ - get_dimm_config(mci); + rc = get_dimm_config(mci); + if (rc < 0) { + edac_dbg(0, "MC: failed to get_dimm_config()\n"); + goto fail; + } get_memory_layout(mci); /* record ptr to the generic device */ -- cgit v1.2.3 From d14e3a201f06c85527e176f7ebfd967b405b6185 Mon Sep 17 00:00:00 2001 From: Qiuxu Zhuo Date: Tue, 23 May 2017 08:09:34 +0800 Subject: EDAC, sb_edac: Bump driver version and do some cleanups Collapse 'case:' in *_mci_bind_devs() and update driver version from 1.1.1 to 1.1.2. Signed-off-by: Qiuxu Zhuo Cc: linux-edac Link: http://lkml.kernel.org/r/20170523000934.87971-1-qiuxu.zhuo@intel.com Signed-off-by: Borislav Petkov --- drivers/edac/sb_edac.c | 65 ++++++++++++++++---------------------------------- 1 file changed, 21 insertions(+), 44 deletions(-) diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index 30eb91011ac9..89fd6bd64df6 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -35,7 +35,7 @@ static LIST_HEAD(sbridge_edac_list); /* * Alter this version for the module when modifications are made */ -#define SBRIDGE_REVISION " Ver: 1.1.1 " +#define SBRIDGE_REVISION " Ver: 1.1.2 " #define EDAC_MOD_STR "sbridge_edac" /* @@ -2353,6 +2353,13 @@ static int sbridge_get_all_devices(u8 *num_mc, return 0; } +/* + * Device IDs for {SBRIDGE,IBRIDGE,HASWELL,BROADWELL}_IMC_HA0_TAD0 are in + * the format: XXXa. So we can convert from a device to the corresponding + * channel like this + */ +#define TAD_DEV_TO_CHAN(dev) (((dev) & 0xf) - 0xa) + static int sbridge_mci_bind_devs(struct mem_ctl_info *mci, struct sbridge_dev *sbridge_dev) { @@ -2390,7 +2397,7 @@ static int sbridge_mci_bind_devs(struct mem_ctl_info *mci, case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2: case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3: { - int id = pdev->device - PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0; + int id = TAD_DEV_TO_CHAN(pdev->device); pvt->pci_tad[id] = pdev; saw_chan_mask |= 1 << id; } @@ -2442,6 +2449,7 @@ static int ibridge_mci_bind_devs(struct mem_ctl_info *mci, switch (pdev->device) { case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0: + case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1: pvt->pci_ha = pdev; break; case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA: @@ -2455,8 +2463,12 @@ static int ibridge_mci_bind_devs(struct mem_ctl_info *mci, case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD1: case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2: case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3: + case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0: + case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1: + case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD2: + case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD3: { - int id = pdev->device - PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0; + int id = TAD_DEV_TO_CHAN(pdev->device); pvt->pci_tad[id] = pdev; saw_chan_mask |= 1 << id; } @@ -2476,19 +2488,6 @@ static int ibridge_mci_bind_devs(struct mem_ctl_info *mci, case PCI_DEVICE_ID_INTEL_IBRIDGE_BR1: pvt->pci_br1 = pdev; break; - case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1: - pvt->pci_ha = pdev; - break; - case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0: - case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1: - case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD2: - case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD3: - { - int id = pdev->device - PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0; - pvt->pci_tad[id] = pdev; - saw_chan_mask |= 1 << id; - } - break; default: goto error; } @@ -2548,9 +2547,11 @@ static int haswell_mci_bind_devs(struct mem_ctl_info *mci, pvt->pci_sad1 = pdev; break; case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0: + case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1: pvt->pci_ha = pdev; break; case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA: + case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA: pvt->pci_ta = pdev; break; case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TM: @@ -2561,20 +2562,12 @@ static int haswell_mci_bind_devs(struct mem_ctl_info *mci, case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD1: case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD2: case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD3: - { - int id = pdev->device - PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD0; - - pvt->pci_tad[id] = pdev; - saw_chan_mask |= 1 << id; - } - break; case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD0: case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD1: case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD2: case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD3: { - int id = pdev->device - PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD0; - + int id = TAD_DEV_TO_CHAN(pdev->device); pvt->pci_tad[id] = pdev; saw_chan_mask |= 1 << id; } @@ -2586,12 +2579,6 @@ static int haswell_mci_bind_devs(struct mem_ctl_info *mci, if (!pvt->pci_ddrio) pvt->pci_ddrio = pdev; break; - case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1: - pvt->pci_ha = pdev; - break; - case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA: - pvt->pci_ta = pdev; - break; default: break; } @@ -2645,9 +2632,11 @@ static int broadwell_mci_bind_devs(struct mem_ctl_info *mci, pvt->pci_sad1 = pdev; break; case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0: + case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1: pvt->pci_ha = pdev; break; case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA: + case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TA: pvt->pci_ta = pdev; break; case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TM: @@ -2658,18 +2647,12 @@ static int broadwell_mci_bind_devs(struct mem_ctl_info *mci, case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD1: case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD2: case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD3: - { - int id = pdev->device - PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD0; - pvt->pci_tad[id] = pdev; - saw_chan_mask |= 1 << id; - } - break; case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD0: case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD1: case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD2: case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD3: { - int id = pdev->device - PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD0; + int id = TAD_DEV_TO_CHAN(pdev->device); pvt->pci_tad[id] = pdev; saw_chan_mask |= 1 << id; } @@ -2677,12 +2660,6 @@ static int broadwell_mci_bind_devs(struct mem_ctl_info *mci, case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_DDRIO0: pvt->pci_ddrio = pdev; break; - case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1: - pvt->pci_ha = pdev; - break; - case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TA: - pvt->pci_ta = pdev; - break; default: break; } -- cgit v1.2.3 From 0b3df44eeb319186bb3be2f67c8e93a77156c825 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Thu, 18 May 2017 20:31:34 +1200 Subject: EDAC, mv64x60: Fix pdata->name Change this from mpc85xx_pci_err to mv64x60_pci_err. The former is likely a hangover from when this driver was created. Signed-off-by: Chris Packham Cc: linux-edac Cc: linuxppc-dev@lists.ozlabs.org Link: http://lkml.kernel.org/r/20170518083135.28048-3-chris.packham@alliedtelesis.co.nz Signed-off-by: Borislav Petkov --- drivers/edac/mv64x60_edac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/edac/mv64x60_edac.c b/drivers/edac/mv64x60_edac.c index 14b7e7b71eaa..ea0ea41fb8d4 100644 --- a/drivers/edac/mv64x60_edac.c +++ b/drivers/edac/mv64x60_edac.c @@ -116,7 +116,7 @@ static int mv64x60_pci_err_probe(struct platform_device *pdev) pdata = pci->pvt_info; pdata->pci_hose = pdev->id; - pdata->name = "mpc85xx_pci_err"; + pdata->name = "mv64x60_pci_err"; platform_set_drvdata(pdev, pci); pci->dev = &pdev->dev; pci->dev_name = dev_name(&pdev->dev); -- cgit v1.2.3 From 8b9afe59465debe2b1bdba422caa54029a79aec2 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Thu, 18 May 2017 20:31:35 +1200 Subject: EDAC, mv64x60: Replace in_le32()/out_le32() with readl()/writel() To allow this driver to be used on non-powerpc platforms it needs to use io accessors suitable for all platforms. Signed-off-by: Chris Packham Cc: linux-edac Cc: linuxppc-dev@lists.ozlabs.org Link: http://lkml.kernel.org/r/20170518083135.28048-4-chris.packham@alliedtelesis.co.nz Signed-off-by: Borislav Petkov --- drivers/edac/mv64x60_edac.c | 84 ++++++++++++++++++++++----------------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/drivers/edac/mv64x60_edac.c b/drivers/edac/mv64x60_edac.c index ea0ea41fb8d4..6859bba1a133 100644 --- a/drivers/edac/mv64x60_edac.c +++ b/drivers/edac/mv64x60_edac.c @@ -32,21 +32,21 @@ static void mv64x60_pci_check(struct edac_pci_ctl_info *pci) struct mv64x60_pci_pdata *pdata = pci->pvt_info; u32 cause; - cause = in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE); + cause = readl(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE); if (!cause) return; printk(KERN_ERR "Error in PCI %d Interface\n", pdata->pci_hose); printk(KERN_ERR "Cause register: 0x%08x\n", cause); printk(KERN_ERR "Address Low: 0x%08x\n", - in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_ADDR_LO)); + readl(pdata->pci_vbase + MV64X60_PCI_ERROR_ADDR_LO)); printk(KERN_ERR "Address High: 0x%08x\n", - in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_ADDR_HI)); + readl(pdata->pci_vbase + MV64X60_PCI_ERROR_ADDR_HI)); printk(KERN_ERR "Attribute: 0x%08x\n", - in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_ATTR)); + readl(pdata->pci_vbase + MV64X60_PCI_ERROR_ATTR)); printk(KERN_ERR "Command: 0x%08x\n", - in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CMD)); - out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE, ~cause); + readl(pdata->pci_vbase + MV64X60_PCI_ERROR_CMD)); + writel(~cause, pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE); if (cause & MV64X60_PCI_PE_MASK) edac_pci_handle_pe(pci, pci->ctl_name); @@ -61,7 +61,7 @@ static irqreturn_t mv64x60_pci_isr(int irq, void *dev_id) struct mv64x60_pci_pdata *pdata = pci->pvt_info; u32 val; - val = in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE); + val = readl(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE); if (!val) return IRQ_NONE; @@ -93,7 +93,7 @@ static int __init mv64x60_pci_fixup(struct platform_device *pdev) if (!pci_serr) return -ENOMEM; - out_le32(pci_serr, in_le32(pci_serr) & ~0x1); + writel(readl(pci_serr) & ~0x1, pci_serr); iounmap(pci_serr); return 0; @@ -161,10 +161,10 @@ static int mv64x60_pci_err_probe(struct platform_device *pdev) goto err; } - out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE, 0); - out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_MASK, 0); - out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_MASK, - MV64X60_PCIx_ERR_MASK_VAL); + writel(0, pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE); + writel(0, pdata->pci_vbase + MV64X60_PCI_ERROR_MASK); + writel(MV64X60_PCIx_ERR_MASK_VAL, + pdata->pci_vbase + MV64X60_PCI_ERROR_MASK); if (edac_pci_add_device(pci, pdata->edac_idx) > 0) { edac_dbg(3, "failed edac_pci_add_device()\n"); @@ -233,23 +233,23 @@ static void mv64x60_sram_check(struct edac_device_ctl_info *edac_dev) struct mv64x60_sram_pdata *pdata = edac_dev->pvt_info; u32 cause; - cause = in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE); + cause = readl(pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE); if (!cause) return; printk(KERN_ERR "Error in internal SRAM\n"); printk(KERN_ERR "Cause register: 0x%08x\n", cause); printk(KERN_ERR "Address Low: 0x%08x\n", - in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_ADDR_LO)); + readl(pdata->sram_vbase + MV64X60_SRAM_ERR_ADDR_LO)); printk(KERN_ERR "Address High: 0x%08x\n", - in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_ADDR_HI)); + readl(pdata->sram_vbase + MV64X60_SRAM_ERR_ADDR_HI)); printk(KERN_ERR "Data Low: 0x%08x\n", - in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_DATA_LO)); + readl(pdata->sram_vbase + MV64X60_SRAM_ERR_DATA_LO)); printk(KERN_ERR "Data High: 0x%08x\n", - in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_DATA_HI)); + readl(pdata->sram_vbase + MV64X60_SRAM_ERR_DATA_HI)); printk(KERN_ERR "Parity: 0x%08x\n", - in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_PARITY)); - out_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE, 0); + readl(pdata->sram_vbase + MV64X60_SRAM_ERR_PARITY)); + writel(0, pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE); edac_device_handle_ue(edac_dev, 0, 0, edac_dev->ctl_name); } @@ -260,7 +260,7 @@ static irqreturn_t mv64x60_sram_isr(int irq, void *dev_id) struct mv64x60_sram_pdata *pdata = edac_dev->pvt_info; u32 cause; - cause = in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE); + cause = readl(pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE); if (!cause) return IRQ_NONE; @@ -322,7 +322,7 @@ static int mv64x60_sram_err_probe(struct platform_device *pdev) } /* setup SRAM err registers */ - out_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE, 0); + writel(0, pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE); edac_dev->mod_name = EDAC_MOD_STR; edac_dev->ctl_name = pdata->name; @@ -398,7 +398,7 @@ static void mv64x60_cpu_check(struct edac_device_ctl_info *edac_dev) struct mv64x60_cpu_pdata *pdata = edac_dev->pvt_info; u32 cause; - cause = in_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE) & + cause = readl(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE) & MV64x60_CPU_CAUSE_MASK; if (!cause) return; @@ -406,16 +406,16 @@ static void mv64x60_cpu_check(struct edac_device_ctl_info *edac_dev) printk(KERN_ERR "Error on CPU interface\n"); printk(KERN_ERR "Cause register: 0x%08x\n", cause); printk(KERN_ERR "Address Low: 0x%08x\n", - in_le32(pdata->cpu_vbase[0] + MV64x60_CPU_ERR_ADDR_LO)); + readl(pdata->cpu_vbase[0] + MV64x60_CPU_ERR_ADDR_LO)); printk(KERN_ERR "Address High: 0x%08x\n", - in_le32(pdata->cpu_vbase[0] + MV64x60_CPU_ERR_ADDR_HI)); + readl(pdata->cpu_vbase[0] + MV64x60_CPU_ERR_ADDR_HI)); printk(KERN_ERR "Data Low: 0x%08x\n", - in_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_DATA_LO)); + readl(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_DATA_LO)); printk(KERN_ERR "Data High: 0x%08x\n", - in_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_DATA_HI)); + readl(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_DATA_HI)); printk(KERN_ERR "Parity: 0x%08x\n", - in_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_PARITY)); - out_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE, 0); + readl(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_PARITY)); + writel(0, pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE); edac_device_handle_ue(edac_dev, 0, 0, edac_dev->ctl_name); } @@ -426,7 +426,7 @@ static irqreturn_t mv64x60_cpu_isr(int irq, void *dev_id) struct mv64x60_cpu_pdata *pdata = edac_dev->pvt_info; u32 cause; - cause = in_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE) & + cause = readl(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE) & MV64x60_CPU_CAUSE_MASK; if (!cause) return IRQ_NONE; @@ -515,9 +515,9 @@ static int mv64x60_cpu_err_probe(struct platform_device *pdev) } /* setup CPU err registers */ - out_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE, 0); - out_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_MASK, 0); - out_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_MASK, 0x000000ff); + writel(0, pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE); + writel(0, pdata->cpu_vbase[1] + MV64x60_CPU_ERR_MASK); + writel(0x000000ff, pdata->cpu_vbase[1] + MV64x60_CPU_ERR_MASK); edac_dev->mod_name = EDAC_MOD_STR; edac_dev->ctl_name = pdata->name; @@ -596,13 +596,13 @@ static void mv64x60_mc_check(struct mem_ctl_info *mci) u32 comp_ecc; u32 syndrome; - reg = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR); + reg = readl(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR); if (!reg) return; err_addr = reg & ~0x3; - sdram_ecc = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_RCVD); - comp_ecc = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CALC); + sdram_ecc = readl(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_RCVD); + comp_ecc = readl(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CALC); syndrome = sdram_ecc ^ comp_ecc; /* first bit clear in ECC Err Reg, 1 bit error, correctable by HW */ @@ -620,7 +620,7 @@ static void mv64x60_mc_check(struct mem_ctl_info *mci) mci->ctl_name, ""); /* clear the error */ - out_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR, 0); + writel(0, pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR); } static irqreturn_t mv64x60_mc_isr(int irq, void *dev_id) @@ -629,7 +629,7 @@ static irqreturn_t mv64x60_mc_isr(int irq, void *dev_id) struct mv64x60_mc_pdata *pdata = mci->pvt_info; u32 reg; - reg = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR); + reg = readl(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR); if (!reg) return IRQ_NONE; @@ -664,7 +664,7 @@ static void mv64x60_init_csrows(struct mem_ctl_info *mci, get_total_mem(pdata); - ctl = in_le32(pdata->mc_vbase + MV64X60_SDRAM_CONFIG); + ctl = readl(pdata->mc_vbase + MV64X60_SDRAM_CONFIG); csrow = mci->csrows[0]; dimm = csrow->channels[0]->dimm; @@ -753,7 +753,7 @@ static int mv64x60_mc_err_probe(struct platform_device *pdev) goto err; } - ctl = in_le32(pdata->mc_vbase + MV64X60_SDRAM_CONFIG); + ctl = readl(pdata->mc_vbase + MV64X60_SDRAM_CONFIG); if (!(ctl & MV64X60_SDRAM_ECC)) { /* Non-ECC RAM? */ printk(KERN_WARNING "%s: No ECC DIMMs discovered\n", __func__); @@ -779,10 +779,10 @@ static int mv64x60_mc_err_probe(struct platform_device *pdev) mv64x60_init_csrows(mci, pdata); /* setup MC registers */ - out_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR, 0); - ctl = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CNTL); + writel(0, pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR); + ctl = readl(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CNTL); ctl = (ctl & 0xff00ffff) | 0x10000; - out_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CNTL, ctl); + writel(ctl, pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CNTL); res = edac_mc_add_mc(mci); if (res) { -- cgit v1.2.3 From 7103de0e5872605d34e951fd03c30fe7d87ea703 Mon Sep 17 00:00:00 2001 From: Jason Baron Date: Fri, 26 May 2017 14:34:43 -0400 Subject: EDAC, ie31200: Add Intel Kaby Lake CPU support Kaby Lake seems to work just like Skylake. Reported-and-tested-by: Doug Thompson Signed-off-by: Jason Baron Cc: Mauro Carvalho Chehab Cc: Tony Luck Link: http://lkml.kernel.org/r/1495823683-32569-1-git-send-email-jbaron@akamai.com Signed-off-by: Borislav Petkov --- drivers/edac/ie31200_edac.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/edac/ie31200_edac.c b/drivers/edac/ie31200_edac.c index 2733fb5938a4..4260579e6901 100644 --- a/drivers/edac/ie31200_edac.c +++ b/drivers/edac/ie31200_edac.c @@ -18,10 +18,12 @@ * 0c04: Xeon E3-1200 v3/4th Gen Core Processor DRAM Controller * 0c08: Xeon E3-1200 v3 Processor DRAM Controller * 1918: Xeon E3-1200 v5 Skylake Host Bridge/DRAM Registers + * 5918: Xeon E3-1200 Xeon E3-1200 v6/7th Gen Core Processor Host Bridge/DRAM Registers * * Based on Intel specification: * http://www.intel.com/content/dam/www/public/us/en/documents/datasheets/xeon-e3-1200v3-vol-2-datasheet.pdf * http://www.intel.com/content/www/us/en/processors/xeon/xeon-e3-1200-family-vol-2-datasheet.html + * http://www.intel.com/content/www/us/en/processors/core/7th-gen-core-family-mobile-h-processor-lines-datasheet-vol-2.html * * According to the above datasheet (p.16): * " @@ -57,6 +59,7 @@ #define PCI_DEVICE_ID_INTEL_IE31200_HB_6 0x0c04 #define PCI_DEVICE_ID_INTEL_IE31200_HB_7 0x0c08 #define PCI_DEVICE_ID_INTEL_IE31200_HB_8 0x1918 +#define PCI_DEVICE_ID_INTEL_IE31200_HB_9 0x5918 #define IE31200_DIMMS 4 #define IE31200_RANKS 8 @@ -376,7 +379,12 @@ static int ie31200_probe1(struct pci_dev *pdev, int dev_idx) void __iomem *window; struct ie31200_priv *priv; u32 addr_decode, mad_offset; - bool skl = (pdev->device == PCI_DEVICE_ID_INTEL_IE31200_HB_8); + + /* + * Kaby Lake seems to work like Skylake. Please re-visit this logic + * when adding new CPU support. + */ + bool skl = (pdev->device >= PCI_DEVICE_ID_INTEL_IE31200_HB_8); edac_dbg(0, "MC:\n"); @@ -559,6 +567,9 @@ static const struct pci_device_id ie31200_pci_tbl[] = { { PCI_VEND_DEV(INTEL, IE31200_HB_8), PCI_ANY_ID, PCI_ANY_ID, 0, 0, IE31200}, + { + PCI_VEND_DEV(INTEL, IE31200_HB_9), PCI_ANY_ID, PCI_ANY_ID, 0, 0, + IE31200}, { 0, } /* 0 terminated list. */ -- cgit v1.2.3 From 7d2fdaa694c596671c0d1d8d625966f7eb8cdea8 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Tue, 30 May 2017 09:21:40 +1200 Subject: EDAC, mv64x60: Check driver registration success Check the return status of platform_driver_register() in mv64x60_edac_init(). Only output messages and initialise the edac_op_state if the registration is successful. Signed-off-by: Chris Packham Cc: linux-edac Cc: linuxppc-dev@lists.ozlabs.org Link: http://lkml.kernel.org/r/20170529212142.25572-2-chris.packham@alliedtelesis.co.nz Signed-off-by: Borislav Petkov --- drivers/edac/mv64x60_edac.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/edac/mv64x60_edac.c b/drivers/edac/mv64x60_edac.c index 6859bba1a133..77bfc3d882a8 100644 --- a/drivers/edac/mv64x60_edac.c +++ b/drivers/edac/mv64x60_edac.c @@ -853,10 +853,15 @@ static struct platform_driver * const drivers[] = { static int __init mv64x60_edac_init(void) { - int ret = 0; + int ret; + + ret = platform_register_drivers(drivers, ARRAY_SIZE(drivers)); + if (ret) + return ret; printk(KERN_INFO "Marvell MV64x60 EDAC driver " MV64x60_REVISION "\n"); printk(KERN_INFO "\t(C) 2006-2007 MontaVista Software\n"); + /* make sure error reporting method is sane */ switch (edac_op_state) { case EDAC_OPSTATE_POLL: @@ -867,7 +872,7 @@ static int __init mv64x60_edac_init(void) break; } - return platform_register_drivers(drivers, ARRAY_SIZE(drivers)); + return 0; } module_init(mv64x60_edac_init); -- cgit v1.2.3 From cf97825862f0acd7d6bad67da59962e4badc870a Mon Sep 17 00:00:00 2001 From: Vadim Lomovtsev Date: Wed, 31 May 2017 18:51:57 +0300 Subject: EDAC, thunderx: Fix a warning during l2c debugfs node creation Compare the number of debugfs entries created by thunderx_create_debugfs_nodes() with the requested number of entries to properly determine whether to print a warning. Signed-off-by: Vadim Lomovtsev Cc: linux-edac Cc: linux-mips@linux-mips.org Link: http://lkml.kernel.org/r/20170531155157.93583-1-stemerkhanov@cavium.com Signed-off-by: Sergey Temerkhanov Signed-off-by: Borislav Petkov --- drivers/edac/thunderx_edac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/edac/thunderx_edac.c b/drivers/edac/thunderx_edac.c index 86d585cb6d32..2d352b40ae1c 100644 --- a/drivers/edac/thunderx_edac.c +++ b/drivers/edac/thunderx_edac.c @@ -2080,7 +2080,7 @@ static int thunderx_l2c_probe(struct pci_dev *pdev, if (IS_ENABLED(CONFIG_EDAC_DEBUG)) { l2c->debugfs = edac_debugfs_create_dir(pdev->dev.kobj.name); - thunderx_create_debugfs_nodes(l2c->debugfs, l2c_devattr, + ret = thunderx_create_debugfs_nodes(l2c->debugfs, l2c_devattr, l2c, dfs_entries); if (ret != dfs_entries) { -- cgit v1.2.3 From 3b405e30cbcac3aa327ae04a29e7da5d084a4933 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Thu, 8 Jun 2017 09:55:30 +1200 Subject: EDAC, mv64x60: Sanity check edac_op_state before registering edac_op_state is a module parameter which affects the behaviour of the driver probe which can potentially be invoked as soon as the platform driver registration happens. Because of this we need to ensure that we sanity check the module parameter before calling platform_register_drivers(). Signed-off-by: Chris Packham Cc: linux-edac Link: http://lkml.kernel.org/r/20170607215530.8604-1-chris.packham@alliedtelesis.co.nz Signed-off-by: Borislav Petkov --- drivers/edac/mv64x60_edac.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/edac/mv64x60_edac.c b/drivers/edac/mv64x60_edac.c index 77bfc3d882a8..d3650df94fe8 100644 --- a/drivers/edac/mv64x60_edac.c +++ b/drivers/edac/mv64x60_edac.c @@ -853,11 +853,6 @@ static struct platform_driver * const drivers[] = { static int __init mv64x60_edac_init(void) { - int ret; - - ret = platform_register_drivers(drivers, ARRAY_SIZE(drivers)); - if (ret) - return ret; printk(KERN_INFO "Marvell MV64x60 EDAC driver " MV64x60_REVISION "\n"); printk(KERN_INFO "\t(C) 2006-2007 MontaVista Software\n"); @@ -872,7 +867,7 @@ static int __init mv64x60_edac_init(void) break; } - return 0; + return platform_register_drivers(drivers, ARRAY_SIZE(drivers)); } module_init(mv64x60_edac_init); -- cgit v1.2.3 From bdf1bf1744355d83cd44e160f2d3dcc28df5140b Mon Sep 17 00:00:00 2001 From: Yazen Ghannam Date: Mon, 12 Jun 2017 11:58:23 -0500 Subject: EDAC, mce_amd: Fix typo in SMCA error description Fix typo in "poison consumption" error description. Signed-off-by: Yazen Ghannam Cc: linux-edac Link: http://lkml.kernel.org/r/1497286703-62853-1-git-send-email-Yazen.Ghannam@amd.com Signed-off-by: Borislav Petkov --- drivers/edac/mce_amd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c index ba35b7ea3686..9a2658a256a9 100644 --- a/drivers/edac/mce_amd.c +++ b/drivers/edac/mce_amd.c @@ -161,7 +161,7 @@ static const char * const smca_ls_mce_desc[] = { "Sys Read data error thread 0", "Sys read data error thread 1", "DC tag error type 2", - "DC data error type 1 (poison comsumption)", + "DC data error type 1 (poison consumption)", "DC data error type 2", "DC data error type 3", "DC tag error type 4", -- cgit v1.2.3 From 133e4455c9b49071906775319e2e6d083a4f024d Mon Sep 17 00:00:00 2001 From: Qiuxu Zhuo Date: Thu, 8 Jun 2017 19:33:51 +0800 Subject: EDAC, sb_edac: Avoid creating SOCK memory controller Xiaolong Ye reported the following failure on Broadwell D server: EDAC sbridge: Some needed devices are missing EDAC MC: Removed device 0 for sbridge_edac.c Broadwell SrcID#0_Ha#0: DEV 0000:ff:12.0 EDAC sbridge: Couldn't find mci handler EDAC sbridge: Failed to register device with error -19. Broadwell D (only IMC0 per socket) and Broadwell X (IMC0 and IMC1 per socket) use the same PCI device IDs for IMC0 per socket, then they share pci_dev_descr_broadwell_table (n_imcs_per_sock=2). In this case, Broadwell D wrongly creates the nonexistent SOCK EDAC memory controller and reports above error messages, since it has no IMC1 per socket. Avoid creating the nonexistent SOCK memory controller. Reported-and-tested-by: Xiaolong Ye Signed-off-by: Qiuxu Zhuo Cc: Tony Luck Cc: linux-edac Link: http://lkml.kernel.org/r/20170608113351.25323-1-qiuxu.zhuo@intel.com [ Massage. ] Signed-off-by: Borislav Petkov --- drivers/edac/sb_edac.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index 89fd6bd64df6..80d860cb0746 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -2260,6 +2260,10 @@ static int sbridge_get_onedevice(struct pci_dev **prev, next_imc: sbridge_dev = get_sbridge_dev(bus, dev_descr->dom, multi_bus, sbridge_dev); if (!sbridge_dev) { + + if (dev_descr->dom == SOCK) + goto out_imc; + sbridge_dev = alloc_sbridge_dev(bus, dev_descr->dom, table); if (!sbridge_dev) { pci_dev_put(pdev); @@ -2285,6 +2289,7 @@ next_imc: if (dev_descr->dom == SOCK && i < table->n_imcs_per_sock) goto next_imc; +out_imc: /* Be sure that the device is enabled */ if (unlikely(pci_enable_device(pdev) < 0)) { sbridge_printk(KERN_ERR, -- cgit v1.2.3 From ff0abed4922ffbd40dc4e5a78b8ea56a5eb68ec7 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Wed, 7 Jun 2017 11:54:59 +1200 Subject: EDAC, altera: Simplify calculation of total memory Use of_address_to_resource() and resource_size() instead of manually parsing the "reg" property from the "memory" node(s). Signed-off-by: Chris Packham Tested-by: Thor Thayer Cc: linux-edac Link: http://lkml.kernel.org/r/20170606235500.22772-3-chris.packham@alliedtelesis.co.nz Signed-off-by: Borislav Petkov --- drivers/edac/altera_edac.c | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c index 122637530b15..db75d4b614f7 100644 --- a/drivers/edac/altera_edac.c +++ b/drivers/edac/altera_edac.c @@ -214,24 +214,16 @@ static void altr_sdr_mc_create_debugfs_nodes(struct mem_ctl_info *mci) static unsigned long get_total_mem(void) { struct device_node *np = NULL; - const unsigned int *reg, *reg_end; - int len, sw, aw; - unsigned long start, size, total_mem = 0; + struct resource res; + int ret; + unsigned long total_mem = 0; for_each_node_by_type(np, "memory") { - aw = of_n_addr_cells(np); - sw = of_n_size_cells(np); - reg = (const unsigned int *)of_get_property(np, "reg", &len); - reg_end = reg + (len / sizeof(u32)); - - total_mem = 0; - do { - start = of_read_number(reg, aw); - reg += aw; - size = of_read_number(reg, sw); - reg += sw; - total_mem += size; - } while (reg < reg_end); + ret = of_address_to_resource(np, 0, &res); + if (ret) + continue; + + total_mem += resource_size(&res); } edac_dbg(0, "total_mem 0x%lx\n", total_mem); return total_mem; -- cgit v1.2.3 From ee514c7a2379385fcec363f2f5f8db4eb56bc48c Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 22 Jun 2017 17:05:35 -0500 Subject: EDAC, pnd2: Return proper error value from apl_rd_reg() Add code comment to make it clear that the fall-through is intentional and, OR ret with its previous value to avoid overwriting it so that callers can check the correct return value. Signed-off-by: Gustavo A. R. Silva Cc: Qiuxu Zhuo Cc: Tony Luck Cc: linux-edac Link: http://lkml.kernel.org/r/20170622220535.GA4896@embeddedgus [ Massage a bit. ] Signed-off-by: Borislav Petkov --- drivers/edac/pnd2_edac.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/edac/pnd2_edac.c b/drivers/edac/pnd2_edac.c index 1cad5a9af8d0..e1748d7e5190 100644 --- a/drivers/edac/pnd2_edac.c +++ b/drivers/edac/pnd2_edac.c @@ -168,14 +168,15 @@ int sbi_send(int port, int off, int op, u32 *data) static int apl_rd_reg(int port, int off, int op, void *data, size_t sz, char *name) { - int ret = 0; + int ret = 0; edac_dbg(2, "Read %s port=%x off=%x op=%x\n", name, port, off, op); switch (sz) { case 8: ret = sbi_send(port, off + 4, op, (u32 *)(data + 4)); + /* fall through */ case 4: - ret = sbi_send(port, off, op, (u32 *)data); + ret |= sbi_send(port, off, op, (u32 *)data); pnd2_printk(KERN_DEBUG, "%s=%x%08x ret=%d\n", name, sz == 8 ? *((u32 *)(data + 4)) : 0, *((u32 *)data), ret); break; -- cgit v1.2.3 From 77641dacead2cbfe22d10f4e7c07867d86900057 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 23 Jun 2017 09:48:55 +0100 Subject: EDAC, pnd2: Make function sbi_send() static The function sbi_send() is local to just pnd2_edac.c and does not need to be in global scope, so make it static. Signed-off-by: Colin Ian King Cc: Tony Luck Cc: linux-edac Link: http://lkml.kernel.org/r/20170623084855.9197-1-colin.king@canonical.com Signed-off-by: Borislav Petkov --- drivers/edac/pnd2_edac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/edac/pnd2_edac.c b/drivers/edac/pnd2_edac.c index e1748d7e5190..407f239553f4 100644 --- a/drivers/edac/pnd2_edac.c +++ b/drivers/edac/pnd2_edac.c @@ -131,7 +131,7 @@ static struct mem_ctl_info *pnd2_mci; #ifdef CONFIG_X86_INTEL_SBI_APL #include "linux/platform_data/sbi_apl.h" -int sbi_send(int port, int off, int op, u32 *data) +static int sbi_send(int port, int off, int op, u32 *data) { struct sbi_apl_message sbi_arg; int ret, read = 0; @@ -160,7 +160,7 @@ int sbi_send(int port, int off, int op, u32 *data) return ret; } #else -int sbi_send(int port, int off, int op, u32 *data) +static int sbi_send(int port, int off, int op, u32 *data) { return -EUNATCH; } -- cgit v1.2.3 From a8c8261425649da58bdf08221570e5335ad33a31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Lefaure?= Date: Wed, 28 Jun 2017 20:57:29 -0400 Subject: EDAC, i5000, i5400: Fix definition of NRECMEMB register MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the i5000 and i5400 drivers, the NRECMEMB register is defined as a 16-bit value, which results in wrong shifts in the code, as reported by sparse. In the datasheets ([1], section 3.9.22.20 and [2], section 3.9.22.21), this register is a 32-bit register. A u32 value for the register fixes the wrong shifts warnings and matches the datasheet. Also fix the mask to access to the CAS bits [27:16] in the i5000 driver. [1]: https://www.intel.com/content/dam/doc/datasheet/5000p-5000v-5000z-chipset-memory-controller-hub-datasheet.pdf [2]: https://www.intel.se/content/dam/doc/datasheet/5400-chipset-memory-controller-hub-datasheet.pdf Signed-off-by: Jérémy Lefaure Cc: linux-edac Link: http://lkml.kernel.org/r/20170629005729.8478-1-jeremy.lefaure@lse.epita.fr Signed-off-by: Borislav Petkov --- drivers/edac/i5000_edac.c | 6 +++--- drivers/edac/i5400_edac.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c index f683919981b0..8f5a56e25bd2 100644 --- a/drivers/edac/i5000_edac.c +++ b/drivers/edac/i5000_edac.c @@ -227,7 +227,7 @@ #define NREC_RDWR(x) (((x)>>11) & 1) #define NREC_RANK(x) (((x)>>8) & 0x7) #define NRECMEMB 0xC0 -#define NREC_CAS(x) (((x)>>16) & 0xFFFFFF) +#define NREC_CAS(x) (((x)>>16) & 0xFFF) #define NREC_RAS(x) ((x) & 0x7FFF) #define NRECFGLOG 0xC4 #define NREEECFBDA 0xC8 @@ -371,7 +371,7 @@ struct i5000_error_info { /* These registers are input ONLY if there was a * Non-Recoverable Error */ u16 nrecmema; /* Non-Recoverable Mem log A */ - u16 nrecmemb; /* Non-Recoverable Mem log B */ + u32 nrecmemb; /* Non-Recoverable Mem log B */ }; @@ -407,7 +407,7 @@ static void i5000_get_error_info(struct mem_ctl_info *mci, NERR_FAT_FBD, &info->nerr_fat_fbd); pci_read_config_word(pvt->branchmap_werrors, NRECMEMA, &info->nrecmema); - pci_read_config_word(pvt->branchmap_werrors, + pci_read_config_dword(pvt->branchmap_werrors, NRECMEMB, &info->nrecmemb); /* Clear the error bits, by writing them back */ diff --git a/drivers/edac/i5400_edac.c b/drivers/edac/i5400_edac.c index 37a9ba71da44..cd889edc8516 100644 --- a/drivers/edac/i5400_edac.c +++ b/drivers/edac/i5400_edac.c @@ -368,7 +368,7 @@ struct i5400_error_info { /* These registers are input ONLY if there was a Non-Rec Error */ u16 nrecmema; /* Non-Recoverable Mem log A */ - u16 nrecmemb; /* Non-Recoverable Mem log B */ + u32 nrecmemb; /* Non-Recoverable Mem log B */ }; @@ -458,7 +458,7 @@ static void i5400_get_error_info(struct mem_ctl_info *mci, NERR_FAT_FBD, &info->nerr_fat_fbd); pci_read_config_word(pvt->branchmap_werrors, NRECMEMA, &info->nrecmema); - pci_read_config_word(pvt->branchmap_werrors, + pci_read_config_dword(pvt->branchmap_werrors, NRECMEMB, &info->nrecmemb); /* Clear the error bits, by writing them back */ -- cgit v1.2.3 From 164c29244d4beb9a105102c42821f4925e4a0c7a Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Wed, 28 Jun 2017 16:44:07 -0700 Subject: EDAC, pnd2: Fix Apollo Lake DIMM detection Non-existent or empty DIMM slots result in error return from RD_REGP(). But we shouldn't give up on failure. So long as we find at least one DIMM we can continue. Signed-off-by: Tony Luck Cc: Qiuxu Zhuo Cc: linux-edac Link: http://lkml.kernel.org/r/20170628234407.21521-1-tony.luck@intel.com Signed-off-by: Borislav Petkov --- drivers/edac/pnd2_edac.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/edac/pnd2_edac.c b/drivers/edac/pnd2_edac.c index 407f239553f4..8e599490f6de 100644 --- a/drivers/edac/pnd2_edac.c +++ b/drivers/edac/pnd2_edac.c @@ -424,16 +424,21 @@ static void dnv_mk_region(char *name, struct region *rp, void *asym) static int apl_get_registers(void) { + int ret = -ENODEV; int i; if (RD_REG(&asym_2way, b_cr_asym_2way_mem_region_mchbar)) return -ENODEV; + /* + * RD_REGP() will fail for unpopulated or non-existent + * DIMM slots. Return success if we find at least one DIMM. + */ for (i = 0; i < APL_NUM_CHANNELS; i++) - if (RD_REGP(&drp0[i], d_cr_drp0, apl_dports[i])) - return -ENODEV; + if (!RD_REGP(&drp0[i], d_cr_drp0, apl_dports[i])) + ret = 0; - return 0; + return ret; } static int dnv_get_registers(void) -- cgit v1.2.3