USB: EHCI: use hrtimer for async schedule

This patch (as1576) adds hrtimer support for managing ehci-hcd's
async schedule.  Just as with the earlier change to the periodic
schedule management, two new hrtimer events take care of everything.

One event polls at 1-ms intervals to see when the Asynchronous
Schedule Status (ASS) flag matches the Asynchronous Schedule Enable
(ASE) value; the schedule's state must not be changed until it does.
The other event delays for 15 ms after the async schedule becomes
empty before turning it off.

The new events replace a busy-wait poll and a kernel timer usage.
They also replace the rather illogical method currently used for
indicating the async schedule should be turned off: attempting to
unlink the dedicated QH at the head of the async list.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Alan Stern
2012-07-11 11:22:21 -04:00
committed by Greg Kroah-Hartman
parent 9671cd7a91
commit 314466101c
4 changed files with 86 additions and 49 deletions

View File

@@ -79,8 +79,10 @@ enum ehci_rh_state {
* ehci-timer.c) in parallel with this list.
*/
enum ehci_hrtimer_event {
EHCI_HRTIMER_POLL_ASS, /* Poll for async schedule off */
EHCI_HRTIMER_POLL_PSS, /* Poll for periodic schedule off */
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 */
};
#define EHCI_HRTIMER_NO_EVENT 99
@@ -93,6 +95,7 @@ struct ehci_hcd { /* one per controller */
struct hrtimer hrtimer;
int PSS_poll_count;
int ASS_poll_count;
/* glue to PCI and HCD framework */
struct ehci_caps __iomem *caps;
@@ -110,6 +113,7 @@ struct ehci_hcd { /* one per controller */
struct ehci_qh *async_unlink_last;
struct ehci_qh *qh_scan_next;
unsigned scanning : 1;
unsigned async_count; /* async activity count */
/* periodic schedule support */
#define DEFAULT_I_TDPS 1024 /* some HCs can do less */
@@ -229,7 +233,6 @@ static inline void iaa_watchdog_done(struct ehci_hcd *ehci)
enum ehci_timer_action {
TIMER_IO_WATCHDOG,
TIMER_ASYNC_SHRINK,
TIMER_ASYNC_OFF,
};
static inline void