aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ehci-sched.c
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2012-05-14 13:47:20 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-05-14 15:50:22 -0400
commit65b8e5cbdddc86474372bdb48dc233b06710a576 (patch)
tree9c2c0740badd05e06c10a2586e119957e089d394 /drivers/usb/host/ehci-sched.c
parent61af9c3f894a48297db3cc01aa38910bd6f92c27 (diff)
USB: EHCI: improve full-speed isochronous scheduling routine
This patch (as1555) improves the code ehci-hcd uses while checking the periodic schedule for isochronous transfers to full-speed devices. In addition to making sure that a new transfer does not violate the restrictions on the high-speed schedule, it also has to check the restrictions on the full-speed part of the bus, i.e., the part beyond the Transaction Translator (TT). It does this by calling tt_available() (or tt_no_collision() if CONFIG_USB_EHCI_TT_NEWSCHED isn't enabled). However it calls that routine on each pass through a loop over the frames being modified, which is an unnecessary expense because tt_available() (or tt_no_collision) already does its own loop over frames. It is sufficient to do the check just once, before starting the loop. In addition, the function calls incorrectly converted the transfer's period from microframes to frames by doing a left shift instead of a right shift. The patch fixes this while moving the calls. 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-sched.c')
-rw-r--r--drivers/usb/host/ehci-sched.c40
1 files changed, 21 insertions, 19 deletions
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index cb7667967e5a..33182c6d1ff9 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -1331,34 +1331,36 @@ sitd_slot_ok (
1331 if (mask & ~0xffff) 1331 if (mask & ~0xffff)
1332 return 0; 1332 return 0;
1333 1333
1334 /* check bandwidth */
1335 uframe %= period_uframes;
1336 frame = uframe >> 3;
1337
1338#ifdef CONFIG_USB_EHCI_TT_NEWSCHED
1339 /* The tt's fullspeed bus bandwidth must be available.
1340 * tt_available scheduling guarantees 10+% for control/bulk.
1341 */
1342 uf = uframe & 7;
1343 if (!tt_available(ehci, period_uframes >> 3,
1344 stream->udev, frame, uf, stream->tt_usecs))
1345 return 0;
1346#else
1347 /* tt must be idle for start(s), any gap, and csplit.
1348 * assume scheduling slop leaves 10+% for control/bulk.
1349 */
1350 if (!tt_no_collision(ehci, period_uframes >> 3,
1351 stream->udev, frame, mask))
1352 return 0;
1353#endif
1354
1334 /* this multi-pass logic is simple, but performance may 1355 /* this multi-pass logic is simple, but performance may
1335 * suffer when the schedule data isn't cached. 1356 * suffer when the schedule data isn't cached.
1336 */ 1357 */
1337
1338 /* check bandwidth */
1339 uframe %= period_uframes;
1340 do { 1358 do {
1341 u32 max_used; 1359 u32 max_used;
1342 1360
1343 frame = uframe >> 3; 1361 frame = uframe >> 3;
1344 uf = uframe & 7; 1362 uf = uframe & 7;
1345 1363
1346#ifdef CONFIG_USB_EHCI_TT_NEWSCHED
1347 /* The tt's fullspeed bus bandwidth must be available.
1348 * tt_available scheduling guarantees 10+% for control/bulk.
1349 */
1350 if (!tt_available (ehci, period_uframes << 3,
1351 stream->udev, frame, uf, stream->tt_usecs))
1352 return 0;
1353#else
1354 /* tt must be idle for start(s), any gap, and csplit.
1355 * assume scheduling slop leaves 10+% for control/bulk.
1356 */
1357 if (!tt_no_collision (ehci, period_uframes << 3,
1358 stream->udev, frame, mask))
1359 return 0;
1360#endif
1361
1362 /* check starts (OUT uses more than one) */ 1364 /* check starts (OUT uses more than one) */
1363 max_used = ehci->uframe_periodic_max - stream->usecs; 1365 max_used = ehci->uframe_periodic_max - stream->usecs;
1364 for (tmp = stream->raw_mask & 0xff; tmp; tmp >>= 1, uf++) { 1366 for (tmp = stream->raw_mask & 0xff; tmp; tmp >>= 1, uf++) {