diff options
author | Olivier Sobrie <olivier@sobrie.be> | 2014-04-10 23:44:21 +0400 |
---|---|---|
committer | Marc Kleine-Budde <mkl@pengutronix.de> | 2014-04-25 00:54:16 +0400 |
commit | e59e36e7333702d1d835113ced85243bb7f30f99 (patch) | |
tree | d440b886917c2095cacb9259634eaa6d7c602314 /drivers/net/can | |
parent | 869ba1e67a894f45ba3da32af66f25104fab7d8f (diff) | |
download | linux-e59e36e7333702d1d835113ced85243bb7f30f99.tar.xz |
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>
Diffstat (limited to 'drivers/net/can')
-rw-r--r-- | drivers/net/can/usb/kvaser_usb.c | 49 |
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, void *buf; int actual_len; int err; - int pos = 0; + int pos; + unsigned long to = jiffies + msecs_to_jiffies(USB_RECV_TIMEOUT); buf = kzalloc(RX_BUFFER_SIZE, GFP_KERNEL); if (!buf) return -ENOMEM; - err = usb_bulk_msg(dev->udev, - usb_rcvbulkpipe(dev->udev, - dev->bulk_in->bEndpointAddress), - buf, RX_BUFFER_SIZE, &actual_len, - USB_RECV_TIMEOUT); - if (err < 0) - goto end; + do { + err = usb_bulk_msg(dev->udev, + usb_rcvbulkpipe(dev->udev, + dev->bulk_in->bEndpointAddress), + buf, RX_BUFFER_SIZE, &actual_len, + USB_RECV_TIMEOUT); + if (err < 0) + goto end; - while (pos <= actual_len - MSG_HEADER_LEN) { - tmp = buf + pos; + pos = 0; + while (pos <= actual_len - MSG_HEADER_LEN) { + tmp = buf + pos; - if (!tmp->len) - break; + if (!tmp->len) + break; - if (pos + tmp->len > actual_len) { - dev_err(dev->udev->dev.parent, "Format error\n"); - break; - } + if (pos + tmp->len > actual_len) { + dev_err(dev->udev->dev.parent, + "Format error\n"); + break; + } - if (tmp->id == id) { - memcpy(msg, tmp, tmp->len); - goto end; - } + if (tmp->id == id) { + memcpy(msg, tmp, tmp->len); + goto end; + } - pos += tmp->len; - } + pos += tmp->len; + } + } while (time_before(jiffies, to)); err = -EINVAL; |