Netdev List
 help / color / mirror / Atom feed
* [PATCH v6] can: dev: can_fill_info(): don't wake up controller if interface is down
@ 2026-10-21  2:33 ChunYuZhiQiang
  2026-10-21  2:39 ` netdev-bot+sinfo
  0 siblings, 1 reply; 3+ messages in thread
From: ChunYuZhiQiang @ 2026-10-21  2:33 UTC (permalink / raw)
  To: netdev-bot+sinfo
  Cc: netdev, linux-can, mkl, kernel, haibo.chen, shawnguo, imx, stable,
	ChunYuZhiQiang

If the interface is down, the CAN controller might be powered down, the
clock disabled, and/or its external reset asserted.

Don't call do_get_berr_counter() or do_get_auto_tdcv() to read the CAN
controller if the interface is down. This fixes a generic logic problem
that exists on all platforms.

As a result, IFLA_CAN_BERR_COUNTER is no longer reported for down
interfaces, and the automatic TDCV readback is skipped. The other TDC
parameters are still reported, as they are meaningful while the
interface is down. This is intentional: the counters and the automatic
TDCV are not meaningful in that state, and calling into the driver can
wake a runtime-suspended controller or touch registers whose clocks are
gated.

Fixes: ec56acfef2af1 ("can: flexcan: flexcan_get_berr_counter(): switch on clocks before accessing ecr register")
Cc: stable@vger.kernel.org
Signed-off-by: ChunYuZhiQiang <chunyuzhiqiang@yinhe.ht>
---
v6:
 - Only gate do_get_auto_tdcv() on netif_running(), as suggested by
   Vincent Mailhol and Marc Kleine-Budde. The other TDC parameters are
   still reported for down interfaces.
 - Adjust can_tdc_get_size() so that only the automatic TDCV size is
   skipped when the interface is down.
 - Keep the berr-counter gating unchanged.
---
 drivers/net/can/dev/netlink.c | 21 ++++++++++++---------
 1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/drivers/net/can/dev/netlink.c b/drivers/net/can/dev/netlink.c
index 6f83b87d54fc..ae0cef791ef3 100644
--- a/drivers/net/can/dev/netlink.c
+++ b/drivers/net/can/dev/netlink.c
@@ -517,7 +517,7 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
 }
 
 static size_t can_tdc_get_size(struct data_bittiming_params *dbt_params,
-			       u32 tdc_flags)
+			       u32 tdc_flags, bool auto_tdcv_running)
 {
 	bool tdc_manual = tdc_flags & CAN_CTRLMODE_TDC_MANUAL_MASK;
 	size_t size;
@@ -538,7 +538,7 @@ static size_t can_tdc_get_size(struct data_bittiming_params *dbt_params,
 	}
 
 	if (tdc_flags) {
-		if (tdc_manual || dbt_params->do_get_auto_tdcv)
+		if (tdc_manual || (dbt_params->do_get_auto_tdcv && auto_tdcv_running))
 			size += nla_total_size(sizeof(u32));	/* IFLA_CAN_TDCV */
 		size += nla_total_size(sizeof(u32));		/* IFLA_CAN_TDCO */
 		if (dbt_params->tdc_const->tdcf_max)
@@ -548,8 +548,9 @@ static size_t can_tdc_get_size(struct data_bittiming_params *dbt_params,
 	return size;
 }
 
-static size_t can_data_bittiming_get_size(struct data_bittiming_params *dbt_params,
-					  u32 tdc_flags)
+static size_t
+can_data_bittiming_get_size(struct data_bittiming_params *dbt_params,
+			    u32 tdc_flags, bool auto_tdcv_running)
 {
 	size_t size = 0;
 
@@ -560,7 +561,8 @@ static size_t can_data_bittiming_get_size(struct data_bittiming_params *dbt_para
 	if (dbt_params->data_bitrate_const)		/* IFLA_CAN_DATA_BITRATE_CONST */
 		size += nla_total_size(sizeof(*dbt_params->data_bitrate_const) *
 				       dbt_params->data_bitrate_const_cnt);
-	size += can_tdc_get_size(dbt_params, tdc_flags);/* IFLA_CAN_TDC */
+
+	size += can_tdc_get_size(dbt_params, tdc_flags, auto_tdcv_running); /* IFLA_CAN_TDC */
 
 	return size;
 }
@@ -584,7 +586,7 @@ static size_t can_get_size(const struct net_device *dev)
 	size += nla_total_size(sizeof(u32));			/* IFLA_CAN_STATE */
 	size += nla_total_size(sizeof(struct can_ctrlmode));	/* IFLA_CAN_CTRLMODE */
 	size += nla_total_size(sizeof(u32));			/* IFLA_CAN_RESTART_MS */
-	if (priv->do_get_berr_counter)				/* IFLA_CAN_BERR_COUNTER */
+	if (priv->do_get_berr_counter && netif_running(dev))	/* IFLA_CAN_BERR_COUNTER */
 		size += nla_total_size(sizeof(struct can_berr_counter));
 	if (priv->termination_const) {
 		size += nla_total_size(sizeof(priv->termination));		/* IFLA_CAN_TERMINATION */
@@ -598,7 +600,8 @@ static size_t can_get_size(const struct net_device *dev)
 	size += can_ctrlmode_ext_get_size();			/* IFLA_CAN_CTRLMODE_EXT */
 
 	size += can_data_bittiming_get_size(&priv->fd,
-					    priv->ctrlmode & CAN_CTRLMODE_FD_TDC_MASK);
+					    priv->ctrlmode & CAN_CTRLMODE_FD_TDC_MASK,
+					    netif_running(dev));
 
 	return size;
 }
@@ -675,7 +678,7 @@ static int can_tdc_fill_info(struct sk_buff *skb, const struct net_device *dev,
 		if (tdc_manual) {
 			tdcv = tdc->tdcv;
 			err = 0;
-		} else if (dbt_params->do_get_auto_tdcv) {
+		} else if (dbt_params->do_get_auto_tdcv && netif_running(dev)) {
 			err = dbt_params->do_get_auto_tdcv(dev, &tdcv);
 		}
 		if (!err && nla_put_u32(skb, IFLA_CAN_TDC_TDCV, tdcv))
@@ -735,7 +738,7 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev)
 	    nla_put(skb, IFLA_CAN_CTRLMODE, sizeof(cm), &cm) ||
 	    nla_put_u32(skb, IFLA_CAN_RESTART_MS, priv->restart_ms) ||
 
-	    (priv->do_get_berr_counter &&
+	    (priv->do_get_berr_counter && netif_running(dev) &&
 	     !priv->do_get_berr_counter(dev, &bec) &&
 	     nla_put(skb, IFLA_CAN_BERR_COUNTER, sizeof(bec), &bec)) ||
 
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH v6] can: dev: can_fill_info(): don't wake up controller if interface is down
  2026-10-21  2:33 [PATCH v6] can: dev: can_fill_info(): don't wake up controller if interface is down ChunYuZhiQiang
@ 2026-10-21  2:39 ` netdev-bot+sinfo
  2026-10-21  2:56   ` RE:[PATCH " 淳于智强
  0 siblings, 1 reply; 3+ messages in thread
From: netdev-bot+sinfo @ 2026-10-21  2:39 UTC (permalink / raw)
  To: ChunYuZhiQiang
  Cc: netdev, linux-can, mkl, kernel, haibo.chen, shawnguo, imx, stable

Hi!

This is an automated message. This series looks like a fix, but its
commit messages seem to be missing some information:

 - How the issue was discovered, e.g. hit in production, hit during
   development, syzbot report, manual code inspection, LLM or static
   analysis tool scan.

 - Whether the issue was actually triggered, or is only theoretical
   (e.g. found by code inspection). If it was triggered please include
   the symptoms, like the stack trace or error messages.

Please do not repost the series just to address the above. Instead,
reply to this email with the missing information, so that reviewers
can take it into account. If the series needs another revision for
other reasons, please include the information in the commit messages
then.

The evaluation is done by an LLM so it may be wrong, if you think
that is the case please reply and explain.

^ permalink raw reply	[flat|nested] 3+ messages in thread

* RE:[PATCH v6] can: dev: can_fill_info(): don't wake up controller if interface is down
  2026-10-21  2:39 ` netdev-bot+sinfo
@ 2026-10-21  2:56   ` 淳于智强
  0 siblings, 0 replies; 3+ messages in thread
From: 淳于智强 @ 2026-10-21  2:56 UTC (permalink / raw)
  To: netdev-bot+sinfo
  Cc: netdev, linux-can, mkl, kernel, haibo.chen, shawnguo, imx, stable

Hi,

> - How the issue was discovered, e.g. hit in production, hit during
>   development, syzbot report, manual code inspection, LLM or static
>   analysis tool scan.
>
> - Whether the issue was actually triggered, or is only theoretical
>   (e.g. found by code inspection). If it was triggered please include
>   the symptoms, like the stack trace or error messages.

The berr-counter issue was actually triggered on an i.MX8QXP board
during development. It reproduces 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
     flexcan_get_berr_counter+0x4c/0x8c
     can_fill_info+0x1f8/0x434
     rtnl_fill_ifinfo+0x8fc/0xbb4
     rtnl_dump_ifinfo+0x364/0x448

The root cause is platform-specific: on i.MX8QXP the CAN clocks are
gated through the SCU LPCG and the subsystem shares the IMX_SC_R_CAN_0
power domain. flexcan_runtime_resume() only calls flexcan_clks_enable();
there is a window where pm_runtime_resume_and_get() has returned but the
clock has not actually reached the module yet, and the immediate ECR
read in that window hits an un-clocked target and raises the external
abort. This is the same class of problem that was already fixed for
m_can in commit 91a55c72a821d ("can: m_can: m_can_get_berr_counter():
don't wake up controller if interface is down").

The TDC auto readback part was pointed out by the Sashiko AI review of
this series. It is based on code inspection of can_tdc_fill_info() and
xcan_get_auto_tdcv(), which reads XCAN_SR without taking a runtime PM
reference. I have not triggered that path on hardware, so no stack trace
is available for it; the patch gates it as a precaution.

Tested on i.MX8QXP: after the patch, "ip link show" no longer triggers
the abort.

Thanks,
ChunYuZhiQiang

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-10-21  2:56 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-21  2:33 [PATCH v6] can: dev: can_fill_info(): don't wake up controller if interface is down ChunYuZhiQiang
2026-10-21  2:39 ` netdev-bot+sinfo
2026-10-21  2:56   ` RE:[PATCH " 淳于智强

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox