From af169f4dd515f52e26c4c476c3340a710db69887 Mon Sep 17 00:00:00 2001 From: Nico Huber Date: Thu, 22 Nov 2012 11:14:03 +0100 Subject: 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 Reviewed-on: http://review.coreboot.org/1902 Reviewed-by: Patrick Georgi Tested-by: build bot (Jenkins) --- payloads/libpayload/drivers/usb/ehci.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'payloads/libpayload/drivers') 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); } -- cgit v1.2.3