Commit e59e36e7 authored by Olivier Sobrie's avatar Olivier Sobrie Committed by Marc Kleine-Budde

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: default avatarOlivier Sobrie <olivier@sobrie.be>
Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
parent 869ba1e6
...@@ -379,38 +379,43 @@ static int kvaser_usb_wait_msg(const struct kvaser_usb *dev, u8 id, ...@@ -379,38 +379,43 @@ static int kvaser_usb_wait_msg(const struct kvaser_usb *dev, u8 id,
void *buf; void *buf;
int actual_len; int actual_len;
int err; int err;
int pos = 0; int pos;
unsigned long to = jiffies + msecs_to_jiffies(USB_RECV_TIMEOUT);
buf = kzalloc(RX_BUFFER_SIZE, GFP_KERNEL); buf = kzalloc(RX_BUFFER_SIZE, GFP_KERNEL);
if (!buf) if (!buf)
return -ENOMEM; return -ENOMEM;
err = usb_bulk_msg(dev->udev, do {
usb_rcvbulkpipe(dev->udev, err = usb_bulk_msg(dev->udev,
dev->bulk_in->bEndpointAddress), usb_rcvbulkpipe(dev->udev,
buf, RX_BUFFER_SIZE, &actual_len, dev->bulk_in->bEndpointAddress),
USB_RECV_TIMEOUT); buf, RX_BUFFER_SIZE, &actual_len,
if (err < 0) USB_RECV_TIMEOUT);
goto end; if (err < 0)
goto end;
while (pos <= actual_len - MSG_HEADER_LEN) { pos = 0;
tmp = buf + pos; while (pos <= actual_len - MSG_HEADER_LEN) {
tmp = buf + pos;
if (!tmp->len) if (!tmp->len)
break; break;
if (pos + tmp->len > actual_len) { if (pos + tmp->len > actual_len) {
dev_err(dev->udev->dev.parent, "Format error\n"); dev_err(dev->udev->dev.parent,
break; "Format error\n");
} break;
}
if (tmp->id == id) { if (tmp->id == id) {
memcpy(msg, tmp, tmp->len); memcpy(msg, tmp, tmp->len);
goto end; goto end;
} }
pos += tmp->len; pos += tmp->len;
} }
} while (time_before(jiffies, to));
err = -EINVAL; err = -EINVAL;
......
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