summaryrefslogtreecommitdiff
path: root/drivers/usb/host/ehci-q.c
diff options
context:
space:
mode:
authorDavid Brownell <david-b@pacbell.net>2006-01-20 22:35:55 (GMT)
committerGreg Kroah-Hartman <gregkh@suse.de>2006-03-20 22:49:55 (GMT)
commitd0852299381326c5d8eb67771aa98108050e6901 (patch)
treee4965e920fceeada861e5722228eb4472627c991 /drivers/usb/host/ehci-q.c
parentd5fb7f1b5b832946eaf450b2a695ec3e7fd2d351 (diff)
downloadlinux-fsl-qoriq-d0852299381326c5d8eb67771aa98108050e6901.tar.xz
[PATCH] USB: EHCI unlink tweaks
This patch modifies the behavior of the EHCI driver in an unlink path that seems to be causing various issues on some systems. Those problems have included issues with disconnection, driver unbinding, and similar cases where urb unlinking would just not work right. This patch should help avoid those problems by not turning off the async (control/bulk) schedule until it's not expecting an "async advance" IRQ, which comes from the processing passing the schedule head. Whether the driver attempts to do such things is dependent on system timings, so many folk would never have seen these problems. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/ehci-q.c')
-rw-r--r--drivers/usb/host/ehci-q.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index 6e28e59..5ada7cd 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -1022,12 +1022,14 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
/* stop async schedule right now? */
if (unlikely (qh == ehci->async)) {
/* can't get here without STS_ASS set */
- if (ehci_to_hcd(ehci)->state != HC_STATE_HALT) {
+ if (ehci_to_hcd(ehci)->state != HC_STATE_HALT
+ && !ehci->reclaim) {
+ /* ... and CMD_IAAD clear */
writel (cmd & ~CMD_ASE, &ehci->regs->command);
wmb ();
// handshake later, if we need to
+ timer_action_done (ehci, TIMER_ASYNC_OFF);
}
- timer_action_done (ehci, TIMER_ASYNC_OFF);
return;
}