diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/host/uhci-debug.c | 5 | ||||
-rw-r--r-- | drivers/usb/host/uhci-hcd.h | 1 | ||||
-rw-r--r-- | drivers/usb/host/uhci-q.c | 138 |
3 files changed, 83 insertions, 61 deletions
diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c index 3faccbd68547..6814783adf91 100644 --- a/drivers/usb/host/uhci-debug.c +++ b/drivers/usb/host/uhci-debug.c | |||
@@ -189,6 +189,11 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space) | |||
189 | space, "", nurbs); | 189 | space, "", nurbs); |
190 | } | 190 | } |
191 | 191 | ||
192 | if (qh->udev) { | ||
193 | out += sprintf(out, "%*s Dummy TD\n", space, ""); | ||
194 | out += uhci_show_td(qh->dummy_td, out, len - (out - buf), 0); | ||
195 | } | ||
196 | |||
192 | return out - buf; | 197 | return out - buf; |
193 | } | 198 | } |
194 | 199 | ||
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h index 7a9481c09a05..c057956667b5 100644 --- a/drivers/usb/host/uhci-hcd.h +++ b/drivers/usb/host/uhci-hcd.h | |||
@@ -128,6 +128,7 @@ struct uhci_qh { | |||
128 | struct usb_device *udev; | 128 | struct usb_device *udev; |
129 | struct list_head queue; /* Queue of urbps for this QH */ | 129 | struct list_head queue; /* Queue of urbps for this QH */ |
130 | struct uhci_qh *skel; /* Skeleton for this QH */ | 130 | struct uhci_qh *skel; /* Skeleton for this QH */ |
131 | struct uhci_td *dummy_td; /* Dummy TD to end the queue */ | ||
131 | 132 | ||
132 | unsigned int unlink_frame; /* When the QH was unlinked */ | 133 | unsigned int unlink_frame; /* When the QH was unlinked */ |
133 | int state; /* QH_STATE_xxx; see above */ | 134 | int state; /* QH_STATE_xxx; see above */ |
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index b1b551a3d14e..c4194182dcc4 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c | |||
@@ -48,10 +48,6 @@ static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci) | |||
48 | return NULL; | 48 | return NULL; |
49 | 49 | ||
50 | td->dma_handle = dma_handle; | 50 | td->dma_handle = dma_handle; |
51 | |||
52 | td->link = UHCI_PTR_TERM; | ||
53 | td->buffer = 0; | ||
54 | |||
55 | td->frame = -1; | 51 | td->frame = -1; |
56 | 52 | ||
57 | INIT_LIST_HEAD(&td->list); | 53 | INIT_LIST_HEAD(&td->list); |
@@ -221,6 +217,11 @@ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, | |||
221 | INIT_LIST_HEAD(&qh->node); | 217 | INIT_LIST_HEAD(&qh->node); |
222 | 218 | ||
223 | if (udev) { /* Normal QH */ | 219 | if (udev) { /* Normal QH */ |
220 | qh->dummy_td = uhci_alloc_td(uhci); | ||
221 | if (!qh->dummy_td) { | ||
222 | dma_pool_free(uhci->qh_pool, qh, dma_handle); | ||
223 | return NULL; | ||
224 | } | ||
224 | qh->state = QH_STATE_IDLE; | 225 | qh->state = QH_STATE_IDLE; |
225 | qh->hep = hep; | 226 | qh->hep = hep; |
226 | qh->udev = udev; | 227 | qh->udev = udev; |
@@ -244,6 +245,7 @@ static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) | |||
244 | if (qh->udev) { | 245 | if (qh->udev) { |
245 | qh->hep->hcpriv = NULL; | 246 | qh->hep->hcpriv = NULL; |
246 | usb_put_dev(qh->udev); | 247 | usb_put_dev(qh->udev); |
248 | uhci_free_td(uhci, qh->dummy_td); | ||
247 | } | 249 | } |
248 | dma_pool_free(uhci->qh_pool, qh, qh->dma_handle); | 250 | dma_pool_free(uhci->qh_pool, qh, qh->dma_handle); |
249 | } | 251 | } |
@@ -531,22 +533,20 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, | |||
531 | /* The "pipe" thing contains the destination in bits 8--18 */ | 533 | /* The "pipe" thing contains the destination in bits 8--18 */ |
532 | destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP; | 534 | destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP; |
533 | 535 | ||
534 | /* 3 errors */ | 536 | /* 3 errors, dummy TD remains inactive */ |
535 | status = TD_CTRL_ACTIVE | uhci_maxerr(3); | 537 | status = uhci_maxerr(3); |
536 | if (urb->dev->speed == USB_SPEED_LOW) | 538 | if (urb->dev->speed == USB_SPEED_LOW) |
537 | status |= TD_CTRL_LS; | 539 | status |= TD_CTRL_LS; |
538 | 540 | ||
539 | /* | 541 | /* |
540 | * Build the TD for the control request setup packet | 542 | * Build the TD for the control request setup packet |
541 | */ | 543 | */ |
542 | td = uhci_alloc_td(uhci); | 544 | td = qh->dummy_td; |
543 | if (!td) | ||
544 | return -ENOMEM; | ||
545 | |||
546 | uhci_add_td_to_urb(urb, td); | 545 | uhci_add_td_to_urb(urb, td); |
547 | uhci_fill_td(td, status, destination | uhci_explen(8), | 546 | uhci_fill_td(td, status, destination | uhci_explen(8), |
548 | urb->setup_dma); | 547 | urb->setup_dma); |
549 | plink = &td->link; | 548 | plink = &td->link; |
549 | status |= TD_CTRL_ACTIVE; | ||
550 | 550 | ||
551 | /* | 551 | /* |
552 | * If direction is "send", change the packet ID from SETUP (0x2D) | 552 | * If direction is "send", change the packet ID from SETUP (0x2D) |
@@ -568,7 +568,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, | |||
568 | 568 | ||
569 | td = uhci_alloc_td(uhci); | 569 | td = uhci_alloc_td(uhci); |
570 | if (!td) | 570 | if (!td) |
571 | return -ENOMEM; | 571 | goto nomem; |
572 | *plink = cpu_to_le32(td->dma_handle); | 572 | *plink = cpu_to_le32(td->dma_handle); |
573 | 573 | ||
574 | /* Alternate Data0/1 (start with Data1) */ | 574 | /* Alternate Data0/1 (start with Data1) */ |
@@ -588,7 +588,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, | |||
588 | */ | 588 | */ |
589 | td = uhci_alloc_td(uhci); | 589 | td = uhci_alloc_td(uhci); |
590 | if (!td) | 590 | if (!td) |
591 | return -ENOMEM; | 591 | goto nomem; |
592 | *plink = cpu_to_le32(td->dma_handle); | 592 | *plink = cpu_to_le32(td->dma_handle); |
593 | 593 | ||
594 | /* | 594 | /* |
@@ -608,6 +608,20 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, | |||
608 | uhci_add_td_to_urb(urb, td); | 608 | uhci_add_td_to_urb(urb, td); |
609 | uhci_fill_td(td, status | TD_CTRL_IOC, | 609 | uhci_fill_td(td, status | TD_CTRL_IOC, |
610 | destination | uhci_explen(0), 0); | 610 | destination | uhci_explen(0), 0); |
611 | plink = &td->link; | ||
612 | |||
613 | /* | ||
614 | * Build the new dummy TD and activate the old one | ||
615 | */ | ||
616 | td = uhci_alloc_td(uhci); | ||
617 | if (!td) | ||
618 | goto nomem; | ||
619 | *plink = cpu_to_le32(td->dma_handle); | ||
620 | |||
621 | uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0); | ||
622 | wmb(); | ||
623 | qh->dummy_td->status |= __constant_cpu_to_le32(TD_CTRL_ACTIVE); | ||
624 | qh->dummy_td = td; | ||
611 | 625 | ||
612 | /* Low-speed transfers get a different queue, and won't hog the bus. | 626 | /* Low-speed transfers get a different queue, and won't hog the bus. |
613 | * Also, some devices enumerate better without FSBR; the easiest way | 627 | * Also, some devices enumerate better without FSBR; the easiest way |
@@ -620,8 +634,12 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, | |||
620 | qh->skel = uhci->skel_fs_control_qh; | 634 | qh->skel = uhci->skel_fs_control_qh; |
621 | uhci_inc_fsbr(uhci, urb); | 635 | uhci_inc_fsbr(uhci, urb); |
622 | } | 636 | } |
623 | |||
624 | return 0; | 637 | return 0; |
638 | |||
639 | nomem: | ||
640 | /* Remove the dummy TD from the td_list so it doesn't get freed */ | ||
641 | uhci_remove_td_from_urb(qh->dummy_td); | ||
642 | return -ENOMEM; | ||
625 | } | 643 | } |
626 | 644 | ||
627 | /* | 645 | /* |
@@ -761,16 +779,19 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, | |||
761 | int maxsze = le16_to_cpu(qh->hep->desc.wMaxPacketSize); | 779 | int maxsze = le16_to_cpu(qh->hep->desc.wMaxPacketSize); |
762 | int len = urb->transfer_buffer_length; | 780 | int len = urb->transfer_buffer_length; |
763 | dma_addr_t data = urb->transfer_dma; | 781 | dma_addr_t data = urb->transfer_dma; |
764 | __le32 *plink, fake_link; | 782 | __le32 *plink; |
783 | unsigned int toggle; | ||
765 | 784 | ||
766 | if (len < 0) | 785 | if (len < 0) |
767 | return -EINVAL; | 786 | return -EINVAL; |
768 | 787 | ||
769 | /* The "pipe" thing contains the destination in bits 8--18 */ | 788 | /* The "pipe" thing contains the destination in bits 8--18 */ |
770 | destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe); | 789 | destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe); |
790 | toggle = usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), | ||
791 | usb_pipeout(urb->pipe)); | ||
771 | 792 | ||
772 | /* 3 errors */ | 793 | /* 3 errors, dummy TD remains inactive */ |
773 | status = TD_CTRL_ACTIVE | uhci_maxerr(3); | 794 | status = uhci_maxerr(3); |
774 | if (urb->dev->speed == USB_SPEED_LOW) | 795 | if (urb->dev->speed == USB_SPEED_LOW) |
775 | status |= TD_CTRL_LS; | 796 | status |= TD_CTRL_LS; |
776 | if (usb_pipein(urb->pipe)) | 797 | if (usb_pipein(urb->pipe)) |
@@ -779,7 +800,8 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, | |||
779 | /* | 800 | /* |
780 | * Build the DATA TDs | 801 | * Build the DATA TDs |
781 | */ | 802 | */ |
782 | plink = &fake_link; | 803 | plink = NULL; |
804 | td = qh->dummy_td; | ||
783 | do { /* Allow zero length packets */ | 805 | do { /* Allow zero length packets */ |
784 | int pktsze = maxsze; | 806 | int pktsze = maxsze; |
785 | 807 | ||
@@ -789,24 +811,23 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, | |||
789 | status &= ~TD_CTRL_SPD; | 811 | status &= ~TD_CTRL_SPD; |
790 | } | 812 | } |
791 | 813 | ||
792 | td = uhci_alloc_td(uhci); | 814 | if (plink) { |
793 | if (!td) | 815 | td = uhci_alloc_td(uhci); |
794 | return -ENOMEM; | 816 | if (!td) |
795 | *plink = cpu_to_le32(td->dma_handle); | 817 | goto nomem; |
796 | 818 | *plink = cpu_to_le32(td->dma_handle); | |
819 | } | ||
797 | uhci_add_td_to_urb(urb, td); | 820 | uhci_add_td_to_urb(urb, td); |
798 | uhci_fill_td(td, status, | 821 | uhci_fill_td(td, status, |
799 | destination | uhci_explen(pktsze) | | 822 | destination | uhci_explen(pktsze) | |
800 | (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), | 823 | (toggle << TD_TOKEN_TOGGLE_SHIFT), |
801 | usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT), | 824 | data); |
802 | data); | ||
803 | plink = &td->link; | 825 | plink = &td->link; |
826 | status |= TD_CTRL_ACTIVE; | ||
804 | 827 | ||
805 | data += pktsze; | 828 | data += pktsze; |
806 | len -= maxsze; | 829 | len -= maxsze; |
807 | 830 | toggle ^= 1; | |
808 | usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), | ||
809 | usb_pipeout(urb->pipe)); | ||
810 | } while (len > 0); | 831 | } while (len > 0); |
811 | 832 | ||
812 | /* | 833 | /* |
@@ -821,17 +842,17 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, | |||
821 | urb->transfer_buffer_length > 0) { | 842 | urb->transfer_buffer_length > 0) { |
822 | td = uhci_alloc_td(uhci); | 843 | td = uhci_alloc_td(uhci); |
823 | if (!td) | 844 | if (!td) |
824 | return -ENOMEM; | 845 | goto nomem; |
825 | *plink = cpu_to_le32(td->dma_handle); | 846 | *plink = cpu_to_le32(td->dma_handle); |
826 | 847 | ||
827 | uhci_add_td_to_urb(urb, td); | 848 | uhci_add_td_to_urb(urb, td); |
828 | uhci_fill_td(td, status, destination | uhci_explen(0) | | 849 | uhci_fill_td(td, status, |
829 | (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), | 850 | destination | uhci_explen(0) | |
830 | usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT), | 851 | (toggle << TD_TOKEN_TOGGLE_SHIFT), |
831 | data); | 852 | data); |
853 | plink = &td->link; | ||
832 | 854 | ||
833 | usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), | 855 | toggle ^= 1; |
834 | usb_pipeout(urb->pipe)); | ||
835 | } | 856 | } |
836 | 857 | ||
837 | /* Set the interrupt-on-completion flag on the last packet. | 858 | /* Set the interrupt-on-completion flag on the last packet. |
@@ -842,7 +863,27 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, | |||
842 | * flag setting. */ | 863 | * flag setting. */ |
843 | td->status |= __constant_cpu_to_le32(TD_CTRL_IOC); | 864 | td->status |= __constant_cpu_to_le32(TD_CTRL_IOC); |
844 | 865 | ||
866 | /* | ||
867 | * Build the new dummy TD and activate the old one | ||
868 | */ | ||
869 | td = uhci_alloc_td(uhci); | ||
870 | if (!td) | ||
871 | goto nomem; | ||
872 | *plink = cpu_to_le32(td->dma_handle); | ||
873 | |||
874 | uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0); | ||
875 | wmb(); | ||
876 | qh->dummy_td->status |= __constant_cpu_to_le32(TD_CTRL_ACTIVE); | ||
877 | qh->dummy_td = td; | ||
878 | |||
879 | usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), | ||
880 | usb_pipeout(urb->pipe), toggle); | ||
845 | return 0; | 881 | return 0; |
882 | |||
883 | nomem: | ||
884 | /* Remove the dummy TD from the td_list so it doesn't get freed */ | ||
885 | uhci_remove_td_from_urb(qh->dummy_td); | ||
886 | return -ENOMEM; | ||
846 | } | 887 | } |
847 | 888 | ||
848 | /* | 889 | /* |
@@ -1169,31 +1210,6 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd, | |||
1169 | * become idle, so we can activate it right away. */ | 1210 | * become idle, so we can activate it right away. */ |
1170 | if (qh->queue.next == &urbp->node) | 1211 | if (qh->queue.next == &urbp->node) |
1171 | uhci_activate_qh(uhci, qh); | 1212 | uhci_activate_qh(uhci, qh); |
1172 | |||
1173 | /* If the QH is already active, we have a race with the hardware. | ||
1174 | * This won't get fixed until dummy TDs are added. */ | ||
1175 | else if (qh->state == QH_STATE_ACTIVE) { | ||
1176 | |||
1177 | /* If the URB isn't first on its queue, adjust the link pointer | ||
1178 | * of the last TD in the previous URB. */ | ||
1179 | if (urbp->node.prev != &urbp->qh->queue) { | ||
1180 | struct urb_priv *purbp = list_entry(urbp->node.prev, | ||
1181 | struct urb_priv, node); | ||
1182 | struct uhci_td *ptd = list_entry(purbp->td_list.prev, | ||
1183 | struct uhci_td, list); | ||
1184 | struct uhci_td *td = list_entry(urbp->td_list.next, | ||
1185 | struct uhci_td, list); | ||
1186 | |||
1187 | ptd->link = cpu_to_le32(td->dma_handle); | ||
1188 | |||
1189 | } | ||
1190 | if (qh_element(qh) == UHCI_PTR_TERM) { | ||
1191 | struct uhci_td *td = list_entry(urbp->td_list.next, | ||
1192 | struct uhci_td, list); | ||
1193 | |||
1194 | qh->element = cpu_to_le32(td->dma_handle); | ||
1195 | } | ||
1196 | } | ||
1197 | goto done; | 1213 | goto done; |
1198 | 1214 | ||
1199 | err_submit_failed: | 1215 | err_submit_failed: |