summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNico Huber <nico.huber@secunet.com>2012-11-22 11:14:03 +0100
committerPatrick Georgi <patrick@georgi-clan.de>2012-11-23 18:18:59 +0100
commitaf169f4dd515f52e26c4c476c3340a710db69887 (patch)
treef1727b8facc20f74827fad6f1a598a5242642b12
parentb2db28babe0e64e08b1a754b65dd7e437f8d82a9 (diff)
libpayload: ehci: Prevent some race conditions
Prevent race conditions, when an interrupt-queue underrun occurred and the controller is currently working on our queue head or a transfer is still in progress. Change-Id: Ia14f80a08071306ee5d1349780be081bfacb206a Signed-off-by: Nico Huber <nico.huber@secunet.com> Reviewed-on: http://review.coreboot.org/1902 Reviewed-by: Patrick Georgi <patrick@georgi-clan.de> Tested-by: build bot (Jenkins)
-rw-r--r--payloads/libpayload/drivers/usb/ehci.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/payloads/libpayload/drivers/usb/ehci.c b/payloads/libpayload/drivers/usb/ehci.c
index 4ff137e40b..6a1cfb5791 100644
--- a/payloads/libpayload/drivers/usb/ehci.c
+++ b/payloads/libpayload/drivers/usb/ehci.c
@@ -626,8 +626,14 @@ static u8 *ehci_poll_intr_queue(void *const queue)
intrq->head = intrq->head->next;
}
/* reset queue if we fully processed it after underrun */
- else if (intrq->qh.td.next_qtd & QTD_TERMINATE) {
+ else if ((intrq->qh.td.next_qtd & QTD_TERMINATE) &&
+ /* to prevent race conditions:
+ not our head and not active */
+ (intrq->qh.current_td_ptr !=
+ virt_to_phys(&intrq->head->td)) &&
+ !(intrq->qh.td.token & QTD_ACTIVE)) {
usb_debug("resetting underrun ehci interrupt queue.\n");
+ intrq->qh.current_td_ptr = 0;
memset((void *)&intrq->qh.td, 0, sizeof(intrq->qh.td));
intrq->qh.td.next_qtd = virt_to_phys(&intrq->head->td);
}