uhci-q.c (5a84d159061d914c8dd4aa372ac6e9529c2be453) uhci-q.c (28b9325e6ae45ffb5e99fedcafe00f25fcaacf06)
1/*
2 * Universal Host Controller Interface driver for USB.
3 *
4 * Maintainer: Alan Stern <stern@rowland.harvard.edu>
5 *
6 * (C) Copyright 1999 Linus Torvalds
7 * (C) Copyright 1999-2002 Johannes Erdfelt, johannes@erdfelt.com
8 * (C) Copyright 1999 Randy Dunlap

--- 32 unchanged lines hidden (view full) ---

41/*
42 * Full-Speed Bandwidth Reclamation (FSBR).
43 * We turn on FSBR whenever a queue that wants it is advancing,
44 * and leave it on for a short time thereafter.
45 */
46static void uhci_fsbr_on(struct uhci_hcd *uhci)
47{
48 uhci->fsbr_is_on = 1;
1/*
2 * Universal Host Controller Interface driver for USB.
3 *
4 * Maintainer: Alan Stern <stern@rowland.harvard.edu>
5 *
6 * (C) Copyright 1999 Linus Torvalds
7 * (C) Copyright 1999-2002 Johannes Erdfelt, johannes@erdfelt.com
8 * (C) Copyright 1999 Randy Dunlap

--- 32 unchanged lines hidden (view full) ---

41/*
42 * Full-Speed Bandwidth Reclamation (FSBR).
43 * We turn on FSBR whenever a queue that wants it is advancing,
44 * and leave it on for a short time thereafter.
45 */
46static void uhci_fsbr_on(struct uhci_hcd *uhci)
47{
48 uhci->fsbr_is_on = 1;
49 uhci->skel_term_qh->link = cpu_to_le32(
50 uhci->skel_fs_control_qh->dma_handle) | UHCI_PTR_QH;
49 uhci->skel_term_qh->link = LINK_TO_QH(uhci->skel_fs_control_qh);
51}
52
53static void uhci_fsbr_off(struct uhci_hcd *uhci)
54{
55 uhci->fsbr_is_on = 0;
56 uhci->skel_term_qh->link = UHCI_PTR_TERM;
57}
58

--- 94 unchanged lines hidden (view full) ---

153
154 ftd = uhci->frame_cpu[framenum];
155 ltd = list_entry(ftd->fl_list.prev, struct uhci_td, fl_list);
156
157 list_add_tail(&td->fl_list, &ftd->fl_list);
158
159 td->link = ltd->link;
160 wmb();
50}
51
52static void uhci_fsbr_off(struct uhci_hcd *uhci)
53{
54 uhci->fsbr_is_on = 0;
55 uhci->skel_term_qh->link = UHCI_PTR_TERM;
56}
57

--- 94 unchanged lines hidden (view full) ---

152
153 ftd = uhci->frame_cpu[framenum];
154 ltd = list_entry(ftd->fl_list.prev, struct uhci_td, fl_list);
155
156 list_add_tail(&td->fl_list, &ftd->fl_list);
157
158 td->link = ltd->link;
159 wmb();
161 ltd->link = cpu_to_le32(td->dma_handle);
160 ltd->link = LINK_TO_TD(td);
162 } else {
163 td->link = uhci->frame[framenum];
164 wmb();
161 } else {
162 td->link = uhci->frame[framenum];
163 wmb();
165 uhci->frame[framenum] = cpu_to_le32(td->dma_handle);
164 uhci->frame[framenum] = LINK_TO_TD(td);
166 uhci->frame_cpu[framenum] = td;
167 }
168}
169
170static inline void uhci_remove_td_from_frame_list(struct uhci_hcd *uhci,
171 struct uhci_td *td)
172{
173 /* If it's not inserted, don't remove it */

--- 5 unchanged lines hidden (view full) ---

179 if (uhci->frame_cpu[td->frame] == td) {
180 if (list_empty(&td->fl_list)) {
181 uhci->frame[td->frame] = td->link;
182 uhci->frame_cpu[td->frame] = NULL;
183 } else {
184 struct uhci_td *ntd;
185
186 ntd = list_entry(td->fl_list.next, struct uhci_td, fl_list);
165 uhci->frame_cpu[framenum] = td;
166 }
167}
168
169static inline void uhci_remove_td_from_frame_list(struct uhci_hcd *uhci,
170 struct uhci_td *td)
171{
172 /* If it's not inserted, don't remove it */

--- 5 unchanged lines hidden (view full) ---

178 if (uhci->frame_cpu[td->frame] == td) {
179 if (list_empty(&td->fl_list)) {
180 uhci->frame[td->frame] = td->link;
181 uhci->frame_cpu[td->frame] = NULL;
182 } else {
183 struct uhci_td *ntd;
184
185 ntd = list_entry(td->fl_list.next, struct uhci_td, fl_list);
187 uhci->frame[td->frame] = cpu_to_le32(ntd->dma_handle);
186 uhci->frame[td->frame] = LINK_TO_TD(ntd);
188 uhci->frame_cpu[td->frame] = ntd;
189 }
190 } else {
191 struct uhci_td *ptd;
192
193 ptd = list_entry(td->fl_list.prev, struct uhci_td, fl_list);
194 ptd->link = td->link;
195 }

--- 220 unchanged lines hidden (view full) ---

416 /* Set the element pointer if it isn't set already.
417 * This isn't needed for Isochronous queues, but it doesn't hurt. */
418 if (qh_element(qh) == UHCI_PTR_TERM) {
419 struct urb_priv *urbp = list_entry(qh->queue.next,
420 struct urb_priv, node);
421 struct uhci_td *td = list_entry(urbp->td_list.next,
422 struct uhci_td, list);
423
187 uhci->frame_cpu[td->frame] = ntd;
188 }
189 } else {
190 struct uhci_td *ptd;
191
192 ptd = list_entry(td->fl_list.prev, struct uhci_td, fl_list);
193 ptd->link = td->link;
194 }

--- 220 unchanged lines hidden (view full) ---

415 /* Set the element pointer if it isn't set already.
416 * This isn't needed for Isochronous queues, but it doesn't hurt. */
417 if (qh_element(qh) == UHCI_PTR_TERM) {
418 struct urb_priv *urbp = list_entry(qh->queue.next,
419 struct urb_priv, node);
420 struct uhci_td *td = list_entry(urbp->td_list.next,
421 struct uhci_td, list);
422
424 qh->element = cpu_to_le32(td->dma_handle);
423 qh->element = LINK_TO_TD(td);
425 }
426
427 /* Treat the queue as if it has just advanced */
428 qh->wait_expired = 0;
429 qh->advance_jiffies = jiffies;
430
431 if (qh->state == QH_STATE_ACTIVE)
432 return;

--- 5 unchanged lines hidden (view full) ---

438 uhci->next_qh = list_entry(qh->node.next, struct uhci_qh,
439 node);
440 list_move_tail(&qh->node, &qh->skel->node);
441
442 /* Link it into the schedule */
443 pqh = list_entry(qh->node.prev, struct uhci_qh, node);
444 qh->link = pqh->link;
445 wmb();
424 }
425
426 /* Treat the queue as if it has just advanced */
427 qh->wait_expired = 0;
428 qh->advance_jiffies = jiffies;
429
430 if (qh->state == QH_STATE_ACTIVE)
431 return;

--- 5 unchanged lines hidden (view full) ---

437 uhci->next_qh = list_entry(qh->node.next, struct uhci_qh,
438 node);
439 list_move_tail(&qh->node, &qh->skel->node);
440
441 /* Link it into the schedule */
442 pqh = list_entry(qh->node.prev, struct uhci_qh, node);
443 qh->link = pqh->link;
444 wmb();
446 pqh->link = UHCI_PTR_QH | cpu_to_le32(qh->dma_handle);
445 pqh->link = LINK_TO_QH(qh);
447}
448
449/*
450 * Take a QH off the hardware schedule
451 */
452static void uhci_unlink_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
453{
454 struct uhci_qh *pqh;

--- 277 unchanged lines hidden (view full) ---

732 * Build the DATA TDs
733 */
734 while (len > 0) {
735 int pktsze = min(len, maxsze);
736
737 td = uhci_alloc_td(uhci);
738 if (!td)
739 goto nomem;
446}
447
448/*
449 * Take a QH off the hardware schedule
450 */
451static void uhci_unlink_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
452{
453 struct uhci_qh *pqh;

--- 277 unchanged lines hidden (view full) ---

731 * Build the DATA TDs
732 */
733 while (len > 0) {
734 int pktsze = min(len, maxsze);
735
736 td = uhci_alloc_td(uhci);
737 if (!td)
738 goto nomem;
740 *plink = cpu_to_le32(td->dma_handle);
739 *plink = LINK_TO_TD(td);
741
742 /* Alternate Data0/1 (start with Data1) */
743 destination ^= TD_TOKEN_TOGGLE;
744
745 uhci_add_td_to_urbp(td, urbp);
746 uhci_fill_td(td, status, destination | uhci_explen(pktsze),
747 data);
748 plink = &td->link;
749
750 data += pktsze;
751 len -= pktsze;
752 }
753
754 /*
755 * Build the final TD for control status
756 */
757 td = uhci_alloc_td(uhci);
758 if (!td)
759 goto nomem;
740
741 /* Alternate Data0/1 (start with Data1) */
742 destination ^= TD_TOKEN_TOGGLE;
743
744 uhci_add_td_to_urbp(td, urbp);
745 uhci_fill_td(td, status, destination | uhci_explen(pktsze),
746 data);
747 plink = &td->link;
748
749 data += pktsze;
750 len -= pktsze;
751 }
752
753 /*
754 * Build the final TD for control status
755 */
756 td = uhci_alloc_td(uhci);
757 if (!td)
758 goto nomem;
760 *plink = cpu_to_le32(td->dma_handle);
759 *plink = LINK_TO_TD(td);
761
762 /*
763 * It's IN if the pipe is an output pipe or we're not expecting
764 * data back.
765 */
766 destination &= ~TD_TOKEN_PID_MASK;
767 if (usb_pipeout(urb->pipe) || !urb->transfer_buffer_length)
768 destination |= USB_PID_IN;

--- 10 unchanged lines hidden (view full) ---

779 plink = &td->link;
780
781 /*
782 * Build the new dummy TD and activate the old one
783 */
784 td = uhci_alloc_td(uhci);
785 if (!td)
786 goto nomem;
760
761 /*
762 * It's IN if the pipe is an output pipe or we're not expecting
763 * data back.
764 */
765 destination &= ~TD_TOKEN_PID_MASK;
766 if (usb_pipeout(urb->pipe) || !urb->transfer_buffer_length)
767 destination |= USB_PID_IN;

--- 10 unchanged lines hidden (view full) ---

778 plink = &td->link;
779
780 /*
781 * Build the new dummy TD and activate the old one
782 */
783 td = uhci_alloc_td(uhci);
784 if (!td)
785 goto nomem;
787 *plink = cpu_to_le32(td->dma_handle);
786 *plink = LINK_TO_TD(td);
788
789 uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0);
790 wmb();
791 qh->dummy_td->status |= __constant_cpu_to_le32(TD_CTRL_ACTIVE);
792 qh->dummy_td = td;
793
794 /* Low-speed transfers get a different queue, and won't hog the bus.
795 * Also, some devices enumerate better without FSBR; the easiest way

--- 59 unchanged lines hidden (view full) ---

855 if (!(urb->transfer_flags & URB_SHORT_NOT_OK))
856 status &= ~TD_CTRL_SPD;
857 }
858
859 if (plink) {
860 td = uhci_alloc_td(uhci);
861 if (!td)
862 goto nomem;
787
788 uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0);
789 wmb();
790 qh->dummy_td->status |= __constant_cpu_to_le32(TD_CTRL_ACTIVE);
791 qh->dummy_td = td;
792
793 /* Low-speed transfers get a different queue, and won't hog the bus.
794 * Also, some devices enumerate better without FSBR; the easiest way

--- 59 unchanged lines hidden (view full) ---

854 if (!(urb->transfer_flags & URB_SHORT_NOT_OK))
855 status &= ~TD_CTRL_SPD;
856 }
857
858 if (plink) {
859 td = uhci_alloc_td(uhci);
860 if (!td)
861 goto nomem;
863 *plink = cpu_to_le32(td->dma_handle);
862 *plink = LINK_TO_TD(td);
864 }
865 uhci_add_td_to_urbp(td, urbp);
866 uhci_fill_td(td, status,
867 destination | uhci_explen(pktsze) |
868 (toggle << TD_TOKEN_TOGGLE_SHIFT),
869 data);
870 plink = &td->link;
871 status |= TD_CTRL_ACTIVE;

--- 11 unchanged lines hidden (view full) ---

883 * prepared above.
884 */
885 if ((urb->transfer_flags & URB_ZERO_PACKET) &&
886 usb_pipeout(urb->pipe) && len == 0 &&
887 urb->transfer_buffer_length > 0) {
888 td = uhci_alloc_td(uhci);
889 if (!td)
890 goto nomem;
863 }
864 uhci_add_td_to_urbp(td, urbp);
865 uhci_fill_td(td, status,
866 destination | uhci_explen(pktsze) |
867 (toggle << TD_TOKEN_TOGGLE_SHIFT),
868 data);
869 plink = &td->link;
870 status |= TD_CTRL_ACTIVE;

--- 11 unchanged lines hidden (view full) ---

882 * prepared above.
883 */
884 if ((urb->transfer_flags & URB_ZERO_PACKET) &&
885 usb_pipeout(urb->pipe) && len == 0 &&
886 urb->transfer_buffer_length > 0) {
887 td = uhci_alloc_td(uhci);
888 if (!td)
889 goto nomem;
891 *plink = cpu_to_le32(td->dma_handle);
890 *plink = LINK_TO_TD(td);
892
893 uhci_add_td_to_urbp(td, urbp);
894 uhci_fill_td(td, status,
895 destination | uhci_explen(0) |
896 (toggle << TD_TOKEN_TOGGLE_SHIFT),
897 data);
898 plink = &td->link;
899

--- 9 unchanged lines hidden (view full) ---

909 td->status |= __constant_cpu_to_le32(TD_CTRL_IOC);
910
911 /*
912 * Build the new dummy TD and activate the old one
913 */
914 td = uhci_alloc_td(uhci);
915 if (!td)
916 goto nomem;
891
892 uhci_add_td_to_urbp(td, urbp);
893 uhci_fill_td(td, status,
894 destination | uhci_explen(0) |
895 (toggle << TD_TOKEN_TOGGLE_SHIFT),
896 data);
897 plink = &td->link;
898

--- 9 unchanged lines hidden (view full) ---

908 td->status |= __constant_cpu_to_le32(TD_CTRL_IOC);
909
910 /*
911 * Build the new dummy TD and activate the old one
912 */
913 td = uhci_alloc_td(uhci);
914 if (!td)
915 goto nomem;
917 *plink = cpu_to_le32(td->dma_handle);
916 *plink = LINK_TO_TD(td);
918
919 uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0);
920 wmb();
921 qh->dummy_td->status |= __constant_cpu_to_le32(TD_CTRL_ACTIVE);
922 qh->dummy_td = td;
923
924 usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
925 usb_pipeout(urb->pipe), toggle);

--- 74 unchanged lines hidden (view full) ---

1000
1001 td = list_entry(urbp->td_list.prev, struct uhci_td, list);
1002 if (qh->type == USB_ENDPOINT_XFER_CONTROL) {
1003
1004 /* When a control transfer is short, we have to restart
1005 * the queue at the status stage transaction, which is
1006 * the last TD. */
1007 WARN_ON(list_empty(&urbp->td_list));
917
918 uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0);
919 wmb();
920 qh->dummy_td->status |= __constant_cpu_to_le32(TD_CTRL_ACTIVE);
921 qh->dummy_td = td;
922
923 usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
924 usb_pipeout(urb->pipe), toggle);

--- 74 unchanged lines hidden (view full) ---

999
1000 td = list_entry(urbp->td_list.prev, struct uhci_td, list);
1001 if (qh->type == USB_ENDPOINT_XFER_CONTROL) {
1002
1003 /* When a control transfer is short, we have to restart
1004 * the queue at the status stage transaction, which is
1005 * the last TD. */
1006 WARN_ON(list_empty(&urbp->td_list));
1008 qh->element = cpu_to_le32(td->dma_handle);
1007 qh->element = LINK_TO_TD(td);
1009 tmp = td->list.prev;
1010 ret = -EINPROGRESS;
1011
1012 } else {
1013
1014 /* When a bulk/interrupt transfer is short, we have to
1015 * fix up the toggles of the following URBs on the queue
1016 * before restarting the queue at the next URB. */

--- 544 unchanged lines hidden (view full) ---

1561
1562 /* The queue hasn't advanced; check for timeout */
1563 if (qh->wait_expired)
1564 goto done;
1565
1566 if (time_after(jiffies, qh->advance_jiffies + QH_WAIT_TIMEOUT)) {
1567
1568 /* Detect the Intel bug and work around it */
1008 tmp = td->list.prev;
1009 ret = -EINPROGRESS;
1010
1011 } else {
1012
1013 /* When a bulk/interrupt transfer is short, we have to
1014 * fix up the toggles of the following URBs on the queue
1015 * before restarting the queue at the next URB. */

--- 544 unchanged lines hidden (view full) ---

1560
1561 /* The queue hasn't advanced; check for timeout */
1562 if (qh->wait_expired)
1563 goto done;
1564
1565 if (time_after(jiffies, qh->advance_jiffies + QH_WAIT_TIMEOUT)) {
1566
1567 /* Detect the Intel bug and work around it */
1569 if (qh->post_td && qh_element(qh) ==
1570 cpu_to_le32(qh->post_td->dma_handle)) {
1568 if (qh->post_td && qh_element(qh) == LINK_TO_TD(qh->post_td)) {
1571 qh->element = qh->post_td->link;
1572 qh->advance_jiffies = jiffies;
1573 ret = 1;
1574 goto done;
1575 }
1576
1577 qh->wait_expired = 1;
1578

--- 73 unchanged lines hidden ---
1569 qh->element = qh->post_td->link;
1570 qh->advance_jiffies = jiffies;
1571 ret = 1;
1572 goto done;
1573 }
1574
1575 qh->wait_expired = 1;
1576

--- 73 unchanged lines hidden ---