@@ -2586,6 +2586,7 @@ pci_xhci_xfer_complete(struct pci_xhci_vdev *xdev,
2586
2586
uint32_t edtla ;
2587
2587
uint32_t i ;
2588
2588
int err = XHCI_TRB_ERROR_SUCCESS ;
2589
+ int rem_len = 0 ;
2589
2590
2590
2591
dev_ctx = pci_xhci_get_dev_ctx (xdev , slot );
2591
2592
@@ -2626,11 +2627,12 @@ pci_xhci_xfer_complete(struct pci_xhci_vdev *xdev,
2626
2627
trbflags = trb -> dwTrb3 ;
2627
2628
2628
2629
UPRINTF (LDBG , "xfer[%d] done?%u:%d trb %x %016lx %x "
2629
- "(err %d) IOC?%d\r\n" ,
2630
+ "(err %d) IOC?%d, chained %d \r\n" ,
2630
2631
i , xfer -> data [i ].processed , xfer -> data [i ].blen ,
2631
2632
XHCI_TRB_3_TYPE_GET (trbflags ), evtrb .qwTrb0 ,
2632
2633
trbflags , err ,
2633
- trb -> dwTrb3 & XHCI_TRB_3_IOC_BIT ? 1 : 0 );
2634
+ trb -> dwTrb3 & XHCI_TRB_3_IOC_BIT ? 1 : 0 ,
2635
+ xfer -> data [i ].chained );
2634
2636
2635
2637
if (xfer -> data [i ].processed < USB_XFER_BLK_HANDLED ) {
2636
2638
xfer -> head = (int )i ;
@@ -2643,6 +2645,21 @@ pci_xhci_xfer_complete(struct pci_xhci_vdev *xdev,
2643
2645
edtla += xfer -> data [i ].bdone ;
2644
2646
2645
2647
trb -> dwTrb3 = (trb -> dwTrb3 & ~0x1 ) | (xfer -> data [i ].ccs );
2648
+ if (xfer -> data [i ].chained == 1 ) {
2649
+ rem_len += xfer -> data [i ].blen ;
2650
+ i = (i + 1 ) % USB_MAX_XFER_BLOCKS ;
2651
+
2652
+ /* When the chained == 1, this 'continue' will delay
2653
+ * the IOC behavior which could decrease the number
2654
+ * of virtual interrupts. This could GREATLY improve
2655
+ * the performance especially under ISOCH scenario.
2656
+ */
2657
+ continue ;
2658
+ } else
2659
+ rem_len += xfer -> data [i ].blen ;
2660
+
2661
+ if (rem_len > 0 )
2662
+ err = XHCI_TRB_ERROR_SHORT_PKT ;
2646
2663
2647
2664
/* Only interrupt if IOC or short packet */
2648
2665
if (!(trb -> dwTrb3 & XHCI_TRB_3_IOC_BIT ) &&
@@ -2654,7 +2671,7 @@ pci_xhci_xfer_complete(struct pci_xhci_vdev *xdev,
2654
2671
}
2655
2672
2656
2673
evtrb .dwTrb2 = XHCI_TRB_2_ERROR_SET (err ) |
2657
- XHCI_TRB_2_REM_SET (xfer -> data [ i ]. blen );
2674
+ XHCI_TRB_2_REM_SET (rem_len );
2658
2675
2659
2676
evtrb .dwTrb3 = XHCI_TRB_3_TYPE_SET (XHCI_TRB_EVENT_TRANSFER ) |
2660
2677
XHCI_TRB_3_SLOT_SET (slot ) | XHCI_TRB_3_EP_SET (epid );
@@ -2675,6 +2692,7 @@ pci_xhci_xfer_complete(struct pci_xhci_vdev *xdev,
2675
2692
break ;
2676
2693
2677
2694
i = (i + 1 ) % USB_MAX_XFER_BLOCKS ;
2695
+ rem_len = 0 ;
2678
2696
}
2679
2697
2680
2698
return err ;
@@ -2782,6 +2800,7 @@ pci_xhci_handle_transfer(struct pci_xhci_vdev *xdev,
2782
2800
uint32_t trbflags ;
2783
2801
int do_intr , err ;
2784
2802
int do_retry ;
2803
+ bool is_isoch = false;
2785
2804
2786
2805
ep_ctx -> dwEpCtx0 = FIELD_REPLACE (ep_ctx -> dwEpCtx0 ,
2787
2806
XHCI_ST_EPCTX_RUNNING , 0x7 , 0 );
@@ -2858,8 +2877,11 @@ pci_xhci_handle_transfer(struct pci_xhci_vdev *xdev,
2858
2877
xfer_block -> processed = USB_XFER_BLK_HANDLED ;
2859
2878
break ;
2860
2879
2861
- case XHCI_TRB_TYPE_NORMAL :
2862
2880
case XHCI_TRB_TYPE_ISOCH :
2881
+ is_isoch = true;
2882
+ /* fall through */
2883
+
2884
+ case XHCI_TRB_TYPE_NORMAL :
2863
2885
if (setup_trb != NULL ) {
2864
2886
UPRINTF (LWRN , "trb not supposed to be in "
2865
2887
"ctl scope\r\n" );
@@ -2931,6 +2953,10 @@ pci_xhci_handle_transfer(struct pci_xhci_vdev *xdev,
2931
2953
xfer_block -> trbnext , xfer_block -> ccs );
2932
2954
}
2933
2955
2956
+ if (is_isoch == true || XHCI_TRB_3_TYPE_GET (trbflags ) ==
2957
+ XHCI_TRB_TYPE_EVENT_DATA /* win10 needs it */ )
2958
+ continue ;
2959
+
2934
2960
/* handle current batch that requires interrupt on complete */
2935
2961
if (trbflags & XHCI_TRB_3_IOC_BIT ) {
2936
2962
UPRINTF (LDBG , "trb IOC bit set\r\n" );
0 commit comments