Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit eb77e6b8 authored by Yazen Ghannam's avatar Yazen Ghannam Committed by Borislav Petkov
Browse files

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



The wrong index into the csbases/csmasks arrays was being passed to
the function to compute the chip select sizes, which resulted in the
wrong size being computed. Address that so that the correct values are
computed and printed.

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

Reported-by: default avatarBenjamin Bennett <benbennett@gmail.com>
Signed-off-by: default avatarYazen Ghannam <yazen.ghannam@amd.com>
Cc: <stable@vger.kernel.org> # 4.10.x
Cc: linux-edac <linux-edac@vger.kernel.org>
Link: http://lkml.kernel.org/r/1493313114-11260-1-git-send-email-Yazen.Ghannam@amd.com


[ Remove unneeded integer math comment, minor cleanups. ]
Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
parent f8d5549d
Loading
Loading
Loading
Loading
+19 −21
Original line number Diff line number Diff line
@@ -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,26 +2758,22 @@ 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;
	u32 cs_mode, nr_pages;

	if (!pvt->umc)
		csrow_nr >>= 1;

	/*
	 * The math on this doesn't look right on the surface because x/2*4 can
	 * be simplified to x*2 but this expression makes use of the fact that
	 * it is integral math where 1/2=0. This intermediate value becomes the
	 * number of bits to shift the DBAM register to extract the proper CSROW
	 * field.
	 */
	cs_mode = DBAM_DIMM(csrow_nr / 2, dbam);
	cs_mode = DBAM_DIMM(csrow_nr, dbam);

	nr_pages = pvt->ops->dbam_to_cs(pvt, dct, cs_mode, (csrow_nr / 2))
							   << (20 - PAGE_SHIFT);
	nr_pages   = pvt->ops->dbam_to_cs(pvt, dct, cs_mode, csrow_nr);
	nr_pages <<= 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;