[PATCH 11/18] EDAC/synopsys: Read full data pattern on errors

From: Serge Semin
Date: Mon Aug 22 2022 - 15:16:39 EST


DW uMCTL2 DDRC calculates ECC for the DQ-bus word. If non-Full bus width
mode is activated the leftover DQ-bits will be padded with zeros, but the
ECC syndrome is calculated for the whole width anyway [1]. For some reason
the DW uMCTL2 DDRC driver currently doesn't read the whole SDRAM word in
case of the ECC errors even though the 64-bit DQ-bus has been supported
for a long time. Let's fix that by extending the data field of the ECC
error info structure and reading the upper 32-bits part of the data
pattern if an ECC error happens and the DDR controller has been configured
with the 64-bits DQ bus. As before the data will be printed as a part of
the custom error message passed to the edac_mc_handle_error() method.

[1] DesignWare® Cores Enhanced Universal DDR Memory Controller (uMCTL2)
Databook, Version 3.91a, October 2020, p.424-425

Signed-off-by: Serge Semin <Sergey.Semin@xxxxxxxxxxxxxxxxxxxx>
---
drivers/edac/synopsys_edac.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index 5a116c9ebeda..124b0167898e 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -309,7 +309,7 @@ struct snps_ecc_error_info {
u32 bank;
u32 bankgrp;
u32 bitpos;
- u32 data;
+ u64 data;
};

/**
@@ -418,6 +418,8 @@ static int snps_get_error_info(struct snps_edac_priv *priv)
p->ceinfo.col = FIELD_GET(ECC_CEADDR1_COL_MASK, regval);

p->ceinfo.data = readl(base + ECC_CSYND0_OFST);
+ if (priv->info.dq_width == SNPS_DQ_64)
+ p->ceinfo.data |= (u64)readl(base + ECC_CSYND1_OFST) << 32;

edac_dbg(2, "ECCCSYN0: 0x%08X ECCCSYN1: 0x%08X ECCCSYN2: 0x%08X\n",
readl(base + ECC_CSYND0_OFST), readl(base + ECC_CSYND1_OFST),
@@ -436,6 +438,8 @@ static int snps_get_error_info(struct snps_edac_priv *priv)
p->ueinfo.col = FIELD_GET(ECC_CEADDR1_COL_MASK, regval);

p->ueinfo.data = readl(base + ECC_UESYND0_OFST);
+ if (priv->info.dq_width == SNPS_DQ_64)
+ p->ueinfo.data |= (u64)readl(base + ECC_UESYND1_OFST) << 32;

out:
spin_lock_irqsave(&priv->lock, flags);
@@ -466,7 +470,7 @@ static void snps_handle_error(struct mem_ctl_info *mci, struct snps_ecc_status *
pinf = &p->ceinfo;

snprintf(priv->message, SNPS_EDAC_MSG_SIZE,
- "Row %d Col %d Bank %d Bank Group %d Bit %d Data 0x%08x",
+ "Row %d Col %d Bank %d Bank Group %d Bit %d Data 0x%08llx",
pinf->row, pinf->col, pinf->bank, pinf->bankgrp,
pinf->bitpos, pinf->data);

@@ -479,8 +483,9 @@ static void snps_handle_error(struct mem_ctl_info *mci, struct snps_ecc_status *
pinf = &p->ueinfo;

snprintf(priv->message, SNPS_EDAC_MSG_SIZE,
- "Row %d Col %d Bank %d Bank Group %d",
- pinf->row, pinf->col, pinf->bank, pinf->bankgrp);
+ "Row %d Col %d Bank %d Bank Group %d Data 0x%08llx",
+ pinf->row, pinf->col, pinf->bank, pinf->bankgrp,
+ pinf->data);

edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci,
p->ue_cnt, 0, 0, 0, 0, 0, -1,
--
2.35.1