Skip to content

Commit 35e6dbf

Browse files
shubhraamdbp3tk0v
authored andcommitted
EDAC/synopsys: Fix error injection on Zynq UltraScale+
The Zynq UltraScale+ MPSoC DDR has a disjoint memory from 2GB to 32GB. The DDR host interface has a contiguous memory so while injecting errors, the driver should remove the hole else the injection fails as the address translation is incorrect. Introduce a get_mem_info() function pointer and set it for Zynq UltraScale+ platform to return host address. Fixes: 1a81361 ("EDAC, synopsys: Add Error Injection support for ZynqMP DDR controller") Signed-off-by: Shubhrajyoti Datta <[email protected]> Signed-off-by: Borislav Petkov (AMD) <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 8400291 commit 35e6dbf

File tree

1 file changed

+34
-1
lines changed

1 file changed

+34
-1
lines changed

drivers/edac/synopsys_edac.c

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <linux/module.h>
1111
#include <linux/platform_device.h>
1212
#include <linux/spinlock.h>
13+
#include <linux/sizes.h>
1314
#include <linux/interrupt.h>
1415
#include <linux/of.h>
1516

@@ -337,13 +338,17 @@ struct synps_edac_priv {
337338
* @get_mtype: Get mtype.
338339
* @get_dtype: Get dtype.
339340
* @get_ecc_state: Get ECC state.
341+
* @get_mem_info: Get EDAC memory info
340342
* @quirks: To differentiate IPs.
341343
*/
342344
struct synps_platform_data {
343345
int (*get_error_info)(struct synps_edac_priv *priv);
344346
enum mem_type (*get_mtype)(const void __iomem *base);
345347
enum dev_type (*get_dtype)(const void __iomem *base);
346348
bool (*get_ecc_state)(void __iomem *base);
349+
#ifdef CONFIG_EDAC_DEBUG
350+
u64 (*get_mem_info)(struct synps_edac_priv *priv);
351+
#endif
347352
int quirks;
348353
};
349354

@@ -402,6 +407,25 @@ static int zynq_get_error_info(struct synps_edac_priv *priv)
402407
return 0;
403408
}
404409

410+
#ifdef CONFIG_EDAC_DEBUG
411+
/**
412+
* zynqmp_get_mem_info - Get the current memory info.
413+
* @priv: DDR memory controller private instance data.
414+
*
415+
* Return: host interface address.
416+
*/
417+
static u64 zynqmp_get_mem_info(struct synps_edac_priv *priv)
418+
{
419+
u64 hif_addr = 0, linear_addr;
420+
421+
linear_addr = priv->poison_addr;
422+
if (linear_addr >= SZ_32G)
423+
linear_addr = linear_addr - SZ_32G + SZ_2G;
424+
hif_addr = linear_addr >> 3;
425+
return hif_addr;
426+
}
427+
#endif
428+
405429
/**
406430
* zynqmp_get_error_info - Get the current ECC error info.
407431
* @priv: DDR memory controller private instance data.
@@ -922,6 +946,9 @@ static const struct synps_platform_data zynqmp_edac_def = {
922946
.get_mtype = zynqmp_get_mtype,
923947
.get_dtype = zynqmp_get_dtype,
924948
.get_ecc_state = zynqmp_get_ecc_state,
949+
#ifdef CONFIG_EDAC_DEBUG
950+
.get_mem_info = zynqmp_get_mem_info,
951+
#endif
925952
.quirks = (DDR_ECC_INTR_SUPPORT
926953
#ifdef CONFIG_EDAC_DEBUG
927954
| DDR_ECC_DATA_POISON_SUPPORT
@@ -975,10 +1002,16 @@ MODULE_DEVICE_TABLE(of, synps_edac_match);
9751002
static void ddr_poison_setup(struct synps_edac_priv *priv)
9761003
{
9771004
int col = 0, row = 0, bank = 0, bankgrp = 0, rank = 0, regval;
1005+
const struct synps_platform_data *p_data;
9781006
int index;
9791007
ulong hif_addr = 0;
9801008

981-
hif_addr = priv->poison_addr >> 3;
1009+
p_data = priv->p_data;
1010+
1011+
if (p_data->get_mem_info)
1012+
hif_addr = p_data->get_mem_info(priv);
1013+
else
1014+
hif_addr = priv->poison_addr >> 3;
9821015

9831016
for (index = 0; index < DDR_MAX_ROW_SHIFT; index++) {
9841017
if (priv->row_shift[index])

0 commit comments

Comments
 (0)