From b4329d1a2a42d3c49ac4b76ec86b6c9db19ea1e9 Mon Sep 17 00:00:00 2001 From: Yuri Benditovich Date: Mon, 28 Jan 2019 20:05:09 +0000 Subject: [PATCH] usb: implement XHCI underrun/overrun events Implement underrun/overrun events of isochronous endpoints according to XHCI spec (4.10.3.1) Guest software restarts data streaming when receives these events. The XHCI reports these events using interrupter assigned to the slot (as these events do not have TRB), so current commit adds the field of assigned interrupter to the XHCISlot structure. Guest software assigns interrupter to the slot on 'Address Device' and 'Evaluate Context' commands. Signed-off-by: Yuri Benditovich Message-id: 20190128200444.5128-3-yuri.benditovich@janustech.com Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 17 +++++++++++++++-- hw/usb/hcd-xhci.h | 1 + 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 1a8fd9644e..19c64f7ff4 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -1949,6 +1949,16 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid) while (1) { length = xhci_ring_chain_length(xhci, ring); if (length <= 0) { + if (epctx->type == ET_ISO_OUT || epctx->type == ET_ISO_IN) { + /* 4.10.3.1 */ + XHCIEvent ev = { ER_TRANSFER }; + ev.ccode = epctx->type == ET_ISO_IN ? + CC_RING_OVERRUN : CC_RING_UNDERRUN; + ev.slotid = epctx->slotid; + ev.epid = epctx->epid; + ev.ptr = epctx->ring.dequeue; + xhci_event(xhci, &ev, xhci->slots[epctx->slotid-1].intr); + } break; } xfer = xhci_ep_alloc_xfer(epctx, length); @@ -2028,6 +2038,7 @@ static TRBCCode xhci_disable_slot(XHCIState *xhci, unsigned int slotid) xhci->slots[slotid-1].enabled = 0; xhci->slots[slotid-1].addressed = 0; xhci->slots[slotid-1].uport = NULL; + xhci->slots[slotid-1].intr = 0; return CC_SUCCESS; } @@ -2127,6 +2138,7 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, slot = &xhci->slots[slotid-1]; slot->uport = uport; slot->ctx = octx; + slot->intr = get_field(slot_ctx[2], TRB_INTR); /* Make sure device is in USB_STATE_DEFAULT state */ usb_device_reset(dev); @@ -2300,8 +2312,9 @@ static TRBCCode xhci_evaluate_slot(XHCIState *xhci, unsigned int slotid, slot_ctx[1] &= ~0xFFFF; /* max exit latency */ slot_ctx[1] |= islot_ctx[1] & 0xFFFF; - slot_ctx[2] &= ~0xFF00000; /* interrupter target */ - slot_ctx[2] |= islot_ctx[2] & 0xFF000000; + /* update interrupter target field */ + xhci->slots[slotid-1].intr = get_field(islot_ctx[2], TRB_INTR); + set_field(&slot_ctx[2], xhci->slots[slotid-1].intr, TRB_INTR); DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n", slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]); diff --git a/hw/usb/hcd-xhci.h b/hw/usb/hcd-xhci.h index fc36a4c787..240caa4e51 100644 --- a/hw/usb/hcd-xhci.h +++ b/hw/usb/hcd-xhci.h @@ -140,6 +140,7 @@ typedef struct XHCIPort { typedef struct XHCISlot { bool enabled; bool addressed; + uint16_t intr; dma_addr_t ctx; USBPort *uport; XHCIEPContext *eps[31]; -- GitLab