aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAristeu Rozanski <aris@redhat.com>2015-06-12 15:08:17 -0400
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>2015-09-08 19:33:48 -0400
commit12f0721c5a70408e86257c5c99605cf743cd44c6 (patch)
tree4b6e40b65b4814051df9df3817dceb2e03f599ca
parent7179385afef252cd3f52c0a06cc0c405ae6d66bc (diff)
sb_edac: correctly fetch DIMM width on Ivy Bridge and Haswell
dimm_dev_type has been incorrectly determined in sb_edac. This patch fixes it for Ivy Bridge and Haswell only since nothing like exists for Sandy Bridge. We tested this patch in multiple systems matching the results with the installed memory modules. Acked-by: Tony Luck <tony.luck@intel.com> Signed-off-by: Aristeu Rozanski <aris@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
-rw-r--r--drivers/edac/sb_edac.c60
1 files changed, 49 insertions, 11 deletions
diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c
index 84b740d64b50..cf1268ddef0c 100644
--- a/drivers/edac/sb_edac.c
+++ b/drivers/edac/sb_edac.c
@@ -280,6 +280,7 @@ struct sbridge_info {
280 u8 max_interleave; 280 u8 max_interleave;
281 u8 (*get_node_id)(struct sbridge_pvt *pvt); 281 u8 (*get_node_id)(struct sbridge_pvt *pvt);
282 enum mem_type (*get_memory_type)(struct sbridge_pvt *pvt); 282 enum mem_type (*get_memory_type)(struct sbridge_pvt *pvt);
283 enum dev_type (*get_width)(struct sbridge_pvt *pvt, u32 mtr);
283 struct pci_dev *pci_vtd; 284 struct pci_dev *pci_vtd;
284}; 285};
285 286
@@ -768,6 +769,49 @@ out:
768 return mtype; 769 return mtype;
769} 770}
770 771
772static enum dev_type sbridge_get_width(struct sbridge_pvt *pvt, u32 mtr)
773{
774 /* there's no way to figure out */
775 return DEV_UNKNOWN;
776}
777
778static enum dev_type __ibridge_get_width(u32 mtr)
779{
780 enum dev_type type;
781
782 switch (mtr) {
783 case 3:
784 type = DEV_UNKNOWN;
785 break;
786 case 2:
787 type = DEV_X16;
788 break;
789 case 1:
790 type = DEV_X8;
791 break;
792 case 0:
793 type = DEV_X4;
794 break;
795 }
796
797 return type;
798}
799
800static enum dev_type ibridge_get_width(struct sbridge_pvt *pvt, u32 mtr)
801{
802 /*
803 * ddr3_width on the documentation but also valid for DDR4 on
804 * Haswell
805 */
806 return __ibridge_get_width(GET_BITFIELD(mtr, 7, 8));
807}
808
809static enum dev_type broadwell_get_width(struct sbridge_pvt *pvt, u32 mtr)
810{
811 /* ddr3_width on the documentation but also valid for DDR4 */
812 return __ibridge_get_width(GET_BITFIELD(mtr, 8, 9));
813}
814
771static u8 get_node_id(struct sbridge_pvt *pvt) 815static u8 get_node_id(struct sbridge_pvt *pvt)
772{ 816{
773 u32 reg; 817 u32 reg;
@@ -972,17 +1016,7 @@ static int get_dimm_config(struct mem_ctl_info *mci)
972 1016
973 dimm->nr_pages = npages; 1017 dimm->nr_pages = npages;
974 dimm->grain = 32; 1018 dimm->grain = 32;
975 switch (banks) { 1019 dimm->dtype = pvt->info.get_width(pvt, mtr);
976 case 16:
977 dimm->dtype = DEV_X16;
978 break;
979 case 8:
980 dimm->dtype = DEV_X8;
981 break;
982 case 4:
983 dimm->dtype = DEV_X4;
984 break;
985 }
986 dimm->mtype = mtype; 1020 dimm->mtype = mtype;
987 dimm->edac_mode = mode; 1021 dimm->edac_mode = mode;
988 snprintf(dimm->label, sizeof(dimm->label), 1022 snprintf(dimm->label, sizeof(dimm->label),
@@ -2371,6 +2405,7 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
2371 pvt->info.interleave_list = ibridge_interleave_list; 2405 pvt->info.interleave_list = ibridge_interleave_list;
2372 pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list); 2406 pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list);
2373 pvt->info.interleave_pkg = ibridge_interleave_pkg; 2407 pvt->info.interleave_pkg = ibridge_interleave_pkg;
2408 pvt->info.get_width = ibridge_get_width;
2374 mci->ctl_name = kasprintf(GFP_KERNEL, "Ivy Bridge Socket#%d", mci->mc_idx); 2409 mci->ctl_name = kasprintf(GFP_KERNEL, "Ivy Bridge Socket#%d", mci->mc_idx);
2375 2410
2376 /* Store pci devices at mci for faster access */ 2411 /* Store pci devices at mci for faster access */
@@ -2390,6 +2425,7 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
2390 pvt->info.interleave_list = sbridge_interleave_list; 2425 pvt->info.interleave_list = sbridge_interleave_list;
2391 pvt->info.max_interleave = ARRAY_SIZE(sbridge_interleave_list); 2426 pvt->info.max_interleave = ARRAY_SIZE(sbridge_interleave_list);
2392 pvt->info.interleave_pkg = sbridge_interleave_pkg; 2427 pvt->info.interleave_pkg = sbridge_interleave_pkg;
2428 pvt->info.get_width = sbridge_get_width;
2393 mci->ctl_name = kasprintf(GFP_KERNEL, "Sandy Bridge Socket#%d", mci->mc_idx); 2429 mci->ctl_name = kasprintf(GFP_KERNEL, "Sandy Bridge Socket#%d", mci->mc_idx);
2394 2430
2395 /* Store pci devices at mci for faster access */ 2431 /* Store pci devices at mci for faster access */
@@ -2409,6 +2445,7 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
2409 pvt->info.interleave_list = ibridge_interleave_list; 2445 pvt->info.interleave_list = ibridge_interleave_list;
2410 pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list); 2446 pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list);
2411 pvt->info.interleave_pkg = ibridge_interleave_pkg; 2447 pvt->info.interleave_pkg = ibridge_interleave_pkg;
2448 pvt->info.get_width = ibridge_get_width;
2412 mci->ctl_name = kasprintf(GFP_KERNEL, "Haswell Socket#%d", mci->mc_idx); 2449 mci->ctl_name = kasprintf(GFP_KERNEL, "Haswell Socket#%d", mci->mc_idx);
2413 2450
2414 /* Store pci devices at mci for faster access */ 2451 /* Store pci devices at mci for faster access */
@@ -2428,6 +2465,7 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
2428 pvt->info.interleave_list = ibridge_interleave_list; 2465 pvt->info.interleave_list = ibridge_interleave_list;
2429 pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list); 2466 pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list);
2430 pvt->info.interleave_pkg = ibridge_interleave_pkg; 2467 pvt->info.interleave_pkg = ibridge_interleave_pkg;
2468 pvt->info.get_width = broadwell_get_width;
2431 mci->ctl_name = kasprintf(GFP_KERNEL, "Broadwell Socket#%d", mci->mc_idx); 2469 mci->ctl_name = kasprintf(GFP_KERNEL, "Broadwell Socket#%d", mci->mc_idx);
2432 2470
2433 /* Store pci devices at mci for faster access */ 2471 /* Store pci devices at mci for faster access */