Commit 3b1890e4 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'edac_urgent_for_v6.16_rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/ras/ras

Pull EDAC fix from Borislav Petkov:

 - Consider secondary address mask registers in amd64_edac in order to
   get the correct total memory size of the system

* tag 'edac_urgent_for_v6.16_rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/ras/ras:
  EDAC/amd64: Fix size calculation for Non-Power-of-Two DIMMs
parents cc69ac7a a3f30406
Loading
Loading
Loading
Loading
+36 −21
Original line number Diff line number Diff line
@@ -1209,7 +1209,9 @@ static int umc_get_cs_mode(int dimm, u8 ctrl, struct amd64_pvt *pvt)
	if (csrow_enabled(2 * dimm + 1, ctrl, pvt))
		cs_mode |= CS_ODD_PRIMARY;

	/* Asymmetric dual-rank DIMM support. */
	if (csrow_sec_enabled(2 * dimm, ctrl, pvt))
		cs_mode |= CS_EVEN_SECONDARY;

	if (csrow_sec_enabled(2 * dimm + 1, ctrl, pvt))
		cs_mode |= CS_ODD_SECONDARY;

@@ -1230,12 +1232,13 @@ static int umc_get_cs_mode(int dimm, u8 ctrl, struct amd64_pvt *pvt)
	return cs_mode;
}

static int __addr_mask_to_cs_size(u32 addr_mask_orig, unsigned int cs_mode,
				  int csrow_nr, int dimm)
static int calculate_cs_size(u32 mask, unsigned int cs_mode)
{
	u32 msb, weight, num_zero_bits;
	u32 addr_mask_deinterleaved;
	int size = 0;
	int msb, weight, num_zero_bits;
	u32 deinterleaved_mask;

	if (!mask)
		return 0;

	/*
	 * The number of zero bits in the mask is equal to the number of bits
@@ -1248,19 +1251,30 @@ static int __addr_mask_to_cs_size(u32 addr_mask_orig, unsigned int cs_mode,
	 * without swapping with the most significant bit. This can be handled
	 * by keeping the MSB where it is and ignoring the single zero bit.
	 */
	msb = fls(addr_mask_orig) - 1;
	weight = hweight_long(addr_mask_orig);
	msb = fls(mask) - 1;
	weight = hweight_long(mask);
	num_zero_bits = msb - weight - !!(cs_mode & CS_3R_INTERLEAVE);

	/* Take the number of zero bits off from the top of the mask. */
	addr_mask_deinterleaved = GENMASK_ULL(msb - num_zero_bits, 1);
	deinterleaved_mask = GENMASK(msb - num_zero_bits, 1);
	edac_dbg(1, "  Deinterleaved AddrMask: 0x%x\n", deinterleaved_mask);

	return (deinterleaved_mask >> 2) + 1;
}

static int __addr_mask_to_cs_size(u32 addr_mask, u32 addr_mask_sec,
				  unsigned int cs_mode, int csrow_nr, int dimm)
{
	int size;

	edac_dbg(1, "CS%d DIMM%d AddrMasks:\n", csrow_nr, dimm);
	edac_dbg(1, "  Original AddrMask: 0x%x\n", addr_mask_orig);
	edac_dbg(1, "  Deinterleaved AddrMask: 0x%x\n", addr_mask_deinterleaved);
	edac_dbg(1, "  Primary AddrMask: 0x%x\n", addr_mask);

	/* Register [31:1] = Address [39:9]. Size is in kBs here. */
	size = (addr_mask_deinterleaved >> 2) + 1;
	size = calculate_cs_size(addr_mask, cs_mode);

	edac_dbg(1, "  Secondary AddrMask: 0x%x\n", addr_mask_sec);
	size += calculate_cs_size(addr_mask_sec, cs_mode);

	/* Return size in MBs. */
	return size >> 10;
@@ -1269,8 +1283,8 @@ static int __addr_mask_to_cs_size(u32 addr_mask_orig, unsigned int cs_mode,
static int umc_addr_mask_to_cs_size(struct amd64_pvt *pvt, u8 umc,
				    unsigned int cs_mode, int csrow_nr)
{
	u32 addr_mask = 0, addr_mask_sec = 0;
	int cs_mask_nr = csrow_nr;
	u32 addr_mask_orig;
	int dimm, size = 0;

	/* No Chip Selects are enabled. */
@@ -1308,13 +1322,13 @@ static int umc_addr_mask_to_cs_size(struct amd64_pvt *pvt, u8 umc,
	if (!pvt->flags.zn_regs_v2)
		cs_mask_nr >>= 1;

	/* Asymmetric dual-rank DIMM support. */
	if ((csrow_nr & 1) && (cs_mode & CS_ODD_SECONDARY))
		addr_mask_orig = pvt->csels[umc].csmasks_sec[cs_mask_nr];
	else
		addr_mask_orig = pvt->csels[umc].csmasks[cs_mask_nr];
	if (cs_mode & (CS_EVEN_PRIMARY | CS_ODD_PRIMARY))
		addr_mask = pvt->csels[umc].csmasks[cs_mask_nr];

	if (cs_mode & (CS_EVEN_SECONDARY | CS_ODD_SECONDARY))
		addr_mask_sec = pvt->csels[umc].csmasks_sec[cs_mask_nr];

	return __addr_mask_to_cs_size(addr_mask_orig, cs_mode, csrow_nr, dimm);
	return __addr_mask_to_cs_size(addr_mask, addr_mask_sec, cs_mode, csrow_nr, dimm);
}

static void umc_debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl)
@@ -3512,9 +3526,10 @@ static void gpu_get_err_info(struct mce *m, struct err_info *err)
static int gpu_addr_mask_to_cs_size(struct amd64_pvt *pvt, u8 umc,
				    unsigned int cs_mode, int csrow_nr)
{
	u32 addr_mask_orig = pvt->csels[umc].csmasks[csrow_nr];
	u32 addr_mask		= pvt->csels[umc].csmasks[csrow_nr];
	u32 addr_mask_sec	= pvt->csels[umc].csmasks_sec[csrow_nr];

	return __addr_mask_to_cs_size(addr_mask_orig, cs_mode, csrow_nr, csrow_nr >> 1);
	return __addr_mask_to_cs_size(addr_mask, addr_mask_sec, cs_mode, csrow_nr, csrow_nr >> 1);
}

static void gpu_debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl)