Skip to content

Commit 828d0d8

Browse files
author
CKI KWF Bot
committed
Merge: EDAC/amd64: Fix size calculation for Non-Power-of-Two DIMMs
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/7219 JIRA: https://issues.redhat.com/browse/RHEL-101167 Fix DIMM size calculation in amd64_edac module Signed-off-by: Joel Savitz <jsavitz@redhat.com> Approved-by: Rafael Aquini <raquini@redhat.com> Approved-by: Steve Best <sbest@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Approved-by: Aristeu Rozanski <arozansk@redhat.com> Merged-by: CKI GitLab Kmaint Pipeline Bot <26919896-cki-kmaint-pipeline-bot@users.noreply.gitlab.com>
2 parents f197184 + ef66a0a commit 828d0d8

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
@@ -1212,7 +1212,9 @@ static int umc_get_cs_mode(int dimm, u8 ctrl, struct amd64_pvt *pvt)
12121212
if (csrow_enabled(2 * dimm + 1, ctrl, pvt))
12131213
cs_mode |= CS_ODD_PRIMARY;
12141214

1215-
/* Asymmetric dual-rank DIMM support. */
1215+
if (csrow_sec_enabled(2 * dimm, ctrl, pvt))
1216+
cs_mode |= CS_EVEN_SECONDARY;
1217+
12161218
if (csrow_sec_enabled(2 * dimm + 1, ctrl, pvt))
12171219
cs_mode |= CS_ODD_SECONDARY;
12181220

@@ -1233,12 +1235,13 @@ static int umc_get_cs_mode(int dimm, u8 ctrl, struct amd64_pvt *pvt)
12331235
return cs_mode;
12341236
}
12351237

1236-
static int __addr_mask_to_cs_size(u32 addr_mask_orig, unsigned int cs_mode,
1237-
int csrow_nr, int dimm)
1238+
static int calculate_cs_size(u32 mask, unsigned int cs_mode)
12381239
{
1239-
u32 msb, weight, num_zero_bits;
1240-
u32 addr_mask_deinterleaved;
1241-
int size = 0;
1240+
int msb, weight, num_zero_bits;
1241+
u32 deinterleaved_mask;
1242+
1243+
if (!mask)
1244+
return 0;
12421245

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

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

12611273
edac_dbg(1, "CS%d DIMM%d AddrMasks:\n", csrow_nr, dimm);
1262-
edac_dbg(1, " Original AddrMask: 0x%x\n", addr_mask_orig);
1263-
edac_dbg(1, " Deinterleaved AddrMask: 0x%x\n", addr_mask_deinterleaved);
1274+
edac_dbg(1, " Primary AddrMask: 0x%x\n", addr_mask);
12641275

12651276
/* Register [31:1] = Address [39:9]. Size is in kBs here. */
1266-
size = (addr_mask_deinterleaved >> 2) + 1;
1277+
size = calculate_cs_size(addr_mask, cs_mode);
1278+
1279+
edac_dbg(1, " Secondary AddrMask: 0x%x\n", addr_mask_sec);
1280+
size += calculate_cs_size(addr_mask_sec, cs_mode);
12671281

12681282
/* Return size in MBs. */
12691283
return size >> 10;
@@ -1272,8 +1286,8 @@ static int __addr_mask_to_cs_size(u32 addr_mask_orig, unsigned int cs_mode,
12721286
static int umc_addr_mask_to_cs_size(struct amd64_pvt *pvt, u8 umc,
12731287
unsigned int cs_mode, int csrow_nr)
12741288
{
1289+
u32 addr_mask = 0, addr_mask_sec = 0;
12751290
int cs_mask_nr = csrow_nr;
1276-
u32 addr_mask_orig;
12771291
int dimm, size = 0;
12781292

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

1314-
/* Asymmetric dual-rank DIMM support. */
1315-
if ((csrow_nr & 1) && (cs_mode & CS_ODD_SECONDARY))
1316-
addr_mask_orig = pvt->csels[umc].csmasks_sec[cs_mask_nr];
1317-
else
1318-
addr_mask_orig = pvt->csels[umc].csmasks[cs_mask_nr];
1328+
if (cs_mode & (CS_EVEN_PRIMARY | CS_ODD_PRIMARY))
1329+
addr_mask = pvt->csels[umc].csmasks[cs_mask_nr];
1330+
1331+
if (cs_mode & (CS_EVEN_SECONDARY | CS_ODD_SECONDARY))
1332+
addr_mask_sec = pvt->csels[umc].csmasks_sec[cs_mask_nr];
13191333

1320-
return __addr_mask_to_cs_size(addr_mask_orig, cs_mode, csrow_nr, dimm);
1334+
return __addr_mask_to_cs_size(addr_mask, addr_mask_sec, cs_mode, csrow_nr, dimm);
13211335
}
13221336

13231337
static void umc_debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl)
@@ -3519,9 +3533,10 @@ static void gpu_get_err_info(struct mce *m, struct err_info *err)
35193533
static int gpu_addr_mask_to_cs_size(struct amd64_pvt *pvt, u8 umc,
35203534
unsigned int cs_mode, int csrow_nr)
35213535
{
3522-
u32 addr_mask_orig = pvt->csels[umc].csmasks[csrow_nr];
3536+
u32 addr_mask = pvt->csels[umc].csmasks[csrow_nr];
3537+
u32 addr_mask_sec = pvt->csels[umc].csmasks_sec[csrow_nr];
35233538

3524-
return __addr_mask_to_cs_size(addr_mask_orig, cs_mode, csrow_nr, csrow_nr >> 1);
3539+
return __addr_mask_to_cs_size(addr_mask, addr_mask_sec, cs_mode, csrow_nr, csrow_nr >> 1);
35253540
}
35263541

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

0 commit comments

Comments
 (0)