Commit fe354159 authored by Linus Torvalds's avatar Linus Torvalds

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()
parents e6643593 537bddd0
...@@ -238,11 +238,9 @@ static int al_mc_edac_probe(struct platform_device *pdev) ...@@ -238,11 +238,9 @@ static int al_mc_edac_probe(struct platform_device *pdev)
if (!mci) if (!mci)
return -ENOMEM; return -ENOMEM;
ret = devm_add_action(&pdev->dev, devm_al_mc_edac_free, mci); ret = devm_add_action_or_reset(&pdev->dev, devm_al_mc_edac_free, mci);
if (ret) { if (ret)
edac_mc_free(mci);
return ret; return ret;
}
platform_set_drvdata(pdev, mci); platform_set_drvdata(pdev, mci);
al_mc = mci->pvt_info; al_mc = mci->pvt_info;
...@@ -293,11 +291,9 @@ static int al_mc_edac_probe(struct platform_device *pdev) ...@@ -293,11 +291,9 @@ static int al_mc_edac_probe(struct platform_device *pdev)
return ret; return ret;
} }
ret = devm_add_action(&pdev->dev, devm_al_mc_edac_del, &pdev->dev); ret = devm_add_action_or_reset(&pdev->dev, devm_al_mc_edac_del, &pdev->dev);
if (ret) { if (ret)
edac_mc_del_mc(&pdev->dev);
return ret; return ret;
}
if (al_mc->irq_ue > 0) { if (al_mc->irq_ue > 0) {
ret = devm_request_irq(&pdev->dev, ret = devm_request_irq(&pdev->dev,
......
...@@ -1065,12 +1065,14 @@ static void debug_dump_dramcfg_low(struct amd64_pvt *pvt, u32 dclr, int chan) ...@@ -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_ODD_PRIMARY BIT(1)
#define CS_EVEN_SECONDARY BIT(2) #define CS_EVEN_SECONDARY BIT(2)
#define CS_ODD_SECONDARY BIT(3) #define CS_ODD_SECONDARY BIT(3)
#define CS_3R_INTERLEAVE BIT(4)
#define CS_EVEN (CS_EVEN_PRIMARY | CS_EVEN_SECONDARY) #define CS_EVEN (CS_EVEN_PRIMARY | CS_EVEN_SECONDARY)
#define CS_ODD (CS_ODD_PRIMARY | CS_ODD_SECONDARY) #define CS_ODD (CS_ODD_PRIMARY | CS_ODD_SECONDARY)
static int f17_get_cs_mode(int dimm, u8 ctrl, struct amd64_pvt *pvt) static int f17_get_cs_mode(int dimm, u8 ctrl, struct amd64_pvt *pvt)
{ {
u8 base, count = 0;
int cs_mode = 0; int cs_mode = 0;
if (csrow_enabled(2 * dimm, ctrl, pvt)) 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) ...@@ -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)) if (csrow_sec_enabled(2 * dimm + 1, ctrl, pvt))
cs_mode |= CS_ODD_SECONDARY; 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; return cs_mode;
} }
...@@ -1891,10 +1907,14 @@ static int f17_addr_mask_to_cs_size(struct amd64_pvt *pvt, u8 umc, ...@@ -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 * The MSB is the number of bits in the full mask because BIT[0] is
* always 0. * 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; msb = fls(addr_mask_orig) - 1;
weight = hweight_long(addr_mask_orig); 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. */ /* Take the number of zero bits off from the top of the mask. */
addr_mask_deinterleaved = GENMASK_ULL(msb - num_zero_bits, 1); 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, ...@@ -66,14 +66,12 @@ unsigned int edac_dimm_info_location(struct dimm_info *dimm, char *buf,
char *p = buf; char *p = buf;
for (i = 0; i < mci->n_layers; i++) { 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], edac_layer_name[mci->layers[i].type],
dimm->location[i]); dimm->location[i]);
p += n; p += n;
len -= n; len -= n;
count += n; count += n;
if (!len)
break;
} }
return count; return count;
...@@ -341,19 +339,16 @@ static int edac_mc_alloc_dimms(struct mem_ctl_info *mci) ...@@ -341,19 +339,16 @@ static int edac_mc_alloc_dimms(struct mem_ctl_info *mci)
*/ */
len = sizeof(dimm->label); len = sizeof(dimm->label);
p = 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; p += n;
len -= n; len -= n;
for (layer = 0; layer < mci->n_layers; layer++) { for (layer = 0; layer < mci->n_layers; layer++) {
n = snprintf(p, len, "%s#%u", n = scnprintf(p, len, "%s#%u",
edac_layer_name[mci->layers[layer].type], edac_layer_name[mci->layers[layer].type],
pos[layer]); pos[layer]);
p += n; p += n;
len -= n; len -= n;
dimm->location[layer] = pos[layer]; dimm->location[layer] = pos[layer];
if (len <= 0)
break;
} }
/* Link it to the csrows old API data */ /* 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, ...@@ -1027,12 +1022,13 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type,
const char *other_detail) const char *other_detail)
{ {
struct dimm_info *dimm; struct dimm_info *dimm;
char *p; char *p, *end;
int row = -1, chan = -1; int row = -1, chan = -1;
int pos[EDAC_MAX_LAYERS] = { top_layer, mid_layer, low_layer }; int pos[EDAC_MAX_LAYERS] = { top_layer, mid_layer, low_layer };
int i, n_labels = 0; int i, n_labels = 0;
struct edac_raw_error_desc *e = &mci->error_desc; struct edac_raw_error_desc *e = &mci->error_desc;
bool any_memory = true; bool any_memory = true;
const char *prefix;
edac_dbg(3, "MC%d\n", mci->mc_idx); 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, ...@@ -1087,6 +1083,8 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type,
*/ */
p = e->label; p = e->label;
*p = '\0'; *p = '\0';
end = p + sizeof(e->label);
prefix = "";
mci_for_each_dimm(mci, dimm) { mci_for_each_dimm(mci, dimm) {
if (top_layer >= 0 && top_layer != dimm->location[0]) 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, ...@@ -1114,12 +1112,8 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type,
p = e->label; p = e->label;
*p = '\0'; *p = '\0';
} else { } else {
if (p != e->label) { p += scnprintf(p, end - p, "%s%s", prefix, dimm->label);
strcpy(p, OTHER_LABEL); prefix = OTHER_LABEL;
p += strlen(OTHER_LABEL);
}
strcpy(p, dimm->label);
p += strlen(p);
} }
/* /*
...@@ -1141,25 +1135,25 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type, ...@@ -1141,25 +1135,25 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type,
} }
if (any_memory) if (any_memory)
strcpy(e->label, "any memory"); strscpy(e->label, "any memory", sizeof(e->label));
else if (!*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); edac_inc_csrow(e, row, chan);
/* Fill the RAM location data */ /* Fill the RAM location data */
p = e->location; p = e->location;
end = p + sizeof(e->location);
prefix = "";
for (i = 0; i < mci->n_layers; i++) { for (i = 0; i < mci->n_layers; i++) {
if (pos[i] < 0) if (pos[i] < 0)
continue; continue;
p += sprintf(p, "%s:%d ", p += scnprintf(p, end - p, "%s%s:%d", prefix,
edac_layer_name[mci->layers[i].type], edac_layer_name[mci->layers[i].type], pos[i]);
pos[i]); prefix = " ";
} }
if (p > e->location)
*(p - 1) = '\0';
edac_raw_mc_handle_error(e); edac_raw_mc_handle_error(e);
} }
......
...@@ -744,7 +744,7 @@ static ssize_t mci_ue_count_show(struct device *dev, ...@@ -744,7 +744,7 @@ static ssize_t mci_ue_count_show(struct device *dev,
{ {
struct mem_ctl_info *mci = to_mci(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, static ssize_t mci_ce_count_show(struct device *dev,
...@@ -753,7 +753,7 @@ 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); 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, static ssize_t mci_ce_noinfo_show(struct device *dev,
...@@ -762,7 +762,7 @@ 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); 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, static ssize_t mci_ue_noinfo_show(struct device *dev,
...@@ -771,7 +771,7 @@ 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); 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, static ssize_t mci_seconds_show(struct device *dev,
......
...@@ -1052,7 +1052,7 @@ static u64 haswell_get_tohm(struct sbridge_pvt *pvt) ...@@ -1052,7 +1052,7 @@ static u64 haswell_get_tohm(struct sbridge_pvt *pvt)
pci_read_config_dword(pvt->info.pci_vtd, HASWELL_TOHM_1, &reg); pci_read_config_dword(pvt->info.pci_vtd, HASWELL_TOHM_1, &reg);
rc = ((reg << 6) | rc) << 26; rc = ((reg << 6) | rc) << 26;
return rc | 0x1ffffff; return rc | 0x3ffffff;
} }
static u64 knl_get_tolm(struct sbridge_pvt *pvt) static u64 knl_get_tolm(struct sbridge_pvt *pvt)
......
...@@ -245,11 +245,8 @@ static int ti_edac_probe(struct platform_device *pdev) ...@@ -245,11 +245,8 @@ static int ti_edac_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
reg = devm_ioremap_resource(dev, res); reg = devm_ioremap_resource(dev, res);
if (IS_ERR(reg)) { if (IS_ERR(reg))
edac_printk(KERN_ERR, EDAC_MOD_NAME,
"EMIF controller regs not defined\n");
return PTR_ERR(reg); return PTR_ERR(reg);
}
layers[0].type = EDAC_MC_LAYER_ALL_MEM; layers[0].type = EDAC_MC_LAYER_ALL_MEM;
layers[0].size = 1; layers[0].size = 1;
...@@ -281,8 +278,6 @@ static int ti_edac_probe(struct platform_device *pdev) ...@@ -281,8 +278,6 @@ static int ti_edac_probe(struct platform_device *pdev)
error_irq = platform_get_irq(pdev, 0); error_irq = platform_get_irq(pdev, 0);
if (error_irq < 0) { if (error_irq < 0) {
ret = error_irq; ret = error_irq;
edac_printk(KERN_ERR, EDAC_MOD_NAME,
"EMIF irq number not defined.\n");
goto err; goto err;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment