summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWolfgang Grandegger <wg@grandegger.com>2017-09-14 18:37:14 +0200
committerSasha Levin <alexander.levin@verizon.com>2017-11-05 23:54:34 -0500
commitb13ca583e158071685cd80081605bcd81afe20f9 (patch)
tree55da7e36d70c762dd08272839385ace63e09f7dc
parent6983d6cf651e2619e94475a1efd104f46a09f4eb (diff)
downloadlinux-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.c10
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)