diff options
Diffstat (limited to 'drivers/usb/host/uhci-hcd.c')
-rw-r--r-- | drivers/usb/host/uhci-hcd.c | 51 |
1 files changed, 29 insertions, 22 deletions
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); | |||
92 | static void wakeup_rh(struct uhci_hcd *uhci); | 92 | static void wakeup_rh(struct uhci_hcd *uhci); |
93 | static void uhci_get_current_frame_number(struct uhci_hcd *uhci); | 93 | static 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 | */ | ||
98 | static __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 | /* |