From e59a8cf1eb2196cdaded214ccd1b819c8faad238 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 17 Apr 2012 12:33:58 +0200 Subject: [PATCH 01/13] usb-ehci: remove hack To answer the question in the comment removed by this patch: I think this was needed because several places in the ehci emulation did not check the T bit of link entries correctly and thus might have followed invalid references. See commit 2a5ff735dc1074171a0cbb1dc228d6d6e907f571 Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 23631a47c9..10a5b15890 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -133,7 +133,6 @@ #define NB_MAXINTRATE 8 // Max rate at which controller issues ints #define NB_PORTS 6 // Number of downstream ports #define BUFF_SIZE 5*4096 // Max bytes to transfer per transaction -#define MAX_ITERATIONS 20 // Max number of QH before we break the loop #define MAX_QH 100 // Max allowable queue heads in a chain /* Internal periodic / asynchronous schedule state machine states @@ -1931,24 +1930,8 @@ static void ehci_advance_state(EHCIState *ehci, { EHCIQueue *q = NULL; int again; - int iter = 0; do { - if (ehci_get_state(ehci, async) == EST_FETCHQH) { - iter++; - /* if we are roaming a lot of QH without executing a qTD - * something is wrong with the linked list. TO-DO: why is - * this hack needed? - */ - assert(iter < MAX_ITERATIONS); -#if 0 - if (iter > MAX_ITERATIONS) { - DPRINTF("\n*** advance_state: bailing on MAX ITERATIONS***\n"); - ehci_set_state(ehci, async, EST_ACTIVE); - break; - } -#endif - } switch(ehci_get_state(ehci, async)) { case EST_WAITLISTHEAD: again = ehci_state_waitlisthead(ehci, async); @@ -1984,7 +1967,6 @@ static void ehci_advance_state(EHCIState *ehci, break; case EST_EXECUTE: - iter = 0; again = ehci_state_execute(q, async); break; From 0cc6a0f19e3de830eaa898ad31c0bc607470b8cb Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 19 Apr 2012 13:07:54 +0200 Subject: [PATCH 02/13] usb-ehci: add missing usb_packet_init() call Signed-off-by: Gerd Hoffmann --- hw/usb/core.c | 1 + hw/usb/hcd-ehci.c | 1 + 2 files changed, 2 insertions(+) diff --git a/hw/usb/core.c b/hw/usb/core.c index 9a14a53852..0e02da7601 100644 --- a/hw/usb/core.c +++ b/hw/usb/core.c @@ -501,6 +501,7 @@ void usb_packet_set_state(USBPacket *p, USBPacketState state) void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep) { assert(!usb_packet_is_inflight(p)); + assert(p->iov.iov != NULL); p->pid = pid; p->ep = ep; p->result = 0; diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 10a5b15890..c6f21ac7b6 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -664,6 +664,7 @@ static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, int async) q = g_malloc0(sizeof(*q)); q->ehci = ehci; + usb_packet_init(&q->packet); QTAILQ_INSERT_HEAD(head, q, next); trace_usb_ehci_queue_action(q, "alloc"); return q; From 8a771f77e2abfb81f1f33a986810c16ecae54ca7 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 3 Apr 2012 14:21:47 +0200 Subject: [PATCH 03/13] usb-ehci: Ensure frindex writes leave a valid frindex value frindex is a 14 bits counter, so bits 31-14 should always be 0, and after the commit titled "usb-ehci: frindex always is a 14 bits counter" we rely on frindex always being a multiple of 8. I've not seen this in practice, but theoretically a guest can write a value >= 0x4000 or a value which is not a multiple of 8 value to frindex, this patch ensures that things will still work when that happens. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index c6f21ac7b6..4ff4d40a8c 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -1101,6 +1101,10 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val) val &= USBINTR_MASK; break; + case FRINDEX: + val &= 0x00003ff8; /* frindex is 14bits and always a multiple of 8 */ + break; + case CONFIGFLAG: val &= 0x1; if (val) { From 6d7aeeeb8985634a2015e804045a1ca52573ccc5 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 18 Apr 2012 12:08:29 +0200 Subject: [PATCH 04/13] usb-storage: fix request canceling Little fix for usb packet handling on i/o cancelation. The usb packet pointer (s->packet) is cleared at the wrong place: The scsi request cancel handler does it. When a usb packet is canceled the usb-storage emulation canceles the scsi request if present. In most cases there is one, so usually s->packet is cleared as needed even with the code sitting at the wrong place. If there is no scsi request in flight s->packet is not cleared though. The usb-storage emulation will then try to complete an usb packet which is not in flight any more and thereby trigger an assert() in the usb core. Fix this by clearing s->packet at the correct place, which is the usb packet cancel header. Signed-off-by: Gerd Hoffmann --- hw/usb/dev-storage.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index d865a5ef93..3d2f244127 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -268,7 +268,6 @@ static void usb_msd_request_cancelled(SCSIRequest *req) if (req == s->req) { scsi_req_unref(s->req); s->req = NULL; - s->packet = NULL; s->scsi_len = 0; } } @@ -330,6 +329,9 @@ static void usb_msd_cancel_io(USBDevice *dev, USBPacket *p) { MSDState *s = DO_UPCAST(MSDState, dev, dev); + assert(s->packet == p); + s->packet = NULL; + if (s->req) { scsi_req_cancel(s->req); } From 818d59dc179b2861e49f3c6472787a23935aac0d Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 19 Apr 2012 13:35:07 +0200 Subject: [PATCH 05/13] usb-host: don't dereference invalid iovecs usb-host assumes the first iovec element is always valid. In case of a zero-length packet this isn't true though. Signed-off-by: Gerd Hoffmann --- hw/usb/host-linux.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/usb/host-linux.c b/hw/usb/host-linux.c index 061a1b7825..c3684c8f92 100644 --- a/hw/usb/host-linux.c +++ b/hw/usb/host-linux.c @@ -884,16 +884,16 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p) } v = 0; - prem = p->iov.iov[v].iov_len; - pbuf = p->iov.iov[v].iov_base; + prem = 0; + pbuf = NULL; rem = p->iov.size; while (rem) { if (prem == 0) { - v++; assert(v < p->iov.niov); prem = p->iov.iov[v].iov_len; pbuf = p->iov.iov[v].iov_base; assert(prem <= rem); + v++; } aurb = async_alloc(s); aurb->packet = p; From 0b377169b18d702d980d526578d8515900ca6eb1 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 19 Apr 2012 13:36:40 +0200 Subject: [PATCH 06/13] usb-host: fix zero-length packets usb-host optimizes away zero-length packets by not entering the processing loop at all. Which isn't correct, we should submit a zero-length urb to the host devicein that case. This patch makes sure we run the processing loop at least once. Signed-off-by: Gerd Hoffmann --- hw/usb/host-linux.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/usb/host-linux.c b/hw/usb/host-linux.c index c3684c8f92..048f8ffa8b 100644 --- a/hw/usb/host-linux.c +++ b/hw/usb/host-linux.c @@ -887,8 +887,8 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p) prem = 0; pbuf = NULL; rem = p->iov.size; - while (rem) { - if (prem == 0) { + do { + if (prem == 0 && rem > 0) { assert(v < p->iov.niov); prem = p->iov.iov[v].iov_len; pbuf = p->iov.iov[v].iov_base; @@ -938,7 +938,7 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p) return USB_RET_STALL; } } - } + } while (rem > 0); return USB_RET_ASYNC; } From 59a70ccd3be29d2c5034cf7f22de0cf4e9156432 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 4 Apr 2012 10:15:58 +1000 Subject: [PATCH 07/13] usb-xhci: Use PCI DMA helper functions Shortly before 1.0, we added helper functions / wrappers for doing PCI DMA from individual devices. This makes what's going on clearer and means that when we add IOMMU support somewhere in the future, only the general PCI code will have to change, not every device that uses PCI DMA. However, usb-xhci is not using these wrappers, despite being a PCI only device. This patch remedies the situation, using the pci dma functions instead of direct calls to cpu_physical_memory_{read,write}(). Likewise address parameters for DMA are changed to dma_addr_t instead of target_phys_addr_t. [ kraxel: removed #ifdefs ] Signed-off-by: David Gibson Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 190 ++++++++++++++++++++++------------------------ 1 file changed, 92 insertions(+), 98 deletions(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 73b0c7f5e5..fd13bbab27 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -22,7 +22,6 @@ #include "qemu-timer.h" #include "hw/usb.h" #include "hw/pci.h" -#include "hw/qdev-addr.h" #include "hw/msi.h" //#define DEBUG_XHCI @@ -140,7 +139,7 @@ typedef struct XHCITRB { uint64_t parameter; uint32_t status; uint32_t control; - target_phys_addr_t addr; + dma_addr_t addr; bool ccs; } XHCITRB; @@ -291,8 +290,8 @@ typedef enum EPType { } EPType; typedef struct XHCIRing { - target_phys_addr_t base; - target_phys_addr_t dequeue; + dma_addr_t base; + dma_addr_t dequeue; bool ccs; } XHCIRing; @@ -345,7 +344,7 @@ typedef struct XHCIEPContext { unsigned int next_bg; XHCITransfer bg_transfers[BG_XFERS]; EPType type; - target_phys_addr_t pctx; + dma_addr_t pctx; unsigned int max_psize; bool has_bg; uint32_t state; @@ -353,7 +352,7 @@ typedef struct XHCIEPContext { typedef struct XHCISlot { bool enabled; - target_phys_addr_t ctx; + dma_addr_t ctx; unsigned int port; unsigned int devaddr; XHCIEPContext * eps[31]; @@ -402,7 +401,7 @@ struct XHCIState { uint32_t erdp_low; uint32_t erdp_high; - target_phys_addr_t er_start; + dma_addr_t er_start; uint32_t er_size; bool er_pcs; unsigned int er_ep_idx; @@ -479,22 +478,22 @@ static const char *trb_name(XHCITRB *trb) static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid); -static inline target_phys_addr_t xhci_addr64(uint32_t low, uint32_t high) +static inline dma_addr_t xhci_addr64(uint32_t low, uint32_t high) { -#if TARGET_PHYS_ADDR_BITS > 32 - return low | ((target_phys_addr_t)high << 32); -#else - return low; -#endif + if (sizeof(dma_addr_t) == 4) { + return low; + } else { + return low | (((dma_addr_t)high << 16) << 16); + } } -static inline target_phys_addr_t xhci_mask64(uint64_t addr) +static inline dma_addr_t xhci_mask64(uint64_t addr) { -#if TARGET_PHYS_ADDR_BITS > 32 - return addr; -#else - return addr & 0xffffffff; -#endif + if (sizeof(dma_addr_t) == 4) { + return addr & 0xffffffff; + } else { + return addr; + } } static void xhci_irq_update(XHCIState *xhci) @@ -532,7 +531,7 @@ static void xhci_die(XHCIState *xhci) static void xhci_write_event(XHCIState *xhci, XHCIEvent *event) { XHCITRB ev_trb; - target_phys_addr_t addr; + dma_addr_t addr; ev_trb.parameter = cpu_to_le64(event->ptr); ev_trb.status = cpu_to_le32(event->length | (event->ccode << 24)); @@ -548,7 +547,7 @@ static void xhci_write_event(XHCIState *xhci, XHCIEvent *event) trb_name(&ev_trb)); addr = xhci->er_start + TRB_SIZE*xhci->er_ep_idx; - cpu_physical_memory_write(addr, (uint8_t *) &ev_trb, TRB_SIZE); + pci_dma_write(&xhci->pci_dev, addr, &ev_trb, TRB_SIZE); xhci->er_ep_idx++; if (xhci->er_ep_idx >= xhci->er_size) { @@ -559,7 +558,7 @@ static void xhci_write_event(XHCIState *xhci, XHCIEvent *event) static void xhci_events_update(XHCIState *xhci) { - target_phys_addr_t erdp; + dma_addr_t erdp; unsigned int dp_idx; bool do_irq = 0; @@ -570,8 +569,8 @@ static void xhci_events_update(XHCIState *xhci) erdp = xhci_addr64(xhci->erdp_low, xhci->erdp_high); if (erdp < xhci->er_start || erdp >= (xhci->er_start + TRB_SIZE*xhci->er_size)) { - fprintf(stderr, "xhci: ERDP out of bounds: "TARGET_FMT_plx"\n", erdp); - fprintf(stderr, "xhci: ER at "TARGET_FMT_plx" len %d\n", + fprintf(stderr, "xhci: ERDP out of bounds: "DMA_ADDR_FMT"\n", erdp); + fprintf(stderr, "xhci: ER at "DMA_ADDR_FMT" len %d\n", xhci->er_start, xhci->er_size); xhci_die(xhci); return; @@ -630,7 +629,7 @@ static void xhci_events_update(XHCIState *xhci) static void xhci_event(XHCIState *xhci, XHCIEvent *event) { - target_phys_addr_t erdp; + dma_addr_t erdp; unsigned int dp_idx; if (xhci->er_full) { @@ -649,8 +648,8 @@ static void xhci_event(XHCIState *xhci, XHCIEvent *event) erdp = xhci_addr64(xhci->erdp_low, xhci->erdp_high); if (erdp < xhci->er_start || erdp >= (xhci->er_start + TRB_SIZE*xhci->er_size)) { - fprintf(stderr, "xhci: ERDP out of bounds: "TARGET_FMT_plx"\n", erdp); - fprintf(stderr, "xhci: ER at "TARGET_FMT_plx" len %d\n", + fprintf(stderr, "xhci: ERDP out of bounds: "DMA_ADDR_FMT"\n", erdp); + fprintf(stderr, "xhci: ER at "DMA_ADDR_FMT" len %d\n", xhci->er_start, xhci->er_size); xhci_die(xhci); return; @@ -686,7 +685,7 @@ static void xhci_event(XHCIState *xhci, XHCIEvent *event) } static void xhci_ring_init(XHCIState *xhci, XHCIRing *ring, - target_phys_addr_t base) + dma_addr_t base) { ring->base = base; ring->dequeue = base; @@ -694,18 +693,18 @@ static void xhci_ring_init(XHCIState *xhci, XHCIRing *ring, } static TRBType xhci_ring_fetch(XHCIState *xhci, XHCIRing *ring, XHCITRB *trb, - target_phys_addr_t *addr) + dma_addr_t *addr) { while (1) { TRBType type; - cpu_physical_memory_read(ring->dequeue, (uint8_t *) trb, TRB_SIZE); + pci_dma_read(&xhci->pci_dev, ring->dequeue, trb, TRB_SIZE); trb->addr = ring->dequeue; trb->ccs = ring->ccs; le64_to_cpus(&trb->parameter); le32_to_cpus(&trb->status); le32_to_cpus(&trb->control); - DPRINTF("xhci: TRB fetched [" TARGET_FMT_plx "]: " + DPRINTF("xhci: TRB fetched [" DMA_ADDR_FMT "]: " "%016" PRIx64 " %08x %08x %s\n", ring->dequeue, trb->parameter, trb->status, trb->control, trb_name(trb)); @@ -735,19 +734,19 @@ static int xhci_ring_chain_length(XHCIState *xhci, const XHCIRing *ring) { XHCITRB trb; int length = 0; - target_phys_addr_t dequeue = ring->dequeue; + dma_addr_t dequeue = ring->dequeue; bool ccs = ring->ccs; /* hack to bundle together the two/three TDs that make a setup transfer */ bool control_td_set = 0; while (1) { TRBType type; - cpu_physical_memory_read(dequeue, (uint8_t *) &trb, TRB_SIZE); + pci_dma_read(&xhci->pci_dev, dequeue, &trb, TRB_SIZE); le64_to_cpus(&trb.parameter); le32_to_cpus(&trb.status); le32_to_cpus(&trb.control); - DPRINTF("xhci: TRB peeked [" TARGET_FMT_plx "]: " + DPRINTF("xhci: TRB peeked [" DMA_ADDR_FMT "]: " "%016" PRIx64 " %08x %08x\n", dequeue, trb.parameter, trb.status, trb.control); @@ -790,8 +789,8 @@ static void xhci_er_reset(XHCIState *xhci) xhci_die(xhci); return; } - target_phys_addr_t erstba = xhci_addr64(xhci->erstba_low, xhci->erstba_high); - cpu_physical_memory_read(erstba, (uint8_t *) &seg, sizeof(seg)); + dma_addr_t erstba = xhci_addr64(xhci->erstba_low, xhci->erstba_high); + pci_dma_read(&xhci->pci_dev, erstba, &seg, sizeof(seg)); le32_to_cpus(&seg.addr_low); le32_to_cpus(&seg.addr_high); le32_to_cpus(&seg.size); @@ -807,7 +806,7 @@ static void xhci_er_reset(XHCIState *xhci) xhci->er_pcs = 1; xhci->er_full = 0; - DPRINTF("xhci: event ring:" TARGET_FMT_plx " [%d]\n", + DPRINTF("xhci: event ring:" DMA_ADDR_FMT " [%d]\n", xhci->er_start, xhci->er_size); } @@ -833,24 +832,24 @@ static void xhci_set_ep_state(XHCIState *xhci, XHCIEPContext *epctx, return; } - cpu_physical_memory_read(epctx->pctx, (uint8_t *) ctx, sizeof(ctx)); + pci_dma_read(&xhci->pci_dev, epctx->pctx, ctx, sizeof(ctx)); ctx[0] &= ~EP_STATE_MASK; ctx[0] |= state; ctx[2] = epctx->ring.dequeue | epctx->ring.ccs; ctx[3] = (epctx->ring.dequeue >> 16) >> 16; - DPRINTF("xhci: set epctx: " TARGET_FMT_plx " state=%d dequeue=%08x%08x\n", + DPRINTF("xhci: set epctx: " DMA_ADDR_FMT " state=%d dequeue=%08x%08x\n", epctx->pctx, state, ctx[3], ctx[2]); - cpu_physical_memory_write(epctx->pctx, (uint8_t *) ctx, sizeof(ctx)); + pci_dma_write(&xhci->pci_dev, epctx->pctx, ctx, sizeof(ctx)); epctx->state = state; } static TRBCCode xhci_enable_ep(XHCIState *xhci, unsigned int slotid, - unsigned int epid, target_phys_addr_t pctx, + unsigned int epid, dma_addr_t pctx, uint32_t *ctx) { XHCISlot *slot; XHCIEPContext *epctx; - target_phys_addr_t dequeue; + dma_addr_t dequeue; int i; assert(slotid >= 1 && slotid <= MAXSLOTS); @@ -1087,7 +1086,7 @@ static TRBCCode xhci_set_ep_dequeue(XHCIState *xhci, unsigned int slotid, { XHCISlot *slot; XHCIEPContext *epctx; - target_phys_addr_t dequeue; + dma_addr_t dequeue; assert(slotid >= 1 && slotid <= MAXSLOTS); @@ -1142,7 +1141,7 @@ static int xhci_xfer_data(XHCITransfer *xfer, uint8_t *data, for (i = 0; i < xfer->trb_count; i++) { XHCITRB *trb = &xfer->trbs[i]; - target_phys_addr_t addr; + dma_addr_t addr; unsigned int chunk = 0; switch (TRB_TYPE(*trb)) { @@ -1173,11 +1172,11 @@ static int xhci_xfer_data(XHCITransfer *xfer, uint8_t *data, memcpy(data, &idata, chunk); } else { DPRINTF("xhci_xfer_data: r/w(%d) %d bytes at " - TARGET_FMT_plx "\n", in_xfer, chunk, addr); + DMA_ADDR_FMT "\n", in_xfer, chunk, addr); if (in_xfer) { - cpu_physical_memory_write(addr, data, chunk); + pci_dma_write(&xhci->pci_dev, addr, data, chunk); } else { - cpu_physical_memory_read(addr, data, chunk); + pci_dma_read(&xhci->pci_dev, addr, data, chunk); } #ifdef DEBUG_DATA unsigned int count = chunk; @@ -1240,7 +1239,7 @@ static void xhci_stall_ep(XHCITransfer *xfer) epctx->ring.ccs = xfer->trbs[0].ccs; xhci_set_ep_state(xhci, epctx, EP_HALTED); DPRINTF("xhci: stalled slot %d ep %d\n", xfer->slotid, xfer->epid); - DPRINTF("xhci: will continue at "TARGET_FMT_plx"\n", epctx->ring.dequeue); + DPRINTF("xhci: will continue at "DMA_ADDR_FMT"\n", epctx->ring.dequeue); } static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, @@ -1802,7 +1801,7 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, { XHCISlot *slot; USBDevice *dev; - target_phys_addr_t ictx, octx, dcbaap; + dma_addr_t ictx, octx, dcbaap; uint64_t poctx; uint32_t ictl_ctx[2]; uint32_t slot_ctx[4]; @@ -1815,15 +1814,14 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, DPRINTF("xhci_address_slot(%d)\n", slotid); dcbaap = xhci_addr64(xhci->dcbaap_low, xhci->dcbaap_high); - cpu_physical_memory_read(dcbaap + 8*slotid, - (uint8_t *) &poctx, sizeof(poctx)); + pci_dma_read(&xhci->pci_dev, dcbaap + 8*slotid, &poctx, sizeof(poctx)); ictx = xhci_mask64(pictx); octx = xhci_mask64(le64_to_cpu(poctx)); - DPRINTF("xhci: input context at "TARGET_FMT_plx"\n", ictx); - DPRINTF("xhci: output context at "TARGET_FMT_plx"\n", octx); + DPRINTF("xhci: input context at "DMA_ADDR_FMT"\n", ictx); + DPRINTF("xhci: output context at "DMA_ADDR_FMT"\n", octx); - cpu_physical_memory_read(ictx, (uint8_t *) ictl_ctx, sizeof(ictl_ctx)); + pci_dma_read(&xhci->pci_dev, ictx, ictl_ctx, sizeof(ictl_ctx)); if (ictl_ctx[0] != 0x0 || ictl_ctx[1] != 0x3) { fprintf(stderr, "xhci: invalid input context control %08x %08x\n", @@ -1831,8 +1829,8 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, return CC_TRB_ERROR; } - cpu_physical_memory_read(ictx+32, (uint8_t *) slot_ctx, sizeof(slot_ctx)); - cpu_physical_memory_read(ictx+64, (uint8_t *) ep0_ctx, sizeof(ep0_ctx)); + pci_dma_read(&xhci->pci_dev, ictx+32, slot_ctx, sizeof(slot_ctx)); + pci_dma_read(&xhci->pci_dev, ictx+64, ep0_ctx, sizeof(ep0_ctx)); DPRINTF("xhci: input slot context: %08x %08x %08x %08x\n", slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]); @@ -1881,8 +1879,8 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, DPRINTF("xhci: output ep0 context: %08x %08x %08x %08x %08x\n", ep0_ctx[0], ep0_ctx[1], ep0_ctx[2], ep0_ctx[3], ep0_ctx[4]); - cpu_physical_memory_write(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx)); - cpu_physical_memory_write(octx+32, (uint8_t *) ep0_ctx, sizeof(ep0_ctx)); + pci_dma_write(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx)); + pci_dma_write(&xhci->pci_dev, octx+32, ep0_ctx, sizeof(ep0_ctx)); return res; } @@ -1891,7 +1889,7 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid, uint64_t pictx, bool dc) { - target_phys_addr_t ictx, octx; + dma_addr_t ictx, octx; uint32_t ictl_ctx[2]; uint32_t slot_ctx[4]; uint32_t islot_ctx[4]; @@ -1905,8 +1903,8 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid, ictx = xhci_mask64(pictx); octx = xhci->slots[slotid-1].ctx; - DPRINTF("xhci: input context at "TARGET_FMT_plx"\n", ictx); - DPRINTF("xhci: output context at "TARGET_FMT_plx"\n", octx); + DPRINTF("xhci: input context at "DMA_ADDR_FMT"\n", ictx); + DPRINTF("xhci: output context at "DMA_ADDR_FMT"\n", octx); if (dc) { for (i = 2; i <= 31; i++) { @@ -1915,17 +1913,17 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid, } } - cpu_physical_memory_read(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx)); + pci_dma_read(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx)); slot_ctx[3] &= ~(SLOT_STATE_MASK << SLOT_STATE_SHIFT); slot_ctx[3] |= SLOT_ADDRESSED << SLOT_STATE_SHIFT; DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n", slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]); - cpu_physical_memory_write(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx)); + pci_dma_write(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx)); return CC_SUCCESS; } - cpu_physical_memory_read(ictx, (uint8_t *) ictl_ctx, sizeof(ictl_ctx)); + pci_dma_read(&xhci->pci_dev, ictx, ictl_ctx, sizeof(ictl_ctx)); if ((ictl_ctx[0] & 0x3) != 0x0 || (ictl_ctx[1] & 0x3) != 0x1) { fprintf(stderr, "xhci: invalid input context control %08x %08x\n", @@ -1933,8 +1931,8 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid, return CC_TRB_ERROR; } - cpu_physical_memory_read(ictx+32, (uint8_t *) islot_ctx, sizeof(islot_ctx)); - cpu_physical_memory_read(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx)); + pci_dma_read(&xhci->pci_dev, ictx+32, islot_ctx, sizeof(islot_ctx)); + pci_dma_read(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx)); if (SLOT_STATE(slot_ctx[3]) < SLOT_ADDRESSED) { fprintf(stderr, "xhci: invalid slot state %08x\n", slot_ctx[3]); @@ -1946,8 +1944,8 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid, xhci_disable_ep(xhci, slotid, i); } if (ictl_ctx[1] & (1<pci_dev, ictx+32+(32*i), ep_ctx, + sizeof(ep_ctx)); DPRINTF("xhci: input ep%d.%d context: %08x %08x %08x %08x %08x\n", i/2, i%2, ep_ctx[0], ep_ctx[1], ep_ctx[2], ep_ctx[3], ep_ctx[4]); @@ -1959,8 +1957,7 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid, DPRINTF("xhci: output ep%d.%d context: %08x %08x %08x %08x %08x\n", i/2, i%2, ep_ctx[0], ep_ctx[1], ep_ctx[2], ep_ctx[3], ep_ctx[4]); - cpu_physical_memory_write(octx+(32*i), - (uint8_t *) ep_ctx, sizeof(ep_ctx)); + pci_dma_write(&xhci->pci_dev, octx+(32*i), ep_ctx, sizeof(ep_ctx)); } } @@ -1972,7 +1969,7 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid, DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n", slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]); - cpu_physical_memory_write(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx)); + pci_dma_write(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx)); return CC_SUCCESS; } @@ -1981,7 +1978,7 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid, static TRBCCode xhci_evaluate_slot(XHCIState *xhci, unsigned int slotid, uint64_t pictx) { - target_phys_addr_t ictx, octx; + dma_addr_t ictx, octx; uint32_t ictl_ctx[2]; uint32_t iep0_ctx[5]; uint32_t ep0_ctx[5]; @@ -1994,10 +1991,10 @@ static TRBCCode xhci_evaluate_slot(XHCIState *xhci, unsigned int slotid, ictx = xhci_mask64(pictx); octx = xhci->slots[slotid-1].ctx; - DPRINTF("xhci: input context at "TARGET_FMT_plx"\n", ictx); - DPRINTF("xhci: output context at "TARGET_FMT_plx"\n", octx); + DPRINTF("xhci: input context at "DMA_ADDR_FMT"\n", ictx); + DPRINTF("xhci: output context at "DMA_ADDR_FMT"\n", octx); - cpu_physical_memory_read(ictx, (uint8_t *) ictl_ctx, sizeof(ictl_ctx)); + pci_dma_read(&xhci->pci_dev, ictx, ictl_ctx, sizeof(ictl_ctx)); if (ictl_ctx[0] != 0x0 || ictl_ctx[1] & ~0x3) { fprintf(stderr, "xhci: invalid input context control %08x %08x\n", @@ -2006,13 +2003,12 @@ static TRBCCode xhci_evaluate_slot(XHCIState *xhci, unsigned int slotid, } if (ictl_ctx[1] & 0x1) { - cpu_physical_memory_read(ictx+32, - (uint8_t *) islot_ctx, sizeof(islot_ctx)); + pci_dma_read(&xhci->pci_dev, ictx+32, islot_ctx, sizeof(islot_ctx)); DPRINTF("xhci: input slot context: %08x %08x %08x %08x\n", islot_ctx[0], islot_ctx[1], islot_ctx[2], islot_ctx[3]); - cpu_physical_memory_read(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx)); + pci_dma_read(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx)); slot_ctx[1] &= ~0xFFFF; /* max exit latency */ slot_ctx[1] |= islot_ctx[1] & 0xFFFF; @@ -2022,18 +2018,17 @@ static TRBCCode xhci_evaluate_slot(XHCIState *xhci, unsigned int slotid, DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n", slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]); - cpu_physical_memory_write(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx)); + pci_dma_write(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx)); } if (ictl_ctx[1] & 0x2) { - cpu_physical_memory_read(ictx+64, - (uint8_t *) iep0_ctx, sizeof(iep0_ctx)); + pci_dma_read(&xhci->pci_dev, ictx+64, iep0_ctx, sizeof(iep0_ctx)); DPRINTF("xhci: input ep0 context: %08x %08x %08x %08x %08x\n", iep0_ctx[0], iep0_ctx[1], iep0_ctx[2], iep0_ctx[3], iep0_ctx[4]); - cpu_physical_memory_read(octx+32, (uint8_t *) ep0_ctx, sizeof(ep0_ctx)); + pci_dma_read(&xhci->pci_dev, octx+32, ep0_ctx, sizeof(ep0_ctx)); ep0_ctx[1] &= ~0xFFFF0000; /* max packet size*/ ep0_ctx[1] |= iep0_ctx[1] & 0xFFFF0000; @@ -2041,8 +2036,7 @@ static TRBCCode xhci_evaluate_slot(XHCIState *xhci, unsigned int slotid, DPRINTF("xhci: output ep0 context: %08x %08x %08x %08x %08x\n", ep0_ctx[0], ep0_ctx[1], ep0_ctx[2], ep0_ctx[3], ep0_ctx[4]); - cpu_physical_memory_write(octx+32, - (uint8_t *) ep0_ctx, sizeof(ep0_ctx)); + pci_dma_write(&xhci->pci_dev, octx+32, ep0_ctx, sizeof(ep0_ctx)); } return CC_SUCCESS; @@ -2051,7 +2045,7 @@ static TRBCCode xhci_evaluate_slot(XHCIState *xhci, unsigned int slotid, static TRBCCode xhci_reset_slot(XHCIState *xhci, unsigned int slotid) { uint32_t slot_ctx[4]; - target_phys_addr_t octx; + dma_addr_t octx; int i; assert(slotid >= 1 && slotid <= MAXSLOTS); @@ -2059,7 +2053,7 @@ static TRBCCode xhci_reset_slot(XHCIState *xhci, unsigned int slotid) octx = xhci->slots[slotid-1].ctx; - DPRINTF("xhci: output context at "TARGET_FMT_plx"\n", octx); + DPRINTF("xhci: output context at "DMA_ADDR_FMT"\n", octx); for (i = 2; i <= 31; i++) { if (xhci->slots[slotid-1].eps[i-1]) { @@ -2067,12 +2061,12 @@ static TRBCCode xhci_reset_slot(XHCIState *xhci, unsigned int slotid) } } - cpu_physical_memory_read(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx)); + pci_dma_read(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx)); slot_ctx[3] &= ~(SLOT_STATE_MASK << SLOT_STATE_SHIFT); slot_ctx[3] |= SLOT_DEFAULT << SLOT_STATE_SHIFT; DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n", slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]); - cpu_physical_memory_write(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx)); + pci_dma_write(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx)); return CC_SUCCESS; } @@ -2095,19 +2089,19 @@ static unsigned int xhci_get_slot(XHCIState *xhci, XHCIEvent *event, XHCITRB *tr static TRBCCode xhci_get_port_bandwidth(XHCIState *xhci, uint64_t pctx) { - target_phys_addr_t ctx; + dma_addr_t ctx; uint8_t bw_ctx[MAXPORTS+1]; DPRINTF("xhci_get_port_bandwidth()\n"); ctx = xhci_mask64(pctx); - DPRINTF("xhci: bandwidth context at "TARGET_FMT_plx"\n", ctx); + DPRINTF("xhci: bandwidth context at "DMA_ADDR_FMT"\n", ctx); /* TODO: actually implement real values here */ bw_ctx[0] = 0; memset(&bw_ctx[1], 80, MAXPORTS); /* 80% */ - cpu_physical_memory_write(ctx, bw_ctx, sizeof(bw_ctx)); + pci_dma_write(&xhci->pci_dev, ctx, bw_ctx, sizeof(bw_ctx)); return CC_SUCCESS; } @@ -2128,13 +2122,13 @@ static uint32_t xhci_nec_challenge(uint32_t hi, uint32_t lo) return ~val; } -static void xhci_via_challenge(uint64_t addr) +static void xhci_via_challenge(XHCIState *xhci, uint64_t addr) { uint32_t buf[8]; uint32_t obuf[8]; - target_phys_addr_t paddr = xhci_mask64(addr); + dma_addr_t paddr = xhci_mask64(addr); - cpu_physical_memory_read(paddr, (uint8_t *) &buf, 32); + pci_dma_read(&xhci->pci_dev, paddr, &buf, 32); memcpy(obuf, buf, sizeof(obuf)); @@ -2150,7 +2144,7 @@ static void xhci_via_challenge(uint64_t addr) obuf[7] = obuf[2] ^ obuf[3] ^ 0x65866593; } - cpu_physical_memory_write(paddr, (uint8_t *) &obuf, 32); + pci_dma_write(&xhci->pci_dev, paddr, &obuf, 32); } static void xhci_process_commands(XHCIState *xhci) @@ -2158,7 +2152,7 @@ static void xhci_process_commands(XHCIState *xhci) XHCITRB trb; TRBType type; XHCIEvent event = {ER_COMMAND_COMPLETE, CC_SUCCESS}; - target_phys_addr_t addr; + dma_addr_t addr; unsigned int i, slotid = 0; DPRINTF("xhci_process_commands()\n"); @@ -2247,7 +2241,7 @@ static void xhci_process_commands(XHCIState *xhci) event.ccode = xhci_get_port_bandwidth(xhci, trb.parameter); break; case CR_VENDOR_VIA_CHALLENGE_RESPONSE: - xhci_via_challenge(trb.parameter); + xhci_via_challenge(xhci, trb.parameter); break; case CR_VENDOR_NEC_FIRMWARE_REVISION: event.type = 48; /* NEC reply */ @@ -2537,7 +2531,7 @@ static void xhci_oper_write(XHCIState *xhci, uint32_t reg, uint32_t val) xhci_event(xhci, &event); DPRINTF("xhci: command ring stopped (CRCR=%08x)\n", xhci->crcr_low); } else { - target_phys_addr_t base = xhci_addr64(xhci->crcr_low & ~0x3f, val); + dma_addr_t base = xhci_addr64(xhci->crcr_low & ~0x3f, val); xhci_ring_init(xhci, &xhci->cmd_ring, base); } xhci->crcr_low &= ~(CRCR_CA | CRCR_CS); From 215bff17ed89733c23174494cbff63ab941368ca Mon Sep 17 00:00:00 2001 From: Lai Jiangshan Date: Mon, 2 Apr 2012 14:35:30 +0800 Subject: [PATCH 08/13] usb-xhci: fix bit test use & instead of the wrong && Signed-off-by: Lai Jiangshan Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index fd13bbab27..5cf1a64699 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -501,7 +501,7 @@ static void xhci_irq_update(XHCIState *xhci) int level = 0; if (xhci->iman & IMAN_IP && xhci->iman & IMAN_IE && - xhci->usbcmd && USBCMD_INTE) { + xhci->usbcmd & USBCMD_INTE) { level = 1; } From 1510168e273a12a56e3bd4488b4b2904f5138e09 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 31 Mar 2012 17:14:21 +0200 Subject: [PATCH 09/13] usb-redir: An interface count of 0 is a valid value An interface-count of 0 happens when a device is in unconfigured state when it gets redirected. So we should not use 0 to detect not having received interface info from our peer. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/redirect.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 94ab4632ca..3e6e7e9c73 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -39,6 +39,7 @@ #include "hw/usb.h" #define MAX_ENDPOINTS 32 +#define NO_INTERFACE_INFO 255 /* Valid interface_count always <= 32 */ #define EP2I(ep_address) (((ep_address & 0x80) >> 3) | (ep_address & 0x0f)) #define I2EP(i) (((i & 0x10) << 3) | (i & 0x0f)) @@ -970,7 +971,7 @@ static void usbredir_handle_destroy(USBDevice *udev) static int usbredir_check_filter(USBRedirDevice *dev) { - if (dev->interface_info.interface_count == 0) { + if (dev->interface_info.interface_count == NO_INTERFACE_INFO) { ERROR("No interface info for device\n"); goto error; } @@ -1134,7 +1135,7 @@ static void usbredir_device_disconnect(void *priv) QTAILQ_INIT(&dev->endpoint[i].bufpq); } usb_ep_init(&dev->dev); - dev->interface_info.interface_count = 0; + dev->interface_info.interface_count = NO_INTERFACE_INFO; } static void usbredir_interface_info(void *priv, From a0625c56e0db19029cb69e28859af56b2ae19f3f Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 31 Mar 2012 17:14:22 +0200 Subject: [PATCH 10/13] usb-redir: Reset device address and speed on disconnect Without this disconnected devices look like the last redirected device in the monitor in "info usb". Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/redirect.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 3e6e7e9c73..b2576e86a6 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -1136,6 +1136,8 @@ static void usbredir_device_disconnect(void *priv) } usb_ep_init(&dev->dev); dev->interface_info.interface_count = NO_INTERFACE_INFO; + dev->dev.addr = 0; + dev->dev.speed = 0; } static void usbredir_interface_info(void *priv, From b15cf49b78edb74dc783a7cacbc8391cbc728edc Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 31 Mar 2012 17:14:23 +0200 Subject: [PATCH 11/13] usb-redir: Not finding an async urb id is not an error We clear our pending async urb list on device disconnect and we may still receive "packet complete" packets from our peer after this, which will then refer to packet ids no longer in our list. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/redirect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index b2576e86a6..51c27b4051 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -277,7 +277,7 @@ static AsyncURB *async_find(USBRedirDevice *dev, uint32_t packet_id) return aurb; } } - ERROR("could not find async urb for packet_id %u\n", packet_id); + DPRINTF("could not find async urb for packet_id %u\n", packet_id); return NULL; } From 9d55d1adc848a3dc1d2431c4ec4e7e4ea37fa0ee Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 20 Apr 2012 12:33:30 +0200 Subject: [PATCH 12/13] usb: add serial number generator This patch adds a function which creates unique serial numbers for usb devices and puts it into use. Windows guests tend to become unhappy if they find two identical usb devices in the system. Effects range from non-functional devices (with yellow exclamation mark in device manager) to BSODs. Handing out unique serial numbers to devices fixes this. With this patch applied almost all emulated devices get a generated, unique serial number. There are two exceptions: * usb-storage devices will prefer a user-specified serial number and will only get a generated number in case the serial property is unset. * usb-hid devices keep the fixed serial number "42" as it is used to signal "remote wakeup actually works". See commit 7b074a22dab4bdda9864b933f1bc811a3db42845 Signed-off-by: Gerd Hoffmann --- hw/usb/desc.c | 32 ++++++++++++++++++++++++++++++++ hw/usb/desc.h | 1 + hw/usb/dev-audio.c | 1 + hw/usb/dev-bluetooth.c | 1 + hw/usb/dev-hub.c | 1 + hw/usb/dev-network.c | 1 + hw/usb/dev-serial.c | 1 + hw/usb/dev-smartcard-reader.c | 1 + hw/usb/dev-storage.c | 2 ++ hw/usb/dev-wacom.c | 1 + 10 files changed, 42 insertions(+) diff --git a/hw/usb/desc.c b/hw/usb/desc.c index 3c77368cb0..e8a3c6af3d 100644 --- a/hw/usb/desc.c +++ b/hw/usb/desc.c @@ -1,3 +1,5 @@ +#include + #include "hw/usb.h" #include "hw/usb/desc.h" #include "trace.h" @@ -412,6 +414,36 @@ void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str) s->str = g_strdup(str); } +/* + * This function creates a serial number for a usb device. + * The serial number should: + * (a) Be unique within the virtual machine. + * (b) Be constant, so you don't get a new one each + * time the guest is started. + * So we are using the physical location to generate a serial number + * from it. It has three pieces: First a fixed, device-specific + * prefix. Second the device path of the host controller (which is + * the pci address in most cases). Third the physical port path. + * Results in serial numbers like this: "314159-0000:00:1d.7-3". + */ +void usb_desc_create_serial(USBDevice *dev) +{ + DeviceState *hcd = dev->qdev.parent_bus->parent; + const USBDesc *desc = usb_device_get_usb_desc(dev); + int index = desc->id.iSerialNumber; + char serial[64]; + int dst; + + assert(index != 0 && desc->str[index] != NULL); + dst = snprintf(serial, sizeof(serial), "%s", desc->str[index]); + if (hcd && hcd->parent_bus && hcd->parent_bus->info->get_dev_path) { + char *path = hcd->parent_bus->info->get_dev_path(hcd); + dst += snprintf(serial+dst, sizeof(serial)-dst, "-%s", path); + } + dst += snprintf(serial+dst, sizeof(serial)-dst, "-%s", dev->port->path); + usb_desc_set_string(dev, index, serial); +} + const char *usb_desc_get_string(USBDevice *dev, uint8_t index) { USBDescString *s; diff --git a/hw/usb/desc.h b/hw/usb/desc.h index d164e8f891..7cf5442945 100644 --- a/hw/usb/desc.h +++ b/hw/usb/desc.h @@ -171,6 +171,7 @@ int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len); void usb_desc_init(USBDevice *dev); void usb_desc_attach(USBDevice *dev); void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str); +void usb_desc_create_serial(USBDevice *dev); const char *usb_desc_get_string(USBDevice *dev, uint8_t index); int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len); int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len); diff --git a/hw/usb/dev-audio.c b/hw/usb/dev-audio.c index 426b95c82b..79b75fb628 100644 --- a/hw/usb/dev-audio.c +++ b/hw/usb/dev-audio.c @@ -648,6 +648,7 @@ static int usb_audio_initfn(USBDevice *dev) { USBAudioState *s = DO_UPCAST(USBAudioState, dev, dev); + usb_desc_create_serial(dev); usb_desc_init(dev); s->dev.opaque = s; AUD_register_card("usb-audio", &s->card); diff --git a/hw/usb/dev-bluetooth.c b/hw/usb/dev-bluetooth.c index 195370c24a..6b74eff4ad 100644 --- a/hw/usb/dev-bluetooth.c +++ b/hw/usb/dev-bluetooth.c @@ -494,6 +494,7 @@ static void usb_bt_handle_destroy(USBDevice *dev) static int usb_bt_initfn(USBDevice *dev) { + usb_desc_create_serial(dev); usb_desc_init(dev); return 0; } diff --git a/hw/usb/dev-hub.c b/hw/usb/dev-hub.c index 9c9166551e..b5962da72a 100644 --- a/hw/usb/dev-hub.c +++ b/hw/usb/dev-hub.c @@ -520,6 +520,7 @@ static int usb_hub_initfn(USBDevice *dev) USBHubPort *port; int i; + usb_desc_create_serial(dev); usb_desc_init(dev); s->intr = usb_ep_get(dev, USB_TOKEN_IN, 1); for (i = 0; i < NUM_PORTS; i++) { diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c index cff55f223e..b238a0973d 100644 --- a/hw/usb/dev-network.c +++ b/hw/usb/dev-network.c @@ -1324,6 +1324,7 @@ static int usb_net_initfn(USBDevice *dev) { USBNetState *s = DO_UPCAST(USBNetState, dev, dev); + usb_desc_create_serial(dev); usb_desc_init(dev); s->rndis_state = RNDIS_UNINITIALIZED; diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c index 8dcac8bc88..56743ee020 100644 --- a/hw/usb/dev-serial.c +++ b/hw/usb/dev-serial.c @@ -479,6 +479,7 @@ static int usb_serial_initfn(USBDevice *dev) { USBSerialState *s = DO_UPCAST(USBSerialState, dev, dev); + usb_desc_create_serial(dev); usb_desc_init(dev); if (!s->cs) { diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c index 8e66675d86..3b7604e8b1 100644 --- a/hw/usb/dev-smartcard-reader.c +++ b/hw/usb/dev-smartcard-reader.c @@ -1189,6 +1189,7 @@ static int ccid_initfn(USBDevice *dev) { USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev); + usb_desc_create_serial(dev); usb_desc_init(dev); qbus_create_inplace(&s->bus.qbus, &ccid_bus_info, &dev->qdev, NULL); s->intr = usb_ep_get(dev, USB_TOKEN_IN, CCID_INT_IN_EP); diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index 3d2f244127..ae22fb1c97 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -546,6 +546,8 @@ static int usb_msd_initfn(USBDevice *dev) } if (s->serial) { usb_desc_set_string(dev, STR_SERIALNUMBER, s->serial); + } else { + usb_desc_create_serial(dev); } usb_desc_init(dev); diff --git a/hw/usb/dev-wacom.c b/hw/usb/dev-wacom.c index c1cfd74403..3b51d458f4 100644 --- a/hw/usb/dev-wacom.c +++ b/hw/usb/dev-wacom.c @@ -339,6 +339,7 @@ static void usb_wacom_handle_destroy(USBDevice *dev) static int usb_wacom_initfn(USBDevice *dev) { USBWacomState *s = DO_UPCAST(USBWacomState, dev, dev); + usb_desc_create_serial(dev); usb_desc_init(dev); s->changed = 1; return 0; From aba1f242834a4365ca3250cd4d14226d66e77ed5 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 20 Apr 2012 15:13:24 +0200 Subject: [PATCH 13/13] usb-uhci: update irq line on reset uhci_reset() clears irq mask and irq status registers, but doesn't update the irq line. Which may result in suspious IRQs after uhci reset. Fix it. Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-uhci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 266d550b9c..9e211a0bb4 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -369,6 +369,7 @@ static void uhci_reset(void *opaque) } uhci_async_cancel_all(s); + uhci_update_irq(s); } static void uhci_pre_save(void *opaque)