From c19537a1143d493897850576394f082914f39ef1 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 9 Aug 2012 10:57:32 +0200 Subject: [PATCH 1/4] usb: async control xfer fixup Need to clear p->result after copying setup data using usb_packet_copy() because we'll reuse the USBPacket for the data transfer. Signed-off-by: Gerd Hoffmann --- hw/usb/core.c | 1 + hw/usb/host-linux.c | 1 + 2 files changed, 2 insertions(+) diff --git a/hw/usb/core.c b/hw/usb/core.c index 01a7622837..c7e5bc047f 100644 --- a/hw/usb/core.c +++ b/hw/usb/core.c @@ -107,6 +107,7 @@ static int do_token_setup(USBDevice *s, USBPacket *p) } usb_packet_copy(p, s->setup_buf, p->iov.size); + p->result = 0; s->setup_len = (s->setup_buf[7] << 8) | s->setup_buf[6]; s->setup_index = 0; diff --git a/hw/usb/host-linux.c b/hw/usb/host-linux.c index d55be878ad..8df92074d3 100644 --- a/hw/usb/host-linux.c +++ b/hw/usb/host-linux.c @@ -1045,6 +1045,7 @@ static int usb_host_handle_control(USBDevice *dev, USBPacket *p, /* Note request is (bRequestType << 8) | bRequest */ trace_usb_host_req_control(s->bus_num, s->addr, p, request, value, index); + assert(p->result == 0); switch (request) { case DeviceOutRequest | USB_REQ_SET_ADDRESS: From 0daf53047da0b817e40c4931580e59e73b420f41 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 10 Aug 2012 13:06:05 +0200 Subject: [PATCH 2/4] usb: update uas product id Pick other product id to fix clash with audio. Current usage list (after applying this patch): 46f4:0001 -- usb-storage 46f4:0002 -- usb-audio 46f4:0003 -- usb-uas Signed-off-by: Gerd Hoffmann --- hw/usb/dev-uas.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c index 9b02ff48fa..b13eeba565 100644 --- a/hw/usb/dev-uas.c +++ b/hw/usb/dev-uas.c @@ -223,7 +223,7 @@ static const USBDescDevice desc_device_high = { static const USBDesc desc = { .id = { .idVendor = 0x46f4, /* CRC16() of "QEMU" */ - .idProduct = 0x0002, + .idProduct = 0x0003, .bcdDevice = 0, .iManufacturer = STR_MANUFACTURER, .iProduct = STR_PRODUCT, From 6d3b6d3d2deaf682def95e3e512ad0e17f02274f Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 15 Aug 2012 13:55:40 +0200 Subject: [PATCH 3/4] ehci: fix Interrupt Threshold Control implementation First, not all interrupts are subject to Interrupt Threshold Control, some of them must be delivered without delay. Second, Interrupt Threshold Control state must be part of vmstate, otherwise we might loose IRQs on migration. Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 104c21d315..e4895095cf 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -575,7 +575,12 @@ static inline void ehci_update_irq(EHCIState *s) /* flag interrupt condition */ static inline void ehci_raise_irq(EHCIState *s, int intr) { - s->usbsts_pending |= intr; + if (intr & (USBSTS_PCD | USBSTS_FLR | USBSTS_HSE)) { + s->usbsts |= intr; + ehci_update_irq(s); + } else { + s->usbsts_pending |= intr; + } } /* @@ -2466,13 +2471,16 @@ static int usb_ehci_post_load(void *opaque, int version_id) static const VMStateDescription vmstate_ehci = { .name = "ehci", - .version_id = 1, + .version_id = 2, + .minimum_version_id = 1, .post_load = usb_ehci_post_load, .fields = (VMStateField[]) { VMSTATE_PCI_DEVICE(dev, EHCIState), /* mmio registers */ VMSTATE_UINT32(usbcmd, EHCIState), VMSTATE_UINT32(usbsts, EHCIState), + VMSTATE_UINT32_V(usbsts_pending, EHCIState, 2), + VMSTATE_UINT32_V(usbsts_frindex, EHCIState, 2), VMSTATE_UINT32(usbintr, EHCIState), VMSTATE_UINT32(frindex, EHCIState), VMSTATE_UINT32(ctrldssegment, EHCIState), From 47d073cc3b8ad4a3ef1dba7055b35a87fa4091ff Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 15 Aug 2012 17:08:54 +0200 Subject: [PATCH 4/4] ehci: Fix setting of halt bit from usbcmd register updates This fixes linux guests started without any USB devices not seeing newly plugged devices until "lsusb" is done inside the guest. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index e4895095cf..8b94b17723 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -1187,22 +1187,23 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val) break; } - if (((USBCMD_RUNSTOP | USBCMD_PSE | USBCMD_ASE) & val) != - ((USBCMD_RUNSTOP | USBCMD_PSE | USBCMD_ASE) & s->usbcmd)) { - if (s->pstate == EST_INACTIVE) { - SET_LAST_RUN_CLOCK(s); - } - ehci_update_halt(s); - s->async_stepdown = 0; - qemu_mod_timer(s->frame_timer, qemu_get_clock_ns(vm_clock)); - } - /* not supporting dynamic frame list size at the moment */ if ((val & USBCMD_FLS) && !(s->usbcmd & USBCMD_FLS)) { fprintf(stderr, "attempt to set frame list size -- value %d\n", val & USBCMD_FLS); val &= ~USBCMD_FLS; } + + if (((USBCMD_RUNSTOP | USBCMD_PSE | USBCMD_ASE) & val) != + ((USBCMD_RUNSTOP | USBCMD_PSE | USBCMD_ASE) & s->usbcmd)) { + if (s->pstate == EST_INACTIVE) { + SET_LAST_RUN_CLOCK(s); + } + s->usbcmd = val; /* Set usbcmd for ehci_update_halt() */ + ehci_update_halt(s); + s->async_stepdown = 0; + qemu_mod_timer(s->frame_timer, qemu_get_clock_ns(vm_clock)); + } break; case USBSTS: