This patch (as1584) fixes a minor bug that has been present in
ehci-hcd since the beginning.

Scanning the schedules for URB completions is single-threaded.  If a
completion interrupt occurs while an URB is being given back, the
interrupt handler realizes that a scan is in progress on another CPU
and avoids starting a new one.

This means that completion events can be lost.  If an URB completes
after it has been scanned but while a scan is still in progress, the
driver won't notice and won't rescan the completed URB.

The patch fixes the problem by adding a new flag to indicate that
another scan is needed after the current scan is done.  The flag gets
set whenever a completion interrupt occurs while a scan is in
progress.  The rescan will see the completion, thus preventing it from
getting lost.

Signed-off-by: Alan Stern <st...@rowland.harvard.edu>

---

 drivers/usb/host/ehci-hcd.c |   13 ++++++++++---
 drivers/usb/host/ehci.h     |    3 ++-
 2 files changed, 12 insertions(+), 4 deletions(-)

Index: usb-3.4/drivers/usb/host/ehci.h
===================================================================
--- usb-3.4.orig/drivers/usb/host/ehci.h
+++ usb-3.4/drivers/usb/host/ehci.h
@@ -113,7 +113,8 @@ struct ehci_hcd {                   /* one per controlle
        enum ehci_rh_state      rh_state;
 
        /* general schedule support */
-       unsigned                scanning:1;
+       bool                    scanning:1;
+       bool                    need_rescan:1;
        bool                    intr_unlinking:1;
        bool                    async_unlinking:1;
 
Index: usb-3.4/drivers/usb/host/ehci-hcd.c
===================================================================
--- usb-3.4.orig/drivers/usb/host/ehci-hcd.c
+++ usb-3.4/drivers/usb/host/ehci-hcd.c
@@ -400,14 +400,21 @@ static void ehci_work (struct ehci_hcd *
         * it reports urb completions.  this flag guards against bogus
         * attempts at re-entrant schedule scanning.
         */
-       if (ehci->scanning)
+       if (ehci->scanning) {
+               ehci->need_rescan = true;
                return;
-       ehci->scanning = 1;
+       }
+       ehci->scanning = true;
+
+ rescan:
+       ehci->need_rescan = false;
        if (ehci->async_count)
                scan_async(ehci);
        if (ehci->next_uframe != -1)
                scan_periodic (ehci);
-       ehci->scanning = 0;
+       if (ehci->need_rescan)
+               goto rescan;
+       ehci->scanning = false;
 
        /* the IO watchdog guards against hardware or driver bugs that
         * misplace IRQs, and should let us run completely without IRQs.


--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to