aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlivier Sobrie <olivier@sobrie.be>2014-04-10 15:44:21 -0400
committerMarc Kleine-Budde <mkl@pengutronix.de>2014-04-24 16:54:16 -0400
commite59e36e7333702d1d835113ced85243bb7f30f99 (patch)
treed440b886917c2095cacb9259634eaa6d7c602314
parent869ba1e67a894f45ba3da32af66f25104fab7d8f (diff)
can: kvaser_usb: add retries/timeout to kvaser_usb_wait_msg()
On some Kvaser hardware, the firmware returns extra messages after the request for card info. For instance on a Leaf Light v2: --> CMD_GET_CARD_INFO <-- CMD_USB_THROTTLE <-- CMD_GET_CARD_INFO2 <-- CMD_GET_CARD_INFO_REQ When it happens, the probing function fails because we only read the first usb message. To overcome this issue, we add a mechanism of retries to the kvaser_usb_wait_msg() function. I tested this patch with the following hardware: - Kvaser Leaf Light - Kvaser Leaf Light v2 - Kvaser USBCan R This patch is necessary for the Leaf Light v2 hardware. Signed-off-by: Olivier Sobrie <olivier@sobrie.be> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
-rw-r--r--drivers/net/can/usb/kvaser_usb.c49
1 files changed, 27 insertions, 22 deletions
diff --git a/drivers/net/can/usb/kvaser_usb.c b/drivers/net/can/usb/kvaser_usb.c
index 4ca46edc061d..7a1c5ec23268 100644
--- a/drivers/net/can/usb/kvaser_usb.c
+++ b/drivers/net/can/usb/kvaser_usb.c
@@ -379,38 +379,43 @@ static int kvaser_usb_wait_msg(const struct kvaser_usb *dev, u8 id,
379 void *buf; 379 void *buf;
380 int actual_len; 380 int actual_len;
381 int err; 381 int err;
382 int pos = 0; 382 int pos;
383 unsigned long to = jiffies + msecs_to_jiffies(USB_RECV_TIMEOUT);
383 384
384 buf = kzalloc(RX_BUFFER_SIZE, GFP_KERNEL); 385 buf = kzalloc(RX_BUFFER_SIZE, GFP_KERNEL);
385 if (!buf) 386 if (!buf)
386 return -ENOMEM; 387 return -ENOMEM;
387 388
388 err = usb_bulk_msg(dev->udev, 389 do {
389 usb_rcvbulkpipe(dev->udev, 390 err = usb_bulk_msg(dev->udev,
390 dev->bulk_in->bEndpointAddress), 391 usb_rcvbulkpipe(dev->udev,
391 buf, RX_BUFFER_SIZE, &actual_len, 392 dev->bulk_in->bEndpointAddress),
392 USB_RECV_TIMEOUT); 393 buf, RX_BUFFER_SIZE, &actual_len,
393 if (err < 0) 394 USB_RECV_TIMEOUT);
394 goto end; 395 if (err < 0)
396 goto end;
395 397
396 while (pos <= actual_len - MSG_HEADER_LEN) { 398 pos = 0;
397 tmp = buf + pos; 399 while (pos <= actual_len - MSG_HEADER_LEN) {
400 tmp = buf + pos;
398 401
399 if (!tmp->len) 402 if (!tmp->len)
400 break; 403 break;
401 404
402 if (pos + tmp->len > actual_len) { 405 if (pos + tmp->len > actual_len) {
403 dev_err(dev->udev->dev.parent, "Format error\n"); 406 dev_err(dev->udev->dev.parent,
404 break; 407 "Format error\n");
405 } 408 break;
409 }
406 410
407 if (tmp->id == id) { 411 if (tmp->id == id) {
408 memcpy(msg, tmp, tmp->len); 412 memcpy(msg, tmp, tmp->len);
409 goto end; 413 goto end;
410 } 414 }
411 415
412 pos += tmp->len; 416 pos += tmp->len;
413 } 417 }
418 } while (time_before(jiffies, to));
414 419
415 err = -EINVAL; 420 err = -EINVAL;
416 421