diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2012-07-11 11:22:26 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-07-16 16:54:25 -0700 |
commit | df2022553dd8d34d49e16c19d851ea619438f0ef (patch) | |
tree | 9850c967e0fbee1cb99e900c2e60a0ad50b528da /drivers/usb/host/ehci.h | |
parent | 314466101c6ae14f6f5db8a86eda1509ba2c02a8 (diff) | |
download | linux-3.10-df2022553dd8d34d49e16c19d851ea619438f0ef.tar.gz linux-3.10-df2022553dd8d34d49e16c19d851ea619438f0ef.tar.bz2 linux-3.10-df2022553dd8d34d49e16c19d851ea619438f0ef.zip |
USB: EHCI: use hrtimer for interrupt QH unlink
This patch (as1577) adds hrtimer support for unlinking interrupt QHs
in ehci-hcd. The current code relies on a fixed delay of either 2 or
55 us, which is not always adequate and in any case is totally bogus.
Thanks to internal caching, the EHCI hardware may continue to access
an interrupt QH for more than a millisecond after it has been unlinked.
In fact, the EHCI spec doesn't say how long to wait before using an
unlinked interrupt QH. The patch sets the delay to 9 microframes
minimum, which ought to be adequate.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/host/ehci.h')
-rw-r--r-- | drivers/usb/host/ehci.h | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index bf06bbb77ba..f36f1f85d7f 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -81,6 +81,7 @@ enum ehci_rh_state { enum ehci_hrtimer_event { EHCI_HRTIMER_POLL_ASS, /* Poll for async schedule off */ EHCI_HRTIMER_POLL_PSS, /* Poll for periodic schedule off */ + EHCI_HRTIMER_UNLINK_INTR, /* Wait for interrupt QH unlink */ EHCI_HRTIMER_DISABLE_PERIODIC, /* Wait to disable periodic sched */ EHCI_HRTIMER_DISABLE_ASYNC, /* Wait to disable async sched */ EHCI_HRTIMER_NUM_EVENTS /* Must come last */ @@ -106,13 +107,16 @@ struct ehci_hcd { /* one per controller */ spinlock_t lock; enum ehci_rh_state rh_state; + /* general schedule support */ + unsigned scanning:1; + bool intr_unlinking:1; + /* async schedule support */ struct ehci_qh *async; struct ehci_qh *dummy; /* For AMD quirk use */ struct ehci_qh *async_unlink; struct ehci_qh *async_unlink_last; struct ehci_qh *qh_scan_next; - unsigned scanning : 1; unsigned async_count; /* async activity count */ /* periodic schedule support */ @@ -123,6 +127,9 @@ struct ehci_hcd { /* one per controller */ unsigned i_thresh; /* uframes HC might cache */ union ehci_shadow *pshadow; /* mirror hw periodic table */ + struct ehci_qh *intr_unlink; + struct ehci_qh *intr_unlink_last; + unsigned intr_unlink_cycle; int next_uframe; /* scan periodic, start here */ unsigned periodic_count; /* periodic activity count */ unsigned uframe_periodic_max; /* max periodic time per uframe */ @@ -385,6 +392,7 @@ struct ehci_qh { struct ehci_qh *unlink_next; /* next on unlink list */ unsigned long unlink_time; + unsigned unlink_cycle; unsigned stamp; u8 needs_rescan; /* Dequeue during giveback */ |