• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

linux-3.0.x for AP-SH4A-0A Board


Commit MetaInfo

Revisão22007e1ddbe599373b116ecf3485ebf842405f73 (tree)
Hora2011-08-05 13:58:32
AutorAlan Stern <stern@rowl...>
CommiterGreg Kroah-Hartman

Mensagem de Log

USB: EHCI: go back to using the system clock for QH unlinks

commit 004c19682884d4f40000ce1ded53f4a1d0b18206 upstream.

This patch (as1477) fixes a problem affecting a few types of EHCI
controller. Contrary to what one might expect, these controllers
automatically stop their internal frame counter when no ports are
enabled. Since ehci-hcd currently relies on the frame counter for
determining when it should unlink QHs from the async schedule, those
controllers run into trouble: The frame counter stops and the QHs
never get unlinked.

Some systems have also experienced other problems traced back to
commit b963801164618e25fbdc0cd452ce49c3628b46c8 (USB: ehci-hcd unlink
speedups), which made the original switch from using the system clock
to using the frame counter. It never became clear what the reason was
for these problems, but evidently it is related to use of the frame
counter.

To fix all these problems, this patch more or less reverts that commit
and goes back to using the system clock. But this can't be done
cleanly because other changes have since been made to the scan_async()
subroutine. One of these changes involved the tricky logic that tries
to avoid rescanning QHs that have already been seen when the scanning
loop is restarted, which happens whenever an URB is given back.
Switching back to clock-based unlinks would make this logic even more
complicated.

Therefore the new code doesn't rescan the entire async list whenever a
giveback occurs. Instead it rescans only the current QH and continues
on from there. This requires the use of a separate pointer to keep
track of the next QH to scan, since the current QH may be unlinked
while the scanning is in progress. That new pointer must be global,
so that it can be adjusted forward whenever the _next_ QH gets
unlinked. (uhci-hcd uses this same trick.)

Simplification of the scanning loop removes a level of indentation,
which accounts for the size of the patch. The amount of code changed
is relatively small, and it isn't exactly a reversion of the
b963801164 commit.

This fixes Bugzilla #32432.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Tested-by: Matej Kenda <matejken@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

Mudança Sumário

Diff

--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -94,7 +94,8 @@ static const char hcd_name [] = "ehci_hcd";
9494 #define EHCI_IAA_MSECS 10 /* arbitrary */
9595 #define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */
9696 #define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */
97-#define EHCI_SHRINK_FRAMES 5 /* async qh unlink delay */
97+#define EHCI_SHRINK_JIFFIES (DIV_ROUND_UP(HZ, 200) + 1)
98+ /* 200-ms async qh unlink delay */
9899
99100 /* Initial IRQ latency: faster than hw default */
100101 static int log2_irq_thresh = 0; // 0 to 6
@@ -152,10 +153,7 @@ timer_action(struct ehci_hcd *ehci, enum ehci_timer_action action)
152153 break;
153154 /* case TIMER_ASYNC_SHRINK: */
154155 default:
155- /* add a jiffie since we synch against the
156- * 8 KHz uframe counter.
157- */
158- t = DIV_ROUND_UP(EHCI_SHRINK_FRAMES * HZ, 1000) + 1;
156+ t = EHCI_SHRINK_JIFFIES;
159157 break;
160158 }
161159 mod_timer(&ehci->watchdog, t + jiffies);
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -1231,6 +1231,8 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
12311231
12321232 prev->hw->hw_next = qh->hw->hw_next;
12331233 prev->qh_next = qh->qh_next;
1234+ if (ehci->qh_scan_next == qh)
1235+ ehci->qh_scan_next = qh->qh_next.qh;
12341236 wmb ();
12351237
12361238 /* If the controller isn't running, we don't have to wait for it */
@@ -1256,53 +1258,49 @@ static void scan_async (struct ehci_hcd *ehci)
12561258 struct ehci_qh *qh;
12571259 enum ehci_timer_action action = TIMER_IO_WATCHDOG;
12581260
1259- ehci->stamp = ehci_readl(ehci, &ehci->regs->frame_index);
12601261 timer_action_done (ehci, TIMER_ASYNC_SHRINK);
1261-rescan:
12621262 stopped = !HC_IS_RUNNING(ehci_to_hcd(ehci)->state);
1263- qh = ehci->async->qh_next.qh;
1264- if (likely (qh != NULL)) {
1265- do {
1266- /* clean any finished work for this qh */
1267- if (!list_empty(&qh->qtd_list) && (stopped ||
1268- qh->stamp != ehci->stamp)) {
1269- int temp;
1270-
1271- /* unlinks could happen here; completion
1272- * reporting drops the lock. rescan using
1273- * the latest schedule, but don't rescan
1274- * qhs we already finished (no looping)
1275- * unless the controller is stopped.
1276- */
1277- qh = qh_get (qh);
1278- qh->stamp = ehci->stamp;
1279- temp = qh_completions (ehci, qh);
1280- if (qh->needs_rescan)
1281- unlink_async(ehci, qh);
1282- qh_put (qh);
1283- if (temp != 0) {
1284- goto rescan;
1285- }
1286- }
12871263
1288- /* unlink idle entries, reducing DMA usage as well
1289- * as HCD schedule-scanning costs. delay for any qh
1290- * we just scanned, there's a not-unusual case that it
1291- * doesn't stay idle for long.
1292- * (plus, avoids some kind of re-activation race.)
1264+ ehci->qh_scan_next = ehci->async->qh_next.qh;
1265+ while (ehci->qh_scan_next) {
1266+ qh = ehci->qh_scan_next;
1267+ ehci->qh_scan_next = qh->qh_next.qh;
1268+ rescan:
1269+ /* clean any finished work for this qh */
1270+ if (!list_empty(&qh->qtd_list)) {
1271+ int temp;
1272+
1273+ /*
1274+ * Unlinks could happen here; completion reporting
1275+ * drops the lock. That's why ehci->qh_scan_next
1276+ * always holds the next qh to scan; if the next qh
1277+ * gets unlinked then ehci->qh_scan_next is adjusted
1278+ * in start_unlink_async().
12931279 */
1294- if (list_empty(&qh->qtd_list)
1295- && qh->qh_state == QH_STATE_LINKED) {
1296- if (!ehci->reclaim && (stopped ||
1297- ((ehci->stamp - qh->stamp) & 0x1fff)
1298- >= EHCI_SHRINK_FRAMES * 8))
1299- start_unlink_async(ehci, qh);
1300- else
1301- action = TIMER_ASYNC_SHRINK;
1302- }
1280+ qh = qh_get(qh);
1281+ temp = qh_completions(ehci, qh);
1282+ if (qh->needs_rescan)
1283+ unlink_async(ehci, qh);
1284+ qh->unlink_time = jiffies + EHCI_SHRINK_JIFFIES;
1285+ qh_put(qh);
1286+ if (temp != 0)
1287+ goto rescan;
1288+ }
13031289
1304- qh = qh->qh_next.qh;
1305- } while (qh);
1290+ /* unlink idle entries, reducing DMA usage as well
1291+ * as HCD schedule-scanning costs. delay for any qh
1292+ * we just scanned, there's a not-unusual case that it
1293+ * doesn't stay idle for long.
1294+ * (plus, avoids some kind of re-activation race.)
1295+ */
1296+ if (list_empty(&qh->qtd_list)
1297+ && qh->qh_state == QH_STATE_LINKED) {
1298+ if (!ehci->reclaim && (stopped ||
1299+ time_after_eq(jiffies, qh->unlink_time)))
1300+ start_unlink_async(ehci, qh);
1301+ else
1302+ action = TIMER_ASYNC_SHRINK;
1303+ }
13061304 }
13071305 if (action == TIMER_ASYNC_SHRINK)
13081306 timer_action (ehci, TIMER_ASYNC_SHRINK);
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -75,6 +75,7 @@ struct ehci_hcd { /* one per controller */
7575 struct ehci_qh *async;
7676 struct ehci_qh *dummy; /* For AMD quirk use */
7777 struct ehci_qh *reclaim;
78+ struct ehci_qh *qh_scan_next;
7879 unsigned scanning : 1;
7980
8081 /* periodic schedule support */
@@ -117,7 +118,6 @@ struct ehci_hcd { /* one per controller */
117118 struct timer_list iaa_watchdog;
118119 struct timer_list watchdog;
119120 unsigned long actions;
120- unsigned stamp;
121121 unsigned periodic_stamp;
122122 unsigned random_frame;
123123 unsigned long next_statechange;
@@ -343,6 +343,7 @@ struct ehci_qh {
343343 struct ehci_qh *reclaim; /* next to reclaim */
344344
345345 struct ehci_hcd *ehci;
346+ unsigned long unlink_time;
346347
347348 /*
348349 * Do NOT use atomic operations for QH refcounting. On some CPUs