diff options
author | Anthony Liguori <aliguori@us.ibm.com> | 2013-04-08 10:36:40 -0500 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2013-04-08 10:36:40 -0500 |
commit | 2a7a239ff09aa87cc3682a976c7a57d9ea1321d7 (patch) | |
tree | e0043f932da9fac985bcd3c9ba03e700f82f04ad /hw | |
parent | 9196dd411d580c27f85daa209ff9a501d719ebc0 (diff) | |
parent | aa1c9e971e80d25b92908dce3dec7c38b49480ea (diff) |
Merge remote-tracking branch 'kraxel/usb.79' into staging
# By Gerd Hoffmann (7) and Hans de Goede (3)
# Via Gerd Hoffmann
* kraxel/usb.79:
usb-tablet: Don't claim wakeup capability for USB-2 version
usb: update docs for bus name change
usb-hub: report status changes only once
usb-hub: limit chain length
xhci: zap unused name field
xhci: remove unimplemented printfs
xhci: remove leftover debug printf
xhci: fix numintrs sanity checks
usb-redir: Add flow control support
usb-redir: Fix crash on migration with no client connected
Diffstat (limited to 'hw')
-rw-r--r-- | hw/usb.h | 1 | ||||
-rw-r--r-- | hw/usb/bus.c | 2 | ||||
-rw-r--r-- | hw/usb/dev-hid.c | 2 | ||||
-rw-r--r-- | hw/usb/dev-hub.c | 12 | ||||
-rw-r--r-- | hw/usb/hcd-xhci.c | 28 | ||||
-rw-r--r-- | hw/usb/redirect.c | 37 |
6 files changed, 63 insertions, 19 deletions
@@ -337,6 +337,7 @@ typedef struct USBPortOps { struct USBPort { USBDevice *dev; int speedmask; + int hubcount; char path[16]; USBPortOps *ops; void *opaque; diff --git a/hw/usb/bus.c b/hw/usb/bus.c index e58cd9ade2..b10c290cf4 100644 --- a/hw/usb/bus.c +++ b/hw/usb/bus.c @@ -341,8 +341,10 @@ void usb_port_location(USBPort *downstream, USBPort *upstream, int portnr) if (upstream) { snprintf(downstream->path, sizeof(downstream->path), "%s.%d", upstream->path, portnr); + downstream->hubcount = upstream->hubcount + 1; } else { snprintf(downstream->path, sizeof(downstream->path), "%d", portnr); + downstream->hubcount = 0; } } diff --git a/hw/usb/dev-hid.c b/hw/usb/dev-hid.c index 9701048887..317b4740e2 100644 --- a/hw/usb/dev-hid.c +++ b/hw/usb/dev-hid.c @@ -236,7 +236,7 @@ static const USBDescDevice desc_device_tablet2 = { .bNumInterfaces = 1, .bConfigurationValue = 1, .iConfiguration = STR_CONFIG_TABLET, - .bmAttributes = 0xa0, + .bmAttributes = 0x80, .bMaxPower = 50, .nif = 1, .ifs = &desc_iface_tablet2, diff --git a/hw/usb/dev-hub.c b/hw/usb/dev-hub.c index 504c98c350..0b71abd028 100644 --- a/hw/usb/dev-hub.c +++ b/hw/usb/dev-hub.c @@ -25,6 +25,7 @@ #include "trace.h" #include "hw/usb.h" #include "hw/usb/desc.h" +#include "qemu/error-report.h" #define NUM_PORTS 8 @@ -32,6 +33,7 @@ typedef struct USBHubPort { USBPort port; uint16_t wPortStatus; uint16_t wPortChange; + uint16_t wPortChange_reported; } USBHubPort; typedef struct USBHubState { @@ -466,8 +468,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) + if (port->wPortChange && + port->wPortChange_reported != port->wPortChange) { status |= (1 << (i + 1)); + } + port->wPortChange_reported = port->wPortChange; } if (status != 0) { for(i = 0; i < n; i++) { @@ -514,6 +519,11 @@ static int usb_hub_initfn(USBDevice *dev) USBHubPort *port; int i; + if (dev->port->hubcount == 5) { + error_report("usb hub chain too deep"); + return -1; + } + usb_desc_create_serial(dev); usb_desc_init(dev); s->intr = usb_ep_get(dev, USB_TOKEN_IN, 1); diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 5aa342bda5..efd4b0dbde 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -452,7 +452,6 @@ struct XHCIState { MemoryRegion mem_oper; MemoryRegion mem_runtime; MemoryRegion mem_doorbell; - const char *name; unsigned int devaddr; /* properties */ @@ -1172,8 +1171,6 @@ static void xhci_set_ep_state(XHCIState *xhci, XHCIEPContext *epctx, uint32_t ctx[5]; uint32_t ctx2[2]; - fprintf(stderr, "%s: epid %d, state %d\n", - __func__, epctx->epid, state); xhci_dma_read_u32s(xhci, epctx->pctx, ctx, sizeof(ctx)); ctx[0] &= ~EP_STATE_MASK; ctx[0] |= state; @@ -2568,7 +2565,7 @@ static void xhci_process_commands(XHCIState *xhci) } break; default: - fprintf(stderr, "xhci: unimplemented command %d\n", type); + trace_usb_xhci_unimplemented("command", type); event.ccode = CC_TRB_ERROR; break; } @@ -2767,7 +2764,7 @@ static uint64_t xhci_cap_read(void *ptr, hwaddr reg, unsigned size) ret = 0x00000000; /* reserved */ break; default: - fprintf(stderr, "xhci_cap_read: reg %d unimplemented\n", (int)reg); + trace_usb_xhci_unimplemented("cap read", reg); ret = 0; } @@ -2790,8 +2787,7 @@ static uint64_t xhci_port_read(void *ptr, hwaddr reg, unsigned size) break; case 0x0c: /* reserved */ default: - fprintf(stderr, "xhci_port_read (port %d): reg 0x%x unimplemented\n", - port->portnr, (uint32_t)reg); + trace_usb_xhci_unimplemented("port read", reg); ret = 0; } @@ -2831,8 +2827,7 @@ static void xhci_port_write(void *ptr, hwaddr reg, case 0x04: /* PORTPMSC */ case 0x08: /* PORTLI */ default: - fprintf(stderr, "xhci_port_write (port %d): reg 0x%x unimplemented\n", - port->portnr, (uint32_t)reg); + trace_usb_xhci_unimplemented("port write", reg); } } @@ -2870,7 +2865,7 @@ static uint64_t xhci_oper_read(void *ptr, hwaddr reg, unsigned size) ret = xhci->config; break; default: - fprintf(stderr, "xhci_oper_read: reg 0x%x unimplemented\n", (int)reg); + trace_usb_xhci_unimplemented("oper read", reg); ret = 0; } @@ -2935,7 +2930,7 @@ static void xhci_oper_write(void *ptr, hwaddr reg, xhci->config = val & 0xff; break; default: - fprintf(stderr, "xhci_oper_write: reg 0x%x unimplemented\n", (int)reg); + trace_usb_xhci_unimplemented("oper write", reg); } } @@ -2951,8 +2946,7 @@ static uint64_t xhci_runtime_read(void *ptr, hwaddr reg, ret = xhci_mfindex_get(xhci) & 0x3fff; break; default: - fprintf(stderr, "xhci_runtime_read: reg 0x%x unimplemented\n", - (int)reg); + trace_usb_xhci_unimplemented("runtime read", reg); break; } } else { @@ -2996,7 +2990,7 @@ static void xhci_runtime_write(void *ptr, hwaddr reg, trace_usb_xhci_runtime_write(reg, val); if (reg < 0x20) { - fprintf(stderr, "%s: reg 0x%x unimplemented\n", __func__, (int)reg); + trace_usb_xhci_unimplemented("runtime write", reg); return; } @@ -3038,8 +3032,7 @@ static void xhci_runtime_write(void *ptr, hwaddr reg, xhci_events_update(xhci, v); break; default: - fprintf(stderr, "xhci_oper_write: reg 0x%x unimplemented\n", - (int)reg); + trace_usb_xhci_unimplemented("oper write", reg); } } @@ -3290,6 +3283,9 @@ static int usb_xhci_initfn(struct PCIDevice *dev) if (xhci->numintrs > MAXINTRS) { xhci->numintrs = MAXINTRS; } + while (xhci->numintrs & (xhci->numintrs - 1)) { /* ! power of 2 */ + xhci->numintrs++; + } if (xhci->numintrs < 1) { xhci->numintrs = 1; } diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index d02a7b94c4..0ddb0818d8 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -104,6 +104,8 @@ struct USBRedirDevice { /* Data passed from chardev the fd_read cb to the usbredirparser read cb */ const uint8_t *read_buf; int read_buf_size; + /* Active chardev-watch-tag */ + guint watch; /* For async handling of close */ QEMUBH *chardev_close_bh; /* To delay the usb attach in case of quick chardev close + open */ @@ -254,9 +256,21 @@ static int usbredir_read(void *priv, uint8_t *data, int count) return count; } +static gboolean usbredir_write_unblocked(GIOChannel *chan, GIOCondition cond, + void *opaque) +{ + USBRedirDevice *dev = opaque; + + dev->watch = 0; + usbredirparser_do_write(dev->parser); + + return FALSE; +} + static int usbredir_write(void *priv, uint8_t *data, int count) { USBRedirDevice *dev = priv; + int r; if (!dev->cs->be_open) { return 0; @@ -267,7 +281,17 @@ static int usbredir_write(void *priv, uint8_t *data, int count) return 0; } - return qemu_chr_fe_write(dev->cs, data, count); + r = qemu_chr_fe_write(dev->cs, data, count); + if (r < count) { + if (!dev->watch) { + dev->watch = qemu_chr_fe_add_watch(dev->cs, G_IO_OUT, + usbredir_write_unblocked, dev); + } + if (r < 0) { + r = 0; + } + } + return r; } /* @@ -1085,6 +1109,10 @@ static void usbredir_chardev_close_bh(void *opaque) usbredirparser_destroy(dev->parser); dev->parser = NULL; } + if (dev->watch) { + g_source_remove(dev->watch); + dev->watch = 0; + } } static void usbredir_create_parser(USBRedirDevice *dev) @@ -1317,6 +1345,9 @@ static void usbredir_handle_destroy(USBDevice *udev) if (dev->parser) { usbredirparser_destroy(dev->parser); } + if (dev->watch) { + g_source_remove(dev->watch); + } free(dev->filter_rules); } @@ -1973,6 +2004,10 @@ static int usbredir_post_load(void *priv, int version_id) { USBRedirDevice *dev = priv; + if (dev->parser == NULL) { + return 0; + } + switch (dev->device_info.speed) { case usb_redir_speed_low: dev->dev.speed = USB_SPEED_LOW; |