summaryrefslogtreecommitdiff
path: root/drivers/usb/host/ehci-hcd.c
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2012-07-11 11:22:21 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-07-16 16:54:25 -0700
commit314466101c6ae14f6f5db8a86eda1509ba2c02a8 (patch)
treed2605336919a20a1ee122c813ca7ddc479755d12 /drivers/usb/host/ehci-hcd.c
parent9671cd7a91059bcd27665a884ee6568d31ef6857 (diff)
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>
Diffstat (limited to 'drivers/usb/host/ehci-hcd.c')
-rw-r--r--drivers/usb/host/ehci-hcd.c13
1 files changed, 3 insertions, 10 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index fd7ae16f77be..21d6fbc0a327 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -95,7 +95,6 @@ static const char hcd_name [] = "ehci_hcd";
#define EHCI_IAA_MSECS 10 /* arbitrary */
#define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */
-#define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */
#define EHCI_SHRINK_JIFFIES (DIV_ROUND_UP(HZ, 200) + 1)
/* 5-ms async qh unlink delay */
@@ -137,7 +136,7 @@ timer_action(struct ehci_hcd *ehci, enum ehci_timer_action action)
* SHRINK were pending, OFF would never be requested.
*/
if (timer_pending(&ehci->watchdog)
- && ((BIT(TIMER_ASYNC_SHRINK) | BIT(TIMER_ASYNC_OFF))
+ && (BIT(TIMER_ASYNC_SHRINK)
& ehci->actions))
return;
@@ -150,9 +149,6 @@ timer_action(struct ehci_hcd *ehci, enum ehci_timer_action action)
return;
t = EHCI_IO_JIFFIES;
break;
- case TIMER_ASYNC_OFF:
- t = EHCI_ASYNC_JIFFIES;
- break;
/* case TIMER_ASYNC_SHRINK: */
default:
t = EHCI_SHRINK_JIFFIES;
@@ -376,10 +372,6 @@ static void ehci_watchdog(unsigned long param)
spin_lock_irqsave(&ehci->lock, flags);
- /* stop async processing after it's idled a bit */
- if (test_bit (TIMER_ASYNC_OFF, &ehci->actions))
- start_unlink_async (ehci, ehci->async);
-
/* ehci could run by timer, without IRQs ... */
ehci_work (ehci);
@@ -470,7 +462,8 @@ static void ehci_work (struct ehci_hcd *ehci)
if (ehci->scanning)
return;
ehci->scanning = 1;
- scan_async (ehci);
+ if (ehci->async_count)
+ scan_async(ehci);
if (ehci->next_uframe != -1)
scan_periodic (ehci);
ehci->scanning = 0;