- amd64_edac: Add support for three-rank interleaving mode which is
present on AMD zen2 servers - The usual fixes and cleanups all over EDAC land -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEzv7L6UO9uDPlPSfHEsHwGGHeVUoFAmF/rQAACgkQEsHwGGHe VUqTsg//QSI/akiJnnZ5Ea3CMsFAWH/LIAZzjWa3zcit6OcxrjRMsym1JGs4llUY 7Uis0lGTUH2je3kFrYdPVGXyoWPNdsQCQi/89Anabl5Jrf2u7N2MmUIKcCnzQWjS PHb4BSSWW2zR8wU8UXOo2I1QKltenKlaO97uE9Te9YZCYZ6PzS0z2qevd0SCPUtF tPQ+AqYNKE0JNNAqlPietSHs7MisyCuxTHqLiwC0QNuKJ3GhCtVhmYGKqaLOMcfr oKdBFaAZOhmtUFT0z8cLka8sKO5WDfqli9Qp6Zphv9E6iz6gJq7NCBaKRz8gOkPi boOjmSOhCi/xJq63DUtfKOogVRM+qhms1Kxni3EgJxyGR/oLwnVX4n0AopKBstb6 AsHPUB8AxrtnEtoBPFM/bO18Eto3HkCZD2yCzztOc5NmtUnVlIh2/qN4oYjBG7pc 20iXwZ49OAYVQwrLdoNvyXQ5BdKGC5tyMgvPWVyOO8Iad2YYfM5iUWDGSycEWSo3 /xZgVljbFRBwjxaTqgoUDxOlBEgQsDg4ENTathCpxuR+meac/kqGZDSLc0zc7hV1 zV2kHB7y6gWGAQiuS3Lq+j0BTNtgbUi43R61J00ecQEIOomsBaWLi6uewNJmvOZ9 Ef7c0t/ree/PMTaXVer0IA8lU3vcHBMTrbNtQsPb4TCRsZOgFhI= =O0zA -----END PGP SIGNATURE----- Merge tag 'edac_updates_for_v5.16' of git://git.kernel.org/pub/scm/linux/kernel/git/ras/ras Pull EDAC updates from Borislav Petkov: "A small pile of EDAC updates which the autumn wind blew my way. :) - amd64_edac: Add support for three-rank interleaving mode which is present on AMD zen2 servers - The usual fixes and cleanups all over EDAC land" * tag 'edac_updates_for_v5.16' of git://git.kernel.org/pub/scm/linux/kernel/git/ras/ras: EDAC/sb_edac: Fix top-of-high-memory value for Broadwell/Haswell EDAC/ti: Remove redundant error messages EDAC/amd64: Handle three rank interleaving mode EDAC/mc_sysfs: Print MC-scope sysfs counters unsigned EDAC/al_mc: Make use of the helper function devm_add_action_or_reset() EDAC/mc: Replace strcpy(), sprintf() and snprintf() with strscpy() or scnprintf()
This commit is contained in:
commit
fe354159ca
@ -238,11 +238,9 @@ static int al_mc_edac_probe(struct platform_device *pdev)
|
||||
if (!mci)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = devm_add_action(&pdev->dev, devm_al_mc_edac_free, mci);
|
||||
if (ret) {
|
||||
edac_mc_free(mci);
|
||||
ret = devm_add_action_or_reset(&pdev->dev, devm_al_mc_edac_free, mci);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, mci);
|
||||
al_mc = mci->pvt_info;
|
||||
@ -293,11 +291,9 @@ static int al_mc_edac_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = devm_add_action(&pdev->dev, devm_al_mc_edac_del, &pdev->dev);
|
||||
if (ret) {
|
||||
edac_mc_del_mc(&pdev->dev);
|
||||
ret = devm_add_action_or_reset(&pdev->dev, devm_al_mc_edac_del, &pdev->dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (al_mc->irq_ue > 0) {
|
||||
ret = devm_request_irq(&pdev->dev,
|
||||
|
@ -1065,12 +1065,14 @@ static void debug_dump_dramcfg_low(struct amd64_pvt *pvt, u32 dclr, int chan)
|
||||
#define CS_ODD_PRIMARY BIT(1)
|
||||
#define CS_EVEN_SECONDARY BIT(2)
|
||||
#define CS_ODD_SECONDARY BIT(3)
|
||||
#define CS_3R_INTERLEAVE BIT(4)
|
||||
|
||||
#define CS_EVEN (CS_EVEN_PRIMARY | CS_EVEN_SECONDARY)
|
||||
#define CS_ODD (CS_ODD_PRIMARY | CS_ODD_SECONDARY)
|
||||
|
||||
static int f17_get_cs_mode(int dimm, u8 ctrl, struct amd64_pvt *pvt)
|
||||
{
|
||||
u8 base, count = 0;
|
||||
int cs_mode = 0;
|
||||
|
||||
if (csrow_enabled(2 * dimm, ctrl, pvt))
|
||||
@ -1083,6 +1085,20 @@ static int f17_get_cs_mode(int dimm, u8 ctrl, struct amd64_pvt *pvt)
|
||||
if (csrow_sec_enabled(2 * dimm + 1, ctrl, pvt))
|
||||
cs_mode |= CS_ODD_SECONDARY;
|
||||
|
||||
/*
|
||||
* 3 Rank inteleaving support.
|
||||
* There should be only three bases enabled and their two masks should
|
||||
* be equal.
|
||||
*/
|
||||
for_each_chip_select(base, ctrl, pvt)
|
||||
count += csrow_enabled(base, ctrl, pvt);
|
||||
|
||||
if (count == 3 &&
|
||||
pvt->csels[ctrl].csmasks[0] == pvt->csels[ctrl].csmasks[1]) {
|
||||
edac_dbg(1, "3R interleaving in use.\n");
|
||||
cs_mode |= CS_3R_INTERLEAVE;
|
||||
}
|
||||
|
||||
return cs_mode;
|
||||
}
|
||||
|
||||
@ -1891,10 +1907,14 @@ static int f17_addr_mask_to_cs_size(struct amd64_pvt *pvt, u8 umc,
|
||||
*
|
||||
* The MSB is the number of bits in the full mask because BIT[0] is
|
||||
* always 0.
|
||||
*
|
||||
* In the special 3 Rank interleaving case, a single bit is flipped
|
||||
* 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);
|
||||
num_zero_bits = msb - weight;
|
||||
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);
|
||||
|
@ -66,14 +66,12 @@ unsigned int edac_dimm_info_location(struct dimm_info *dimm, char *buf,
|
||||
char *p = buf;
|
||||
|
||||
for (i = 0; i < mci->n_layers; i++) {
|
||||
n = snprintf(p, len, "%s %d ",
|
||||
n = scnprintf(p, len, "%s %d ",
|
||||
edac_layer_name[mci->layers[i].type],
|
||||
dimm->location[i]);
|
||||
p += n;
|
||||
len -= n;
|
||||
count += n;
|
||||
if (!len)
|
||||
break;
|
||||
}
|
||||
|
||||
return count;
|
||||
@ -341,19 +339,16 @@ static int edac_mc_alloc_dimms(struct mem_ctl_info *mci)
|
||||
*/
|
||||
len = sizeof(dimm->label);
|
||||
p = dimm->label;
|
||||
n = snprintf(p, len, "mc#%u", mci->mc_idx);
|
||||
n = scnprintf(p, len, "mc#%u", mci->mc_idx);
|
||||
p += n;
|
||||
len -= n;
|
||||
for (layer = 0; layer < mci->n_layers; layer++) {
|
||||
n = snprintf(p, len, "%s#%u",
|
||||
edac_layer_name[mci->layers[layer].type],
|
||||
pos[layer]);
|
||||
n = scnprintf(p, len, "%s#%u",
|
||||
edac_layer_name[mci->layers[layer].type],
|
||||
pos[layer]);
|
||||
p += n;
|
||||
len -= n;
|
||||
dimm->location[layer] = pos[layer];
|
||||
|
||||
if (len <= 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Link it to the csrows old API data */
|
||||
@ -1027,12 +1022,13 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type,
|
||||
const char *other_detail)
|
||||
{
|
||||
struct dimm_info *dimm;
|
||||
char *p;
|
||||
char *p, *end;
|
||||
int row = -1, chan = -1;
|
||||
int pos[EDAC_MAX_LAYERS] = { top_layer, mid_layer, low_layer };
|
||||
int i, n_labels = 0;
|
||||
struct edac_raw_error_desc *e = &mci->error_desc;
|
||||
bool any_memory = true;
|
||||
const char *prefix;
|
||||
|
||||
edac_dbg(3, "MC%d\n", mci->mc_idx);
|
||||
|
||||
@ -1087,6 +1083,8 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type,
|
||||
*/
|
||||
p = e->label;
|
||||
*p = '\0';
|
||||
end = p + sizeof(e->label);
|
||||
prefix = "";
|
||||
|
||||
mci_for_each_dimm(mci, dimm) {
|
||||
if (top_layer >= 0 && top_layer != dimm->location[0])
|
||||
@ -1114,12 +1112,8 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type,
|
||||
p = e->label;
|
||||
*p = '\0';
|
||||
} else {
|
||||
if (p != e->label) {
|
||||
strcpy(p, OTHER_LABEL);
|
||||
p += strlen(OTHER_LABEL);
|
||||
}
|
||||
strcpy(p, dimm->label);
|
||||
p += strlen(p);
|
||||
p += scnprintf(p, end - p, "%s%s", prefix, dimm->label);
|
||||
prefix = OTHER_LABEL;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1141,25 +1135,25 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type,
|
||||
}
|
||||
|
||||
if (any_memory)
|
||||
strcpy(e->label, "any memory");
|
||||
strscpy(e->label, "any memory", sizeof(e->label));
|
||||
else if (!*e->label)
|
||||
strcpy(e->label, "unknown memory");
|
||||
strscpy(e->label, "unknown memory", sizeof(e->label));
|
||||
|
||||
edac_inc_csrow(e, row, chan);
|
||||
|
||||
/* Fill the RAM location data */
|
||||
p = e->location;
|
||||
end = p + sizeof(e->location);
|
||||
prefix = "";
|
||||
|
||||
for (i = 0; i < mci->n_layers; i++) {
|
||||
if (pos[i] < 0)
|
||||
continue;
|
||||
|
||||
p += sprintf(p, "%s:%d ",
|
||||
edac_layer_name[mci->layers[i].type],
|
||||
pos[i]);
|
||||
p += scnprintf(p, end - p, "%s%s:%d", prefix,
|
||||
edac_layer_name[mci->layers[i].type], pos[i]);
|
||||
prefix = " ";
|
||||
}
|
||||
if (p > e->location)
|
||||
*(p - 1) = '\0';
|
||||
|
||||
edac_raw_mc_handle_error(e);
|
||||
}
|
||||
|
@ -744,7 +744,7 @@ static ssize_t mci_ue_count_show(struct device *dev,
|
||||
{
|
||||
struct mem_ctl_info *mci = to_mci(dev);
|
||||
|
||||
return sprintf(data, "%d\n", mci->ue_mc);
|
||||
return sprintf(data, "%u\n", mci->ue_mc);
|
||||
}
|
||||
|
||||
static ssize_t mci_ce_count_show(struct device *dev,
|
||||
@ -753,7 +753,7 @@ static ssize_t mci_ce_count_show(struct device *dev,
|
||||
{
|
||||
struct mem_ctl_info *mci = to_mci(dev);
|
||||
|
||||
return sprintf(data, "%d\n", mci->ce_mc);
|
||||
return sprintf(data, "%u\n", mci->ce_mc);
|
||||
}
|
||||
|
||||
static ssize_t mci_ce_noinfo_show(struct device *dev,
|
||||
@ -762,7 +762,7 @@ static ssize_t mci_ce_noinfo_show(struct device *dev,
|
||||
{
|
||||
struct mem_ctl_info *mci = to_mci(dev);
|
||||
|
||||
return sprintf(data, "%d\n", mci->ce_noinfo_count);
|
||||
return sprintf(data, "%u\n", mci->ce_noinfo_count);
|
||||
}
|
||||
|
||||
static ssize_t mci_ue_noinfo_show(struct device *dev,
|
||||
@ -771,7 +771,7 @@ static ssize_t mci_ue_noinfo_show(struct device *dev,
|
||||
{
|
||||
struct mem_ctl_info *mci = to_mci(dev);
|
||||
|
||||
return sprintf(data, "%d\n", mci->ue_noinfo_count);
|
||||
return sprintf(data, "%u\n", mci->ue_noinfo_count);
|
||||
}
|
||||
|
||||
static ssize_t mci_seconds_show(struct device *dev,
|
||||
|
@ -1052,7 +1052,7 @@ static u64 haswell_get_tohm(struct sbridge_pvt *pvt)
|
||||
pci_read_config_dword(pvt->info.pci_vtd, HASWELL_TOHM_1, ®);
|
||||
rc = ((reg << 6) | rc) << 26;
|
||||
|
||||
return rc | 0x1ffffff;
|
||||
return rc | 0x3ffffff;
|
||||
}
|
||||
|
||||
static u64 knl_get_tolm(struct sbridge_pvt *pvt)
|
||||
|
@ -245,11 +245,8 @@ static int ti_edac_probe(struct platform_device *pdev)
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
reg = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(reg)) {
|
||||
edac_printk(KERN_ERR, EDAC_MOD_NAME,
|
||||
"EMIF controller regs not defined\n");
|
||||
if (IS_ERR(reg))
|
||||
return PTR_ERR(reg);
|
||||
}
|
||||
|
||||
layers[0].type = EDAC_MC_LAYER_ALL_MEM;
|
||||
layers[0].size = 1;
|
||||
@ -281,8 +278,6 @@ static int ti_edac_probe(struct platform_device *pdev)
|
||||
error_irq = platform_get_irq(pdev, 0);
|
||||
if (error_irq < 0) {
|
||||
ret = error_irq;
|
||||
edac_printk(KERN_ERR, EDAC_MOD_NAME,
|
||||
"EMIF irq number not defined.\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user