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>
This commit is contained in:
committed by
Marc Kleine-Budde
parent
869ba1e67a
commit
e59e36e733
@@ -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)
|
||||||
|
|
||||||
while (pos <= actual_len - MSG_HEADER_LEN) {
|
|
||||||
tmp = buf + pos;
|
|
||||||
|
|
||||||
if (!tmp->len)
|
|
||||||
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;
|
goto end;
|
||||||
}
|
|
||||||
|
|
||||||
pos += tmp->len;
|
pos = 0;
|
||||||
}
|
while (pos <= actual_len - MSG_HEADER_LEN) {
|
||||||
|
tmp = buf + pos;
|
||||||
|
|
||||||
|
if (!tmp->len)
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos += tmp->len;
|
||||||
|
}
|
||||||
|
} while (time_before(jiffies, to));
|
||||||
|
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user