diff options
author | Anthony Liguori <anthony@codemonkey.ws> | 2013-09-03 12:31:30 -0500 |
---|---|---|
committer | Anthony Liguori <anthony@codemonkey.ws> | 2013-09-03 12:31:30 -0500 |
commit | 9ea0f58fc723daeb9e1dba9a762269e8cbbd1b73 (patch) | |
tree | 1d985efb12e0e411e8a4cf5c842967897600b8f6 /hw | |
parent | 9889e04ac193cad7fa0526573ce0cc752dcabb99 (diff) | |
parent | 31efd2e883018b4c079ad082105bc161fbb3fef8 (diff) |
Merge remote-tracking branch 'kraxel/usb.88' into staging
# By Gerd Hoffmann (10) and Marcel Apfelbaum (1)
# Via Gerd Hoffmann
* kraxel/usb.88:
usb/dev-hid: Modified usb-tablet category from Misc to Input
Revert "usb-hub: report status changes only once"
usb-hub: add tracepoint for status reports
usb: parallelize usb3 streams
uas: add property for request logging
xhci: reset port when disabling slot
xhci: emulate intr endpoint intervals correctly
xhci: fix endpoint interval calculation
xhci: add port to slot_address tracepoint
xhci: add tracepoint for endpoint state changes
xhci: remove leftover debug printf
Message-id: 1378117055-29620-1-git-send-email-kraxel@redhat.com
Signed-off-by: Anthony Liguori <anthony@codemonkey.ws>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/usb/core.c | 7 | ||||
-rw-r--r-- | hw/usb/dev-hid.c | 2 | ||||
-rw-r--r-- | hw/usb/dev-hub.c | 7 | ||||
-rw-r--r-- | hw/usb/dev-uas.c | 15 | ||||
-rw-r--r-- | hw/usb/hcd-xhci.c | 70 |
5 files changed, 78 insertions, 23 deletions
diff --git a/hw/usb/core.c b/hw/usb/core.c index 05948ca9a4..31960c28a8 100644 --- a/hw/usb/core.c +++ b/hw/usb/core.c @@ -403,7 +403,7 @@ void usb_handle_packet(USBDevice *dev, USBPacket *p) p->ep->halted = false; } - if (QTAILQ_EMPTY(&p->ep->queue) || p->ep->pipeline) { + if (QTAILQ_EMPTY(&p->ep->queue) || p->ep->pipeline || p->stream) { usb_process_one(p); if (p->status == USB_RET_ASYNC) { /* hcd drivers cannot handle async for isoc */ @@ -420,7 +420,8 @@ void usb_handle_packet(USBDevice *dev, USBPacket *p) * When pipelining is enabled usb-devices must always return async, * otherwise packets can complete out of order! */ - assert(!p->ep->pipeline || QTAILQ_EMPTY(&p->ep->queue)); + assert(p->stream || !p->ep->pipeline || + QTAILQ_EMPTY(&p->ep->queue)); if (p->status != USB_RET_NAK) { usb_packet_set_state(p, USB_PACKET_COMPLETE); } @@ -434,7 +435,7 @@ void usb_packet_complete_one(USBDevice *dev, USBPacket *p) { USBEndpoint *ep = p->ep; - assert(QTAILQ_FIRST(&ep->queue) == p); + assert(p->stream || QTAILQ_FIRST(&ep->queue) == p); assert(p->status != USB_RET_ASYNC && p->status != USB_RET_NAK); if (p->status != USB_RET_SUCCESS || diff --git a/hw/usb/dev-hid.c b/hw/usb/dev-hid.c index 66c63317d6..59567200ae 100644 --- a/hw/usb/dev-hid.c +++ b/hw/usb/dev-hid.c @@ -658,7 +658,7 @@ static void usb_tablet_class_initfn(ObjectClass *klass, void *data) uc->product_desc = "QEMU USB Tablet"; dc->vmsd = &vmstate_usb_ptr; dc->props = usb_tablet_properties; - set_bit(DEVICE_CATEGORY_MISC, dc->categories); + set_bit(DEVICE_CATEGORY_INPUT, dc->categories); } static const TypeInfo usb_tablet_info = { diff --git a/hw/usb/dev-hub.c b/hw/usb/dev-hub.c index e865a98751..58647b4859 100644 --- a/hw/usb/dev-hub.c +++ b/hw/usb/dev-hub.c @@ -33,7 +33,6 @@ typedef struct USBHubPort { USBPort port; uint16_t wPortStatus; uint16_t wPortChange; - uint16_t wPortChange_reported; } USBHubPort; typedef struct USBHubState { @@ -468,13 +467,11 @@ static void usb_hub_handle_data(USBDevice *dev, USBPacket *p) status = 0; for(i = 0; i < NUM_PORTS; i++) { port = &s->ports[i]; - if (port->wPortChange && - port->wPortChange_reported != port->wPortChange) { + if (port->wPortChange) status |= (1 << (i + 1)); - } - port->wPortChange_reported = port->wPortChange; } if (status != 0) { + trace_usb_hub_status_report(s->dev.addr, status); for(i = 0; i < n; i++) { buf[i] = status >> (8 * i); } diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c index 1569d6e2ef..70ed2d1dbd 100644 --- a/hw/usb/dev-uas.c +++ b/hw/usb/dev-uas.c @@ -113,6 +113,9 @@ struct UASDevice { QTAILQ_HEAD(, UASStatus) results; QTAILQ_HEAD(, UASRequest) requests; + /* properties */ + uint32_t requestlog; + /* usb 2.0 only */ USBPacket *status2; UASRequest *datain2; @@ -692,9 +695,9 @@ static void usb_uas_command(UASDevice *uas, uas_ui *ui) req->req = scsi_req_new(req->dev, req->tag, usb_uas_get_lun(req->lun), ui->command.cdb, req); -#if 1 - scsi_req_print(req->req); -#endif + if (uas->requestlog) { + scsi_req_print(req->req); + } len = scsi_req_enqueue(req->req); if (len) { req->data_size = len; @@ -903,6 +906,11 @@ static const VMStateDescription vmstate_usb_uas = { } }; +static Property uas_properties[] = { + DEFINE_PROP_UINT32("log-scsi-req", UASDevice, requestlog, 0), + DEFINE_PROP_END_OF_LIST(), +}; + static void usb_uas_class_initfn(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -920,6 +928,7 @@ static void usb_uas_class_initfn(ObjectClass *klass, void *data) set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); dc->fw_name = "storage"; dc->vmsd = &vmstate_usb_uas; + dc->props = uas_properties; } static const TypeInfo uas_info = { diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index d5c6588053..f02231dc87 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -355,6 +355,7 @@ typedef struct XHCITransfer { unsigned int streamid; bool in_xfer; bool iso_xfer; + bool timed_xfer; unsigned int trb_count; unsigned int trb_alloced; @@ -586,6 +587,14 @@ static const char *TRBCCode_names[] = { [CC_SPLIT_TRANSACTION_ERROR] = "CC_SPLIT_TRANSACTION_ERROR", }; +static const char *ep_state_names[] = { + [EP_DISABLED] = "disabled", + [EP_RUNNING] = "running", + [EP_HALTED] = "halted", + [EP_STOPPED] = "stopped", + [EP_ERROR] = "error", +}; + static const char *lookup_name(uint32_t index, const char **list, uint32_t llen) { if (index >= llen || list[index] == NULL) { @@ -606,6 +615,12 @@ static const char *event_name(XHCIEvent *event) ARRAY_SIZE(TRBCCode_names)); } +static const char *ep_state_name(uint32_t state) +{ + return lookup_name(state, ep_state_names, + ARRAY_SIZE(ep_state_names)); +} + static uint64_t xhci_mfindex_get(XHCIState *xhci) { int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); @@ -1164,8 +1179,6 @@ static XHCIStreamContext *xhci_find_stream(XHCIEPContext *epctx, if (sctx->sct == -1) { xhci_dma_read_u32s(epctx->xhci, sctx->pctx, ctx, sizeof(ctx)); - fprintf(stderr, "%s: init sctx #%d @ " DMA_ADDR_FMT ": %08x %08x\n", - __func__, streamid, sctx->pctx, ctx[0], ctx[1]); sct = (ctx[0] >> 1) & 0x07; if (epctx->lsa && sct != 1) { *cc_error = CC_INVALID_STREAM_TYPE_ERROR; @@ -1205,6 +1218,11 @@ static void xhci_set_ep_state(XHCIState *xhci, XHCIEPContext *epctx, } xhci_dma_write_u32s(xhci, epctx->pctx, ctx, sizeof(ctx)); + if (epctx->state != state) { + trace_usb_xhci_ep_state(epctx->slotid, epctx->epid, + ep_state_name(epctx->state), + ep_state_name(state)); + } epctx->state = state; } @@ -1257,7 +1275,7 @@ static void xhci_init_epctx(XHCIEPContext *epctx, epctx->ring.ccs = ctx[2] & 1; } - epctx->interval = 1 << (ctx[0] >> 16) & 0xff; + epctx->interval = 1 << ((ctx[0] >> 16) & 0xff); } static TRBCCode xhci_enable_ep(XHCIState *xhci, unsigned int slotid, @@ -1803,6 +1821,7 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer) xfer->in_xfer = bmRequestType & USB_DIR_IN; xfer->iso_xfer = false; + xfer->timed_xfer = false; if (xhci_setup_packet(xfer) < 0) { return -1; @@ -1818,6 +1837,17 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer) return 0; } +static void xhci_calc_intr_kick(XHCIState *xhci, XHCITransfer *xfer, + XHCIEPContext *epctx, uint64_t mfindex) +{ + uint64_t asap = ((mfindex + epctx->interval - 1) & + ~(epctx->interval-1)); + uint64_t kick = epctx->mfindex_last + epctx->interval; + + assert(epctx->interval != 0); + xfer->mfindex_kick = MAX(asap, kick); +} + static void xhci_calc_iso_kick(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx, uint64_t mfindex) { @@ -1840,8 +1870,8 @@ static void xhci_calc_iso_kick(XHCIState *xhci, XHCITransfer *xfer, } } -static void xhci_check_iso_kick(XHCIState *xhci, XHCITransfer *xfer, - XHCIEPContext *epctx, uint64_t mfindex) +static void xhci_check_intr_iso_kick(XHCIState *xhci, XHCITransfer *xfer, + XHCIEPContext *epctx, uint64_t mfindex) { if (xfer->mfindex_kick > mfindex) { timer_mod(epctx->kick_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + @@ -1866,18 +1896,30 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx switch(epctx->type) { case ET_INTR_OUT: case ET_INTR_IN: + xfer->pkts = 0; + xfer->iso_xfer = false; + xfer->timed_xfer = true; + mfindex = xhci_mfindex_get(xhci); + xhci_calc_intr_kick(xhci, xfer, epctx, mfindex); + xhci_check_intr_iso_kick(xhci, xfer, epctx, mfindex); + if (xfer->running_retry) { + return -1; + } + break; case ET_BULK_OUT: case ET_BULK_IN: xfer->pkts = 0; xfer->iso_xfer = false; + xfer->timed_xfer = false; break; case ET_ISO_OUT: case ET_ISO_IN: xfer->pkts = 1; xfer->iso_xfer = true; + xfer->timed_xfer = true; mfindex = xhci_mfindex_get(xhci); xhci_calc_iso_kick(xhci, xfer, epctx, mfindex); - xhci_check_iso_kick(xhci, xfer, epctx, mfindex); + xhci_check_intr_iso_kick(xhci, xfer, epctx, mfindex); if (xfer->running_retry) { return -1; } @@ -1938,13 +1980,18 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, trace_usb_xhci_xfer_retry(xfer); assert(xfer->running_retry); - if (xfer->iso_xfer) { - /* retry delayed iso transfer */ + if (xfer->timed_xfer) { + /* time to kick the transfer? */ mfindex = xhci_mfindex_get(xhci); - xhci_check_iso_kick(xhci, xfer, epctx, mfindex); + xhci_check_intr_iso_kick(xhci, xfer, epctx, mfindex); if (xfer->running_retry) { return; } + xfer->timed_xfer = 0; + xfer->running_retry = 1; + } + if (xfer->iso_xfer) { + /* retry iso transfer */ if (xhci_setup_packet(xfer) < 0) { return; } @@ -2030,7 +2077,7 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, epctx->next_xfer = (epctx->next_xfer + 1) % TD_QUEUE; ep = xfer->packet.ep; } else { - if (!xfer->iso_xfer) { + if (!xfer->timed_xfer) { fprintf(stderr, "xhci: error firing data transfer\n"); } } @@ -2076,6 +2123,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; return CC_SUCCESS; } @@ -2118,7 +2166,6 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, int i; TRBCCode res; - trace_usb_xhci_slot_address(slotid); assert(slotid >= 1 && slotid <= xhci->numslots); dcbaap = xhci_addr64(xhci->dcbaap_low, xhci->dcbaap_high); @@ -2151,6 +2198,7 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, fprintf(stderr, "xhci: port not found\n"); return CC_TRB_ERROR; } + trace_usb_xhci_slot_address(slotid, uport->path); dev = uport->dev; if (!dev) { |