aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/can
diff options
context:
space:
mode:
authorAhmed S. Darwish <ahmed.darwish@valeo.com>2015-02-26 10:22:02 -0500
committerMarc Kleine-Budde <mkl@pengutronix.de>2015-03-09 05:22:24 -0400
commit2fec5104f9c61de4cf2205aa355101e19a81f490 (patch)
tree7c3fa357f160f9bf6dc44d6d4a87bc73ac4117a5 /drivers/net/can
parentdeb2701cf704a2fd03a8b598bf73df3edb08818d (diff)
can: kvaser_usb: Read all messages in a bulk-in URB buffer
The Kvaser firmware can only read and write messages that are not crossing the USB endpoint's wMaxPacketSize boundary. While receiving commands from the CAN device, if the next command in the same URB buffer crossed that max packet size boundary, the firmware puts a zero-length placeholder command in its place then moves the real command to the next boundary mark. The driver did not recognize such behavior, leading to missing a good number of rx events during a heavy rx load session. Moreover, a tx URB context only gets freed upon receiving its respective tx ACK event. Over time, the free tx URB contexts pool gets depleted due to the missing ACK events. Consequently, the netif transmission queue gets __permanently__ stopped; no frames could be sent again except after restarting the CAN newtwork interface. Signed-off-by: Ahmed S. Darwish <ahmed.darwish@valeo.com> Cc: linux-stable <stable@vger.kernel.org> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Diffstat (limited to 'drivers/net/can')
-rw-r--r--drivers/net/can/usb/kvaser_usb.c28
1 files changed, 23 insertions, 5 deletions
diff --git a/drivers/net/can/usb/kvaser_usb.c b/drivers/net/can/usb/kvaser_usb.c
index d986fe83c40d..a316fa4b91ab 100644
--- a/drivers/net/can/usb/kvaser_usb.c
+++ b/drivers/net/can/usb/kvaser_usb.c
@@ -14,6 +14,7 @@
14 * Copyright (C) 2015 Valeo S.A. 14 * Copyright (C) 2015 Valeo S.A.
15 */ 15 */
16 16
17#include <linux/kernel.h>
17#include <linux/completion.h> 18#include <linux/completion.h>
18#include <linux/module.h> 19#include <linux/module.h>
19#include <linux/netdevice.h> 20#include <linux/netdevice.h>
@@ -584,8 +585,15 @@ static int kvaser_usb_wait_msg(const struct kvaser_usb *dev, u8 id,
584 while (pos <= actual_len - MSG_HEADER_LEN) { 585 while (pos <= actual_len - MSG_HEADER_LEN) {
585 tmp = buf + pos; 586 tmp = buf + pos;
586 587
587 if (!tmp->len) 588 /* Handle messages crossing the USB endpoint max packet
588 break; 589 * size boundary. Check kvaser_usb_read_bulk_callback()
590 * for further details.
591 */
592 if (tmp->len == 0) {
593 pos = round_up(pos,
594 dev->bulk_in->wMaxPacketSize);
595 continue;
596 }
589 597
590 if (pos + tmp->len > actual_len) { 598 if (pos + tmp->len > actual_len) {
591 dev_err(dev->udev->dev.parent, 599 dev_err(dev->udev->dev.parent,
@@ -1316,8 +1324,19 @@ static void kvaser_usb_read_bulk_callback(struct urb *urb)
1316 while (pos <= urb->actual_length - MSG_HEADER_LEN) { 1324 while (pos <= urb->actual_length - MSG_HEADER_LEN) {
1317 msg = urb->transfer_buffer + pos; 1325 msg = urb->transfer_buffer + pos;
1318 1326
1319 if (!msg->len) 1327 /* The Kvaser firmware can only read and write messages that
1320 break; 1328 * does not cross the USB's endpoint wMaxPacketSize boundary.
1329 * If a follow-up command crosses such boundary, firmware puts
1330 * a placeholder zero-length command in its place then aligns
1331 * the real command to the next max packet size.
1332 *
1333 * Handle such cases or we're going to miss a significant
1334 * number of events in case of a heavy rx load on the bus.
1335 */
1336 if (msg->len == 0) {
1337 pos = round_up(pos, dev->bulk_in->wMaxPacketSize);
1338 continue;
1339 }
1321 1340
1322 if (pos + msg->len > urb->actual_length) { 1341 if (pos + msg->len > urb->actual_length) {
1323 dev_err(dev->udev->dev.parent, "Format error\n"); 1342 dev_err(dev->udev->dev.parent, "Format error\n");
@@ -1325,7 +1344,6 @@ static void kvaser_usb_read_bulk_callback(struct urb *urb)
1325 } 1344 }
1326 1345
1327 kvaser_usb_handle_message(dev, msg); 1346 kvaser_usb_handle_message(dev, msg);
1328
1329 pos += msg->len; 1347 pos += msg->len;
1330 } 1348 }
1331 1349