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>
This commit is contained in:
committed by
Stefan Reinauer
parent
5e3428ea20
commit
afe86c0b74
@@ -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;
|
||||
|
Reference in New Issue
Block a user