aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ohci-mem.c
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2014-07-18 16:26:12 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-07-18 16:34:07 -0700
commit81e38333513cec155c720432226dabe9f9f76a77 (patch)
tree27889eb4e928866b5ea6496dbcdd9abc1c23e9e3 /drivers/usb/host/ohci-mem.c
parentUSB: OHCI: make URB completions single-threaded (diff)
downloadlinux-dev-81e38333513cec155c720432226dabe9f9f76a77.tar.xz
linux-dev-81e38333513cec155c720432226dabe9f9f76a77.zip
USB: OHCI: add I/O watchdog for orphan TDs
Some OHCI controllers have a bug: They fail to add completed TDs to the done queue. Examining this queue is the only method ohci-hcd has for telling when a transfer is complete; failure to add a TD can result in an URB that never completes and cannot be unlinked. This patch adds a watchdog routine to ohci-hcd. The routine periodically scans the active ED and TD lists, looking for TDs which are finished but not on the done queue. When one is found, and it is certain that the controller hardware will never add the TD to the done queue, the watchdog routine manually puts the TD on the done list so that it can be handled normally. The watchdog routine also checks for a condition indicating the controller has died. If the done queue is non-empty but the HccaDoneHead pointer hasn't been updated for a few hundred milliseconds, we assume the controller will never update it and therefore is dead. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/host/ohci-mem.c')
-rw-r--r--drivers/usb/host/ohci-mem.c1
1 files changed, 1 insertions, 0 deletions
diff --git a/drivers/usb/host/ohci-mem.c b/drivers/usb/host/ohci-mem.c
index 2f20d3dc895b..c9e315c6808a 100644
--- a/drivers/usb/host/ohci-mem.c
+++ b/drivers/usb/host/ohci-mem.c
@@ -28,6 +28,7 @@ static void ohci_hcd_init (struct ohci_hcd *ohci)
ohci->next_statechange = jiffies;
spin_lock_init (&ohci->lock);
INIT_LIST_HEAD (&ohci->pending);
+ INIT_LIST_HEAD(&ohci->eds_in_use);
}
/*-------------------------------------------------------------------------*/