Commit 87751e71 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'edac_urgent_for_v6.18_rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/ras/ras

Pull EDAC fixes from Borislav Petkov:

 - In Versalnet, handle the reporting of non-standard hw errors whose
   information can come in more than one remote processor message.

 - Explicitly reenable ECC checking after a warm reset in Altera OCRAM
   as those registers are reset to default otherwise

 - Fix single-bit error injection in Altera EDAC to not inject errors
   directly in ECC RAM and thus lead to false double-bit errors due to
   same ECC RAM being in concurrent use

* tag 'edac_urgent_for_v6.18_rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/ras/ras:
  EDAC/altera: Use INTTEST register for Ethernet and USB SBE injection
  EDAC/altera: Handle OCRAM ECC enable after warm reset
  EDAC/versalnet: Handle split messages for non-standard errors
parents f824272b 281326be
Loading
Loading
Loading
Loading
+17 −5
Original line number Diff line number Diff line
@@ -1184,10 +1184,22 @@ altr_check_ocram_deps_init(struct altr_edac_device_dev *device)
	if (ret)
		return ret;

	/* Verify OCRAM has been initialized */
	/*
	 * Verify that OCRAM has been initialized.
	 * During a warm reset, OCRAM contents are retained, but the control
	 * and status registers are reset to their default values. Therefore,
	 * ECC must be explicitly re-enabled in the control register.
	 * Error condition: if INITCOMPLETEA is clear and ECC_EN is already set.
	 */
	if (!ecc_test_bits(ALTR_A10_ECC_INITCOMPLETEA,
			   (base + ALTR_A10_ECC_INITSTAT_OFST)))
			   (base + ALTR_A10_ECC_INITSTAT_OFST))) {
		if (!ecc_test_bits(ALTR_A10_ECC_EN,
				   (base + ALTR_A10_ECC_CTRL_OFST)))
			ecc_set_bits(ALTR_A10_ECC_EN,
				     (base + ALTR_A10_ECC_CTRL_OFST));
		else
			return -ENODEV;
	}

	/* Enable IRQ on Single Bit Error */
	writel(ALTR_A10_ECC_SERRINTEN, (base + ALTR_A10_ECC_ERRINTENS_OFST));
@@ -1357,7 +1369,7 @@ static const struct edac_device_prv_data a10_enetecc_data = {
	.ue_set_mask = ALTR_A10_ECC_TDERRA,
	.set_err_ofst = ALTR_A10_ECC_INTTEST_OFST,
	.ecc_irq_handler = altr_edac_a10_ecc_irq,
	.inject_fops = &altr_edac_a10_device_inject2_fops,
	.inject_fops = &altr_edac_a10_device_inject_fops,
};

#endif	/* CONFIG_EDAC_ALTERA_ETHERNET */
@@ -1447,7 +1459,7 @@ static const struct edac_device_prv_data a10_usbecc_data = {
	.ue_set_mask = ALTR_A10_ECC_TDERRA,
	.set_err_ofst = ALTR_A10_ECC_INTTEST_OFST,
	.ecc_irq_handler = altr_edac_a10_ecc_irq,
	.inject_fops = &altr_edac_a10_device_inject2_fops,
	.inject_fops = &altr_edac_a10_device_inject_fops,
};

#endif	/* CONFIG_EDAC_ALTERA_USB */
+13 −11
Original line number Diff line number Diff line
@@ -605,21 +605,23 @@ static int rpmsg_cb(struct rpmsg_device *rpdev, void *data,
	length = result[MSG_ERR_LENGTH];
	offset = result[MSG_ERR_OFFSET];

	if (result[TOTAL_ERR_LENGTH] > length) {
		if (!mc_priv->part_len)
			mc_priv->part_len = length;
		else
			mc_priv->part_len += length;
	/*
		 * The data can come in 2 stretches. Construct the regs from 2
		 * messages the offset indicates the offset from which the data is to
		 * be taken
	 * The data can come in two stretches. Construct the regs from two
	 * messages. The offset indicates the offset from which the data is to
	 * be taken.
	 */
	for (i = 0 ; i < length; i++) {
		k = offset + i;
		j = ERROR_DATA + i;
		mc_priv->regs[k] = result[j];
	}

	if (result[TOTAL_ERR_LENGTH] > length) {
		if (!mc_priv->part_len)
			mc_priv->part_len = length;
		else
			mc_priv->part_len += length;

		if (mc_priv->part_len < result[TOTAL_ERR_LENGTH])
			return 0;
		mc_priv->part_len = 0;
@@ -705,7 +707,7 @@ static int rpmsg_cb(struct rpmsg_device *rpdev, void *data,
	/* Convert to bytes */
	length = result[TOTAL_ERR_LENGTH] * 4;
	log_non_standard_event(sec_type, &amd_versalnet_guid, mc_priv->message,
			       sec_sev, (void *)&result[ERROR_DATA], length);
			       sec_sev, (void *)&mc_priv->regs, length);

	return 0;
}