Currently, calling wakeup_hc in uhci.c causes wakeup_hc to
be called twice, at least with my hardware.  What happens
is that at the end of wakeup_hc, the run/stop bit is run.  My
VIA hub controller raises an interrupt at this point with the
Resume Detect bit set in USBSTS.  When uhci_interrupt
gets the interrupt it sees that this bit is set and calls wakeup_hc.
Fortunately this does not cause an endless loop!  In fact
uhci_interrupt is wrong.  The reason is that the interrupt is
raised when we are not in a global suspend state, in fact just
after we leave this state.  According to the spec,
"[Resume Detect] is only valid if the Host Controller is in a
global suspend state (bit 3 of Command register = 1)."
Thus uhci_interrupt should test bit 3 of the Command register
and bail out if it is not set.  Rather than doing this, the patch
just checks whether uhci->is_suspended is set.  This is a
small race.  Patch is against 2.4.19.

--- linux/drivers/usb/uhci.c.1  2002-10-26 00:23:30.000000000 +0200
+++ linux/drivers/usb/uhci.c    2002-10-26 00:23:36.000000000 +0200
@@ -2459,8 +2459,11 @@
                }
        }
 
-       if (status & USBSTS_RD)
+       if (status & USBSTS_RD) {
+               if (!uhci->is_suspended)
+                       return;
                wakeup_hc(uhci);
+       }
 
        uhci_free_pending_qhs(uhci);
 
--- linux/drivers/usb/uhci.c.1	2002-10-26 00:23:30.000000000 +0200
+++ linux/drivers/usb/uhci.c	2002-10-26 00:23:36.000000000 +0200
@@ -2459,8 +2459,11 @@
 		}
 	}
 
-	if (status & USBSTS_RD)
+	if (status & USBSTS_RD) {
+		if (!uhci->is_suspended)
+			return;
 		wakeup_hc(uhci);
+	}
 
 	uhci_free_pending_qhs(uhci);
 

Reply via email to