diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2006-05-12 11:14:25 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-06-21 18:04:11 -0400 |
commit | b1869000a60b0c72022811f24110a52d3e300b1e (patch) | |
tree | b44930e177a344e63fb7e8b60466a38ae4877b2b /drivers/usb/host | |
parent | 0f28b55db543001d360e4319bfc3f2c4e28ba05f (diff) |
[PATCH] UHCI: Common result routine for Control/Bulk/Interrupt
This patch (as679) combines the result routine for Control URBs with the
routine for Bulk/Interrupt URBs. Along the way I eliminated the
debugging printouts for Control transfers unless the debugging level is
set higher than 1. I also eliminated a long-unused (#ifdef'ed-out)
section that works around some buggy old APC BackUPS devices.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host')
-rw-r--r-- | drivers/usb/host/uhci-q.c | 342 |
1 files changed, 125 insertions, 217 deletions
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index 693e92c1bd9e..30e36031fe21 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c | |||
@@ -619,134 +619,6 @@ nomem: | |||
619 | } | 619 | } |
620 | 620 | ||
621 | /* | 621 | /* |
622 | * If control-IN transfer was short, the status packet wasn't sent. | ||
623 | * This routine changes the element pointer in the QH to point at the | ||
624 | * status TD. It's safe to do this even while the QH is live, because | ||
625 | * the hardware only updates the element pointer following a successful | ||
626 | * transfer. The inactive TD for the short packet won't cause an update, | ||
627 | * so the pointer won't get overwritten. The next time the controller | ||
628 | * sees this QH, it will send the status packet. | ||
629 | */ | ||
630 | static int usb_control_retrigger_status(struct uhci_hcd *uhci, struct urb *urb) | ||
631 | { | ||
632 | struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; | ||
633 | struct uhci_td *td; | ||
634 | |||
635 | urbp->short_transfer = 1; | ||
636 | |||
637 | td = list_entry(urbp->td_list.prev, struct uhci_td, list); | ||
638 | urbp->qh->element = cpu_to_le32(td->dma_handle); | ||
639 | |||
640 | return -EINPROGRESS; | ||
641 | } | ||
642 | |||
643 | |||
644 | static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb) | ||
645 | { | ||
646 | struct list_head *tmp, *head; | ||
647 | struct urb_priv *urbp = urb->hcpriv; | ||
648 | struct uhci_td *td; | ||
649 | unsigned int status; | ||
650 | int ret = 0; | ||
651 | |||
652 | head = &urbp->td_list; | ||
653 | if (urbp->short_transfer) { | ||
654 | tmp = head->prev; | ||
655 | goto status_stage; | ||
656 | } | ||
657 | |||
658 | urb->actual_length = 0; | ||
659 | |||
660 | tmp = head->next; | ||
661 | td = list_entry(tmp, struct uhci_td, list); | ||
662 | |||
663 | /* The first TD is the SETUP stage, check the status, but skip */ | ||
664 | /* the count */ | ||
665 | status = uhci_status_bits(td_status(td)); | ||
666 | if (status & TD_CTRL_ACTIVE) | ||
667 | return -EINPROGRESS; | ||
668 | |||
669 | if (status) | ||
670 | goto td_error; | ||
671 | |||
672 | /* The rest of the TDs (but the last) are data */ | ||
673 | tmp = tmp->next; | ||
674 | while (tmp != head && tmp->next != head) { | ||
675 | unsigned int ctrlstat; | ||
676 | |||
677 | td = list_entry(tmp, struct uhci_td, list); | ||
678 | tmp = tmp->next; | ||
679 | |||
680 | ctrlstat = td_status(td); | ||
681 | status = uhci_status_bits(ctrlstat); | ||
682 | if (status & TD_CTRL_ACTIVE) | ||
683 | return -EINPROGRESS; | ||
684 | |||
685 | urb->actual_length += uhci_actual_length(ctrlstat); | ||
686 | |||
687 | if (status) | ||
688 | goto td_error; | ||
689 | |||
690 | /* Check to see if we received a short packet */ | ||
691 | if (uhci_actual_length(ctrlstat) < | ||
692 | uhci_expected_length(td_token(td))) { | ||
693 | if (urb->transfer_flags & URB_SHORT_NOT_OK) { | ||
694 | ret = -EREMOTEIO; | ||
695 | goto err; | ||
696 | } | ||
697 | |||
698 | return usb_control_retrigger_status(uhci, urb); | ||
699 | } | ||
700 | } | ||
701 | |||
702 | status_stage: | ||
703 | td = list_entry(tmp, struct uhci_td, list); | ||
704 | |||
705 | /* Control status stage */ | ||
706 | status = td_status(td); | ||
707 | |||
708 | #ifdef I_HAVE_BUGGY_APC_BACKUPS | ||
709 | /* APC BackUPS Pro kludge */ | ||
710 | /* It tries to send all of the descriptor instead of the amount */ | ||
711 | /* we requested */ | ||
712 | if (status & TD_CTRL_IOC && /* IOC is masked out by uhci_status_bits */ | ||
713 | status & TD_CTRL_ACTIVE && | ||
714 | status & TD_CTRL_NAK) | ||
715 | return 0; | ||
716 | #endif | ||
717 | |||
718 | status = uhci_status_bits(status); | ||
719 | if (status & TD_CTRL_ACTIVE) | ||
720 | return -EINPROGRESS; | ||
721 | |||
722 | if (status) | ||
723 | goto td_error; | ||
724 | |||
725 | return 0; | ||
726 | |||
727 | td_error: | ||
728 | ret = uhci_map_status(status, uhci_packetout(td_token(td))); | ||
729 | |||
730 | err: | ||
731 | if ((debug == 1 && ret != -EPIPE) || debug > 1) { | ||
732 | /* Some debugging code */ | ||
733 | dev_dbg(uhci_dev(uhci), "%s: failed with status %x\n", | ||
734 | __FUNCTION__, status); | ||
735 | |||
736 | if (errbuf) { | ||
737 | /* Print the chain for debugging purposes */ | ||
738 | uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0); | ||
739 | lprintk(errbuf); | ||
740 | } | ||
741 | } | ||
742 | |||
743 | /* Note that the queue has stopped */ | ||
744 | urbp->qh->element = UHCI_PTR_TERM; | ||
745 | urbp->qh->is_stopped = 1; | ||
746 | return ret; | ||
747 | } | ||
748 | |||
749 | /* | ||
750 | * Common submit for bulk and interrupt | 622 | * Common submit for bulk and interrupt |
751 | */ | 623 | */ |
752 | static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, | 624 | static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, |
@@ -864,86 +736,6 @@ nomem: | |||
864 | return -ENOMEM; | 736 | return -ENOMEM; |
865 | } | 737 | } |
866 | 738 | ||
867 | /* | ||
868 | * Common result for bulk and interrupt | ||
869 | */ | ||
870 | static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb) | ||
871 | { | ||
872 | struct urb_priv *urbp = urb->hcpriv; | ||
873 | struct uhci_td *td; | ||
874 | unsigned int status = 0; | ||
875 | int ret = 0; | ||
876 | |||
877 | urb->actual_length = 0; | ||
878 | |||
879 | list_for_each_entry(td, &urbp->td_list, list) { | ||
880 | unsigned int ctrlstat = td_status(td); | ||
881 | |||
882 | status = uhci_status_bits(ctrlstat); | ||
883 | if (status & TD_CTRL_ACTIVE) | ||
884 | return -EINPROGRESS; | ||
885 | |||
886 | urb->actual_length += uhci_actual_length(ctrlstat); | ||
887 | |||
888 | if (status) | ||
889 | goto td_error; | ||
890 | |||
891 | if (uhci_actual_length(ctrlstat) < | ||
892 | uhci_expected_length(td_token(td))) { | ||
893 | if (urb->transfer_flags & URB_SHORT_NOT_OK) { | ||
894 | ret = -EREMOTEIO; | ||
895 | goto err; | ||
896 | } | ||
897 | |||
898 | /* | ||
899 | * This URB stopped short of its end. We have to | ||
900 | * fix up the toggles of the following URBs on the | ||
901 | * queue and restart the queue. | ||
902 | * | ||
903 | * Do this only the first time we encounter the | ||
904 | * short URB. | ||
905 | */ | ||
906 | if (!urbp->short_transfer) { | ||
907 | urbp->short_transfer = 1; | ||
908 | urbp->qh->initial_toggle = | ||
909 | uhci_toggle(td_token(td)) ^ 1; | ||
910 | uhci_fixup_toggles(urbp->qh, 1); | ||
911 | |||
912 | td = list_entry(urbp->td_list.prev, | ||
913 | struct uhci_td, list); | ||
914 | urbp->qh->element = td->link; | ||
915 | } | ||
916 | break; | ||
917 | } | ||
918 | } | ||
919 | |||
920 | return 0; | ||
921 | |||
922 | td_error: | ||
923 | ret = uhci_map_status(status, uhci_packetout(td_token(td))); | ||
924 | |||
925 | if ((debug == 1 && ret != -EPIPE) || debug > 1) { | ||
926 | /* Some debugging code */ | ||
927 | dev_dbg(uhci_dev(uhci), "%s: failed with status %x\n", | ||
928 | __FUNCTION__, status); | ||
929 | |||
930 | if (debug > 1 && errbuf) { | ||
931 | /* Print the chain for debugging purposes */ | ||
932 | uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0); | ||
933 | lprintk(errbuf); | ||
934 | } | ||
935 | } | ||
936 | err: | ||
937 | |||
938 | /* Note that the queue has stopped and save the next toggle value */ | ||
939 | urbp->qh->element = UHCI_PTR_TERM; | ||
940 | urbp->qh->is_stopped = 1; | ||
941 | urbp->qh->needs_fixup = 1; | ||
942 | urbp->qh->initial_toggle = uhci_toggle(td_token(td)) ^ | ||
943 | (ret == -EREMOTEIO); | ||
944 | return ret; | ||
945 | } | ||
946 | |||
947 | static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb, | 739 | static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb, |
948 | struct uhci_qh *qh) | 740 | struct uhci_qh *qh) |
949 | { | 741 | { |
@@ -972,6 +764,129 @@ static inline int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb, | |||
972 | } | 764 | } |
973 | 765 | ||
974 | /* | 766 | /* |
767 | * Fix up the data structures following a short transfer | ||
768 | */ | ||
769 | static int uhci_fixup_short_transfer(struct uhci_hcd *uhci, | ||
770 | struct uhci_qh *qh, struct urb_priv *urbp, | ||
771 | struct uhci_td *short_td) | ||
772 | { | ||
773 | struct uhci_td *td; | ||
774 | int ret = 0; | ||
775 | |||
776 | td = list_entry(urbp->td_list.prev, struct uhci_td, list); | ||
777 | if (qh->type == USB_ENDPOINT_XFER_CONTROL) { | ||
778 | urbp->short_transfer = 1; | ||
779 | |||
780 | /* When a control transfer is short, we have to restart | ||
781 | * the queue at the status stage transaction, which is | ||
782 | * the last TD. */ | ||
783 | qh->element = cpu_to_le32(td->dma_handle); | ||
784 | ret = -EINPROGRESS; | ||
785 | |||
786 | } else if (!urbp->short_transfer) { | ||
787 | urbp->short_transfer = 1; | ||
788 | |||
789 | /* When a bulk/interrupt transfer is short, we have to | ||
790 | * fix up the toggles of the following URBs on the queue | ||
791 | * before restarting the queue at the next URB. */ | ||
792 | qh->initial_toggle = uhci_toggle(td_token(short_td)) ^ 1; | ||
793 | uhci_fixup_toggles(qh, 1); | ||
794 | |||
795 | qh->element = td->link; | ||
796 | } | ||
797 | |||
798 | return ret; | ||
799 | } | ||
800 | |||
801 | /* | ||
802 | * Common result for control, bulk, and interrupt | ||
803 | */ | ||
804 | static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb) | ||
805 | { | ||
806 | struct urb_priv *urbp = urb->hcpriv; | ||
807 | struct uhci_qh *qh = urbp->qh; | ||
808 | struct uhci_td *td; | ||
809 | struct list_head *tmp; | ||
810 | unsigned status; | ||
811 | int ret = 0; | ||
812 | |||
813 | tmp = urbp->td_list.next; | ||
814 | |||
815 | if (qh->type == USB_ENDPOINT_XFER_CONTROL) { | ||
816 | if (urbp->short_transfer) | ||
817 | tmp = urbp->td_list.prev; | ||
818 | else | ||
819 | urb->actual_length = -8; /* SETUP packet */ | ||
820 | } else | ||
821 | urb->actual_length = 0; | ||
822 | |||
823 | |||
824 | while (tmp != &urbp->td_list) { | ||
825 | unsigned int ctrlstat; | ||
826 | int len; | ||
827 | |||
828 | td = list_entry(tmp, struct uhci_td, list); | ||
829 | tmp = tmp->next; | ||
830 | |||
831 | ctrlstat = td_status(td); | ||
832 | status = uhci_status_bits(ctrlstat); | ||
833 | if (status & TD_CTRL_ACTIVE) | ||
834 | return -EINPROGRESS; | ||
835 | |||
836 | len = uhci_actual_length(ctrlstat); | ||
837 | urb->actual_length += len; | ||
838 | |||
839 | if (status) { | ||
840 | ret = uhci_map_status(status, | ||
841 | uhci_packetout(td_token(td))); | ||
842 | if ((debug == 1 && ret != -EPIPE) || debug > 1) { | ||
843 | /* Some debugging code */ | ||
844 | dev_dbg(uhci_dev(uhci), | ||
845 | "%s: failed with status %x\n", | ||
846 | __FUNCTION__, status); | ||
847 | |||
848 | if (debug > 1 && errbuf) { | ||
849 | /* Print the chain for debugging */ | ||
850 | uhci_show_qh(urbp->qh, errbuf, | ||
851 | ERRBUF_LEN, 0); | ||
852 | lprintk(errbuf); | ||
853 | } | ||
854 | } | ||
855 | |||
856 | } else if (len < uhci_expected_length(td_token(td))) { | ||
857 | |||
858 | /* We received a short packet */ | ||
859 | if (urb->transfer_flags & URB_SHORT_NOT_OK) | ||
860 | ret = -EREMOTEIO; | ||
861 | else if (ctrlstat & TD_CTRL_SPD) | ||
862 | ret = 1; | ||
863 | } | ||
864 | |||
865 | if (ret != 0) | ||
866 | goto err; | ||
867 | } | ||
868 | return ret; | ||
869 | |||
870 | err: | ||
871 | if (ret < 0) { | ||
872 | /* In case a control transfer gets an error | ||
873 | * during the setup stage */ | ||
874 | urb->actual_length = max(urb->actual_length, 0); | ||
875 | |||
876 | /* Note that the queue has stopped and save | ||
877 | * the next toggle value */ | ||
878 | qh->element = UHCI_PTR_TERM; | ||
879 | qh->is_stopped = 1; | ||
880 | qh->needs_fixup = (qh->type != USB_ENDPOINT_XFER_CONTROL); | ||
881 | qh->initial_toggle = uhci_toggle(td_token(td)) ^ | ||
882 | (ret == -EREMOTEIO); | ||
883 | |||
884 | } else /* Short packet received */ | ||
885 | ret = uhci_fixup_short_transfer(uhci, qh, urbp, td); | ||
886 | return ret; | ||
887 | } | ||
888 | |||
889 | /* | ||
975 | * Isochronous transfers | 890 | * Isochronous transfers |
976 | */ | 891 | */ |
977 | static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, | 892 | static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, |
@@ -1276,17 +1191,10 @@ static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh, | |||
1276 | urbp = list_entry(qh->queue.next, struct urb_priv, node); | 1191 | urbp = list_entry(qh->queue.next, struct urb_priv, node); |
1277 | urb = urbp->urb; | 1192 | urb = urbp->urb; |
1278 | 1193 | ||
1279 | switch (qh->type) { | 1194 | if (qh->type == USB_ENDPOINT_XFER_ISOC) |
1280 | case USB_ENDPOINT_XFER_CONTROL: | ||
1281 | status = uhci_result_control(uhci, urb); | ||
1282 | break; | ||
1283 | case USB_ENDPOINT_XFER_ISOC: | ||
1284 | status = uhci_result_isochronous(uhci, urb); | 1195 | status = uhci_result_isochronous(uhci, urb); |
1285 | break; | 1196 | else |
1286 | default: /* USB_ENDPOINT_XFER_BULK or _INT */ | ||
1287 | status = uhci_result_common(uhci, urb); | 1197 | status = uhci_result_common(uhci, urb); |
1288 | break; | ||
1289 | } | ||
1290 | if (status == -EINPROGRESS) | 1198 | if (status == -EINPROGRESS) |
1291 | break; | 1199 | break; |
1292 | 1200 | ||