Commit ce8f29d3 authored by Gerhard Uttenthaler's avatar Gerhard Uttenthaler Committed by Luis Henriques

can: ems_usb: Fix possible tx overflow

commit 90cfde46 upstream.

This patch fixes the problem that more CAN messages could be sent to the
interface as could be send on the CAN bus. This was more likely for slow baud
rates. The sleeping _start_xmit was woken up in the _write_bulk_callback. Under
heavy TX load this produced another bulk transfer without checking the
free_slots variable and hence caused the overflow in the interface.
Signed-off-by: default avatarGerhard Uttenthaler <uttenthaler@ems-wuensche.com>
Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: default avatarLuis Henriques <luis.henriques@canonical.com>
parent b99166f2
...@@ -117,6 +117,9 @@ MODULE_LICENSE("GPL v2"); ...@@ -117,6 +117,9 @@ MODULE_LICENSE("GPL v2");
*/ */
#define EMS_USB_ARM7_CLOCK 8000000 #define EMS_USB_ARM7_CLOCK 8000000
#define CPC_TX_QUEUE_TRIGGER_LOW 25
#define CPC_TX_QUEUE_TRIGGER_HIGH 35
/* /*
* CAN-Message representation in a CPC_MSG. Message object type is * CAN-Message representation in a CPC_MSG. Message object type is
* CPC_MSG_TYPE_CAN_FRAME or CPC_MSG_TYPE_RTR_FRAME or * CPC_MSG_TYPE_CAN_FRAME or CPC_MSG_TYPE_RTR_FRAME or
...@@ -278,6 +281,11 @@ static void ems_usb_read_interrupt_callback(struct urb *urb) ...@@ -278,6 +281,11 @@ static void ems_usb_read_interrupt_callback(struct urb *urb)
switch (urb->status) { switch (urb->status) {
case 0: case 0:
dev->free_slots = dev->intr_in_buffer[1]; dev->free_slots = dev->intr_in_buffer[1];
if(dev->free_slots > CPC_TX_QUEUE_TRIGGER_HIGH){
if (netif_queue_stopped(netdev)){
netif_wake_queue(netdev);
}
}
break; break;
case -ECONNRESET: /* unlink */ case -ECONNRESET: /* unlink */
...@@ -529,8 +537,6 @@ static void ems_usb_write_bulk_callback(struct urb *urb) ...@@ -529,8 +537,6 @@ static void ems_usb_write_bulk_callback(struct urb *urb)
/* Release context */ /* Release context */
context->echo_index = MAX_TX_URBS; context->echo_index = MAX_TX_URBS;
if (netif_queue_stopped(netdev))
netif_wake_queue(netdev);
} }
/* /*
...@@ -590,7 +596,7 @@ static int ems_usb_start(struct ems_usb *dev) ...@@ -590,7 +596,7 @@ static int ems_usb_start(struct ems_usb *dev)
int err, i; int err, i;
dev->intr_in_buffer[0] = 0; dev->intr_in_buffer[0] = 0;
dev->free_slots = 15; /* initial size */ dev->free_slots = 50; /* initial size */
for (i = 0; i < MAX_RX_URBS; i++) { for (i = 0; i < MAX_RX_URBS; i++) {
struct urb *urb = NULL; struct urb *urb = NULL;
...@@ -841,7 +847,7 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne ...@@ -841,7 +847,7 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne
/* Slow down tx path */ /* Slow down tx path */
if (atomic_read(&dev->active_tx_urbs) >= MAX_TX_URBS || if (atomic_read(&dev->active_tx_urbs) >= MAX_TX_URBS ||
dev->free_slots < 5) { dev->free_slots < CPC_TX_QUEUE_TRIGGER_LOW) {
netif_stop_queue(netdev); netif_stop_queue(netdev);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment