aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ehci.h
diff options
context:
space:
mode:
authorDavid Brownell <dbrownell@users.sourceforge.net>2008-06-04 01:21:55 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2008-07-21 18:16:27 -0400
commitb963801164618e25fbdc0cd452ce49c3628b46c8 (patch)
tree149c888f19921f356607c8d7a1c1001e148450ba /drivers/usb/host/ehci.h
parent38f3ad5e7463d4dd490a8081a5f3f9f2dec7ecd6 (diff)
USB: ehci-hcd unlink speedups
This patch fixes some performance bugs observed with some workloads when unlinking EHCI queue header (QH) descriptors from the async ring (control/bulk schedule). The mechanism intended to defer unlinking an empty QH (so there is no penalty in common cases where it's quickly reused) was not working as intended. Sometimes the unlink was scheduled: - too quickly ... which can be a *strong* negative effect, since that QH becomes unavailable for immediate re-use; - too slowly ... wasting DMA cycles, usually a minor issue except for increased bus contention and power usage; Plus there was an extreme case of "too slowly": a logical error in the IAA watchdog-timer conversion meant that sometimes the unlink never got scheduled. The fix replaces a simple counter with a timestamp derived from the controller's 8 KHz microframe counter, and adjusts the timer usage for some issues associated with HZ being less than 8K. (Based on a patch originally by Alan Stern, and good troubleshooting from Leonid.) Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Cc: Alan Stern <stern@rowland.harvard.edu> Cc: Leonid <leonidv11@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/ehci.h')
-rw-r--r--drivers/usb/host/ehci.h5
1 files changed, 4 insertions, 1 deletions
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 90245fd8bac4..5799298364fb 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -198,7 +198,10 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action)
198 break; 198 break;
199 // case TIMER_ASYNC_SHRINK: 199 // case TIMER_ASYNC_SHRINK:
200 default: 200 default:
201 t = EHCI_SHRINK_JIFFIES; 201 /* add a jiffie since we synch against the
202 * 8 KHz uframe counter.
203 */
204 t = DIV_ROUND_UP(EHCI_SHRINK_FRAMES * HZ, 1000) + 1;
202 break; 205 break;
203 } 206 }
204 mod_timer(&ehci->watchdog, t + jiffies); 207 mod_timer(&ehci->watchdog, t + jiffies);