@@ -602,6 +602,8 @@ static void td_submit_urb (
602
602
u32 info = 0 ;
603
603
int is_out = usb_pipeout (urb -> pipe );
604
604
int periodic = 0 ;
605
+ int i , this_sg_len , n ;
606
+ struct scatterlist * sg ;
605
607
606
608
/* OHCI handles the bulk/interrupt data toggles itself. We just
607
609
* use the device toggle bits for resetting, and rely on the fact
@@ -615,10 +617,24 @@ static void td_submit_urb (
615
617
616
618
list_add (& urb_priv -> pending , & ohci -> pending );
617
619
618
- if (data_len )
619
- data = urb -> transfer_dma ;
620
- else
621
- data = 0 ;
620
+ i = urb -> num_mapped_sgs ;
621
+ if (data_len > 0 && i > 0 ) {
622
+ sg = urb -> sg ;
623
+ data = sg_dma_address (sg );
624
+
625
+ /*
626
+ * urb->transfer_buffer_length may be smaller than the
627
+ * size of the scatterlist (or vice versa)
628
+ */
629
+ this_sg_len = min_t (int , sg_dma_len (sg ), data_len );
630
+ } else {
631
+ sg = NULL ;
632
+ if (data_len )
633
+ data = urb -> transfer_dma ;
634
+ else
635
+ data = 0 ;
636
+ this_sg_len = data_len ;
637
+ }
622
638
623
639
/* NOTE: TD_CC is set so we can tell which TDs the HC processed by
624
640
* using TD_CC_GET, as well as by seeing them on the done list.
@@ -639,17 +655,29 @@ static void td_submit_urb (
639
655
? TD_T_TOGGLE | TD_CC | TD_DP_OUT
640
656
: TD_T_TOGGLE | TD_CC | TD_DP_IN ;
641
657
/* TDs _could_ transfer up to 8K each */
642
- while (data_len > 4096 ) {
643
- td_fill (ohci , info , data , 4096 , urb , cnt );
644
- data += 4096 ;
645
- data_len -= 4096 ;
658
+ for (;;) {
659
+ n = min (this_sg_len , 4096 );
660
+
661
+ /* maybe avoid ED halt on final TD short read */
662
+ if (n >= data_len || (i == 1 && n >= this_sg_len )) {
663
+ if (!(urb -> transfer_flags & URB_SHORT_NOT_OK ))
664
+ info |= TD_R ;
665
+ }
666
+ td_fill (ohci , info , data , n , urb , cnt );
667
+ this_sg_len -= n ;
668
+ data_len -= n ;
669
+ data += n ;
646
670
cnt ++ ;
671
+
672
+ if (this_sg_len <= 0 ) {
673
+ if (-- i <= 0 || data_len <= 0 )
674
+ break ;
675
+ sg = sg_next (sg );
676
+ data = sg_dma_address (sg );
677
+ this_sg_len = min_t (int , sg_dma_len (sg ),
678
+ data_len );
679
+ }
647
680
}
648
- /* maybe avoid ED halt on final TD short read */
649
- if (!(urb -> transfer_flags & URB_SHORT_NOT_OK ))
650
- info |= TD_R ;
651
- td_fill (ohci , info , data , data_len , urb , cnt );
652
- cnt ++ ;
653
681
if ((urb -> transfer_flags & URB_ZERO_PACKET )
654
682
&& cnt < urb_priv -> length ) {
655
683
td_fill (ohci , info , 0 , 0 , urb , cnt );
0 commit comments