[PATCH] EDAC,amd64: Fix reporting of Chip Select sizes on Fam17h

From: Yazen Ghannam
Date: Thu Apr 27 2017 - 13:13:29 EST


From: Yazen Ghannam <yazen.ghannam@xxxxxxx>

The wrong value is being passed to our function to compute CS sizes which
results in the wrong size being computed.

Redo the printing function so that the correct values are computed and
printed.

Also, redo how we calculate the number of pages in a CS row.

Tested on AMD Fam15h and Fam17h systems.

Reported-by: Benjamin Bennett <benbennett@xxxxxxxxx>
Signed-off-by: Yazen Ghannam <yazen.ghannam@xxxxxxx>
Cc: <stable@xxxxxxxxxxxxxxx> # 4.10.x
---
drivers/edac/amd64_edac.c | 31 ++++++++++++++++++-------------
1 file changed, 18 insertions(+), 13 deletions(-)

diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index 82dab16..e325a59b 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -782,24 +782,26 @@ static void debug_dump_dramcfg_low(struct amd64_pvt *pvt, u32 dclr, int chan)

static void debug_display_dimm_sizes_df(struct amd64_pvt *pvt, u8 ctrl)
{
- u32 *dcsb = ctrl ? pvt->csels[1].csbases : pvt->csels[0].csbases;
- int dimm, size0, size1;
+ int dimm, size0, size1, cs0, cs1;

edac_printk(KERN_DEBUG, EDAC_MC, "UMC%d chip selects:\n", ctrl);

for (dimm = 0; dimm < 4; dimm++) {
size0 = 0;
+ cs0 = dimm * 2;

- if (dcsb[dimm*2] & DCSB_CS_ENABLE)
- size0 = pvt->ops->dbam_to_cs(pvt, ctrl, 0, dimm);
+ if (csrow_enabled(cs0, ctrl, pvt))
+ size0 = pvt->ops->dbam_to_cs(pvt, ctrl, 0, cs0);

size1 = 0;
- if (dcsb[dimm*2 + 1] & DCSB_CS_ENABLE)
- size1 = pvt->ops->dbam_to_cs(pvt, ctrl, 0, dimm);
+ cs1 = dimm * 2 + 1;
+
+ if (csrow_enabled(cs1, ctrl, pvt))
+ size1 = pvt->ops->dbam_to_cs(pvt, ctrl, 0, cs1);

amd64_info(EDAC_MC ": %d: %5dMB %d: %5dMB\n",
- dimm * 2, size0,
- dimm * 2 + 1, size1);
+ cs0, size0,
+ cs1, size1);
}
}

@@ -2756,11 +2758,11 @@ static void read_mc_regs(struct amd64_pvt *pvt)
* encompasses
*
*/
-static u32 get_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr)
+static u32 get_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr_orig)
{
u32 cs_mode, nr_pages;
u32 dbam = dct ? pvt->dbam1 : pvt->dbam0;
-
+ int csrow_nr = csrow_nr_orig;

/*
* The math on this doesn't look right on the surface because x/2*4 can
@@ -2769,13 +2771,16 @@ static u32 get_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr)
* number of bits to shift the DBAM register to extract the proper CSROW
* field.
*/
- cs_mode = DBAM_DIMM(csrow_nr / 2, dbam);
+ if (!pvt->umc)
+ csrow_nr >>= 1;
+
+ cs_mode = DBAM_DIMM(csrow_nr, dbam);

- nr_pages = pvt->ops->dbam_to_cs(pvt, dct, cs_mode, (csrow_nr / 2))
+ nr_pages = pvt->ops->dbam_to_cs(pvt, dct, cs_mode, csrow_nr)
<< (20 - PAGE_SHIFT);

edac_dbg(0, "csrow: %d, channel: %d, DBAM idx: %d\n",
- csrow_nr, dct, cs_mode);
+ csrow_nr_orig, dct, cs_mode);
edac_dbg(0, "nr_pages/channel: %u\n", nr_pages);

return nr_pages;
--
2.7.4