96 lines
3.3 KiB
Diff
96 lines
3.3 KiB
Diff
From 1729d20333739e6cc23023e405fe8668f08117a2 Mon Sep 17 00:00:00 2001
|
|
From: Alan Stern <stern@rowland.harvard.edu>
|
|
Date: Tue, 17 May 2011 10:40:51 -0400
|
|
Subject: [PATCH 1/2] EHCI: don't rescan interrupt QHs needlessly
|
|
|
|
This patch (as1466) speeds up processing of ehci-hcd's periodic list.
|
|
The existing code will pointlessly rescan an interrupt endpoint queue
|
|
each time it encounters the queue's QH in the periodic list, which can
|
|
happen quite a few times if the endpoint's period is low. On some
|
|
embedded systems, this useless overhead can waste so much time that
|
|
the driver falls hopelessly behind and loses events.
|
|
|
|
The patch introduces a "periodic_stamp" variable, which gets
|
|
incremented each time scan_periodic() runs and each time the scan
|
|
advances to a new frame. If the corresponding stamp in an interrupt
|
|
QH is equal to the current periodic_stamp, we assume the QH has
|
|
already been scanned and skip over it. Otherwise we scan the QH as
|
|
usual, and if none of its URBs have completed then we store the
|
|
current periodic_stamp in the QH's stamp, preventing it from being
|
|
scanned again.
|
|
|
|
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
|
|
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
|
---
|
|
drivers/usb/host/ehci-q.c | 1 +
|
|
drivers/usb/host/ehci-sched.c | 14 ++++++++++----
|
|
drivers/usb/host/ehci.h | 1 +
|
|
3 files changed, 12 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
|
|
index ed8db6a..0079610 100644
|
|
--- a/drivers/usb/host/ehci-q.c
|
|
+++ b/drivers/usb/host/ehci-q.c
|
|
@@ -826,6 +826,7 @@ qh_make (
|
|
is_input, 0,
|
|
hb_mult(maxp) * max_packet(maxp)));
|
|
qh->start = NO_FRAME;
|
|
+ qh->stamp = ehci->periodic_stamp;
|
|
|
|
if (urb->dev->speed == USB_SPEED_HIGH) {
|
|
qh->c_usecs = 0;
|
|
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
|
|
index a530856..9e54e85 100644
|
|
--- a/drivers/usb/host/ehci-sched.c
|
|
+++ b/drivers/usb/host/ehci-sched.c
|
|
@@ -2351,6 +2351,7 @@ scan_periodic (struct ehci_hcd *ehci)
|
|
}
|
|
clock %= mod;
|
|
clock_frame = clock >> 3;
|
|
+ ++ehci->periodic_stamp;
|
|
|
|
for (;;) {
|
|
union ehci_shadow q, *q_p;
|
|
@@ -2379,10 +2380,14 @@ restart:
|
|
temp.qh = qh_get (q.qh);
|
|
type = Q_NEXT_TYPE(ehci, q.qh->hw->hw_next);
|
|
q = q.qh->qh_next;
|
|
- modified = qh_completions (ehci, temp.qh);
|
|
- if (unlikely(list_empty(&temp.qh->qtd_list) ||
|
|
- temp.qh->needs_rescan))
|
|
- intr_deschedule (ehci, temp.qh);
|
|
+ if (temp.qh->stamp != ehci->periodic_stamp) {
|
|
+ modified = qh_completions(ehci, temp.qh);
|
|
+ if (!modified)
|
|
+ temp.qh->stamp = ehci->periodic_stamp;
|
|
+ if (unlikely(list_empty(&temp.qh->qtd_list) ||
|
|
+ temp.qh->needs_rescan))
|
|
+ intr_deschedule(ehci, temp.qh);
|
|
+ }
|
|
qh_put (temp.qh);
|
|
break;
|
|
case Q_TYPE_FSTN:
|
|
@@ -2515,6 +2520,7 @@ restart:
|
|
if (ehci->clock_frame != clock_frame) {
|
|
free_cached_lists(ehci);
|
|
ehci->clock_frame = clock_frame;
|
|
+ ++ehci->periodic_stamp;
|
|
}
|
|
} else {
|
|
now_uframe++;
|
|
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
|
|
index c702e4b..c2c2f9d 100644
|
|
--- a/drivers/usb/host/ehci.h
|
|
+++ b/drivers/usb/host/ehci.h
|
|
@@ -117,6 +117,7 @@ struct ehci_hcd { /* one per controller */
|
|
struct timer_list watchdog;
|
|
unsigned long actions;
|
|
unsigned stamp;
|
|
+ unsigned periodic_stamp;
|
|
unsigned random_frame;
|
|
unsigned long next_statechange;
|
|
ktime_t last_periodic_enable;
|
|
--
|
|
1.7.6
|
|
|