Commit 361aabf3 authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman

USB: EHCI: don't lose events during a scan

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: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 32830f20
...@@ -400,14 +400,21 @@ static void ehci_work (struct ehci_hcd *ehci) ...@@ -400,14 +400,21 @@ static void ehci_work (struct ehci_hcd *ehci)
* it reports urb completions. this flag guards against bogus * it reports urb completions. this flag guards against bogus
* attempts at re-entrant schedule scanning. * attempts at re-entrant schedule scanning.
*/ */
if (ehci->scanning) if (ehci->scanning) {
ehci->need_rescan = true;
return; return;
ehci->scanning = 1; }
ehci->scanning = true;
rescan:
ehci->need_rescan = false;
if (ehci->async_count) if (ehci->async_count)
scan_async(ehci); scan_async(ehci);
if (ehci->next_uframe != -1) if (ehci->next_uframe != -1)
scan_periodic (ehci); 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 /* the IO watchdog guards against hardware or driver bugs that
* misplace IRQs, and should let us run completely without IRQs. * misplace IRQs, and should let us run completely without IRQs.
......
...@@ -113,7 +113,8 @@ struct ehci_hcd { /* one per controller */ ...@@ -113,7 +113,8 @@ struct ehci_hcd { /* one per controller */
enum ehci_rh_state rh_state; enum ehci_rh_state rh_state;
/* general schedule support */ /* general schedule support */
unsigned scanning:1; bool scanning:1;
bool need_rescan:1;
bool intr_unlinking:1; bool intr_unlinking:1;
bool async_unlinking:1; bool async_unlinking:1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment