diff options
author | Shubhrajyoti Datta <shubhrajyoti.datta@amd.com> | 2024-07-11 15:36:56 +0530 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2024-10-04 16:28:49 +0200 |
commit | b3e360e00d21badf3c19da63110020cd03f60415 (patch) | |
tree | 9268c756788852c18971d1db40b54f29e71b6680 /drivers/edac | |
parent | 23752ababd7243622b4643926e85fd78d14a8392 (diff) | |
download | linux-rpi-b3e360e00d21badf3c19da63110020cd03f60415.tar.gz linux-rpi-b3e360e00d21badf3c19da63110020cd03f60415.tar.bz2 linux-rpi-b3e360e00d21badf3c19da63110020cd03f60415.zip |
EDAC/synopsys: Fix error injection on Zynq UltraScale+
[ Upstream commit 35e6dbfe1846caeafabb49b7575adb36b0aa2269 ]
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: 1a81361f75d8 ("EDAC, synopsys: Add Error Injection support for ZynqMP DDR controller")
Signed-off-by: Shubhrajyoti Datta <shubhrajyoti.datta@amd.com>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Link: https://lore.kernel.org/r/20240711100656.31376-1-shubhrajyoti.datta@amd.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'drivers/edac')
-rw-r--r-- | drivers/edac/synopsys_edac.c | 35 |
1 files changed, 34 insertions, 1 deletions
diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c index 1ab2f737e4f1..6ddc90d7ba7c 100644 --- a/drivers/edac/synopsys_edac.c +++ b/drivers/edac/synopsys_edac.c @@ -10,6 +10,7 @@ #include <linux/module.h> #include <linux/platform_device.h> #include <linux/spinlock.h> +#include <linux/sizes.h> #include <linux/interrupt.h> #include <linux/of.h> @@ -337,6 +338,7 @@ struct synps_edac_priv { * @get_mtype: Get mtype. * @get_dtype: Get dtype. * @get_ecc_state: Get ECC state. + * @get_mem_info: Get EDAC memory info * @quirks: To differentiate IPs. */ struct synps_platform_data { @@ -344,6 +346,9 @@ struct synps_platform_data { enum mem_type (*get_mtype)(const void __iomem *base); enum dev_type (*get_dtype)(const void __iomem *base); bool (*get_ecc_state)(void __iomem *base); +#ifdef CONFIG_EDAC_DEBUG + u64 (*get_mem_info)(struct synps_edac_priv *priv); +#endif int quirks; }; @@ -402,6 +407,25 @@ out: return 0; } +#ifdef CONFIG_EDAC_DEBUG +/** + * zynqmp_get_mem_info - Get the current memory info. + * @priv: DDR memory controller private instance data. + * + * Return: host interface address. + */ +static u64 zynqmp_get_mem_info(struct synps_edac_priv *priv) +{ + u64 hif_addr = 0, linear_addr; + + linear_addr = priv->poison_addr; + if (linear_addr >= SZ_32G) + linear_addr = linear_addr - SZ_32G + SZ_2G; + hif_addr = linear_addr >> 3; + return hif_addr; +} +#endif + /** * zynqmp_get_error_info - Get the current ECC error info. * @priv: DDR memory controller private instance data. @@ -922,6 +946,9 @@ static const struct synps_platform_data zynqmp_edac_def = { .get_mtype = zynqmp_get_mtype, .get_dtype = zynqmp_get_dtype, .get_ecc_state = zynqmp_get_ecc_state, +#ifdef CONFIG_EDAC_DEBUG + .get_mem_info = zynqmp_get_mem_info, +#endif .quirks = (DDR_ECC_INTR_SUPPORT #ifdef CONFIG_EDAC_DEBUG | DDR_ECC_DATA_POISON_SUPPORT @@ -975,10 +1002,16 @@ MODULE_DEVICE_TABLE(of, synps_edac_match); static void ddr_poison_setup(struct synps_edac_priv *priv) { int col = 0, row = 0, bank = 0, bankgrp = 0, rank = 0, regval; + const struct synps_platform_data *p_data; int index; ulong hif_addr = 0; - hif_addr = priv->poison_addr >> 3; + p_data = priv->p_data; + + if (p_data->get_mem_info) + hif_addr = p_data->get_mem_info(priv); + else + hif_addr = priv->poison_addr >> 3; for (index = 0; index < DDR_MAX_ROW_SHIFT; index++) { if (priv->row_shift[index]) |