[U-Boot] [PATCH 14/17] musb-new: Properly remove a transfer from the schedule on timeout

Hans de Goede hdegoede at redhat.com
Sun Jan 11 20:34:52 CET 2015


If a transfer / urb times-out, properly remove it from the schedule, rather
then letting it sit on the ep head. This stops the musb code from getting
confused and refusing to queue further transfers after a timeout.

Tested by unplugging a usb-keyboard, replugging it and doing a usb-reset,
before this commit the keyboard would not work after the usb-reset.

Signed-off-by: Hans de Goede <hdegoede at redhat.com>
---
 drivers/usb/musb-new/musb_host.c  | 12 +++++++++---
 drivers/usb/musb-new/musb_host.h  |  1 +
 drivers/usb/musb-new/musb_uboot.c |  3 +++
 drivers/usb/musb-new/usb-compat.h |  1 +
 4 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/musb-new/musb_host.c b/drivers/usb/musb-new/musb_host.c
index bbcee88..437309c 100644
--- a/drivers/usb/musb-new/musb_host.c
+++ b/drivers/usb/musb-new/musb_host.c
@@ -2130,8 +2130,6 @@ done:
 	return ret;
 }
 
-
-#ifndef __UBOOT__
 /*
  * abort a transfer that's at the head of a hardware queue.
  * called with controller locked, irqs blocked
@@ -2195,7 +2193,14 @@ static int musb_cleanup_urb(struct urb *urb, struct musb_qh *qh)
 	return status;
 }
 
-static int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+#ifndef __UBOOT__
+static int musb_urb_dequeue(
+#else
+int musb_urb_dequeue(
+#endif
+	struct usb_hcd *hcd,
+	struct urb *urb,
+	int status)
 {
 	struct musb		*musb = hcd_to_musb(hcd);
 	struct musb_qh		*qh;
@@ -2253,6 +2258,7 @@ done:
 	return ret;
 }
 
+#ifndef __UBOOT__
 /* disable an endpoint */
 static void
 musb_h_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep)
diff --git a/drivers/usb/musb-new/musb_host.h b/drivers/usb/musb-new/musb_host.h
index ebebe0c..546b4a2 100644
--- a/drivers/usb/musb-new/musb_host.h
+++ b/drivers/usb/musb-new/musb_host.h
@@ -110,5 +110,6 @@ static inline struct urb *next_urb(struct musb_qh *qh)
 
 #ifdef __UBOOT__
 int musb_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags);
+int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status);
 #endif
 #endif				/* _MUSB_HOST_H */
diff --git a/drivers/usb/musb-new/musb_uboot.c b/drivers/usb/musb-new/musb_uboot.c
index dab6f9b..e823ad1 100644
--- a/drivers/usb/musb-new/musb_uboot.c
+++ b/drivers/usb/musb-new/musb_uboot.c
@@ -77,6 +77,9 @@ static int submit_urb(struct usb_hcd *hcd, struct urb *urb)
 	} while (urb->status == -EINPROGRESS &&
 		 get_timer(0) < timeout);
 
+	if (urb->status == -EINPROGRESS)
+		musb_urb_dequeue(hcd, urb, -ETIME);
+
 	return urb->status;
 }
 
diff --git a/drivers/usb/musb-new/usb-compat.h b/drivers/usb/musb-new/usb-compat.h
index 27f656f..50bad37 100644
--- a/drivers/usb/musb-new/usb-compat.h
+++ b/drivers/usb/musb-new/usb-compat.h
@@ -48,6 +48,7 @@ struct urb {
 	list_add_tail(&urb->urb_list, &urb->ep->urb_list);	\
 	ret; })
 #define usb_hcd_unlink_urb_from_ep(hcd, urb)	list_del_init(&urb->urb_list)
+#define usb_hcd_check_unlink_urb(hdc, urb, status)	0
 
 static inline void usb_hcd_giveback_urb(struct usb_hcd *hcd,
 					struct urb *urb,
-- 
2.1.0



More information about the U-Boot mailing list