libpayload: usb: Retry get_descriptor() on failure

Certain Lexar USB disks may fail during the first calls to
get_descriptor(..., DT_CFG, ...) for unknown reasons. Therefore, make
several attempts before giving up.

BUG=chromium:466758
TEST=Manual on Samus. Go to recovery mode, verify that Lexar LJDS70 USB
stick is bootable.
BRANCH=None

Change-Id: I476ac22f9c4f844c60ebc6e53af8c144d70bb9d4
Signed-off-by: Patrick Georgi <pgeorgi@chromium.org>
Original-Commit-Id: 93a0570b343479dd22506ad4d7961f0ea4251f8c
Original-Signed-off-by: Shawn Nematbakhsh <shawnn@chromium.org>
Original-Change-Id: Ie581c7c71c53816065c7f59202581888a79e445e
Original-Reviewed-on: https://chromium-review.googlesource.com/302403
Original-Commit-Ready: Shawn N <shawnn@chromium.org>
Original-Tested-by: Shawn N <shawnn@chromium.org>
Original-Reviewed-by: Julius Werner <jwerner@chromium.org>
Reviewed-on: http://review.coreboot.org/12133
Tested-by: build bot (Jenkins)
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
This commit is contained in:
Shawn Nematbakhsh 2015-09-24 14:45:10 -07:00 committed by Patrick Georgi
parent d1adafec05
commit ff5d0b2518
1 changed files with 24 additions and 7 deletions

View File

@ -149,19 +149,36 @@ get_status (usbdev_t *dev, int intf, int rtype, int len, void *data)
return dev->controller->control (dev, IN, sizeof (dr), &dr, len, data);
}
/*
* Certain Lexar / Micron USB 2.0 disks will fail the get_descriptor(DT_CFG)
* call due to timing issues. Work around this by making extra attempts on
* failure.
*/
#define GET_DESCRIPTOR_TRIES 3
int
get_descriptor (usbdev_t *dev, int rtype, int descType, int descIdx,
get_descriptor(usbdev_t *dev, int rtype, int desc_type, int desc_idx,
void *data, size_t len)
{
dev_req_t dr;
int fail_tries = 0;
int ret = 0;
dr.bmRequestType = rtype;
dr.bRequest = GET_DESCRIPTOR;
dr.wValue = descType << 8 | descIdx;
dr.wIndex = 0;
dr.wLength = len;
while (fail_tries++ < GET_DESCRIPTOR_TRIES) {
dr.bmRequestType = rtype;
dr.bRequest = GET_DESCRIPTOR;
dr.wValue = desc_type << 8 | desc_idx;
dr.wIndex = 0;
dr.wLength = len;
return dev->controller->control (dev, IN, sizeof (dr), &dr, len, data);
ret = dev->controller->control(dev, IN,
sizeof(dr), &dr, len, data);
if (ret)
udelay(10);
else
return 0;
}
return ret;
}
int