Skip to content

Commit 3b1890e

Browse files
committed
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
2 parents cc69ac7 + a3f3040 commit 3b1890e

File tree

1 file changed

+36
-21
lines changed

1 file changed

+36
-21
lines changed

drivers/edac/amd64_edac.c

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,7 +1209,9 @@ static int umc_get_cs_mode(int dimm, u8 ctrl, struct amd64_pvt *pvt)
12091209
if (csrow_enabled(2 * dimm + 1, ctrl, pvt))
12101210
cs_mode |= CS_ODD_PRIMARY;
12111211

1212-
/* Asymmetric dual-rank DIMM support. */
1212+
if (csrow_sec_enabled(2 * dimm, ctrl, pvt))
1213+
cs_mode |= CS_EVEN_SECONDARY;
1214+
12131215
if (csrow_sec_enabled(2 * dimm + 1, ctrl, pvt))
12141216
cs_mode |= CS_ODD_SECONDARY;
12151217

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

1233-
static int __addr_mask_to_cs_size(u32 addr_mask_orig, unsigned int cs_mode,
1234-
int csrow_nr, int dimm)
1235+
static int calculate_cs_size(u32 mask, unsigned int cs_mode)
12351236
{
1236-
u32 msb, weight, num_zero_bits;
1237-
u32 addr_mask_deinterleaved;
1238-
int size = 0;
1237+
int msb, weight, num_zero_bits;
1238+
u32 deinterleaved_mask;
1239+
1240+
if (!mask)
1241+
return 0;
12391242

12401243
/*
12411244
* 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,
12481251
* without swapping with the most significant bit. This can be handled
12491252
* by keeping the MSB where it is and ignoring the single zero bit.
12501253
*/
1251-
msb = fls(addr_mask_orig) - 1;
1252-
weight = hweight_long(addr_mask_orig);
1254+
msb = fls(mask) - 1;
1255+
weight = hweight_long(mask);
12531256
num_zero_bits = msb - weight - !!(cs_mode & CS_3R_INTERLEAVE);
12541257

12551258
/* Take the number of zero bits off from the top of the mask. */
1256-
addr_mask_deinterleaved = GENMASK_ULL(msb - num_zero_bits, 1);
1259+
deinterleaved_mask = GENMASK(msb - num_zero_bits, 1);
1260+
edac_dbg(1, " Deinterleaved AddrMask: 0x%x\n", deinterleaved_mask);
1261+
1262+
return (deinterleaved_mask >> 2) + 1;
1263+
}
1264+
1265+
static int __addr_mask_to_cs_size(u32 addr_mask, u32 addr_mask_sec,
1266+
unsigned int cs_mode, int csrow_nr, int dimm)
1267+
{
1268+
int size;
12571269

12581270
edac_dbg(1, "CS%d DIMM%d AddrMasks:\n", csrow_nr, dimm);
1259-
edac_dbg(1, " Original AddrMask: 0x%x\n", addr_mask_orig);
1260-
edac_dbg(1, " Deinterleaved AddrMask: 0x%x\n", addr_mask_deinterleaved);
1271+
edac_dbg(1, " Primary AddrMask: 0x%x\n", addr_mask);
12611272

12621273
/* Register [31:1] = Address [39:9]. Size is in kBs here. */
1263-
size = (addr_mask_deinterleaved >> 2) + 1;
1274+
size = calculate_cs_size(addr_mask, cs_mode);
1275+
1276+
edac_dbg(1, " Secondary AddrMask: 0x%x\n", addr_mask_sec);
1277+
size += calculate_cs_size(addr_mask_sec, cs_mode);
12641278

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

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

1311-
/* Asymmetric dual-rank DIMM support. */
1312-
if ((csrow_nr & 1) && (cs_mode & CS_ODD_SECONDARY))
1313-
addr_mask_orig = pvt->csels[umc].csmasks_sec[cs_mask_nr];
1314-
else
1315-
addr_mask_orig = pvt->csels[umc].csmasks[cs_mask_nr];
1325+
if (cs_mode & (CS_EVEN_PRIMARY | CS_ODD_PRIMARY))
1326+
addr_mask = pvt->csels[umc].csmasks[cs_mask_nr];
1327+
1328+
if (cs_mode & (CS_EVEN_SECONDARY | CS_ODD_SECONDARY))
1329+
addr_mask_sec = pvt->csels[umc].csmasks_sec[cs_mask_nr];
13161330

1317-
return __addr_mask_to_cs_size(addr_mask_orig, cs_mode, csrow_nr, dimm);
1331+
return __addr_mask_to_cs_size(addr_mask, addr_mask_sec, cs_mode, csrow_nr, dimm);
13181332
}
13191333

13201334
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)
35123526
static int gpu_addr_mask_to_cs_size(struct amd64_pvt *pvt, u8 umc,
35133527
unsigned int cs_mode, int csrow_nr)
35143528
{
3515-
u32 addr_mask_orig = pvt->csels[umc].csmasks[csrow_nr];
3529+
u32 addr_mask = pvt->csels[umc].csmasks[csrow_nr];
3530+
u32 addr_mask_sec = pvt->csels[umc].csmasks_sec[csrow_nr];
35163531

3517-
return __addr_mask_to_cs_size(addr_mask_orig, cs_mode, csrow_nr, csrow_nr >> 1);
3532+
return __addr_mask_to_cs_size(addr_mask, addr_mask_sec, cs_mode, csrow_nr, csrow_nr >> 1);
35183533
}
35193534

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

0 commit comments

Comments
 (0)