USB: EHCI: don't lose events during a scan
authorAlan Stern <stern@rowland.harvard.edu>
Wed, 11 Jul 2012 15:22:57 +0000 (11:22 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 16 Jul 2012 23:56:47 +0000 (16:56 -0700)
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 <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci.h

index 74ffd20edff80610265daf247b9ddb5b3fdbc51b..f6cf1d178107bba0f3ae34357b13f57e132a21b3 100644 (file)
@@ -400,14 +400,21 @@ static void ehci_work (struct ehci_hcd *ehci)
         * 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.
index 303c36cc99c900ef27025d8f206d309d09081894..c462d52ac575ab80190e8550070b13ef39aa5ae1 100644 (file)
@@ -113,7 +113,8 @@ struct ehci_hcd {                   /* one per controller */
        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;