diff mbox

[3.13.y-ckt,stable] Patch "can: kvaser_usb: Read all messages in a bulk-in URB buffer" has been added to staging queue

Message ID 1428357517-17066-1-git-send-email-kamal@canonical.com
State New
Headers show

Commit Message

Kamal Mostafa April 6, 2015, 9:58 p.m. UTC
This is a note to let you know that I have just added a patch titled

    can: kvaser_usb: Read all messages in a bulk-in URB buffer

to the linux-3.13.y-queue branch of the 3.13.y-ckt extended stable tree 
which can be found at:

 http://kernel.ubuntu.com/git?p=ubuntu/linux.git;a=shortlog;h=refs/heads/linux-3.13.y-queue

This patch is scheduled to be released in version 3.13.11-ckt19.

If you, or anyone else, feels it should not be added to this tree, please 
reply to this email.

For more information about the 3.13.y-ckt tree, see
https://wiki.ubuntu.com/Kernel/Dev/ExtendedStable

Thanks.
-Kamal

------

From 1d9cf1d4d115eb00805e6bacbfd30305cfc5610f Mon Sep 17 00:00:00 2001
From: "Ahmed S. Darwish" <ahmed.darwish@valeo.com>
Date: Thu, 26 Feb 2015 10:22:02 -0500
Subject: can: kvaser_usb: Read all messages in a bulk-in URB buffer

commit 2fec5104f9c61de4cf2205aa355101e19a81f490 upstream.

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>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Kamal Mostafa <kamal@canonical.com>
---
 drivers/net/can/usb/kvaser_usb.c | 28 +++++++++++++++++++++++-----
 1 file changed, 23 insertions(+), 5 deletions(-)

--
1.9.1
diff mbox

Patch

diff --git a/drivers/net/can/usb/kvaser_usb.c b/drivers/net/can/usb/kvaser_usb.c
index bc8506d..3b2623b 100644
--- a/drivers/net/can/usb/kvaser_usb.c
+++ b/drivers/net/can/usb/kvaser_usb.c
@@ -12,6 +12,7 @@ 
  * Copyright (C) 2012 Olivier Sobrie <olivier@sobrie.be>
  */

+#include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/completion.h>
 #include <linux/module.h>
@@ -397,8 +398,15 @@  static int kvaser_usb_wait_msg(const struct kvaser_usb *dev, u8 id,
 	while (pos <= actual_len - MSG_HEADER_LEN) {
 		tmp = buf + pos;

-		if (!tmp->len)
-			break;
+		/* Handle messages crossing the USB endpoint max packet
+		 * size boundary. Check kvaser_usb_read_bulk_callback()
+		 * for further details.
+		 */
+		if (tmp->len == 0) {
+			pos = round_up(pos,
+				       dev->bulk_in->wMaxPacketSize);
+			continue;
+		}

 		if (pos + tmp->len > actual_len) {
 			dev_err(dev->udev->dev.parent, "Format error\n");
@@ -974,8 +982,19 @@  static void kvaser_usb_read_bulk_callback(struct urb *urb)
 	while (pos <= urb->actual_length - MSG_HEADER_LEN) {
 		msg = urb->transfer_buffer + pos;

-		if (!msg->len)
-			break;
+		/* The Kvaser firmware can only read and write messages that
+		 * does not cross the USB's endpoint wMaxPacketSize boundary.
+		 * If a follow-up command crosses such boundary, firmware puts
+		 * a placeholder zero-length command in its place then aligns
+		 * the real command to the next max packet size.
+		 *
+		 * Handle such cases or we're going to miss a significant
+		 * number of events in case of a heavy rx load on the bus.
+		 */
+		if (msg->len == 0) {
+			pos = round_up(pos, dev->bulk_in->wMaxPacketSize);
+			continue;
+		}

 		if (pos + msg->len > urb->actual_length) {
 			dev_err(dev->udev->dev.parent, "Format error\n");
@@ -983,7 +1002,6 @@  static void kvaser_usb_read_bulk_callback(struct urb *urb)
 		}

 		kvaser_usb_handle_message(dev, msg);
-
 		pos += msg->len;
 	}