[PATCH net v2] can: flexcan: fix synchronous external abort in flexcan_get_berr_counter()
flat view
COLD25d
From: ChunYuZhiQiang <hidden>
Date: 2026-09-29 07:15:42
Also in:
imx, linux-can
Subsystem:
can network drivers, the rest · Maintainers:
Marc Kleine-Budde, Vincent Mailhol, Linus Torvalds
When the interface is down, can_fill_info() still calls
flexcan_get_berr_counter() to fill the error counters for a netlink
dump. On some SoCs (e.g. i.MX8QXP) this can trigger a synchronous
external abort.
The root cause is platform-specific clocking. On i.MX8QXP the CAN
clocks are gated through the SCU LPCG and the whole subsystem shares
the IMX_SC_R_CAN_0 power domain. flexcan_runtime_resume() only calls
flexcan_clks_enable(); combined with the LPCG e10858 synchronization
erratum, there is a window where pm_runtime_resume_and_get() has
returned but the clock has not actually reached the module yet. The
immediate readl(®s->ecr) in that window hits an un-clocked target
and faults with the external abort:
Internal error: synchronous external abort: 0000000096000210 [#1] PREEMPT SMP
pc : flexcan_read_le+0x0/0x18
lr : flexcan_get_berr_counter+0x4c/0x8c
Call trace:
flexcan_read_le+0x0/0x18
can_fill_info+0x1f8/0x434
rtnl_fill_ifinfo+0x8fc/0xbb4
rtnl_dump_ifinfo+0x364/0x448
...
This is the same class of problem that was already fixed for m_can:
commit 91a55c72a821d ("can: m_can: m_can_get_berr_counter(): don't
wake up controller if interface is down")
Fix this by returning early if the interface is not running.
Tested on i.MX8QXP: after the patch, `ip link show` no longer triggers
the abort.
Fixes: ec56acfef2af1 ("can: flexcan: flexcan_get_berr_counter(): switch on clocks before accessing ecr register")
Link: https://lore.kernel.org/netdev/20260915063511.3010642-1-chunyuzhiqiang@yinhe.ht/ (local)
Cc: stable@vger.kernel.org
Signed-off-by: ChunYuZhiQiang <redacted>
---
v1 -> v2:
- Reword the commit message to drop the MDIS reasoning and describe
the actual i.MX8QXP SCU/LPCG clocking window as the root cause.
- Reference the m_can precedent (91a55c72a821d).
- Add Fixes: tag pointing to ec56acfef2af1.
- Add Link: to v1.
drivers/net/can/flexcan/flexcan-core.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/net/can/flexcan/flexcan-core.c b/drivers/net/can/flexcan/flexcan-core.c
index 06d5d35fc1b5..b08779ee2a0a 100644
--- a/drivers/net/can/flexcan/flexcan-core.c
+++ b/drivers/net/can/flexcan/flexcan-core.c@@ -765,6 +765,9 @@ static int flexcan_get_berr_counter(const struct net_device *dev, const struct flexcan_priv *priv = netdev_priv(dev); int err; + if (!netif_running(dev)) + return 0; + err = pm_runtime_resume_and_get(priv->dev); if (err < 0) return err;
--
2.47.3