[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-Id: <20250811210611.3233202-4-stefan.maetje@esd.eu>
Date: Mon, 11 Aug 2025 23:06:08 +0200
From: Stefan Mätje <stefan.maetje@....eu>
To: Marc Kleine-Budde <mkl@...gutronix.de>,
Vincent Mailhol <mailhol.vincent@...adoo.fr>,
Frank Jungclaus <frank.jungclaus@....eu>,
linux-can@...r.kernel.org,
socketcan@....eu
Cc: Simon Horman <horms@...nel.org>,
Olivier Sobrie <olivier@...rie.be>,
Oliver Hartkopp <socketcan@...tkopp.net>,
netdev@...r.kernel.org
Subject: [PATCH 3/6] can: esd_usb: Fix handling of TX context objects
For each TX CAN frame submitted to the USB device the driver saves the
echo skb index in struct esd_tx_urb_context context objects. If the
driver runs out of free context objects CAN transmission stops.
This patch fixes some spots where such context objects are not freed
correctly.
In esd_usb_tx_done_msg() the check for netif_device_present() is moved
after the identification and release of TX context and the release of
the echo skb. This is allowed even if netif_device_present() would
return false because the mentioned operations don't touch the device
itself but only free local acquired resources. This keeps the context
handling with the acknowledged TX jobs in sync.
In esd_usb_start_xmit() a check is performed to see whether a context
object could be allocated. Added a netif_stop_queue() there before the
function is aborted. This makes sure the network queue is stopped and
avoids getting tons of log messages in a situation without free TX
objects. The adjacent log message now also prints the active jobs
counter making a cross check between active jobs and "no free context"
condition possible.
In esd_usb_start_xmit() the error handling of usb_submit_urb() missed to
free the context object together with the echo skb and decreasing the
job count.
Signed-off-by: Stefan Mätje <stefan.maetje@....eu>
---
drivers/net/can/usb/esd_usb.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/drivers/net/can/usb/esd_usb.c b/drivers/net/can/usb/esd_usb.c
index dbdfffe3a4a0..fc28fb52564c 100644
--- a/drivers/net/can/usb/esd_usb.c
+++ b/drivers/net/can/usb/esd_usb.c
@@ -460,9 +460,6 @@ static void esd_usb_tx_done_msg(struct esd_usb_net_priv *priv,
struct net_device *netdev = priv->netdev;
struct esd_tx_urb_context *context;
- if (!netif_device_present(netdev))
- return;
-
context = &priv->tx_contexts[msg->txdone.hnd & (ESD_USB_MAX_TX_URBS - 1)];
if (!msg->txdone.status) {
@@ -478,6 +475,9 @@ static void esd_usb_tx_done_msg(struct esd_usb_net_priv *priv,
context->echo_index = ESD_USB_MAX_TX_URBS;
atomic_dec(&priv->active_tx_jobs);
+ if (!netif_device_present(netdev))
+ return;
+
netif_wake_queue(netdev);
}
@@ -961,9 +961,11 @@ static netdev_tx_t esd_usb_start_xmit(struct sk_buff *skb,
}
}
- /* This may never happen */
+ /* This should never happen */
if (!context) {
- netdev_warn(netdev, "couldn't find free context\n");
+ netdev_warn(netdev, "No free context. Jobs: %d\n",
+ atomic_read(&priv->active_tx_jobs));
+ netif_stop_queue(netdev);
ret = NETDEV_TX_BUSY;
goto releasebuf;
}
@@ -994,6 +996,8 @@ static netdev_tx_t esd_usb_start_xmit(struct sk_buff *skb,
if (err) {
can_free_echo_skb(netdev, context->echo_index, NULL);
+ /* Release used context on error */
+ context->echo_index = ESD_USB_MAX_TX_URBS;
atomic_dec(&priv->active_tx_jobs);
usb_unanchor_urb(urb);
--
2.34.1
Powered by blists - more mailing lists