diff options
author | Nico Huber <nico.huber@secunet.com> | 2012-05-21 14:46:26 +0200 |
---|---|---|
committer | Stefan Reinauer <stefan.reinauer@coreboot.org> | 2012-06-07 23:49:02 +0200 |
commit | afe86c0b74cc7f5dcaefc34155daf299e8377353 (patch) | |
tree | 398d5b1caf5cbdd81f3b3764420343dabc52a455 /payloads/libpayload/drivers/usb/ohci.c | |
parent | 5e3428ea2093e028c7f976b69032b1882e10e6ca (diff) | |
download | coreboot-afe86c0b74cc7f5dcaefc34155daf299e8377353.tar.xz |
libpayload: Add timeouts in the OHCI USB driver
We should always have some timeout when we wait for the hardware. This adds
missing timeouts and a more standard compliant port reset to the OHCI driver.
Change-Id: I2cfcb1039fd12f291e88dcb8b74d41cb5bb2315e
Signed-off-by: Nico Huber <nico.huber@secunet.com>
Reviewed-on: http://review.coreboot.org/1076
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Diffstat (limited to 'payloads/libpayload/drivers/usb/ohci.c')
-rw-r--r-- | payloads/libpayload/drivers/usb/ohci.c | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/payloads/libpayload/drivers/usb/ohci.c b/payloads/libpayload/drivers/usb/ohci.c index 73120a85da..4b3aa39c6c 100644 --- a/payloads/libpayload/drivers/usb/ohci.c +++ b/payloads/libpayload/drivers/usb/ohci.c @@ -195,14 +195,23 @@ dump_td(td_t *cur, int level) } static int -wait_for_ed(usbdev_t *dev, ed_t *head) +wait_for_ed(usbdev_t *dev, ed_t *head, int pages) { td_t *cur; /* wait for results */ + /* TODO: how long to wait? + * give 50ms per page plus another 100ms for now + * this should even work with low-speed + */ + int timeout = pages*50 + 100; while (((head->head_pointer & ~3) != head->tail_pointer) && !(head->head_pointer & 1) && - ((((td_t*)phys_to_virt(head->head_pointer & ~3))->config & TD_CC_MASK) >= TD_CC_NOACCESS)) { + ((((td_t*)phys_to_virt(head->head_pointer & ~3))->config + & TD_CC_MASK) >= TD_CC_NOACCESS) && + timeout--) { + /* don't log every ms */ + if (!(timeout % 100)) debug("intst: %x; ctrl: %x; cmdst: %x; head: %x -> %x, tail: %x, condition: %x\n", OHCI_INST(dev->controller)->opreg->HcInterruptStatus, OHCI_INST(dev->controller)->opreg->HcControl, @@ -213,6 +222,9 @@ wait_for_ed(usbdev_t *dev, ed_t *head) (((td_t*)phys_to_virt(head->head_pointer & ~3))->config & TD_CC_MASK) >> TD_CC_SHIFT); mdelay(1); } + if (timeout < 0) + printf("Error: ohci: endpoint " + "descriptor processing timed out.\n"); #if 0 /* XXX: The following debugging code may follow invalid lists and * cause a reboot. @@ -341,7 +353,8 @@ ohci_control (usbdev_t *dev, direction_t dir, int drlen, void *devreq, int dalen OHCI_INST(dev->controller)->opreg->HcControl |= ControlListEnable; OHCI_INST(dev->controller)->opreg->HcCommandStatus = ControlListFilled; - int failure = wait_for_ed(dev, head); + int failure = wait_for_ed(dev, head, + (dalen==0)?0:(last_page - first_page + 1)); OHCI_INST(dev->controller)->opreg->HcControl &= ~ControlListEnable; /* free memory */ @@ -430,7 +443,8 @@ ohci_bulk (endpoint_t *ep, int dalen, u8 *data, int finalize) OHCI_INST(ep->dev->controller)->opreg->HcControl |= BulkListEnable; OHCI_INST(ep->dev->controller)->opreg->HcCommandStatus = BulkListFilled; - int failure = wait_for_ed(ep->dev, head); + int failure = wait_for_ed(ep->dev, head, + (dalen==0)?0:(last_page - first_page + 1)); OHCI_INST(ep->dev->controller)->opreg->HcControl &= ~BulkListEnable; ep->toggle = head->head_pointer & ED_TOGGLE; |