aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ehci-q.c
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
commitada47b5fe13d89735805b566185f4885f5a3f750 (patch)
tree644b88f8a71896307d71438e9b3af49126ffb22b /drivers/usb/host/ehci-q.c
parent43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff)
parent3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff)
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/usb/host/ehci-q.c')
-rw-r--r--drivers/usb/host/ehci-q.c43
1 files changed, 35 insertions, 8 deletions
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index 139a2cc3f641..89521775c567 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -616,9 +616,11 @@ qh_urb_transaction (
616) { 616) {
617 struct ehci_qtd *qtd, *qtd_prev; 617 struct ehci_qtd *qtd, *qtd_prev;
618 dma_addr_t buf; 618 dma_addr_t buf;
619 int len, maxpacket; 619 int len, this_sg_len, maxpacket;
620 int is_input; 620 int is_input;
621 u32 token; 621 u32 token;
622 int i;
623 struct scatterlist *sg;
622 624
623 /* 625 /*
624 * URBs map to sequences of QTDs: one logical transaction 626 * URBs map to sequences of QTDs: one logical transaction
@@ -659,7 +661,20 @@ qh_urb_transaction (
659 /* 661 /*
660 * data transfer stage: buffer setup 662 * data transfer stage: buffer setup
661 */ 663 */
662 buf = urb->transfer_dma; 664 i = urb->num_sgs;
665 if (len > 0 && i > 0) {
666 sg = urb->sg->sg;
667 buf = sg_dma_address(sg);
668
669 /* urb->transfer_buffer_length may be smaller than the
670 * size of the scatterlist (or vice versa)
671 */
672 this_sg_len = min_t(int, sg_dma_len(sg), len);
673 } else {
674 sg = NULL;
675 buf = urb->transfer_dma;
676 this_sg_len = len;
677 }
663 678
664 if (is_input) 679 if (is_input)
665 token |= (1 /* "in" */ << 8); 680 token |= (1 /* "in" */ << 8);
@@ -675,7 +690,9 @@ qh_urb_transaction (
675 for (;;) { 690 for (;;) {
676 int this_qtd_len; 691 int this_qtd_len;
677 692
678 this_qtd_len = qtd_fill(ehci, qtd, buf, len, token, maxpacket); 693 this_qtd_len = qtd_fill(ehci, qtd, buf, this_sg_len, token,
694 maxpacket);
695 this_sg_len -= this_qtd_len;
679 len -= this_qtd_len; 696 len -= this_qtd_len;
680 buf += this_qtd_len; 697 buf += this_qtd_len;
681 698
@@ -691,8 +708,13 @@ qh_urb_transaction (
691 if ((maxpacket & (this_qtd_len + (maxpacket - 1))) == 0) 708 if ((maxpacket & (this_qtd_len + (maxpacket - 1))) == 0)
692 token ^= QTD_TOGGLE; 709 token ^= QTD_TOGGLE;
693 710
694 if (likely (len <= 0)) 711 if (likely(this_sg_len <= 0)) {
695 break; 712 if (--i <= 0 || len <= 0)
713 break;
714 sg = sg_next(sg);
715 buf = sg_dma_address(sg);
716 this_sg_len = min_t(int, sg_dma_len(sg), len);
717 }
696 718
697 qtd_prev = qtd; 719 qtd_prev = qtd;
698 qtd = ehci_qtd_alloc (ehci, flags); 720 qtd = ehci_qtd_alloc (ehci, flags);
@@ -827,9 +849,10 @@ qh_make (
827 * But interval 1 scheduling is simpler, and 849 * But interval 1 scheduling is simpler, and
828 * includes high bandwidth. 850 * includes high bandwidth.
829 */ 851 */
830 dbg ("intr period %d uframes, NYET!", 852 urb->interval = 1;
831 urb->interval); 853 } else if (qh->period > ehci->periodic_size) {
832 goto done; 854 qh->period = ehci->periodic_size;
855 urb->interval = qh->period << 3;
833 } 856 }
834 } else { 857 } else {
835 int think_time; 858 int think_time;
@@ -852,6 +875,10 @@ qh_make (
852 usb_calc_bus_time (urb->dev->speed, 875 usb_calc_bus_time (urb->dev->speed,
853 is_input, 0, max_packet (maxp))); 876 is_input, 0, max_packet (maxp)));
854 qh->period = urb->interval; 877 qh->period = urb->interval;
878 if (qh->period > ehci->periodic_size) {
879 qh->period = ehci->periodic_size;
880 urb->interval = qh->period;
881 }
855 } 882 }
856 } 883 }
857 884