DORMANTno replies

[PATCH] can: flexcan: fix synchronous external abort in flexcan_get_berr_counter()

From: chunyuzhiqiang <hidden>
Date: 2026-09-15 06:38:06
Also in: linux-can
Subsystem: can network drivers, the rest · Maintainers: Marc Kleine-Budde, Vincent Mailhol, Linus Torvalds

From: ChunYuZhiQiang <redacted>

When the FlexCAN interface is down, can_fill_info() still calls
flexcan_get_berr_counter() to fill the error counters for a netlink
dump. This function calls pm_runtime_resume_and_get(), which only
enables the clocks via flexcan_runtime_resume(), but does not clear
the MCR[MDIS] bit. Since the interface has never been opened, the
FlexCAN module is still disabled (MDIS=1) from register_flexcandev().
Accessing the ECR register then triggers a synchronous external abort.

This can be reproduced on an i.MX8QXP board by simply running
`ip link show` without ever bringing the CAN interface up:

    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
     ...

ftrace shows the exact path:

  can_fill_info() {
    flexcan_get_berr_counter() {
      __pm_runtime_resume() {
        rpm_resume()
          rpm_callback()
            __rpm_callback()
              pm_generic_runtime_resume()
                flexcan_runtime_resume()
                  flexcan_clks_enable() {
                    clk_prepare(); clk_enable();
                    ...
                  }
      }
      do_mem_abort() {
        do_sea()
        ...
      }
    }
  }

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.

Cc: stable@vger.kernel.org
Signed-off-by: ChunYuZhiQiang <redacted>
---
 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 06d5d35fc..b08779ee2 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
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help