* [PATCH 01/10] EDAC/altera: Fix NULL of_node dereference altr_edac_device_probe()
2026-07-27 13:24 [PATCH 00/10] EDAC/altera: Address sashiko reviews part 1 Dinh Nguyen
@ 2026-07-27 13:24 ` Dinh Nguyen
2026-07-27 13:24 ` [PATCH 02/10] EDAC/altera: Fix use-after-free in error paths Dinh Nguyen
` (8 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Dinh Nguyen @ 2026-07-27 13:24 UTC (permalink / raw)
To: bp, tony.luck
Cc: dinguyen, rounakdas2025, niravkumar.l.rabara, linux-edac,
linux-kernel, stable
In altr_edac_device_probe() dereferenced pdev->dev.of_node and
of_match_node() before validating it, which could cause a NULL pointer
dereference when the device tree node is missing. Check the result for
a NULL and bail out with -ENODEV before using it.
Assisted-by: Cursor:claude-4.8-opus
Fixes: c3eea1942a16 ("EDAC, altera: Add Altera L2 cache and OCRAM support")
Closes: https://sashiko.dev/#/patchset/20260719211238.589402-1-rosenp%40gmail.com
Cc: stable@vger.kernel.org
Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
---
drivers/edac/altera_edac.c | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c
index 68846f583eeef..d6ca68d74f78a 100644
--- a/drivers/edac/altera_edac.c
+++ b/drivers/edac/altera_edac.c
@@ -710,9 +710,18 @@ static int altr_edac_device_probe(struct platform_device *pdev)
struct resource *r;
int res = 0;
struct device_node *np = pdev->dev.of_node;
- char *ecc_name = (char *)np->name;
+ const struct of_device_id *edac_dev_match;
+ char *ecc_name;
static int dev_instance;
+ if (!np) {
+ edac_printk(KERN_ERR, EDAC_DEVICE,
+ "Unable to get device tree node\n");
+ return -ENODEV;
+ }
+
+ ecc_name = (char *)np->name;
+
if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL)) {
edac_printk(KERN_ERR, EDAC_DEVICE,
"Unable to open devm\n");
@@ -757,7 +766,14 @@ static int altr_edac_device_probe(struct platform_device *pdev)
}
/* Get driver specific data for this EDAC device */
- drvdata->data = of_match_node(altr_edac_device_of_match, np)->data;
+ edac_dev_match = of_match_node(altr_edac_device_of_match, np);
+ if (!edac_dev_match) {
+ edac_printk(KERN_ERR, EDAC_DEVICE,
+ "%s: Unable to match device\n", ecc_name);
+ res = -ENODEV;
+ goto fail1;
+ }
+ drvdata->data = edac_dev_match->data;
/* Check specific dependencies for the module */
if (drvdata->data->setup) {
--
2.42.0.411.g813d9a9188
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 02/10] EDAC/altera: Fix use-after-free in error paths
2026-07-27 13:24 [PATCH 00/10] EDAC/altera: Address sashiko reviews part 1 Dinh Nguyen
2026-07-27 13:24 ` [PATCH 01/10] EDAC/altera: Fix NULL of_node dereference altr_edac_device_probe() Dinh Nguyen
@ 2026-07-27 13:24 ` Dinh Nguyen
2026-07-27 13:24 ` [PATCH 03/10] EDAC/altera: Guard against NULL match data in altr_sdram_probe() Dinh Nguyen
` (7 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Dinh Nguyen @ 2026-07-27 13:24 UTC (permalink / raw)
To: bp, tony.luck
Cc: dinguyen, rounakdas2025, niravkumar.l.rabara, linux-edac,
linux-kernel, stable
In both altr_edac_a10_device_add() and altr_portb_setup(), the error path
freed dci before releasing the devres group. Since the managed SB/DB IRQ
handlers use altdev(dci->pvt_info) as their data, an IRQ firing between
freeing dci and unregistering the IRQs could dereference freed memory.
Release the devres group first so the managed IRQs are unregistered
before dci is freed.
Assisted-by: Cursor:claude-4.8-opus
Fixes: 911049845d70 ("EDAC, altera: Add Arria10 SD-MMC EDAC support")
Fixes: 588cb03ea208 ("EDAC, altera: Add Arria10 L2 Cache ECC handling")
Closes: https://sashiko.dev/#/patchset/20260719211238.589402-1-rosenp%40gmail.com
Cc: stable@vger.kernel.org
Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
---
drivers/edac/altera_edac.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c
index d6ca68d74f78a..34b33298cf86e 100644
--- a/drivers/edac/altera_edac.c
+++ b/drivers/edac/altera_edac.c
@@ -1625,8 +1625,13 @@ static int altr_portb_setup(struct altr_edac_device_dev *device)
return 0;
err_release_group_1:
- edac_device_free_ctl_info(dci);
+ /*
+ * Release the devres group first so the managed IRQs are
+ * unregistered before dci (which contains the IRQ handler's
+ * data via dci->pvt_info) is freed, avoiding a use-after-free.
+ */
devres_release_group(device->edac->dev, altr_portb_setup);
+ edac_device_free_ctl_info(dci);
edac_printk(KERN_ERR, EDAC_DEVICE,
"%s:Error setting up EDAC device: %d\n", ecc_name, rc);
return rc;
@@ -2029,9 +2034,17 @@ static int altr_edac_a10_device_add(struct altr_arria10_edac *edac,
return 0;
err_release_group1:
+ /*
+ * Release the devres group first so the managed IRQs are
+ * unregistered before dci (which contains the IRQ handler's
+ * data via dci->pvt_info) is freed, avoiding a use-after-free.
+ */
+ devres_release_group(edac->dev, NULL);
edac_device_free_ctl_info(dci);
+ goto err_print;
err_release_group:
devres_release_group(edac->dev, NULL);
+err_print:
edac_printk(KERN_ERR, EDAC_DEVICE,
"%s:Error setting up EDAC device: %d\n", ecc_name, rc);
--
2.42.0.411.g813d9a9188
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 03/10] EDAC/altera: Guard against NULL match data in altr_sdram_probe()
2026-07-27 13:24 [PATCH 00/10] EDAC/altera: Address sashiko reviews part 1 Dinh Nguyen
2026-07-27 13:24 ` [PATCH 01/10] EDAC/altera: Fix NULL of_node dereference altr_edac_device_probe() Dinh Nguyen
2026-07-27 13:24 ` [PATCH 02/10] EDAC/altera: Fix use-after-free in error paths Dinh Nguyen
@ 2026-07-27 13:24 ` Dinh Nguyen
2026-07-27 13:24 ` [PATCH 04/10] EDAC/altera: Fix IRQ domain leak on platform_get_irq() failure Dinh Nguyen
` (6 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Dinh Nguyen @ 2026-07-27 13:24 UTC (permalink / raw)
To: bp, tony.luck
Cc: dinguyen, rounakdas2025, niravkumar.l.rabara, linux-edac,
linux-kernel, stable
sashiko reports: If a device is manually bound and lacks a valid match entry,
of_match_node() or device_get_match_data() could return NULL.
altr_sdram_probe() dereferenced the pointer returned by of_match_node()
and device_get_match_data() without checking it, which could cause a NULL
pointer dereference when no match data is found. Add a guard that logs
an error and returns -ENODEV.
Assisted-by: Cursor:claude-4.8-opus
Fixes: 143f4a5ac5af ("EDAC, altera: Refactor for Altera CycloneV SoC")
Cc: stable@vger.kernel.org
Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
---
drivers/edac/altera_edac.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c
index 34b33298cf86e..8cbf71ce5d2d8 100644
--- a/drivers/edac/altera_edac.c
+++ b/drivers/edac/altera_edac.c
@@ -300,6 +300,10 @@ static int altr_sdram_probe(struct platform_device *pdev)
/* Check specific dependencies for the module */
priv = device_get_match_data(&pdev->dev);
+ if (!priv) {
+ edac_printk(KERN_ERR, EDAC_MC, "No match data found\n");
+ return -ENODEV;
+ }
/* Validate the SDRAM controller has ECC enabled */
if (regmap_read(mc_vbase, priv->ecc_ctrl_offset, &read_reg) ||
--
2.42.0.411.g813d9a9188
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 04/10] EDAC/altera: Fix IRQ domain leak on platform_get_irq() failure
2026-07-27 13:24 [PATCH 00/10] EDAC/altera: Address sashiko reviews part 1 Dinh Nguyen
` (2 preceding siblings ...)
2026-07-27 13:24 ` [PATCH 03/10] EDAC/altera: Guard against NULL match data in altr_sdram_probe() Dinh Nguyen
@ 2026-07-27 13:24 ` Dinh Nguyen
2026-07-27 13:24 ` [PATCH 05/10] EDAC/altera: Fix code leak on dci allocation failure Dinh Nguyen
` (5 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Dinh Nguyen @ 2026-07-27 13:24 UTC (permalink / raw)
To: bp, tony.luck
Cc: dinguyen, rounakdas2025, niravkumar.l.rabara, linux-edac,
linux-kernel, stable
sashiko reports: If platform_get_irq() fails, the function returns without
freeing the previously allocated edac->domain.
altr_edac_a10_probe() created an IRQ domain via irq_domain_create_linear()
but returned without freeing it when the subsequent platform_get_irq()
calls for the SB or DB IRQ failed, leaking the domain. Call
irq_domain_remove() before returning on those error paths.
Assisted-by: Cursor:claude-4.8-opus
Fixes: 13ab8448d2c9 ("EDAC, altera: Add ECC Manager IRQ controller support")
Cc: stable@vger.kernel.org
Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
---
drivers/edac/altera_edac.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c
index 8cbf71ce5d2d8..e5d225f799f39 100644
--- a/drivers/edac/altera_edac.c
+++ b/drivers/edac/altera_edac.c
@@ -2179,8 +2179,10 @@ static int altr_edac_a10_probe(struct platform_device *pdev)
}
edac->sb_irq = platform_get_irq(pdev, 0);
- if (edac->sb_irq < 0)
+ if (edac->sb_irq < 0) {
+ irq_domain_remove(edac->domain);
return edac->sb_irq;
+ }
irq_set_chained_handler_and_data(edac->sb_irq,
altr_edac_a10_irq_handler,
@@ -2210,8 +2212,10 @@ static int altr_edac_a10_probe(struct platform_device *pdev)
}
} else {
edac->db_irq = platform_get_irq(pdev, 1);
- if (edac->db_irq < 0)
+ if (edac->db_irq < 0) {
+ irq_domain_remove(edac->domain);
return edac->db_irq;
+ }
irq_set_chained_handler_and_data(edac->db_irq,
altr_edac_a10_irq_handler, edac);
--
2.42.0.411.g813d9a9188
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 05/10] EDAC/altera: Fix code leak on dci allocation failure
2026-07-27 13:24 [PATCH 00/10] EDAC/altera: Address sashiko reviews part 1 Dinh Nguyen
` (3 preceding siblings ...)
2026-07-27 13:24 ` [PATCH 04/10] EDAC/altera: Fix IRQ domain leak on platform_get_irq() failure Dinh Nguyen
@ 2026-07-27 13:24 ` Dinh Nguyen
2026-07-27 13:24 ` [PATCH 06/10] EDAC/altera: Add suppress_bind_attrs so driver cannot get unbound Dinh Nguyen
` (4 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Dinh Nguyen @ 2026-07-27 13:24 UTC (permalink / raw)
To: bp, tony.luck
Cc: dinguyen, rounakdas2025, niravkumar.l.rabara, linux-edac,
linux-kernel, stable
sashiko reports: If devres_open_group() fails, the function returns -ENOMEM
without freeing the dci structure allocated earlier with edac_device_alloc_ctl_info().
Free the dci structure if devres_open_group() fails.
Fixes: c3eea1942a16 ("EDAC, altera: Add Altera L2 cache and OCRAM support")
Cc: stable@vger.kernel.org
Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
---
drivers/edac/altera_edac.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c
index e5d225f799f39..09e040b244673 100644
--- a/drivers/edac/altera_edac.c
+++ b/drivers/edac/altera_edac.c
@@ -1554,8 +1554,10 @@ static int altr_portb_setup(struct altr_edac_device_dev *device)
altdev = dci->pvt_info;
*altdev = *device;
- if (!devres_open_group(device->edac->dev, altr_portb_setup, GFP_KERNEL))
+ if (!devres_open_group(device->edac->dev, altr_portb_setup, GFP_KERNEL)) {
+ edac_device_free_ctl_info(dci);
return -ENOMEM;
+ }
/* Update PortB specific values */
altdev->edac_dev_name = ecc_name;
--
2.42.0.411.g813d9a9188
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 06/10] EDAC/altera: Add suppress_bind_attrs so driver cannot get unbound
2026-07-27 13:24 [PATCH 00/10] EDAC/altera: Address sashiko reviews part 1 Dinh Nguyen
` (4 preceding siblings ...)
2026-07-27 13:24 ` [PATCH 05/10] EDAC/altera: Fix code leak on dci allocation failure Dinh Nguyen
@ 2026-07-27 13:24 ` Dinh Nguyen
2026-07-27 13:24 ` [PATCH 07/10] EDAC/altera: Drop __init from ECC setup paths for re-probe safety Dinh Nguyen
` (3 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Dinh Nguyen @ 2026-07-27 13:24 UTC (permalink / raw)
To: bp, tony.luck
Cc: dinguyen, rounakdas2025, niravkumar.l.rabara, linux-edac,
linux-kernel, stable
The EDAC driver should not be able to be removed from userspace because a
re-bind would clear out existing memory contents of an active running system.
With this change, remove the .remove functions because they will not
ever get called.
Fixes: 588cb03ea208 ("EDAC, altera: Add Arria10 L2 Cache ECC handling")
Cc: stable@vger.kernel.org
Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
---
drivers/edac/altera_edac.c | 25 ++++---------------------
1 file changed, 4 insertions(+), 21 deletions(-)
diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c
index 09e040b244673..cd2c2d11214d4 100644
--- a/drivers/edac/altera_edac.c
+++ b/drivers/edac/altera_edac.c
@@ -457,15 +457,6 @@ static int altr_sdram_probe(struct platform_device *pdev)
return res;
}
-static void altr_sdram_remove(struct platform_device *pdev)
-{
- struct mem_ctl_info *mci = platform_get_drvdata(pdev);
-
- edac_mc_del_mc(&pdev->dev);
- edac_mc_free(mci);
- platform_set_drvdata(pdev, NULL);
-}
-
/*
* If you want to suspend, need to disable EDAC by removing it
* from the device tree or defconfig.
@@ -485,13 +476,13 @@ static const struct dev_pm_ops altr_sdram_pm_ops = {
static struct platform_driver altr_sdram_edac_driver = {
.probe = altr_sdram_probe,
- .remove = altr_sdram_remove,
.driver = {
.name = "altr_sdram_edac",
#ifdef CONFIG_PM
.pm = &altr_sdram_pm_ops,
#endif
.of_match_table = altr_sdram_ctrl_of_match,
+ .suppress_bind_attrs = true,
},
};
@@ -521,6 +512,7 @@ static struct platform_driver altr_edac_driver = {
.driver = {
.name = "socfpga_ecc_manager",
.of_match_table = altr_edac_of_match,
+ .suppress_bind_attrs = true,
},
};
module_platform_driver(altr_edac_driver);
@@ -823,22 +815,12 @@ static int altr_edac_device_probe(struct platform_device *pdev)
return res;
}
-static void altr_edac_device_remove(struct platform_device *pdev)
-{
- struct edac_device_ctl_info *dci = platform_get_drvdata(pdev);
- struct altr_edac_device_dev *drvdata = dci->pvt_info;
-
- debugfs_remove_recursive(drvdata->debugfs_dir);
- edac_device_del_device(&pdev->dev);
- edac_device_free_ctl_info(dci);
-}
-
static struct platform_driver altr_edac_device_driver = {
.probe = altr_edac_device_probe,
- .remove = altr_edac_device_remove,
.driver = {
.name = "altr_edac_device",
.of_match_table = altr_edac_device_of_match,
+ .suppress_bind_attrs = true,
},
};
module_platform_driver(altr_edac_device_driver);
@@ -2253,6 +2235,7 @@ static struct platform_driver altr_edac_a10_driver = {
.driver = {
.name = "socfpga_a10_ecc_manager",
.of_match_table = altr_edac_a10_of_match,
+ .suppress_bind_attrs = true,
},
};
module_platform_driver(altr_edac_a10_driver);
--
2.42.0.411.g813d9a9188
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 07/10] EDAC/altera: Drop __init from ECC setup paths for re-probe safety
2026-07-27 13:24 [PATCH 00/10] EDAC/altera: Address sashiko reviews part 1 Dinh Nguyen
` (5 preceding siblings ...)
2026-07-27 13:24 ` [PATCH 06/10] EDAC/altera: Add suppress_bind_attrs so driver cannot get unbound Dinh Nguyen
@ 2026-07-27 13:24 ` Dinh Nguyen
2026-07-27 13:24 ` [PATCH 08/10] EDAC/altera: Skip ECC memory init if already initialized Dinh Nguyen
` (2 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Dinh Nguyen @ 2026-07-27 13:24 UTC (permalink / raw)
To: bp, tony.luck
Cc: dinguyen, rounakdas2025, niravkumar.l.rabara, linux-edac,
linux-kernel
sashiko reports: Does suppressing sysfs unbinding fully prevent the
execution of freed __init memory? If altr_sysmgr_regmap_lookup_by_phandle()
returns -EPROBE_DEFER, the probe is deferred until after __init memory is
freed.
The a10 EDAC .setup callbacks (sdmmc, ethernet, nand, dma, usb, qspi)
and their helpers (altr_init_a10_ecc_device_type,
altr_init_a10_ecc_block) were marked __init. These run from the probe
path, which may execute after init memory is freed -- e.g. a probe
deferred via -EPROBE_DEFER that only succeeds once a late/module
dependency appears, or a manual unbind/rebind. Calling __init code then
dereferences freed memory. Remove __init so these functions remain
valid at runtime.
Assisted-by: Cursor:claude-4.8-opus
Fixes: 788586efd116 ("EDAC/altera: Initialize peripheral FIFOs in probe())
Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
---
drivers/edac/altera_edac.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c
index cd2c2d11214d4..d8d2adc9c39ac 100644
--- a/drivers/edac/altera_edac.c
+++ b/drivers/edac/altera_edac.c
@@ -946,7 +946,7 @@ static int __maybe_unused altr_init_memory_port(void __iomem *ioaddr, int port)
return ret;
}
-static __init int __maybe_unused
+static int __maybe_unused
altr_init_a10_ecc_block(struct device_node *np, u32 irq_mask,
u32 ecc_ctrl_en_mask, bool dual_port)
{
@@ -1021,7 +1021,7 @@ altr_init_a10_ecc_block(struct device_node *np, u32 irq_mask,
static int validate_parent_available(struct device_node *np);
static const struct of_device_id altr_edac_a10_device_of_match[];
-static int __init __maybe_unused altr_init_a10_ecc_device_type(char *compat)
+static int __maybe_unused altr_init_a10_ecc_device_type(char *compat)
{
int irq;
struct device_node *child, *np;
@@ -1350,7 +1350,7 @@ static const struct edac_device_prv_data a10_l2ecc_data = {
#ifdef CONFIG_EDAC_ALTERA_ETHERNET
-static int __init socfpga_init_ethernet_ecc(struct altr_edac_device_dev *dev)
+static int socfpga_init_ethernet_ecc(struct altr_edac_device_dev *dev)
{
int ret;
@@ -1380,7 +1380,7 @@ static const struct edac_device_prv_data a10_enetecc_data = {
#ifdef CONFIG_EDAC_ALTERA_NAND
-static int __init socfpga_init_nand_ecc(struct altr_edac_device_dev *device)
+static int socfpga_init_nand_ecc(struct altr_edac_device_dev *device)
{
int ret;
@@ -1410,7 +1410,7 @@ static const struct edac_device_prv_data a10_nandecc_data = {
#ifdef CONFIG_EDAC_ALTERA_DMA
-static int __init socfpga_init_dma_ecc(struct altr_edac_device_dev *device)
+static int socfpga_init_dma_ecc(struct altr_edac_device_dev *device)
{
int ret;
@@ -1440,7 +1440,7 @@ static const struct edac_device_prv_data a10_dmaecc_data = {
#ifdef CONFIG_EDAC_ALTERA_USB
-static int __init socfpga_init_usb_ecc(struct altr_edac_device_dev *device)
+static int socfpga_init_usb_ecc(struct altr_edac_device_dev *device)
{
int ret;
@@ -1470,7 +1470,7 @@ static const struct edac_device_prv_data a10_usbecc_data = {
#ifdef CONFIG_EDAC_ALTERA_QSPI
-static int __init socfpga_init_qspi_ecc(struct altr_edac_device_dev *device)
+static int socfpga_init_qspi_ecc(struct altr_edac_device_dev *device)
{
int ret;
@@ -1625,7 +1625,7 @@ static int altr_portb_setup(struct altr_edac_device_dev *device)
return rc;
}
-static int __init socfpga_init_sdmmc_ecc(struct altr_edac_device_dev *device)
+static int socfpga_init_sdmmc_ecc(struct altr_edac_device_dev *device)
{
int rc = -ENODEV;
struct device_node *child;
--
2.42.0.411.g813d9a9188
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 08/10] EDAC/altera: Skip ECC memory init if already initialized
2026-07-27 13:24 [PATCH 00/10] EDAC/altera: Address sashiko reviews part 1 Dinh Nguyen
` (6 preceding siblings ...)
2026-07-27 13:24 ` [PATCH 07/10] EDAC/altera: Drop __init from ECC setup paths for re-probe safety Dinh Nguyen
@ 2026-07-27 13:24 ` Dinh Nguyen
2026-07-27 13:24 ` [PATCH 09/10] EDAC/altera: Detach sb_irq handler when db_irq setup fails Dinh Nguyen
2026-07-27 13:24 ` [PATCH 10/10] EDAC/altera: Fix error cleanup path in altr_edac_device_probe() Dinh Nguyen
9 siblings, 0 replies; 11+ messages in thread
From: Dinh Nguyen @ 2026-07-27 13:24 UTC (permalink / raw)
To: bp, tony.luck
Cc: dinguyen, rounakdas2025, niravkumar.l.rabara, linux-edac,
linux-kernel, stable
altr_init_memory_port() unconditionally triggered the HW memory-init
block, which clears the entire memory and ECC data. On a re-probe (e.g.
a probe deferred via -EPROBE_DEFER that only succeeds after the
protected peripheral is active, or a rebind) this would wipe live
peripheral memory. Skip the destructive init when the INITCOMPLETE
status bit is already set, so it runs only once.
Assisted-by: Cursor:claude-4.8-opus
Fixes: 1166fde93d5b ("EDAC, altera: Add Arria10 ECC memory init functions")
Cc: stable@vger.kernel.org
Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
---
drivers/edac/altera_edac.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c
index d8d2adc9c39ac..5087aa5ae5612 100644
--- a/drivers/edac/altera_edac.c
+++ b/drivers/edac/altera_edac.c
@@ -930,6 +930,18 @@ static int __maybe_unused altr_init_memory_port(void __iomem *ioaddr, int port)
clear_mask = ALTR_A10_ECC_ERRPENA_MASK;
}
+ /*
+ * The HW init block clears the entire memory and ECC data, so only
+ * run it once. If initialization already completed (e.g. on an
+ * earlier probe or in the bootloader), skip it so a re-probe caused
+ * by deferred probing or a rebind does not wipe an active peripheral.
+ */
+ if (ecc_test_bits(stat_mask, (ioaddr + ALTR_A10_ECC_INITSTAT_OFST))) {
+ /* Clear any pending ECC interrupts */
+ writel(clear_mask, (ioaddr + ALTR_A10_ECC_INTSTAT_OFST));
+ return 0;
+ }
+
ecc_set_bits(init_mask, (ioaddr + ALTR_A10_ECC_CTRL_OFST));
while (limit--) {
if (ecc_test_bits(stat_mask,
--
2.42.0.411.g813d9a9188
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 09/10] EDAC/altera: Detach sb_irq handler when db_irq setup fails
2026-07-27 13:24 [PATCH 00/10] EDAC/altera: Address sashiko reviews part 1 Dinh Nguyen
` (7 preceding siblings ...)
2026-07-27 13:24 ` [PATCH 08/10] EDAC/altera: Skip ECC memory init if already initialized Dinh Nguyen
@ 2026-07-27 13:24 ` Dinh Nguyen
2026-07-27 13:24 ` [PATCH 10/10] EDAC/altera: Fix error cleanup path in altr_edac_device_probe() Dinh Nguyen
9 siblings, 0 replies; 11+ messages in thread
From: Dinh Nguyen @ 2026-07-27 13:24 UTC (permalink / raw)
To: bp, tony.luck
Cc: dinguyen, rounakdas2025, niravkumar.l.rabara, linux-edac,
linux-kernel, stable
altr_edac_a10_probe() installs the sb_irq chained handler before fetching
db_irq. If platform_get_irq() for db_irq fails, the probe returned
without detaching the sb_irq handler, leaving it pointing at the
devm-freed edac struct. Unlink the sb_irq chained handler before
removing the IRQ domain and returning.
Assisted-by: Cursor:claude-4.8-opus
Fixes: d5fc9125566c ("EDAC, altera: Combine Stratix10 and Arria10 probe functions")
Cc: stable@vger.kernel.org
Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
---
drivers/edac/altera_edac.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c
index 5087aa5ae5612..80ca9f511ac98 100644
--- a/drivers/edac/altera_edac.c
+++ b/drivers/edac/altera_edac.c
@@ -2209,6 +2209,8 @@ static int altr_edac_a10_probe(struct platform_device *pdev)
} else {
edac->db_irq = platform_get_irq(pdev, 1);
if (edac->db_irq < 0) {
+ irq_set_chained_handler_and_data(edac->sb_irq,
+ NULL, NULL);
irq_domain_remove(edac->domain);
return edac->db_irq;
}
--
2.42.0.411.g813d9a9188
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 10/10] EDAC/altera: Fix error cleanup path in altr_edac_device_probe()
2026-07-27 13:24 [PATCH 00/10] EDAC/altera: Address sashiko reviews part 1 Dinh Nguyen
` (8 preceding siblings ...)
2026-07-27 13:24 ` [PATCH 09/10] EDAC/altera: Detach sb_irq handler when db_irq setup fails Dinh Nguyen
@ 2026-07-27 13:24 ` Dinh Nguyen
9 siblings, 0 replies; 11+ messages in thread
From: Dinh Nguyen @ 2026-07-27 13:24 UTC (permalink / raw)
To: bp, tony.luck
Cc: dinguyen, rounakdas2025, niravkumar.l.rabara, linux-edac,
linux-kernel, stable
sashiko reports: Does the error cleanup path in
altr_edac_device_probe() free data before unregistering the interrupt
handler? If a failure occurs, dci is explicitly freed via
edac_device_free_ctl_info(dci) before the managed IRQ handler is unregistered
via devres_release_group(). If an interrupt fires in this window, could it
dereference the freed dci?
Clean up the fail1 path to always call devres_release_group() and
conditionally free the dci.
Fixes: c3eea1942a16 ("EDAC, altera: Add Altera L2 cache and OCRAM support")
Cc: stable@vger.kernel.org
Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
---
drivers/edac/altera_edac.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c
index 80ca9f511ac98..b6048a1884f43 100644
--- a/drivers/edac/altera_edac.c
+++ b/drivers/edac/altera_edac.c
@@ -701,7 +701,7 @@ MODULE_DEVICE_TABLE(of, altr_edac_device_of_match);
*/
static int altr_edac_device_probe(struct platform_device *pdev)
{
- struct edac_device_ctl_info *dci;
+ struct edac_device_ctl_info *dci = NULL;
struct altr_edac_device_dev *drvdata;
struct resource *r;
int res = 0;
@@ -729,7 +729,7 @@ static int altr_edac_device_probe(struct platform_device *pdev)
edac_printk(KERN_ERR, EDAC_DEVICE,
"Unable to get mem resource\n");
res = -ENODEV;
- goto fail;
+ goto fail1;
}
if (!devm_request_mem_region(&pdev->dev, r->start, resource_size(r),
@@ -737,7 +737,7 @@ static int altr_edac_device_probe(struct platform_device *pdev)
edac_printk(KERN_ERR, EDAC_DEVICE,
"%s:Error requesting mem region\n", ecc_name);
res = -EBUSY;
- goto fail;
+ goto fail1;
}
dci = edac_device_alloc_ctl_info(sizeof(*drvdata), ecc_name,
@@ -747,7 +747,7 @@ static int altr_edac_device_probe(struct platform_device *pdev)
edac_printk(KERN_ERR, EDAC_DEVICE,
"%s: Unable to allocate EDAC device\n", ecc_name);
res = -ENOMEM;
- goto fail;
+ goto fail1;
}
drvdata = dci->pvt_info;
@@ -806,9 +806,9 @@ static int altr_edac_device_probe(struct platform_device *pdev)
return 0;
fail1:
- edac_device_free_ctl_info(dci);
-fail:
devres_release_group(&pdev->dev, NULL);
+ if (dci)
+ edac_device_free_ctl_info(dci);
edac_printk(KERN_ERR, EDAC_DEVICE,
"%s:Error setting up EDAC device: %d\n", ecc_name, res);
--
2.42.0.411.g813d9a9188
^ permalink raw reply related [flat|nested] 11+ messages in thread