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);