Skip to content

Commit 7dbde27

Browse files
xiaoguangwuacrnsi
authored andcommitted
DM USB: xHCI: use new isoch transfer implementation
The old implementation processes isoch TRB one by one, this method can't support scenario which needs high performance, such as real time USB camera video. New implementions will compose all the isoch TRBs for one Door Bell Ring, and give them to libusb as a single request. The test result shows that this method could greatly improve the porfermance. Tracked-On: #3054 Signed-off-by: Xiaoguang Wu <xiaoguang.wu@intel.com> Acked-by: Yu Wang <yu1.wang@intel.com>
1 parent b57f6f9 commit 7dbde27

File tree

2 files changed

+156
-117
lines changed

2 files changed

+156
-117
lines changed

devicemodel/hw/pci/xhci.c

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2586,6 +2586,7 @@ pci_xhci_xfer_complete(struct pci_xhci_vdev *xdev,
25862586
uint32_t edtla;
25872587
uint32_t i;
25882588
int err = XHCI_TRB_ERROR_SUCCESS;
2589+
int rem_len = 0;
25892590

25902591
dev_ctx = pci_xhci_get_dev_ctx(xdev, slot);
25912592

@@ -2626,11 +2627,12 @@ pci_xhci_xfer_complete(struct pci_xhci_vdev *xdev,
26262627
trbflags = trb->dwTrb3;
26272628

26282629
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",
26302631
i, xfer->data[i].processed, xfer->data[i].blen,
26312632
XHCI_TRB_3_TYPE_GET(trbflags), evtrb.qwTrb0,
26322633
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);
26342636

26352637
if (xfer->data[i].processed < USB_XFER_BLK_HANDLED) {
26362638
xfer->head = (int)i;
@@ -2643,6 +2645,21 @@ pci_xhci_xfer_complete(struct pci_xhci_vdev *xdev,
26432645
edtla += xfer->data[i].bdone;
26442646

26452647
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;
26462663

26472664
/* Only interrupt if IOC or short packet */
26482665
if (!(trb->dwTrb3 & XHCI_TRB_3_IOC_BIT) &&
@@ -2654,7 +2671,7 @@ pci_xhci_xfer_complete(struct pci_xhci_vdev *xdev,
26542671
}
26552672

26562673
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);
26582675

26592676
evtrb.dwTrb3 = XHCI_TRB_3_TYPE_SET(XHCI_TRB_EVENT_TRANSFER) |
26602677
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,
26752692
break;
26762693

26772694
i = (i + 1) % USB_MAX_XFER_BLOCKS;
2695+
rem_len = 0;
26782696
}
26792697

26802698
return err;
@@ -2782,6 +2800,7 @@ pci_xhci_handle_transfer(struct pci_xhci_vdev *xdev,
27822800
uint32_t trbflags;
27832801
int do_intr, err;
27842802
int do_retry;
2803+
bool is_isoch = false;
27852804

27862805
ep_ctx->dwEpCtx0 = FIELD_REPLACE(ep_ctx->dwEpCtx0,
27872806
XHCI_ST_EPCTX_RUNNING, 0x7, 0);
@@ -2858,8 +2877,11 @@ pci_xhci_handle_transfer(struct pci_xhci_vdev *xdev,
28582877
xfer_block->processed = USB_XFER_BLK_HANDLED;
28592878
break;
28602879

2861-
case XHCI_TRB_TYPE_NORMAL:
28622880
case XHCI_TRB_TYPE_ISOCH:
2881+
is_isoch = true;
2882+
/* fall through */
2883+
2884+
case XHCI_TRB_TYPE_NORMAL:
28632885
if (setup_trb != NULL) {
28642886
UPRINTF(LWRN, "trb not supposed to be in "
28652887
"ctl scope\r\n");
@@ -2931,6 +2953,10 @@ pci_xhci_handle_transfer(struct pci_xhci_vdev *xdev,
29312953
xfer_block->trbnext, xfer_block->ccs);
29322954
}
29332955

2956+
if (is_isoch == true || XHCI_TRB_3_TYPE_GET(trbflags) ==
2957+
XHCI_TRB_TYPE_EVENT_DATA /* win10 needs it */)
2958+
continue;
2959+
29342960
/* handle current batch that requires interrupt on complete */
29352961
if (trbflags & XHCI_TRB_3_IOC_BIT) {
29362962
UPRINTF(LDBG, "trb IOC bit set\r\n");

0 commit comments

Comments
 (0)