diff options
author | Wolfgang Grandegger <wg@grandegger.com> | 2017-09-14 18:37:14 +0200 |
---|---|---|
committer | Sasha Levin <alexander.levin@verizon.com> | 2017-11-05 23:54:34 -0500 |
commit | b13ca583e158071685cd80081605bcd81afe20f9 (patch) | |
tree | 55da7e36d70c762dd08272839385ace63e09f7dc | |
parent | 6983d6cf651e2619e94475a1efd104f46a09f4eb (diff) | |
download | linux-rt-b13ca583e158071685cd80081605bcd81afe20f9.tar.gz |
can: gs_usb: fix busy loop if no more TX context is available
[ Upstream commit 97819f943063b622eca44d3644067c190dc75039 ]
If sending messages with no cable connected, it quickly happens that
there is no more TX context available. Then "gs_can_start_xmit()"
returns with "NETDEV_TX_BUSY" and the upper layer does retry
immediately keeping the CPU busy. To fix that issue, I moved
"atomic_dec(&dev->active_tx_urbs)" from "gs_usb_xmit_callback()" to
the TX done handling in "gs_usb_receive_bulk_callback()". Renaming
"active_tx_urbs" to "active_tx_contexts" and moving it into
"gs_[alloc|free]_tx_context()" would also make sense.
Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
Cc: linux-stable <stable@vger.kernel.org>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
-rw-r--r-- | drivers/net/can/usb/gs_usb.c | 10 |
1 files changed, 2 insertions, 8 deletions
diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index d47ae410ba6c..3b850f390fd7 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -356,6 +356,8 @@ static void gs_usb_recieve_bulk_callback(struct urb *urb) gs_free_tx_context(txc); + atomic_dec(&dev->active_tx_urbs); + netif_wake_queue(netdev); } @@ -444,14 +446,6 @@ static void gs_usb_xmit_callback(struct urb *urb) urb->transfer_buffer_length, urb->transfer_buffer, urb->transfer_dma); - - atomic_dec(&dev->active_tx_urbs); - - if (!netif_device_present(netdev)) - return; - - if (netif_queue_stopped(netdev)) - netif_wake_queue(netdev); } static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb, struct net_device *netdev) |