musb-new: Properly remove a transfer from the schedule on timeout
authorHans de Goede <hdegoede@redhat.com>
Sun, 11 Jan 2015 19:34:52 +0000 (20:34 +0100)
committerMarek Vasut <marex@denx.de>
Sun, 18 Jan 2015 11:31:36 +0000 (12:31 +0100)
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@redhat.com>
drivers/usb/musb-new/musb_host.c
drivers/usb/musb-new/musb_host.h
drivers/usb/musb-new/musb_uboot.c
drivers/usb/musb-new/usb-compat.h

index bbcee88241ba33f05cafad51d3162bc63bc12021..437309ceb44a380bfed9b05d73d6f9828db08210 100644 (file)
@@ -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)
index ebebe0c02a57c61b6cd9cb881990714feb0d5c6b..546b4a2715f4549c96e0b426f2dad78e86a1772f 100644 (file)
@@ -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 */
index dab6f9b2134bbe39f54343df47b781196bf55168..e823ad1a747de6d5e62a34eb2b5857bb98a127c2 100644 (file)
@@ -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;
 }
 
index 27f656f0ce518149dddcaae86d63ddc0e9d2f0f4..50bad378c5de95c6527cc1016021a790d4daa087 100644 (file)
@@ -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,