* [PATCH net v2 1/3] can: dev: prevent bus-off recovery when the interface is not running
[not found] <20261014-rockchip-canfd-restart-close-v2-0-c8fbdfad1803@qq.com>
@ 2026-10-14 2:54 ` Cunhao Lu
2026-10-14 2:54 ` Cunhao Lu
2026-10-14 2:54 ` Cunhao Lu
2 siblings, 0 replies; 8+ messages in thread
From: Cunhao Lu @ 2026-10-14 2:54 UTC (permalink / raw)
To: Marc Kleine-Budde, Vincent Mailhol, Heiko Stuebner,
David S. Miller, Wolfgang Grandegger, Oliver Hartkopp, kernel
Cc: linux-can, linux-kernel, linux-arm-kernel, linux-rockchip, stable,
Cunhao Lu
The networking core clears __LINK_STATE_START before calling ndo_stop(),
but CAN bus-off recovery neither checks this state before queuing work
nor before calling the driver's restart callback. Recovery can therefore
be queued or started after the interface has begun closing, potentially
re-enabling hardware while the driver is tearing it down.
Check netif_running() in can_restart() before flushing echo skbs, sending
the restart notification or enabling the carrier. Keep the existing
unsupported-operation check first. In can_bus_off(), only schedule
recovery for a running interface and make the log message reflect that
decision. Keep reporting bus-off and disabling the carrier.
These checks do not wait for recovery that has already passed the check,
nor serialize the check with work submission. Drivers still need to
cancel restart work before tearing down resources and quiesce its
producers before their final cleanup.
Fixes: 39549eef3587 ("can: CAN Network device driver and Netlink interface")
Cc: stable@vger.kernel.org
Signed-off-by: Cunhao Lu <1579567540@qq.com>
---
drivers/net/can/dev/dev.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/net/can/dev/dev.c b/drivers/net/can/dev/dev.c
index 769745e22a3c7..92492c503446e 100644
--- a/drivers/net/can/dev/dev.c
+++ b/drivers/net/can/dev/dev.c
@@ -198,6 +198,9 @@ static int can_restart(struct net_device *dev)
if (!priv->do_set_mode)
return -EOPNOTSUPP;
+ if (!netif_running(dev))
+ return -ENETDOWN;
+
if (netif_carrier_ok(dev))
netdev_err(dev, "Attempt to restart for bus-off recovery, but carrier is OK?\n");
@@ -264,8 +267,9 @@ int can_restart_now(struct net_device *dev)
void can_bus_off(struct net_device *dev)
{
struct can_priv *priv = netdev_priv(dev);
+ const bool restart = priv->restart_ms && netif_running(dev);
- if (priv->restart_ms)
+ if (restart)
netdev_info(dev, "bus-off, scheduling restart in %d ms\n",
priv->restart_ms);
else
@@ -273,7 +277,7 @@ void can_bus_off(struct net_device *dev)
netif_carrier_off(dev);
- if (priv->restart_ms)
+ if (restart)
schedule_delayed_work(&priv->restart_work,
msecs_to_jiffies(priv->restart_ms));
}
--
2.34.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH net v2 1/3] can: dev: prevent bus-off recovery when the interface is not running
@ 2026-10-14 2:54 ` Cunhao Lu
0 siblings, 0 replies; 8+ messages in thread
From: Cunhao Lu @ 2026-10-14 2:54 UTC (permalink / raw)
To: Marc Kleine-Budde, Vincent Mailhol, Heiko Stuebner,
David S. Miller, Wolfgang Grandegger, Oliver Hartkopp, kernel
Cc: linux-can, linux-kernel, linux-arm-kernel, linux-rockchip, stable,
Cunhao Lu
The networking core clears __LINK_STATE_START before calling ndo_stop(),
but CAN bus-off recovery neither checks this state before queuing work
nor before calling the driver's restart callback. Recovery can therefore
be queued or started after the interface has begun closing, potentially
re-enabling hardware while the driver is tearing it down.
Check netif_running() in can_restart() before flushing echo skbs, sending
the restart notification or enabling the carrier. Keep the existing
unsupported-operation check first. In can_bus_off(), only schedule
recovery for a running interface and make the log message reflect that
decision. Keep reporting bus-off and disabling the carrier.
These checks do not wait for recovery that has already passed the check,
nor serialize the check with work submission. Drivers still need to
cancel restart work before tearing down resources and quiesce its
producers before their final cleanup.
Fixes: 39549eef3587 ("can: CAN Network device driver and Netlink interface")
Cc: stable@vger.kernel.org
Signed-off-by: Cunhao Lu <1579567540@qq.com>
---
drivers/net/can/dev/dev.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/net/can/dev/dev.c b/drivers/net/can/dev/dev.c
index 769745e22a3c7..92492c503446e 100644
--- a/drivers/net/can/dev/dev.c
+++ b/drivers/net/can/dev/dev.c
@@ -198,6 +198,9 @@ static int can_restart(struct net_device *dev)
if (!priv->do_set_mode)
return -EOPNOTSUPP;
+ if (!netif_running(dev))
+ return -ENETDOWN;
+
if (netif_carrier_ok(dev))
netdev_err(dev, "Attempt to restart for bus-off recovery, but carrier is OK?\n");
@@ -264,8 +267,9 @@ int can_restart_now(struct net_device *dev)
void can_bus_off(struct net_device *dev)
{
struct can_priv *priv = netdev_priv(dev);
+ const bool restart = priv->restart_ms && netif_running(dev);
- if (priv->restart_ms)
+ if (restart)
netdev_info(dev, "bus-off, scheduling restart in %d ms\n",
priv->restart_ms);
else
@@ -273,7 +277,7 @@ void can_bus_off(struct net_device *dev)
netif_carrier_off(dev);
- if (priv->restart_ms)
+ if (restart)
schedule_delayed_work(&priv->restart_work,
msecs_to_jiffies(priv->restart_ms));
}
--
2.34.1
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH net v2 2/3] can: dev: add close_candev_cancel_restart_sync()
[not found] <20261014-rockchip-canfd-restart-close-v2-0-c8fbdfad1803@qq.com>
@ 2026-10-14 2:54 ` Cunhao Lu
2026-10-14 2:54 ` Cunhao Lu
2026-10-14 2:54 ` Cunhao Lu
2 siblings, 0 replies; 8+ messages in thread
From: Cunhao Lu @ 2026-10-14 2:54 UTC (permalink / raw)
To: Marc Kleine-Budde, Vincent Mailhol, Heiko Stuebner,
David S. Miller, Wolfgang Grandegger, Oliver Hartkopp, kernel
Cc: linux-can, linux-kernel, linux-arm-kernel, linux-rockchip, stable,
Cunhao Lu
Drivers may need to wait for bus-off recovery before tearing down the
IRQ and hardware resources used by their restart callback. Calling
close_candev() at that point also flushes echo skbs, which belongs after
the driver has quiesced the users of those buffers.
Add close_candev_cancel_restart_sync() in linux/can/dev.h so drivers can
cancel the core restart work separately, without accessing can_priv's
work item directly. The helper only cancels restart work; callers must
still stop its producers and call close_candev() for the final cleanup.
Use the helper in close_candev(), preserving its existing cancellation
and echo cleanup order.
Cc: stable@vger.kernel.org
Signed-off-by: Cunhao Lu <1579567540@qq.com>
---
drivers/net/can/dev/dev.c | 4 +---
include/linux/can/dev.h | 12 ++++++++++++
2 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/drivers/net/can/dev/dev.c b/drivers/net/can/dev/dev.c
index 92492c503446e..52e8c4854ae0d 100644
--- a/drivers/net/can/dev/dev.c
+++ b/drivers/net/can/dev/dev.c
@@ -534,9 +534,7 @@ EXPORT_SYMBOL_GPL(of_can_transceiver);
*/
void close_candev(struct net_device *dev)
{
- struct can_priv *priv = netdev_priv(dev);
-
- cancel_delayed_work_sync(&priv->restart_work);
+ close_candev_cancel_restart_sync(dev);
can_flush_echo_skb(dev);
}
EXPORT_SYMBOL_GPL(close_candev);
diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h
index 6d0710d6f571d..a277d12332f15 100644
--- a/include/linux/can/dev.h
+++ b/include/linux/can/dev.h
@@ -22,6 +22,7 @@
#include <linux/can/skb.h>
#include <linux/ethtool.h>
#include <linux/netdevice.h>
+#include <linux/workqueue.h>
/*
* CAN mode
@@ -115,6 +116,17 @@ struct can_priv *safe_candev_priv(struct net_device *dev);
int open_candev(struct net_device *dev);
void close_candev(struct net_device *dev);
+
+/* Cancel bus-off restart before tearing down resources used by the restart
+ * callback. The driver must still call close_candev() for the final cleanup.
+ */
+static inline void close_candev_cancel_restart_sync(struct net_device *dev)
+{
+ struct can_priv *priv = netdev_priv(dev);
+
+ cancel_delayed_work_sync(&priv->restart_work);
+}
+
void can_set_default_mtu(struct net_device *dev);
void can_set_cap_info(struct net_device *dev);
int __must_check can_set_static_ctrlmode(struct net_device *dev,
--
2.34.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH net v2 2/3] can: dev: add close_candev_cancel_restart_sync()
@ 2026-10-14 2:54 ` Cunhao Lu
0 siblings, 0 replies; 8+ messages in thread
From: Cunhao Lu @ 2026-10-14 2:54 UTC (permalink / raw)
To: Marc Kleine-Budde, Vincent Mailhol, Heiko Stuebner,
David S. Miller, Wolfgang Grandegger, Oliver Hartkopp, kernel
Cc: linux-can, linux-kernel, linux-arm-kernel, linux-rockchip, stable,
Cunhao Lu
Drivers may need to wait for bus-off recovery before tearing down the
IRQ and hardware resources used by their restart callback. Calling
close_candev() at that point also flushes echo skbs, which belongs after
the driver has quiesced the users of those buffers.
Add close_candev_cancel_restart_sync() in linux/can/dev.h so drivers can
cancel the core restart work separately, without accessing can_priv's
work item directly. The helper only cancels restart work; callers must
still stop its producers and call close_candev() for the final cleanup.
Use the helper in close_candev(), preserving its existing cancellation
and echo cleanup order.
Cc: stable@vger.kernel.org
Signed-off-by: Cunhao Lu <1579567540@qq.com>
---
drivers/net/can/dev/dev.c | 4 +---
include/linux/can/dev.h | 12 ++++++++++++
2 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/drivers/net/can/dev/dev.c b/drivers/net/can/dev/dev.c
index 92492c503446e..52e8c4854ae0d 100644
--- a/drivers/net/can/dev/dev.c
+++ b/drivers/net/can/dev/dev.c
@@ -534,9 +534,7 @@ EXPORT_SYMBOL_GPL(of_can_transceiver);
*/
void close_candev(struct net_device *dev)
{
- struct can_priv *priv = netdev_priv(dev);
-
- cancel_delayed_work_sync(&priv->restart_work);
+ close_candev_cancel_restart_sync(dev);
can_flush_echo_skb(dev);
}
EXPORT_SYMBOL_GPL(close_candev);
diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h
index 6d0710d6f571d..a277d12332f15 100644
--- a/include/linux/can/dev.h
+++ b/include/linux/can/dev.h
@@ -22,6 +22,7 @@
#include <linux/can/skb.h>
#include <linux/ethtool.h>
#include <linux/netdevice.h>
+#include <linux/workqueue.h>
/*
* CAN mode
@@ -115,6 +116,17 @@ struct can_priv *safe_candev_priv(struct net_device *dev);
int open_candev(struct net_device *dev);
void close_candev(struct net_device *dev);
+
+/* Cancel bus-off restart before tearing down resources used by the restart
+ * callback. The driver must still call close_candev() for the final cleanup.
+ */
+static inline void close_candev_cancel_restart_sync(struct net_device *dev)
+{
+ struct can_priv *priv = netdev_priv(dev);
+
+ cancel_delayed_work_sync(&priv->restart_work);
+}
+
void can_set_default_mtu(struct net_device *dev);
void can_set_cap_info(struct net_device *dev);
int __must_check can_set_static_ctrlmode(struct net_device *dev,
--
2.34.1
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH net v2 3/3] can: rockchip_canfd: cancel bus-off restart before closing the device
[not found] <20261014-rockchip-canfd-restart-close-v2-0-c8fbdfad1803@qq.com>
@ 2026-10-14 2:54 ` Cunhao Lu
2026-10-14 2:54 ` Cunhao Lu
2026-10-14 2:54 ` Cunhao Lu
2 siblings, 0 replies; 8+ messages in thread
From: Cunhao Lu @ 2026-10-14 2:54 UTC (permalink / raw)
To: Marc Kleine-Budde, Vincent Mailhol, Heiko Stuebner,
David S. Miller, Wolfgang Grandegger, Oliver Hartkopp, kernel
Cc: linux-can, linux-kernel, linux-arm-kernel, linux-rockchip, stable,
Cunhao Lu
The close path cancels restart_work through close_candev() only after
freeing the IRQ, disabling RX offload and stopping the controller. A
running restart can re-enable the controller and its interrupts after
IRQ teardown, or restart timestamp work after it has been stopped and
before runtime suspend removes the controller clocks.
Call close_candev_cancel_restart_sync() at the start of ndo_stop(), while
the resources needed by a running restart are still available. The core
netif_running() check prevents a late restart from entering the driver,
while this cancellation waits for one that has already passed the check.
Keep close_candev() after IRQ teardown for the final cancellation and
echo cleanup, including work queued by an IRQ racing with the first
cancellation.
Exclude the IRQ handler while reinitializing hardware in the restart
callback: the handler continues processing after scheduling recovery,
and a shared interrupt can also invoke it while this controller's
interrupts are masked. Keep the shared IRQ enabled while the close path
waits for restart work to finish.
Fixes: ff60bfbaf67f ("can: rockchip_canfd: add driver for Rockchip CAN-FD controller")
Cc: stable@vger.kernel.org
Signed-off-by: Cunhao Lu <1579567540@qq.com>
---
drivers/net/can/rockchip/rockchip_canfd-core.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/net/can/rockchip/rockchip_canfd-core.c b/drivers/net/can/rockchip/rockchip_canfd-core.c
index 37c1c22c40c9..fb8f6b067502 100644
--- a/drivers/net/can/rockchip/rockchip_canfd-core.c
+++ b/drivers/net/can/rockchip/rockchip_canfd-core.c
@@ -356,8 +356,10 @@ static int rkcanfd_set_mode(struct net_device *ndev,
switch (mode) {
case CAN_MODE_START:
+ disable_irq(ndev->irq);
rkcanfd_chip_start(priv);
rkcanfd_chip_interrupts_enable(priv);
+ enable_irq(ndev->irq);
netif_wake_queue(ndev);
break;
@@ -758,6 +760,7 @@ static int rkcanfd_stop(struct net_device *ndev)
{
struct rkcanfd_priv *priv = netdev_priv(ndev);
+ close_candev_cancel_restart_sync(ndev);
netif_stop_queue(ndev);
rkcanfd_chip_interrupts_disable(priv);
--
2.34.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH net v2 3/3] can: rockchip_canfd: cancel bus-off restart before closing the device
@ 2026-10-14 2:54 ` Cunhao Lu
0 siblings, 0 replies; 8+ messages in thread
From: Cunhao Lu @ 2026-10-14 2:54 UTC (permalink / raw)
To: Marc Kleine-Budde, Vincent Mailhol, Heiko Stuebner,
David S. Miller, Wolfgang Grandegger, Oliver Hartkopp, kernel
Cc: linux-can, linux-kernel, linux-arm-kernel, linux-rockchip, stable,
Cunhao Lu
The close path cancels restart_work through close_candev() only after
freeing the IRQ, disabling RX offload and stopping the controller. A
running restart can re-enable the controller and its interrupts after
IRQ teardown, or restart timestamp work after it has been stopped and
before runtime suspend removes the controller clocks.
Call close_candev_cancel_restart_sync() at the start of ndo_stop(), while
the resources needed by a running restart are still available. The core
netif_running() check prevents a late restart from entering the driver,
while this cancellation waits for one that has already passed the check.
Keep close_candev() after IRQ teardown for the final cancellation and
echo cleanup, including work queued by an IRQ racing with the first
cancellation.
Exclude the IRQ handler while reinitializing hardware in the restart
callback: the handler continues processing after scheduling recovery,
and a shared interrupt can also invoke it while this controller's
interrupts are masked. Keep the shared IRQ enabled while the close path
waits for restart work to finish.
Fixes: ff60bfbaf67f ("can: rockchip_canfd: add driver for Rockchip CAN-FD controller")
Cc: stable@vger.kernel.org
Signed-off-by: Cunhao Lu <1579567540@qq.com>
---
drivers/net/can/rockchip/rockchip_canfd-core.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/net/can/rockchip/rockchip_canfd-core.c b/drivers/net/can/rockchip/rockchip_canfd-core.c
index 37c1c22c40c9..fb8f6b067502 100644
--- a/drivers/net/can/rockchip/rockchip_canfd-core.c
+++ b/drivers/net/can/rockchip/rockchip_canfd-core.c
@@ -356,8 +356,10 @@ static int rkcanfd_set_mode(struct net_device *ndev,
switch (mode) {
case CAN_MODE_START:
+ disable_irq(ndev->irq);
rkcanfd_chip_start(priv);
rkcanfd_chip_interrupts_enable(priv);
+ enable_irq(ndev->irq);
netif_wake_queue(ndev);
break;
@@ -758,6 +760,7 @@ static int rkcanfd_stop(struct net_device *ndev)
{
struct rkcanfd_priv *priv = netdev_priv(ndev);
+ close_candev_cancel_restart_sync(ndev);
netif_stop_queue(ndev);
rkcanfd_chip_interrupts_disable(priv);
--
2.34.1
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH net v2 3/3] can: rockchip_canfd: cancel bus-off restart before closing the device
2026-10-14 2:54 ` Cunhao Lu
(?)
@ 2026-10-14 3:05 ` sashiko-bot
2026-10-14 4:35 ` Cunhao Lu
-1 siblings, 1 reply; 8+ messages in thread
From: sashiko-bot @ 2026-10-14 3:05 UTC (permalink / raw)
To: Cunhao Lu
Cc: linux-can, Marc Kleine-Budde, Oliver Hartkopp, Vincent Mailhol,
Oleksij Rempel
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] can: rockchip_canfd: disable_irq() called on shared IRQ
--
commit 580402c6870b4c8a3e1db89526b629150785fd7a
Author: Cunhao Lu <1579567540@qq.com>
can: rockchip_canfd: cancel bus-off restart before closing the device
This commit cancels restart_work during the close path before closing the device
to prevent a running restart from re-enabling the controller. It also uses
disable_irq() during the restart callback to prevent the IRQ handler from
running while the hardware is being reinitialized.
> diff --git a/drivers/net/can/rockchip/rockchip_canfd-core.c b/drivers/net/can/rockchip/rockchip_canfd-core.c
> --- a/drivers/net/can/rockchip/rockchip_canfd-core.c
> +++ b/drivers/net/can/rockchip/rockchip_canfd-core.c
> @@ -356,8 +356,10 @@ static int rkcanfd_set_mode(struct net_device *ndev,
>
> switch (mode) {
> case CAN_MODE_START:
> + disable_irq(ndev->irq);
[Severity: Medium]
Is it safe to call disable_irq() here on a shared interrupt line?
In rkcanfd_open(), the IRQ is explicitly registered as shared:
err = request_irq(ndev->irq, rkcanfd_irq, IRQF_SHARED, ndev->name, priv);
Masking a shared IRQ line globally delays or drops interrupts for all other
devices sharing that line.
Could this driver instead use a software flag paired with synchronize_irq()
or spinlocks to exclude the handler, rather than disabling the physical line?
> rkcanfd_chip_start(priv);
> rkcanfd_chip_interrupts_enable(priv);
> + enable_irq(ndev->irq);
> netif_wake_queue(ndev);
> break;
--
Sashiko AI review · https://sashiko.dev/#/patchset/tencent_196A2433801631CD2FA42998465E26316105@qq.com?part=3
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH net v2 3/3] can: rockchip_canfd: cancel bus-off restart before closing the device
2026-10-14 3:05 ` sashiko-bot
@ 2026-10-14 4:35 ` Cunhao Lu
0 siblings, 0 replies; 8+ messages in thread
From: Cunhao Lu @ 2026-10-14 4:35 UTC (permalink / raw)
To: sashiko-reviews
Cc: linux-can, Marc Kleine-Budde, Oliver Hartkopp, Vincent Mailhol,
Oleksij Rempel
Hi,
> [Severity: Medium]
> Is it safe to call disable_irq() here on a shared interrupt line?
>
> In rkcanfd_open(), the IRQ is explicitly registered as shared:
>
> err = request_irq(ndev->irq, rkcanfd_irq, IRQF_SHARED, ndev->name, priv);
>
> Masking a shared IRQ line globally delays or drops interrupts for all other
> devices sharing that line.
>
> Could this driver instead use a software flag paired with synchronize_irq()
> or spinlocks to exclude the handler, rather than disabling the physical line?
>
> > rkcanfd_chip_start(priv);
> > rkcanfd_chip_interrupts_enable(priv);
> > + enable_irq(ndev->irq);
> > netif_wake_queue(ndev);
> > break;
I agree that disable_irq() affects all users of the shared IRQ and
should be avoided here.
The intent was to exclude the IRQ handler while reinitializing the
controller. Masking the controller's own interrupt sources and calling
synchronize_irq() alone would not be sufficient: another device on the
shared line could still invoke rkcanfd_irq() during reinitialization.
I will fix this issue in v3.
Regards,
Cunhao Lu
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-10-14 4:35 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20261014-rockchip-canfd-restart-close-v2-0-c8fbdfad1803@qq.com>
2026-10-14 2:54 ` [PATCH net v2 1/3] can: dev: prevent bus-off recovery when the interface is not running Cunhao Lu
2026-10-14 2:54 ` Cunhao Lu
2026-10-14 2:54 ` [PATCH net v2 2/3] can: dev: add close_candev_cancel_restart_sync() Cunhao Lu
2026-10-14 2:54 ` Cunhao Lu
2026-10-14 2:54 ` [PATCH net v2 3/3] can: rockchip_canfd: cancel bus-off restart before closing the device Cunhao Lu
2026-10-14 2:54 ` Cunhao Lu
2026-10-14 3:05 ` sashiko-bot
2026-10-14 4:35 ` Cunhao Lu
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.