aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host')
-rw-r--r--drivers/usb/host/uhci-debug.c48
-rw-r--r--drivers/usb/host/uhci-hcd.c51
2 files changed, 72 insertions, 27 deletions
diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
index e345f15b7d87..b40bc1ac9b8c 100644
--- a/drivers/usb/host/uhci-debug.c
+++ b/drivers/usb/host/uhci-debug.c
@@ -347,6 +347,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
347 struct uhci_qh *qh; 347 struct uhci_qh *qh;
348 struct uhci_td *td; 348 struct uhci_td *td;
349 struct list_head *tmp, *head; 349 struct list_head *tmp, *head;
350 int nframes, nerrs;
350 351
351 out += uhci_show_root_hub_state(uhci, out, len - (out - buf)); 352 out += uhci_show_root_hub_state(uhci, out, len - (out - buf));
352 out += sprintf(out, "HC status\n"); 353 out += sprintf(out, "HC status\n");
@@ -355,23 +356,60 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
355 return out - buf; 356 return out - buf;
356 357
357 out += sprintf(out, "Frame List\n"); 358 out += sprintf(out, "Frame List\n");
359 nframes = 10;
360 nerrs = 0;
358 for (i = 0; i < UHCI_NUMFRAMES; ++i) { 361 for (i = 0; i < UHCI_NUMFRAMES; ++i) {
362 __le32 link, qh_dma;
363
364 j = 0;
359 td = uhci->frame_cpu[i]; 365 td = uhci->frame_cpu[i];
366 link = uhci->frame[i];
360 if (!td) 367 if (!td)
361 continue; 368 goto check_link;
362 369
363 out += sprintf(out, "- Frame %d\n", i); \ 370 if (nframes > 0) {
364 if (td->dma_handle != (dma_addr_t)uhci->frame[i]) 371 out += sprintf(out, "- Frame %d -> (%08x)\n",
365 out += sprintf(out, " frame list does not match td->dma_handle!\n"); 372 i, le32_to_cpu(link));
373 j = 1;
374 }
366 375
367 head = &td->fl_list; 376 head = &td->fl_list;
368 tmp = head; 377 tmp = head;
369 do { 378 do {
370 td = list_entry(tmp, struct uhci_td, fl_list); 379 td = list_entry(tmp, struct uhci_td, fl_list);
371 tmp = tmp->next; 380 tmp = tmp->next;
372 out += uhci_show_td(td, out, len - (out - buf), 4); 381 if (cpu_to_le32(td->dma_handle) != link) {
382 if (nframes > 0)
383 out += sprintf(out, " link does "
384 "not match list entry!\n");
385 else
386 ++nerrs;
387 }
388 if (nframes > 0)
389 out += uhci_show_td(td, out,
390 len - (out - buf), 4);
391 link = td->link;
373 } while (tmp != head); 392 } while (tmp != head);
393
394check_link:
395 qh_dma = uhci_frame_skel_link(uhci, i);
396 if (link != qh_dma) {
397 if (nframes > 0) {
398 if (!j) {
399 out += sprintf(out,
400 "- Frame %d -> (%08x)\n",
401 i, le32_to_cpu(link));
402 j = 1;
403 }
404 out += sprintf(out, " link does not match "
405 "QH (%08x)!\n", le32_to_cpu(qh_dma));
406 } else
407 ++nerrs;
408 }
409 nframes -= j;
374 } 410 }
411 if (nerrs > 0)
412 out += sprintf(out, "Skipped %d bad links\n", nerrs);
375 413
376 out += sprintf(out, "Skeleton QHs\n"); 414 out += sprintf(out, "Skeleton QHs\n");
377 415
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index e0d4c2358b39..49b9d390b95f 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -92,6 +92,34 @@ static void suspend_rh(struct uhci_hcd *uhci, enum uhci_rh_state new_state);
92static void wakeup_rh(struct uhci_hcd *uhci); 92static void wakeup_rh(struct uhci_hcd *uhci);
93static void uhci_get_current_frame_number(struct uhci_hcd *uhci); 93static void uhci_get_current_frame_number(struct uhci_hcd *uhci);
94 94
95/*
96 * Calculate the link pointer DMA value for the first Skeleton QH in a frame.
97 */
98static __le32 uhci_frame_skel_link(struct uhci_hcd *uhci, int frame)
99{
100 int skelnum;
101
102 /*
103 * The interrupt queues will be interleaved as evenly as possible.
104 * There's not much to be done about period-1 interrupts; they have
105 * to occur in every frame. But we can schedule period-2 interrupts
106 * in odd-numbered frames, period-4 interrupts in frames congruent
107 * to 2 (mod 4), and so on. This way each frame only has two
108 * interrupt QHs, which will help spread out bandwidth utilization.
109 *
110 * ffs (Find First bit Set) does exactly what we need:
111 * 1,3,5,... => ffs = 0 => use skel_int2_qh = skelqh[8],
112 * 2,6,10,... => ffs = 1 => use skel_int4_qh = skelqh[7], etc.
113 * ffs >= 7 => not on any high-period queue, so use
114 * skel_int1_qh = skelqh[9].
115 * Add in UHCI_NUMFRAMES to insure at least one bit is set.
116 */
117 skelnum = 8 - (int) __ffs(frame | UHCI_NUMFRAMES);
118 if (skelnum <= 1)
119 skelnum = 9;
120 return UHCI_PTR_QH | cpu_to_le32(uhci->skelqh[skelnum]->dma_handle);
121}
122
95#include "uhci-debug.c" 123#include "uhci-debug.c"
96#include "uhci-q.c" 124#include "uhci-q.c"
97#include "uhci-hub.c" 125#include "uhci-hub.c"
@@ -631,32 +659,11 @@ static int uhci_start(struct usb_hcd *hcd)
631 /* 659 /*
632 * Fill the frame list: make all entries point to the proper 660 * Fill the frame list: make all entries point to the proper
633 * interrupt queue. 661 * interrupt queue.
634 *
635 * The interrupt queues will be interleaved as evenly as possible.
636 * There's not much to be done about period-1 interrupts; they have
637 * to occur in every frame. But we can schedule period-2 interrupts
638 * in odd-numbered frames, period-4 interrupts in frames congruent
639 * to 2 (mod 4), and so on. This way each frame only has two
640 * interrupt QHs, which will help spread out bandwidth utilization.
641 */ 662 */
642 for (i = 0; i < UHCI_NUMFRAMES; i++) { 663 for (i = 0; i < UHCI_NUMFRAMES; i++) {
643 int irq;
644
645 /*
646 * ffs (Find First bit Set) does exactly what we need:
647 * 1,3,5,... => ffs = 0 => use skel_int2_qh = skelqh[8],
648 * 2,6,10,... => ffs = 1 => use skel_int4_qh = skelqh[7], etc.
649 * ffs >= 7 => not on any high-period queue, so use
650 * skel_int1_qh = skelqh[9].
651 * Add UHCI_NUMFRAMES to insure at least one bit is set.
652 */
653 irq = 8 - (int) __ffs(i + UHCI_NUMFRAMES);
654 if (irq <= 1)
655 irq = 9;
656 664
657 /* Only place we don't use the frame list routines */ 665 /* Only place we don't use the frame list routines */
658 uhci->frame[i] = UHCI_PTR_QH | 666 uhci->frame[i] = uhci_frame_skel_link(uhci, i);
659 cpu_to_le32(uhci->skelqh[irq]->dma_handle);
660 } 667 }
661 668
662 /* 669 /*