[U-Boot] [PATCH 06/11] usb: ehci: Add timeout on interrupt endpoint operations

Simon Glass sjg at chromium.org
Thu Dec 13 02:55:26 CET 2012


From: Vincent Palatin <vpalatin at chromium.org>

Ensure we cannot get stuck in the keyboard scanning if something wrong
happens (USB device unplugged or fatal I/O error)

Signed-off-by: Vincent Palatin <vpalatin at chromium.org>

Signed-off-by: Simon Glass <sjg at chromium.org>
---
 drivers/usb/host/ehci-hcd.c |   18 ++++++++++++++++--
 1 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 0f4bc49..51aa4b3 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1191,6 +1191,7 @@ destroy_int_queue(struct usb_device *dev, struct int_queue *queue)
 {
 	struct ehci_ctrl *ctrl = dev->controller;
 	int result = -1;
+	unsigned long timeout;
 
 	if (disable_periodic(ctrl) < 0) {
 		debug("FATAL: periodic should never fail, but did");
@@ -1199,6 +1200,7 @@ destroy_int_queue(struct usb_device *dev, struct int_queue *queue)
 	periodic_schedules--;
 
 	struct QH *cur = &ctrl->periodic_queue;
+	timeout = get_timer(0) + 500; /* abort after 500ms */
 	while (!(cur->qh_link & QH_LINK_TERMINATE)) {
 		debug("considering %p, with qh_link %x\n", cur, cur->qh_link);
 		if (NEXT_QH(cur) == queue->first) {
@@ -1208,6 +1210,11 @@ destroy_int_queue(struct usb_device *dev, struct int_queue *queue)
 			goto out;
 		}
 		cur = NEXT_QH(cur);
+		if (get_timer(0) > timeout) {
+			printf("Timeout destroying interrupt endpoint queue\n");
+			result = -1;
+			break;
+		}
 	}
 
 	if (periodic_schedules > 0)
@@ -1229,6 +1236,8 @@ submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
 {
 	void *backbuffer;
 	struct int_queue *queue;
+	unsigned long timeout;
+	int result = 0;
 
 	debug("dev=%p, pipe=%lu, buffer=%p, length=%d, interval=%d",
 	      dev, pipe, buffer, length, interval);
@@ -1253,8 +1262,13 @@ submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
 	queue = create_int_queue(dev, pipe, 1, length, buffer);
 
 	/* TODO: pick some useful timeout rule */
+	timeout = get_timer(0) + USB_TIMEOUT_MS(pipe);
 	while ((backbuffer = poll_int_queue(dev, queue)) == NULL)
-		;
+		if (get_timer(0) > timeout) {
+			printf("Timeout poll on interrupt endpoint\n");
+			result = -1;
+			break;
+		}
 
 	if (backbuffer != buffer) {
 		debug("got wrong buffer back (%x instead of %x)\n",
@@ -1266,5 +1280,5 @@ submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
 		return -1;
 
 	/* everything worked out fine */
-	return 0;
+	return result;
 }
-- 
1.7.7.3



More information about the U-Boot mailing list