Commit fe354159 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
Loading
Loading
Loading
Loading
+4 −8
Original line number Diff line number Diff line
@@ -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,
+21 −1
Original line number Diff line number Diff line
@@ -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);
+18 −24
Original line number Diff line number Diff line
@@ -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",
			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);
}
+4 −4
Original line number Diff line number Diff line
@@ -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,
+1 −1
Original line number Diff line number Diff line
@@ -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);
	rc = ((reg << 6) | rc) << 26;

	return rc | 0x1ffffff;
	return rc | 0x3ffffff;
}

static u64 knl_get_tolm(struct sbridge_pvt *pvt)
Loading