From f902d959626d82422f504760833f78bcbe73df72 Mon Sep 17 00:00:00 2001 From: Shubhi Garg Date: Tue, 21 May 2024 14:23:13 +0530 Subject: [PATCH] drivers: mttcan: fix bus-off restart txfer [Issue]: CAN freezes/stops to send messages after restart from bus-off state. Throws following log from kernel: "write: No buffer space available" [Reason]: When message txfer starts, tx_object (which keeps track of active tx) gets filled. If CAN goes to bus-off state, txfer remains incomplete for some messages. In such case, tx_object bits will not get cleared. It will stop adding more messages in controller RAM. Along with tx_object, from network layer, there are socket echo buffers. When CAN is initialized and up on network, netif_start_queue is pushed to start transmission. When msg txfer starts, socket buffer gets filled and freed only when txfer completes. During bus-off, since network queue remains ON, all the queued msgs get filled in socket buffers and does not allow upcoming msgs. Therefore we see "write: No buffer space available". [Fix]: Clear tx_object when device goes to bus-off state and stop network queue. Start network queue again during restart from bus-off. Bug 4438223 Change-Id: I3cbc6529a90f357372c8b0095bdce4217b133e9b Signed-off-by: Shubhi Garg Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3142091 GVS: buildbot_gerritrpt Reviewed-by: Bibek Basu --- drivers/net/can/mttcan/native/m_ttcan_linux.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/can/mttcan/native/m_ttcan_linux.c b/drivers/net/can/mttcan/native/m_ttcan_linux.c index 5eb5cda0..6f027219 100644 --- a/drivers/net/can/mttcan/native/m_ttcan_linux.c +++ b/drivers/net/can/mttcan/native/m_ttcan_linux.c @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * Copyright (c) 2022-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ #include @@ -505,7 +505,8 @@ static int mttcan_state_change(struct net_device *dev, */ ttcan_set_intrpts(priv->ttcan, 0); priv->can.can_stats.bus_off++; - + priv->ttcan->tx_object = 0; + netif_stop_queue(dev); netif_carrier_off(dev); if (priv->can.restart_ms) @@ -1114,6 +1115,7 @@ restart: priv->can.can_stats.restarts++; mttcan_start(dev); + netif_start_queue(dev); netif_carrier_on(dev); }