[pve-devel] r6561 - in pve-qemu-kvm/trunk: . debian debian/patches
svn-commits at proxmox.com
svn-commits at proxmox.com
Fri Oct 14 16:34:48 CEST 2011
Author: dietmar
Date: 2011-10-14 16:34:48 +0200 (Fri, 14 Oct 2011)
New Revision: 6561
Added:
pve-qemu-kvm/trunk/debian/patches/0001-usb-host-reapurb-error-report-fix.patch
pve-qemu-kvm/trunk/debian/patches/0002-usb-host-fix-halted-endpoints.patch
pve-qemu-kvm/trunk/debian/patches/0003-usb-host-fix-configuration-tracking.patch
pve-qemu-kvm/trunk/debian/patches/0004-usb-host-endpoint-table-fixup.patch
pve-qemu-kvm/trunk/debian/patches/0005-usb-ehci-handle-siTDs.patch
pve-qemu-kvm/trunk/debian/patches/0006-usb-fix-use-after-free.patch
pve-qemu-kvm/trunk/debian/patches/0007-usb-claim-port-at-device-initialization-time.patch
Modified:
pve-qemu-kvm/trunk/Makefile
pve-qemu-kvm/trunk/debian/changelog
pve-qemu-kvm/trunk/debian/patches/series
Log:
add usb fixes
Modified: pve-qemu-kvm/trunk/Makefile
===================================================================
--- pve-qemu-kvm/trunk/Makefile 2011-10-12 04:32:05 UTC (rev 6560)
+++ pve-qemu-kvm/trunk/Makefile 2011-10-14 14:34:48 UTC (rev 6561)
@@ -1,8 +1,8 @@
-RELEASE=1.8
+RELEASE=1.9
# also update debian/changelog
KVMVER=0.15.0
-KVMPKGREL=1
+KVMPKGREL=2
KVMPACKAGE=pve-qemu-kvm
KVMDIR=qemu-kvm
Modified: pve-qemu-kvm/trunk/debian/changelog
===================================================================
--- pve-qemu-kvm/trunk/debian/changelog 2011-10-12 04:32:05 UTC (rev 6560)
+++ pve-qemu-kvm/trunk/debian/changelog 2011-10-14 14:34:48 UTC (rev 6561)
@@ -1,3 +1,9 @@
+pve-qemu-kvm (0.15.0-2) unstable; urgency=low
+
+ * include usb fixes
+
+ -- Proxmox Support Team <support at proxmox.com> Fri, 14 Oct 2011 16:30:56 +0200
+
pve-qemu-kvm (0.15.0-1) unstable; urgency=low
* update to upstream 0.15.0
Added: pve-qemu-kvm/trunk/debian/patches/0001-usb-host-reapurb-error-report-fix.patch
===================================================================
--- pve-qemu-kvm/trunk/debian/patches/0001-usb-host-reapurb-error-report-fix.patch (rev 0)
+++ pve-qemu-kvm/trunk/debian/patches/0001-usb-host-reapurb-error-report-fix.patch 2011-10-14 14:34:48 UTC (rev 6561)
@@ -0,0 +1,36 @@
+From 21d7691889fc7da34b20a73b7ee870d15b49267d Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel at redhat.com>
+Date: Fri, 2 Sep 2011 11:32:27 +0200
+Subject: [PATCH] usb-host: reapurb error report fix
+
+Don't report errors on devices which are in disconnected
+and closing state.
+(cherry picked from commit 3d09d54e57b92aaaba8d4e8c0d1c9901f1a56c7f)
+
+Conflicts:
+
+ usb-linux.c
+---
+ usb-linux.c | 6 ++++--
+ 1 files changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/usb-linux.c b/usb-linux.c
+index 53cc5fc..7d8a103 100644
+--- a/usb-linux.c
++++ b/usb-linux.c
+@@ -308,8 +308,10 @@ static void async_complete(void *opaque)
+ }
+ return;
+ }
+- if (errno == ENODEV && !s->closing) {
+- do_disconnect(s);
++ if (errno == ENODEV) {
++ if (!s->closing) {
++ do_disconnect(s);
++ }
+ return;
+ }
+
+--
+1.5.6.5
+
Added: pve-qemu-kvm/trunk/debian/patches/0002-usb-host-fix-halted-endpoints.patch
===================================================================
--- pve-qemu-kvm/trunk/debian/patches/0002-usb-host-fix-halted-endpoints.patch (rev 0)
+++ pve-qemu-kvm/trunk/debian/patches/0002-usb-host-fix-halted-endpoints.patch 2011-10-14 14:34:48 UTC (rev 6561)
@@ -0,0 +1,64 @@
+From c166f8dbb0db59eab6735e54dc2568e90c181d21 Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel at redhat.com>
+Date: Wed, 24 Aug 2011 10:55:40 +0200
+Subject: [PATCH] usb-host: fix halted endpoints
+
+Two fixes for the price of one ;)
+
+First, reinitialize the endpoint table after device reset.
+This is needed anyway as the reset might have switched interfaces.
+It also clears the endpoint halted state.
+
+Second the CLEAR_HALT ioctl wants a unsigned int passed in as
+argument, not uint8_t.
+
+This gets my usb sd card reader (sandisk micromate) going.
+
+Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
+(cherry picked from commit a8b44be4da11ba57ab3219a55eecbc422663c9b3)
+---
+ usb-linux.c | 7 ++++---
+ 1 files changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/usb-linux.c b/usb-linux.c
+index 7d8a103..1d0ccf8 100644
+--- a/usb-linux.c
++++ b/usb-linux.c
+@@ -142,6 +142,7 @@ static int parse_filter(const char *spec, struct USBAutoFilter *f);
+ static void usb_host_auto_check(void *unused);
+ static int usb_host_read_file(char *line, size_t line_size,
+ const char *device_file, const char *device_name);
++static int usb_linux_update_endp_table(USBHostDevice *s);
+
+ static struct endp_data *get_endp(USBHostDevice *s, int ep)
+ {
+@@ -509,6 +510,7 @@ static void usb_host_handle_reset(USBDevice *dev)
+ ioctl(s->fd, USBDEVFS_RESET);
+
+ usb_host_claim_interfaces(s, s->configuration);
++ usb_linux_update_endp_table(s);
+ }
+
+ static void usb_host_handle_destroy(USBDevice *dev)
+@@ -520,8 +522,6 @@ static void usb_host_handle_destroy(USBDevice *dev)
+ qemu_remove_exit_notifier(&s->exit);
+ }
+
+-static int usb_linux_update_endp_table(USBHostDevice *s);
+-
+ /* iso data is special, we need to keep enough urbs in flight to make sure
+ that the controller never runs out of them, otherwise the device will
+ likely suffer a buffer underrun / overrun. */
+@@ -723,7 +723,8 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
+ }
+
+ if (is_halted(s, p->devep)) {
+- ret = ioctl(s->fd, USBDEVFS_CLEAR_HALT, &ep);
++ unsigned int arg = ep;
++ ret = ioctl(s->fd, USBDEVFS_CLEAR_HALT, &arg);
+ if (ret < 0) {
+ DPRINTF("husb: failed to clear halt. ep 0x%x errno %d\n",
+ ep, errno);
+--
+1.5.6.5
+
Added: pve-qemu-kvm/trunk/debian/patches/0003-usb-host-fix-configuration-tracking.patch
===================================================================
--- pve-qemu-kvm/trunk/debian/patches/0003-usb-host-fix-configuration-tracking.patch (rev 0)
+++ pve-qemu-kvm/trunk/debian/patches/0003-usb-host-fix-configuration-tracking.patch 2011-10-14 14:34:48 UTC (rev 6561)
@@ -0,0 +1,175 @@
+From 154875f43c2188620f48ec70d713e545e493da35 Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel at redhat.com>
+Date: Wed, 24 Aug 2011 14:45:07 +0200
+Subject: [PATCH] usb-host: fix configuration tracking.
+
+It is perfectly fine to leave the usb device in unconfigured state
+(USBHostDevice->configuration == 0). Just do that and wait for the
+guest to explicitly set a configuration. This is closer to what real
+hardware does and it also simplifies the device initialization. There
+is no need to figure how the device is configured on the host.
+
+Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
+(cherry picked from commit b2d7c159824b5cf6af797e8bf52243fcbb42395a)
+---
+ usb-linux.c | 82 +++++++++++++---------------------------------------------
+ 1 files changed, 19 insertions(+), 63 deletions(-)
+
+diff --git a/usb-linux.c b/usb-linux.c
+index 1d0ccf8..74f1a0b 100644
+--- a/usb-linux.c
++++ b/usb-linux.c
+@@ -397,8 +397,11 @@ static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration)
+ int interface, nb_interfaces;
+ int ret, i;
+
+- if (configuration == 0) /* address state - ignore */
++ if (configuration == 0) { /* address state - ignore */
++ dev->ninterfaces = 0;
++ dev->configuration = 0;
+ return 1;
++ }
+
+ DPRINTF("husb: claiming interfaces. config %d\n", configuration);
+
+@@ -423,7 +426,7 @@ static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration)
+
+ printf("husb: config #%d need %d\n", dev->descr[i + 5], configuration);
+
+- if (configuration < 0 || configuration == dev->descr[i + 5]) {
++ if (configuration == dev->descr[i + 5]) {
+ configuration = dev->descr[i + 5];
+ break;
+ }
+@@ -509,7 +512,7 @@ static void usb_host_handle_reset(USBDevice *dev)
+
+ ioctl(s->fd, USBDEVFS_RESET);
+
+- usb_host_claim_interfaces(s, s->configuration);
++ usb_host_claim_interfaces(s, 0);
+ usb_linux_update_endp_table(s);
+ }
+
+@@ -810,6 +813,7 @@ static int usb_host_set_config(USBHostDevice *s, int config)
+ return ctrl_error();
+ }
+ usb_host_claim_interfaces(s, config);
++ usb_linux_update_endp_table(s);
+ return 0;
+ }
+
+@@ -913,51 +917,6 @@ static int usb_host_handle_control(USBDevice *dev, USBPacket *p,
+ return USB_RET_ASYNC;
+ }
+
+-static int usb_linux_get_configuration(USBHostDevice *s)
+-{
+- uint8_t configuration;
+- struct usb_ctrltransfer ct;
+- int ret;
+-
+- if (usb_fs_type == USB_FS_SYS) {
+- char device_name[32], line[1024];
+- int configuration;
+-
+- sprintf(device_name, "%d-%s", s->bus_num, s->port);
+-
+- if (!usb_host_read_file(line, sizeof(line), "bConfigurationValue",
+- device_name)) {
+- goto usbdevfs;
+- }
+- if (sscanf(line, "%d", &configuration) != 1) {
+- goto usbdevfs;
+- }
+- return configuration;
+- }
+-
+-usbdevfs:
+- ct.bRequestType = USB_DIR_IN;
+- ct.bRequest = USB_REQ_GET_CONFIGURATION;
+- ct.wValue = 0;
+- ct.wIndex = 0;
+- ct.wLength = 1;
+- ct.data = &configuration;
+- ct.timeout = 50;
+-
+- ret = ioctl(s->fd, USBDEVFS_CONTROL, &ct);
+- if (ret < 0) {
+- perror("usb_linux_get_configuration");
+- return -1;
+- }
+-
+- /* in address state */
+- if (configuration == 0) {
+- return -1;
+- }
+-
+- return configuration;
+-}
+-
+ static uint8_t usb_linux_get_alt_setting(USBHostDevice *s,
+ uint8_t configuration, uint8_t interface)
+ {
+@@ -1003,16 +962,16 @@ usbdevfs:
+ static int usb_linux_update_endp_table(USBHostDevice *s)
+ {
+ uint8_t *descriptors;
+- uint8_t devep, type, configuration, alt_interface;
++ uint8_t devep, type, alt_interface;
+ int interface, length, i;
+
+ for (i = 0; i < MAX_ENDPOINTS; i++)
+ s->endp_table[i].type = INVALID_EP_TYPE;
+
+- i = usb_linux_get_configuration(s);
+- if (i < 0)
+- return 1;
+- configuration = i;
++ if (s->configuration == 0) {
++ /* not configured yet -- leave all endpoints disabled */
++ return 0;
++ }
+
+ /* get the desired configuration, interface, and endpoint descriptors
+ * from device description */
+@@ -1021,8 +980,9 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
+ i = 0;
+
+ if (descriptors[i + 1] != USB_DT_CONFIG ||
+- descriptors[i + 5] != configuration) {
+- DPRINTF("invalid descriptor data - configuration\n");
++ descriptors[i + 5] != s->configuration) {
++ fprintf(stderr, "invalid descriptor data - configuration %d\n",
++ s->configuration);
+ return 1;
+ }
+ i += descriptors[i];
+@@ -1036,7 +996,8 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
+ }
+
+ interface = descriptors[i + 2];
+- alt_interface = usb_linux_get_alt_setting(s, configuration, interface);
++ alt_interface = usb_linux_get_alt_setting(s, s->configuration,
++ interface);
+
+ /* the current interface descriptor is the active interface
+ * and has endpoints */
+@@ -1175,13 +1136,8 @@ static int usb_host_open(USBHostDevice *dev, int bus_num,
+ #endif
+
+
+- /*
+- * Initial configuration is -1 which makes us claim first
+- * available config. We used to start with 1, which does not
+- * always work. I've seen devices where first config starts
+- * with 2.
+- */
+- if (!usb_host_claim_interfaces(dev, -1)) {
++ /* start unconfigured -- we'll wait for the guest to set a configuration */
++ if (!usb_host_claim_interfaces(dev, 0)) {
+ goto fail;
+ }
+
+--
+1.5.6.5
+
Added: pve-qemu-kvm/trunk/debian/patches/0004-usb-host-endpoint-table-fixup.patch
===================================================================
--- pve-qemu-kvm/trunk/debian/patches/0004-usb-host-endpoint-table-fixup.patch (rev 0)
+++ pve-qemu-kvm/trunk/debian/patches/0004-usb-host-endpoint-table-fixup.patch 2011-10-14 14:34:48 UTC (rev 6561)
@@ -0,0 +1,450 @@
+From aec30fcfcf41918e52eeb987a61d04e8345a62b9 Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel at redhat.com>
+Date: Fri, 2 Sep 2011 11:37:51 +0200
+Subject: [PATCH] usb-host: endpoint table fixup
+
+USB Devices can have up to 15 IN and 15 OUT endpoints, not 15 endpoints
+total. Move from one array to two arrays (one IN, one OUT) to maintain
+the endpoint state.
+(cherry picked from commit 07d4920d2bca19c64827a226b0afdfe8c7f1e3f0)
+
+Conflicts:
+
+ usb-linux.c
+---
+ usb-linux.c | 178 +++++++++++++++++++++++++++++++++-------------------------
+ 1 files changed, 101 insertions(+), 77 deletions(-)
+
+diff --git a/usb-linux.c b/usb-linux.c
+index 74f1a0b..c1c2349 100644
+--- a/usb-linux.c
++++ b/usb-linux.c
+@@ -123,7 +123,8 @@ typedef struct USBHostDevice {
+ uint32_t iso_urb_count;
+ Notifier exit;
+
+- struct endp_data endp_table[MAX_ENDPOINTS];
++ struct endp_data ep_in[MAX_ENDPOINTS];
++ struct endp_data ep_out[MAX_ENDPOINTS];
+ QLIST_HEAD(, AsyncURB) aurbs;
+
+ /* Host side address */
+@@ -144,94 +145,101 @@ static int usb_host_read_file(char *line, size_t line_size,
+ const char *device_file, const char *device_name);
+ static int usb_linux_update_endp_table(USBHostDevice *s);
+
+-static struct endp_data *get_endp(USBHostDevice *s, int ep)
++static struct endp_data *get_endp(USBHostDevice *s, int pid, int ep)
+ {
+- return s->endp_table + ep - 1;
++ struct endp_data *eps = pid == USB_TOKEN_IN ? s->ep_in : s->ep_out;
++ assert(pid == USB_TOKEN_IN || pid == USB_TOKEN_OUT);
++ assert(ep > 0 && ep <= MAX_ENDPOINTS);
++ return eps + ep - 1;
+ }
+
+-static int is_isoc(USBHostDevice *s, int ep)
++static int is_isoc(USBHostDevice *s, int pid, int ep)
+ {
+- return get_endp(s, ep)->type == USBDEVFS_URB_TYPE_ISO;
++ return get_endp(s, pid, ep)->type == USBDEVFS_URB_TYPE_ISO;
+ }
+
+-static int is_valid(USBHostDevice *s, int ep)
++static int is_valid(USBHostDevice *s, int pid, int ep)
+ {
+- return get_endp(s, ep)->type != INVALID_EP_TYPE;
++ return get_endp(s, pid, ep)->type != INVALID_EP_TYPE;
+ }
+
+-static int is_halted(USBHostDevice *s, int ep)
++static int is_halted(USBHostDevice *s, int pid, int ep)
+ {
+- return get_endp(s, ep)->halted;
++ return get_endp(s, pid, ep)->halted;
+ }
+
+-static void clear_halt(USBHostDevice *s, int ep)
++static void clear_halt(USBHostDevice *s, int pid, int ep)
+ {
+- get_endp(s, ep)->halted = 0;
++ get_endp(s, pid, ep)->halted = 0;
+ }
+
+-static void set_halt(USBHostDevice *s, int ep)
++static void set_halt(USBHostDevice *s, int pid, int ep)
+ {
+- get_endp(s, ep)->halted = 1;
++ if (ep != 0) {
++ get_endp(s, pid, ep)->halted = 1;
++ }
+ }
+
+-static int is_iso_started(USBHostDevice *s, int ep)
++static int is_iso_started(USBHostDevice *s, int pid, int ep)
+ {
+- return get_endp(s, ep)->iso_started;
++ return get_endp(s, pid, ep)->iso_started;
+ }
+
+-static void clear_iso_started(USBHostDevice *s, int ep)
++static void clear_iso_started(USBHostDevice *s, int pid, int ep)
+ {
+- get_endp(s, ep)->iso_started = 0;
++ get_endp(s, pid, ep)->iso_started = 0;
+ }
+
+-static void set_iso_started(USBHostDevice *s, int ep)
++static void set_iso_started(USBHostDevice *s, int pid, int ep)
+ {
+- struct endp_data *e = get_endp(s, ep);
++ struct endp_data *e = get_endp(s, pid, ep);
++
+ if (!e->iso_started) {
+ e->iso_started = 1;
+ e->inflight = 0;
+ }
+ }
+
+-static int change_iso_inflight(USBHostDevice *s, int ep, int value)
++static int change_iso_inflight(USBHostDevice *s, int pid, int ep, int value)
+ {
+- struct endp_data *e = get_endp(s, ep);
++ struct endp_data *e = get_endp(s, pid, ep);
+
+ e->inflight += value;
+ return e->inflight;
+ }
+
+-static void set_iso_urb(USBHostDevice *s, int ep, AsyncURB *iso_urb)
++static void set_iso_urb(USBHostDevice *s, int pid, int ep, AsyncURB *iso_urb)
+ {
+- get_endp(s, ep)->iso_urb = iso_urb;
++ get_endp(s, pid, ep)->iso_urb = iso_urb;
+ }
+
+-static AsyncURB *get_iso_urb(USBHostDevice *s, int ep)
++static AsyncURB *get_iso_urb(USBHostDevice *s, int pid, int ep)
+ {
+- return get_endp(s, ep)->iso_urb;
++ return get_endp(s, pid, ep)->iso_urb;
+ }
+
+-static void set_iso_urb_idx(USBHostDevice *s, int ep, int i)
++static void set_iso_urb_idx(USBHostDevice *s, int pid, int ep, int i)
+ {
+- get_endp(s, ep)->iso_urb_idx = i;
++ get_endp(s, pid, ep)->iso_urb_idx = i;
+ }
+
+-static int get_iso_urb_idx(USBHostDevice *s, int ep)
++static int get_iso_urb_idx(USBHostDevice *s, int pid, int ep)
+ {
+- return get_endp(s, ep)->iso_urb_idx;
++ return get_endp(s, pid, ep)->iso_urb_idx;
+ }
+
+-static void set_iso_buffer_used(USBHostDevice *s, int ep, int i)
++static void set_iso_buffer_used(USBHostDevice *s, int pid, int ep, int i)
+ {
+- get_endp(s, ep)->iso_buffer_used = i;
++ get_endp(s, pid, ep)->iso_buffer_used = i;
+ }
+
+-static int get_iso_buffer_used(USBHostDevice *s, int ep)
++static int get_iso_buffer_used(USBHostDevice *s, int pid, int ep)
+ {
+- return get_endp(s, ep)->iso_buffer_used;
++ return get_endp(s, pid, ep)->iso_buffer_used;
+ }
+
+-static void set_max_packet_size(USBHostDevice *s, int ep, uint8_t *descriptor)
++static void set_max_packet_size(USBHostDevice *s, int pid, int ep,
++ uint8_t *descriptor)
+ {
+ int raw = descriptor[4] + (descriptor[5] << 8);
+ int size, microframes;
+@@ -242,12 +250,12 @@ static void set_max_packet_size(USBHostDevice *s, int ep, uint8_t *descriptor)
+ case 2: microframes = 3; break;
+ default: microframes = 1; break;
+ }
+- get_endp(s, ep)->max_packet_size = size * microframes;
++ get_endp(s, pid, ep)->max_packet_size = size * microframes;
+ }
+
+-static int get_max_packet_size(USBHostDevice *s, int ep)
++static int get_max_packet_size(USBHostDevice *s, int pid, int ep)
+ {
+- return get_endp(s, ep)->max_packet_size;
++ return get_endp(s, pid, ep)->max_packet_size;
+ }
+
+ /*
+@@ -327,13 +335,16 @@ static void async_complete(void *opaque)
+ anything else (it is handled further in usb_host_handle_iso_data) */
+ if (aurb->iso_frame_idx == -1) {
+ int inflight;
++ int pid = (aurb->urb.endpoint & USB_DIR_IN) ?
++ USB_TOKEN_IN : USB_TOKEN_OUT;
++ int ep = aurb->urb.endpoint & 0xf;
+ if (aurb->urb.status == -EPIPE) {
+- set_halt(s, aurb->urb.endpoint & 0xf);
++ set_halt(s, pid, ep);
+ }
+ aurb->iso_frame_idx = 0;
+ urbs++;
+- inflight = change_iso_inflight(s, aurb->urb.endpoint & 0xf, -1);
+- if (inflight == 0 && is_iso_started(s, aurb->urb.endpoint & 0xf)) {
++ inflight = change_iso_inflight(s, pid, ep, -1);
++ if (inflight == 0 && is_iso_started(s, pid, ep)) {
+ fprintf(stderr, "husb: out of buffers for iso stream\n");
+ }
+ continue;
+@@ -348,7 +359,7 @@ static void async_complete(void *opaque)
+ break;
+
+ case -EPIPE:
+- set_halt(s, p->devep);
++ set_halt(s, p->pid, p->devep);
+ p->len = USB_RET_STALL;
+ break;
+
+@@ -528,10 +539,10 @@ static void usb_host_handle_destroy(USBDevice *dev)
+ /* iso data is special, we need to keep enough urbs in flight to make sure
+ that the controller never runs out of them, otherwise the device will
+ likely suffer a buffer underrun / overrun. */
+-static AsyncURB *usb_host_alloc_iso(USBHostDevice *s, uint8_t ep, int in)
++static AsyncURB *usb_host_alloc_iso(USBHostDevice *s, int pid, uint8_t ep)
+ {
+ AsyncURB *aurb;
+- int i, j, len = get_max_packet_size(s, ep);
++ int i, j, len = get_max_packet_size(s, pid, ep);
+
+ aurb = qemu_mallocz(s->iso_urb_count * sizeof(*aurb));
+ for (i = 0; i < s->iso_urb_count; i++) {
+@@ -543,23 +554,23 @@ static AsyncURB *usb_host_alloc_iso(USBHostDevice *s, uint8_t ep, int in)
+ aurb[i].urb.number_of_packets = ISO_FRAME_DESC_PER_URB;
+ for (j = 0 ; j < ISO_FRAME_DESC_PER_URB; j++)
+ aurb[i].urb.iso_frame_desc[j].length = len;
+- if (in) {
++ if (pid == USB_TOKEN_IN) {
+ aurb[i].urb.endpoint |= 0x80;
+ /* Mark as fully consumed (idle) */
+ aurb[i].iso_frame_idx = ISO_FRAME_DESC_PER_URB;
+ }
+ }
+- set_iso_urb(s, ep, aurb);
++ set_iso_urb(s, pid, ep, aurb);
+
+ return aurb;
+ }
+
+-static void usb_host_stop_n_free_iso(USBHostDevice *s, uint8_t ep)
++static void usb_host_stop_n_free_iso(USBHostDevice *s, int pid, uint8_t ep)
+ {
+ AsyncURB *aurb;
+ int i, ret, killed = 0, free = 1;
+
+- aurb = get_iso_urb(s, ep);
++ aurb = get_iso_urb(s, pid, ep);
+ if (!aurb) {
+ return;
+ }
+@@ -590,9 +601,9 @@ static void usb_host_stop_n_free_iso(USBHostDevice *s, uint8_t ep)
+ qemu_free(aurb);
+ else
+ printf("husb: leaking iso urbs because of discard failure\n");
+- set_iso_urb(s, ep, NULL);
+- set_iso_urb_idx(s, ep, 0);
+- clear_iso_started(s, ep);
++ set_iso_urb(s, pid, ep, NULL);
++ set_iso_urb_idx(s, pid, ep, 0);
++ clear_iso_started(s, pid, ep);
+ }
+
+ static int urb_status_to_usb_ret(int status)
+@@ -610,16 +621,16 @@ static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
+ AsyncURB *aurb;
+ int i, j, ret, max_packet_size, offset, len = 0;
+
+- max_packet_size = get_max_packet_size(s, p->devep);
++ max_packet_size = get_max_packet_size(s, p->pid, p->devep);
+ if (max_packet_size == 0)
+ return USB_RET_NAK;
+
+- aurb = get_iso_urb(s, p->devep);
++ aurb = get_iso_urb(s, p->pid, p->devep);
+ if (!aurb) {
+- aurb = usb_host_alloc_iso(s, p->devep, in);
++ aurb = usb_host_alloc_iso(s, p->pid, p->devep);
+ }
+
+- i = get_iso_urb_idx(s, p->devep);
++ i = get_iso_urb_idx(s, p->pid, p->devep);
+ j = aurb[i].iso_frame_idx;
+ if (j >= 0 && j < ISO_FRAME_DESC_PER_URB) {
+ if (in) {
+@@ -646,7 +657,7 @@ static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
+ }
+ } else {
+ len = p->len;
+- offset = (j == 0) ? 0 : get_iso_buffer_used(s, p->devep);
++ offset = (j == 0) ? 0 : get_iso_buffer_used(s, p->pid, p->devep);
+
+ /* Check the frame fits */
+ if (len > max_packet_size) {
+@@ -658,27 +669,27 @@ static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
+ memcpy(aurb[i].urb.buffer + offset, p->data, len);
+ aurb[i].urb.iso_frame_desc[j].length = len;
+ offset += len;
+- set_iso_buffer_used(s, p->devep, offset);
++ set_iso_buffer_used(s, p->pid, p->devep, offset);
+
+ /* Start the stream once we have buffered enough data */
+- if (!is_iso_started(s, p->devep) && i == 1 && j == 8) {
+- set_iso_started(s, p->devep);
++ if (!is_iso_started(s, p->pid, p->devep) && i == 1 && j == 8) {
++ set_iso_started(s, p->pid, p->devep);
+ }
+ }
+ aurb[i].iso_frame_idx++;
+ if (aurb[i].iso_frame_idx == ISO_FRAME_DESC_PER_URB) {
+ i = (i + 1) % s->iso_urb_count;
+- set_iso_urb_idx(s, p->devep, i);
++ set_iso_urb_idx(s, p->pid, p->devep, i);
+ }
+ } else {
+ if (in) {
+- set_iso_started(s, p->devep);
++ set_iso_started(s, p->pid, p->devep);
+ } else {
+ DPRINTF("hubs: iso out error no free buffer, dropping packet\n");
+ }
+ }
+
+- if (is_iso_started(s, p->devep)) {
++ if (is_iso_started(s, p->pid, p->devep)) {
+ /* (Re)-submit all fully consumed / filled urbs */
+ for (i = 0; i < s->iso_urb_count; i++) {
+ if (aurb[i].iso_frame_idx == ISO_FRAME_DESC_PER_URB) {
+@@ -698,7 +709,7 @@ static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
+ break;
+ }
+ aurb[i].iso_frame_idx = -1;
+- change_iso_inflight(s, p->devep, +1);
++ change_iso_inflight(s, p->pid, p->devep, 1);
+ }
+ }
+ }
+@@ -715,7 +726,7 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
+ uint8_t *pbuf;
+ uint8_t ep;
+
+- if (!is_valid(s, p->devep)) {
++ if (!is_valid(s, p->pid, p->devep)) {
+ return USB_RET_NAK;
+ }
+
+@@ -725,7 +736,7 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
+ ep = p->devep;
+ }
+
+- if (is_halted(s, p->devep)) {
++ if (is_halted(s, p->pid, p->devep)) {
+ unsigned int arg = ep;
+ ret = ioctl(s->fd, USBDEVFS_CLEAR_HALT, &arg);
+ if (ret < 0) {
+@@ -733,10 +744,10 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
+ ep, errno);
+ return USB_RET_NAK;
+ }
+- clear_halt(s, p->devep);
++ clear_halt(s, p->pid, p->devep);
+ }
+
+- if (is_isoc(s, p->devep)) {
++ if (is_isoc(s, p->pid, p->devep)) {
+ return usb_host_handle_iso_data(s, p, p->pid == USB_TOKEN_IN);
+ }
+
+@@ -823,8 +834,11 @@ static int usb_host_set_interface(USBHostDevice *s, int iface, int alt)
+ int i, ret;
+
+ for (i = 1; i <= MAX_ENDPOINTS; i++) {
+- if (is_isoc(s, i)) {
+- usb_host_stop_n_free_iso(s, i);
++ if (is_isoc(s, USB_TOKEN_IN, i)) {
++ usb_host_stop_n_free_iso(s, USB_TOKEN_IN, i);
++ }
++ if (is_isoc(s, USB_TOKEN_OUT, i)) {
++ usb_host_stop_n_free_iso(s, USB_TOKEN_OUT, i);
+ }
+ }
+
+@@ -963,10 +977,13 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
+ {
+ uint8_t *descriptors;
+ uint8_t devep, type, alt_interface;
+- int interface, length, i;
++ int interface, length, i, ep, pid;
++ struct endp_data *epd;
+
+- for (i = 0; i < MAX_ENDPOINTS; i++)
+- s->endp_table[i].type = INVALID_EP_TYPE;
++ for (i = 0; i < MAX_ENDPOINTS; i++) {
++ s->ep_in[i].type = INVALID_EP_TYPE;
++ s->ep_out[i].type = INVALID_EP_TYPE;
++ }
+
+ if (s->configuration == 0) {
+ /* not configured yet -- leave all endpoints disabled */
+@@ -1020,7 +1037,9 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
+ }
+
+ devep = descriptors[i + 2];
+- if ((devep & 0x0f) == 0) {
++ pid = (devep & USB_DIR_IN) ? USB_TOKEN_IN : USB_TOKEN_OUT;
++ ep = devep & 0xf;
++ if (ep == 0) {
+ fprintf(stderr, "usb-linux: invalid ep descriptor, ep == 0\n");
+ return 1;
+ }
+@@ -1031,7 +1050,7 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
+ break;
+ case 0x01:
+ type = USBDEVFS_URB_TYPE_ISO;
+- set_max_packet_size(s, (devep & 0xf), descriptors + i);
++ set_max_packet_size(s, pid, ep, descriptors + i);
+ break;
+ case 0x02:
+ type = USBDEVFS_URB_TYPE_BULK;
+@@ -1043,8 +1062,10 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
+ DPRINTF("usb_host: malformed endpoint type\n");
+ type = USBDEVFS_URB_TYPE_BULK;
+ }
+- s->endp_table[(devep & 0xf) - 1].type = type;
+- s->endp_table[(devep & 0xf) - 1].halted = 0;
++ epd = get_endp(s, pid, ep);
++ assert(epd->type == INVALID_EP_TYPE);
++ epd->type = type;
++ epd->halted = 0;
+
+ i += descriptors[i];
+ }
+@@ -1206,8 +1227,11 @@ static int usb_host_close(USBHostDevice *dev)
+ qemu_set_fd_handler(dev->fd, NULL, NULL, NULL);
+ dev->closing = 1;
+ for (i = 1; i <= MAX_ENDPOINTS; i++) {
+- if (is_isoc(dev, i)) {
+- usb_host_stop_n_free_iso(dev, i);
++ if (is_isoc(dev, USB_TOKEN_IN, i)) {
++ usb_host_stop_n_free_iso(dev, USB_TOKEN_IN, i);
++ }
++ if (is_isoc(dev, USB_TOKEN_OUT, i)) {
++ usb_host_stop_n_free_iso(dev, USB_TOKEN_OUT, i);
+ }
+ }
+ async_complete(dev);
+--
+1.5.6.5
+
Added: pve-qemu-kvm/trunk/debian/patches/0005-usb-ehci-handle-siTDs.patch
===================================================================
--- pve-qemu-kvm/trunk/debian/patches/0005-usb-ehci-handle-siTDs.patch (rev 0)
+++ pve-qemu-kvm/trunk/debian/patches/0005-usb-ehci-handle-siTDs.patch 2011-10-14 14:34:48 UTC (rev 6561)
@@ -0,0 +1,116 @@
+From 7e6bb4c98ea2f2edfb6df901ea2f83fcada94a8f Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel at redhat.com>
+Date: Fri, 26 Aug 2011 14:13:48 +0200
+Subject: [PATCH] usb-ehci: handle siTDs
+
+This patch adds code to do minimal siTD handling, which is basically
+just following the next pointer. This is good enougth to handle the
+inactive siTDs used by FreeBSD. Active siTDs are skipped too as we
+don't have split transfer support in qemu, additionally a warning is
+printed.
+
+Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
+(cherry picked from commit c57f5348b0c95b46b98b9ddb48b059b29c178452)
+---
+ hw/usb-ehci.c | 43 ++++++++++++++++++++++++++++++++++++++++++-
+ trace-events | 1 +
+ 2 files changed, 43 insertions(+), 1 deletions(-)
+
+diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
+index a4758f9..3ea4c72 100644
+--- a/hw/usb-ehci.c
++++ b/hw/usb-ehci.c
+@@ -148,6 +148,7 @@ typedef enum {
+ EST_FETCHENTRY,
+ EST_FETCHQH,
+ EST_FETCHITD,
++ EST_FETCHSITD,
+ EST_ADVANCEQUEUE,
+ EST_FETCHQTD,
+ EST_EXECUTE,
+@@ -645,6 +646,13 @@ static void ehci_trace_itd(EHCIState *s, target_phys_addr_t addr, EHCIitd *itd)
+ get_field(itd->bufptr[0], ITD_BUFPTR_DEVADDR));
+ }
+
++static void ehci_trace_sitd(EHCIState *s, target_phys_addr_t addr,
++ EHCIsitd *sitd)
++{
++ trace_usb_ehci_sitd(addr, sitd->next,
++ (bool)(sitd->results & SITD_RESULTS_ACTIVE));
++}
++
+ /* queue management */
+
+ static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, int async)
+@@ -1613,8 +1621,13 @@ static int ehci_state_fetchentry(EHCIState *ehci, int async)
+ again = 1;
+ break;
+
++ case NLPTR_TYPE_STITD:
++ ehci_set_state(ehci, async, EST_FETCHSITD);
++ again = 1;
++ break;
++
+ default:
+- // TODO: handle siTD and FSTN types
++ /* TODO: handle FSTN type */
+ fprintf(stderr, "FETCHENTRY: entry at %X is of type %d "
+ "which is not supported yet\n", entry, NLPTR_TYPE_GET(entry));
+ return -1;
+@@ -1730,6 +1743,30 @@ static int ehci_state_fetchitd(EHCIState *ehci, int async)
+ return 1;
+ }
+
++static int ehci_state_fetchsitd(EHCIState *ehci, int async)
++{
++ uint32_t entry;
++ EHCIsitd sitd;
++
++ assert(!async);
++ entry = ehci_get_fetch_addr(ehci, async);
++
++ get_dwords(NLPTR_GET(entry), (uint32_t *)&sitd,
++ sizeof(EHCIsitd) >> 2);
++ ehci_trace_sitd(ehci, entry, &sitd);
++
++ if (!(sitd.results & SITD_RESULTS_ACTIVE)) {
++ /* siTD is not active, nothing to do */;
++ } else {
++ /* TODO: split transfers are not implemented */
++ fprintf(stderr, "WARNING: Skipping active siTD\n");
++ }
++
++ ehci_set_fetch_addr(ehci, async, sitd.next);
++ ehci_set_state(ehci, async, EST_FETCHENTRY);
++ return 1;
++}
++
+ /* Section 4.10.2 - paragraph 3 */
+ static int ehci_state_advqueue(EHCIQueue *q, int async)
+ {
+@@ -2005,6 +2042,10 @@ static void ehci_advance_state(EHCIState *ehci,
+ again = ehci_state_fetchitd(ehci, async);
+ break;
+
++ case EST_FETCHSITD:
++ again = ehci_state_fetchsitd(ehci, async);
++ break;
++
+ case EST_ADVANCEQUEUE:
+ again = ehci_state_advqueue(q, async);
+ break;
+diff --git a/trace-events b/trace-events
+index 713f042..e6f8c37 100644
+--- a/trace-events
++++ b/trace-events
+@@ -223,6 +223,7 @@ disable usb_ehci_qtd_ptrs(void *q, uint32_t addr, uint32_t nxt, uint32_t altnext
+ disable usb_ehci_qtd_fields(uint32_t addr, int tbytes, int cpage, int cerr, int pid) "QTD @ %08x - tbytes %d, cpage %d, cerr %d, pid %d"
+ disable usb_ehci_qtd_bits(uint32_t addr, int ioc, int active, int halt, int babble, int xacterr) "QTD @ %08x - ioc %d, active %d, halt %d, babble %d, xacterr %d"
+ disable usb_ehci_itd(uint32_t addr, uint32_t nxt, uint32_t mplen, uint32_t mult, uint32_t ep, uint32_t devaddr) "ITD @ %08x: next %08x - mplen %d, mult %d, ep %d, dev %d"
++disable usb_ehci_sitd(uint32_t addr, uint32_t nxt, uint32_t active) "ITD @ %08x: next %08x - active %d"
+ disable usb_ehci_port_attach(uint32_t port, const char *device) "attach port #%d - %s"
+ disable usb_ehci_port_detach(uint32_t port) "detach port #%d"
+ disable usb_ehci_port_reset(uint32_t port, int enable) "reset port #%d - %d"
+--
+1.5.6.5
+
Added: pve-qemu-kvm/trunk/debian/patches/0006-usb-fix-use-after-free.patch
===================================================================
--- pve-qemu-kvm/trunk/debian/patches/0006-usb-fix-use-after-free.patch (rev 0)
+++ pve-qemu-kvm/trunk/debian/patches/0006-usb-fix-use-after-free.patch 2011-10-14 14:34:48 UTC (rev 6561)
@@ -0,0 +1,31 @@
+From d3ffc953b3e5cacec22c34c6361e95d6ffcfc8ad Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel at redhat.com>
+Date: Thu, 25 Aug 2011 16:43:15 +0200
+Subject: [PATCH] usb: fix use after free
+
+The ->complete() callback might have released the USBPacket (uhci
+actually does), so we must not touch it after the callback returns.
+
+Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
+(cherry picked from commit 722d89396b6ccb49cd9d3aafd991ae01c8a30744)
+---
+ hw/usb.c | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/hw/usb.c b/hw/usb.c
+index 27a983c..b44e997 100644
+--- a/hw/usb.c
++++ b/hw/usb.c
+@@ -334,8 +334,8 @@ void usb_packet_complete(USBDevice *dev, USBPacket *p)
+ {
+ /* Note: p->owner != dev is possible in case dev is a hub */
+ assert(p->owner != NULL);
+- dev->port->ops->complete(dev->port, p);
+ p->owner = NULL;
++ dev->port->ops->complete(dev->port, p);
+ }
+
+ /* Cancel an active packet. The packed must have been deferred by
+--
+1.5.6.5
+
Added: pve-qemu-kvm/trunk/debian/patches/0007-usb-claim-port-at-device-initialization-time.patch
===================================================================
--- pve-qemu-kvm/trunk/debian/patches/0007-usb-claim-port-at-device-initialization-time.patch (rev 0)
+++ pve-qemu-kvm/trunk/debian/patches/0007-usb-claim-port-at-device-initialization-time.patch 2011-10-14 14:34:48 UTC (rev 6561)
@@ -0,0 +1,473 @@
+From 08cc8c6ea3736d2303d2f720eb9bc1168a2adab5 Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel at redhat.com>
+Date: Thu, 1 Sep 2011 13:56:37 +0200
+Subject: [PATCH] usb: claim port at device initialization time.
+
+This patch makes qemu assign a port when creating the device, not when
+attaching it. For most usb devices this isn't a noticable difference
+because they are in attached state all the time.
+
+The change affects usb-host devices which live in detached state while
+the real device is unplugged from the host. They have a fixed port
+assigned all the time now instead of getting grabbing one on attach and
+releasing it at detach, i.e. they stop floating around at the usb bus.
+
+The change also allows to simplify usb-hub. It doesn't need the
+handle_attach() callback any more to configure the downstream ports.
+This can be done at device initialitation time now. The changed
+initialization order (first grab upstream port, then register downstream
+ports) also fixes some icky corner cases. For example it is not possible
+any more to plug the hub into one of its own downstream ports.
+
+The usb host adapters must care too. USBPort->dev being non-NULL
+doesn't imply any more the device is in attached state. The host
+adapters must additionally check the USBPort->dev->attached flag.
+
+Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
+(cherry picked from commit 763917c9b6d5a6126530d8e52324e653e594c521)
+---
+ hw/usb-bus.c | 110 +++++++++++++++++++++++++++++++++------------------------
+ hw/usb-ehci.c | 22 ++++++------
+ hw/usb-hub.c | 12 +------
+ hw/usb-ohci.c | 4 +-
+ hw/usb-uhci.c | 11 +++---
+ hw/usb.c | 35 ++++++++----------
+ hw/usb.h | 5 ++-
+ trace-events | 6 +++
+ 8 files changed, 110 insertions(+), 95 deletions(-)
+
+diff --git a/hw/usb-bus.c b/hw/usb-bus.c
+index f1dd55e..d384426 100644
+--- a/hw/usb-bus.c
++++ b/hw/usb-bus.c
+@@ -3,6 +3,7 @@
+ #include "qdev.h"
+ #include "sysemu.h"
+ #include "monitor.h"
++#include "trace.h"
+
+ static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent);
+
+@@ -73,9 +74,13 @@ static int usb_qdev_init(DeviceState *qdev, DeviceInfo *base)
+ dev->info = info;
+ dev->auto_attach = 1;
+ QLIST_INIT(&dev->strings);
+- rc = dev->info->init(dev);
+- if (rc == 0 && dev->auto_attach)
++ rc = usb_claim_port(dev);
++ if (rc == 0) {
++ rc = dev->info->init(dev);
++ }
++ if (rc == 0 && dev->auto_attach) {
+ rc = usb_device_attach(dev);
++ }
+ return rc;
+ }
+
+@@ -89,6 +94,9 @@ static int usb_qdev_exit(DeviceState *qdev)
+ if (dev->info->handle_destroy) {
+ dev->info->handle_destroy(dev);
+ }
++ if (dev->port) {
++ usb_release_port(dev);
++ }
+ return 0;
+ }
+
+@@ -205,21 +213,13 @@ void usb_unregister_port(USBBus *bus, USBPort *port)
+ bus->nfree--;
+ }
+
+-static int do_attach(USBDevice *dev)
++int usb_claim_port(USBDevice *dev)
+ {
+ USBBus *bus = usb_bus_from_device(dev);
+ USBPort *port;
+
+- if (dev->attached) {
+- error_report("Error: tried to attach usb device %s twice\n",
+- dev->product_desc);
+- return -1;
+- }
+- if (bus->nfree == 0) {
+- error_report("Error: tried to attach usb device %s to a bus with no free ports\n",
+- dev->product_desc);
+- return -1;
+- }
++ assert(dev->port == NULL);
++
+ if (dev->port_path) {
+ QTAILQ_FOREACH(port, &bus->free, next) {
+ if (strcmp(port->path, dev->port_path) == 0) {
+@@ -227,68 +227,86 @@ static int do_attach(USBDevice *dev)
+ }
+ }
+ if (port == NULL) {
+- error_report("Error: usb port %s (bus %s) not found\n",
+- dev->port_path, bus->qbus.name);
++ error_report("Error: usb port %s (bus %s) not found (in use?)\n",
++ dev->port_path, bus->qbus.name);
+ return -1;
+ }
+ } else {
++ if (bus->nfree == 1 && strcmp(dev->qdev.info->name, "usb-hub") != 0) {
++ /* Create a new hub and chain it on */
++ usb_create_simple(bus, "usb-hub");
++ }
++ if (bus->nfree == 0) {
++ error_report("Error: tried to attach usb device %s to a bus "
++ "with no free ports\n", dev->product_desc);
++ return -1;
++ }
+ port = QTAILQ_FIRST(&bus->free);
+ }
+- if (!(port->speedmask & dev->speedmask)) {
+- error_report("Warning: speed mismatch trying to attach usb device %s to bus %s\n",
+- dev->product_desc, bus->qbus.name);
+- return -1;
+- }
++ trace_usb_port_claim(bus->busnr, port->path);
+
+- dev->attached++;
+ QTAILQ_REMOVE(&bus->free, port, next);
+ bus->nfree--;
+
+- usb_attach(port, dev);
++ dev->port = port;
++ port->dev = dev;
+
+ QTAILQ_INSERT_TAIL(&bus->used, port, next);
+ bus->nused++;
+-
+ return 0;
+ }
+
+-int usb_device_attach(USBDevice *dev)
++void usb_release_port(USBDevice *dev)
+ {
+ USBBus *bus = usb_bus_from_device(dev);
++ USBPort *port = dev->port;
+
+- if (bus->nfree == 1 && dev->port_path == NULL) {
+- /* Create a new hub and chain it on
+- (unless a physical port location is specified). */
+- usb_create_simple(bus, "usb-hub");
+- }
+- return do_attach(dev);
++ assert(port != NULL);
++ trace_usb_port_release(bus->busnr, port->path);
++
++ QTAILQ_REMOVE(&bus->used, port, next);
++ bus->nused--;
++
++ dev->port = NULL;
++ port->dev = NULL;
++
++ QTAILQ_INSERT_TAIL(&bus->free, port, next);
++ bus->nfree++;
+ }
+
+-int usb_device_detach(USBDevice *dev)
++int usb_device_attach(USBDevice *dev)
+ {
+ USBBus *bus = usb_bus_from_device(dev);
+- USBPort *port;
++ USBPort *port = dev->port;
+
+- if (!dev->attached) {
+- error_report("Error: tried to detach unattached usb device %s\n",
+- dev->product_desc);
++ assert(port != NULL);
++ assert(!dev->attached);
++ trace_usb_port_attach(bus->busnr, port->path);
++
++ if (!(port->speedmask & dev->speedmask)) {
++ error_report("Warning: speed mismatch trying to attach "
++ "usb device %s to bus %s\n",
++ dev->product_desc, bus->qbus.name);
+ return -1;
+ }
+- dev->attached--;
+
+- QTAILQ_FOREACH(port, &bus->used, next) {
+- if (port->dev == dev)
+- break;
+- }
+- assert(port != NULL);
++ dev->attached++;
++ usb_attach(port);
+
+- QTAILQ_REMOVE(&bus->used, port, next);
+- bus->nused--;
++ return 0;
++}
++
++int usb_device_detach(USBDevice *dev)
++{
++ USBBus *bus = usb_bus_from_device(dev);
++ USBPort *port = dev->port;
+
+- usb_attach(port, NULL);
++ assert(port != NULL);
++ assert(dev->attached);
++ trace_usb_port_detach(bus->busnr, port->path);
+
+- QTAILQ_INSERT_TAIL(&bus->free, port, next);
+- bus->nfree++;
++ usb_detach(port);
++ dev->attached--;
+ return 0;
+ }
+
+diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
+index 3ea4c72..5bb61bb 100644
+--- a/hw/usb-ehci.c
++++ b/hw/usb-ehci.c
+@@ -856,8 +856,8 @@ static void ehci_reset(void *opaque)
+ */
+ for(i = 0; i < NB_PORTS; i++) {
+ devs[i] = s->ports[i].dev;
+- if (devs[i]) {
+- usb_attach(&s->ports[i], NULL);
++ if (devs[i] && devs[i]->attached) {
++ usb_detach(&s->ports[i]);
+ }
+ }
+
+@@ -877,8 +877,8 @@ static void ehci_reset(void *opaque)
+ } else {
+ s->portsc[i] = PORTSC_PPOWER;
+ }
+- if (devs[i]) {
+- usb_attach(&s->ports[i], devs[i]);
++ if (devs[i] && devs[i]->attached) {
++ usb_attach(&s->ports[i]);
+ }
+ }
+ ehci_queues_rip_all(s);
+@@ -944,15 +944,15 @@ static void handle_port_owner_write(EHCIState *s, int port, uint32_t owner)
+ return;
+ }
+
+- if (dev) {
+- usb_attach(&s->ports[port], NULL);
++ if (dev && dev->attached) {
++ usb_detach(&s->ports[port]);
+ }
+
+ *portsc &= ~PORTSC_POWNER;
+ *portsc |= owner;
+
+- if (dev) {
+- usb_attach(&s->ports[port], dev);
++ if (dev && dev->attached) {
++ usb_attach(&s->ports[port]);
+ }
+ }
+
+@@ -976,8 +976,8 @@ static void handle_port_status_write(EHCIState *s, int port, uint32_t val)
+
+ if (!(val & PORTSC_PRESET) &&(*portsc & PORTSC_PRESET)) {
+ trace_usb_ehci_port_reset(port, 0);
+- if (dev) {
+- usb_attach(&s->ports[port], dev);
++ if (dev && dev->attached) {
++ usb_attach(&s->ports[port]);
+ usb_send_msg(dev, USB_MSG_RESET);
+ *portsc &= ~PORTSC_CSC;
+ }
+@@ -986,7 +986,7 @@ static void handle_port_status_write(EHCIState *s, int port, uint32_t val)
+ * Table 2.16 Set the enable bit(and enable bit change) to indicate
+ * to SW that this port has a high speed device attached
+ */
+- if (dev && (dev->speedmask & USB_SPEED_MASK_HIGH)) {
++ if (dev && dev->attached && (dev->speedmask & USB_SPEED_MASK_HIGH)) {
+ val |= PORTSC_PED;
+ }
+ }
+diff --git a/hw/usb-hub.c b/hw/usb-hub.c
+index b49a2fe..a7a80f0 100644
+--- a/hw/usb-hub.c
++++ b/hw/usb-hub.c
+@@ -213,16 +213,6 @@ static void usb_hub_complete(USBPort *port, USBPacket *packet)
+ usb_packet_complete(&s->dev, packet);
+ }
+
+-static void usb_hub_handle_attach(USBDevice *dev)
+-{
+- USBHubState *s = DO_UPCAST(USBHubState, dev, dev);
+- int i;
+-
+- for (i = 0; i < NUM_PORTS; i++) {
+- usb_port_location(&s->ports[i].port, dev->port, i+1);
+- }
+-}
+-
+ static void usb_hub_handle_reset(USBDevice *dev)
+ {
+ /* XXX: do it */
+@@ -497,6 +487,7 @@ static int usb_hub_initfn(USBDevice *dev)
+ usb_register_port(usb_bus_from_device(dev),
+ &port->port, s, i, &usb_hub_port_ops,
+ USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
++ usb_port_location(&port->port, dev->port, i+1);
+ port->wPortStatus = PORT_STAT_POWER;
+ port->wPortChange = 0;
+ }
+@@ -535,7 +526,6 @@ static struct USBDeviceInfo hub_info = {
+ .usb_desc = &desc_hub,
+ .init = usb_hub_initfn,
+ .handle_packet = usb_hub_handle_packet,
+- .handle_attach = usb_hub_handle_attach,
+ .handle_reset = usb_hub_handle_reset,
+ .handle_control = usb_hub_handle_control,
+ .handle_data = usb_hub_handle_data,
+diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
+index 8491d59..4dd2c1e 100644
+--- a/hw/usb-ohci.c
++++ b/hw/usb-ohci.c
+@@ -448,8 +448,8 @@ static void ohci_reset(void *opaque)
+ {
+ port = &ohci->rhport[i];
+ port->ctrl = 0;
+- if (port->port.dev) {
+- usb_attach(&port->port, port->port.dev);
++ if (port->port.dev && port->port.dev->attached) {
++ usb_attach(&port->port);
+ }
+ }
+ if (ohci->async_td) {
+diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
+index da74c57..b2647b0 100644
+--- a/hw/usb-uhci.c
++++ b/hw/usb-uhci.c
+@@ -338,8 +338,8 @@ static void uhci_reset(void *opaque)
+ for(i = 0; i < NB_PORTS; i++) {
+ port = &s->ports[i];
+ port->ctrl = 0x0080;
+- if (port->port.dev) {
+- usb_attach(&port->port, port->port.dev);
++ if (port->port.dev && port->port.dev->attached) {
++ usb_attach(&port->port);
+ }
+ }
+
+@@ -444,7 +444,7 @@ static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
+ for(i = 0; i < NB_PORTS; i++) {
+ port = &s->ports[i];
+ dev = port->port.dev;
+- if (dev) {
++ if (dev && dev->attached) {
+ usb_send_msg(dev, USB_MSG_RESET);
+ }
+ }
+@@ -484,7 +484,7 @@ static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
+ return;
+ port = &s->ports[n];
+ dev = port->port.dev;
+- if (dev) {
++ if (dev && dev->attached) {
+ /* port reset */
+ if ( (val & UHCI_PORT_RESET) &&
+ !(port->ctrl & UHCI_PORT_RESET) ) {
+@@ -658,8 +658,9 @@ static int uhci_broadcast_packet(UHCIState *s, USBPacket *p)
+ UHCIPort *port = &s->ports[i];
+ USBDevice *dev = port->port.dev;
+
+- if (dev && (port->ctrl & UHCI_PORT_EN))
++ if (dev && dev->attached && (port->ctrl & UHCI_PORT_EN)) {
+ ret = usb_handle_packet(dev, p);
++ }
+ }
+
+ DPRINTF("uhci: packet exit. ret %d len %d\n", ret, p->len);
+diff --git a/hw/usb.c b/hw/usb.c
+index b44e997..b89a609 100644
+--- a/hw/usb.c
++++ b/hw/usb.c
+@@ -26,26 +26,23 @@
+ #include "qemu-common.h"
+ #include "usb.h"
+
+-void usb_attach(USBPort *port, USBDevice *dev)
++void usb_attach(USBPort *port)
+ {
+- if (dev != NULL) {
+- /* attach */
+- if (port->dev) {
+- usb_attach(port, NULL);
+- }
+- dev->port = port;
+- port->dev = dev;
+- port->ops->attach(port);
+- usb_send_msg(dev, USB_MSG_ATTACH);
+- } else {
+- /* detach */
+- dev = port->dev;
+- assert(dev);
+- port->ops->detach(port);
+- usb_send_msg(dev, USB_MSG_DETACH);
+- dev->port = NULL;
+- port->dev = NULL;
+- }
++ USBDevice *dev = port->dev;
++
++ assert(dev != NULL);
++ assert(dev->attached);
++ port->ops->attach(port);
++ usb_send_msg(dev, USB_MSG_ATTACH);
++}
++
++void usb_detach(USBPort *port)
++{
++ USBDevice *dev = port->dev;
++
++ assert(dev != NULL);
++ port->ops->detach(port);
++ usb_send_msg(dev, USB_MSG_DETACH);
+ }
+
+ void usb_wakeup(USBDevice *dev)
+diff --git a/hw/usb.h b/hw/usb.h
+index ded2de2..dfe4449 100644
+--- a/hw/usb.h
++++ b/hw/usb.h
+@@ -295,7 +295,8 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p);
+ void usb_packet_complete(USBDevice *dev, USBPacket *p);
+ void usb_cancel_packet(USBPacket * p);
+
+-void usb_attach(USBPort *port, USBDevice *dev);
++void usb_attach(USBPort *port);
++void usb_detach(USBPort *port);
+ void usb_wakeup(USBDevice *dev);
+ int usb_generic_handle_packet(USBDevice *s, USBPacket *p);
+ void usb_generic_async_ctrl_complete(USBDevice *s, USBPacket *p);
+@@ -372,6 +373,8 @@ int usb_register_companion(const char *masterbus, USBPort *ports[],
+ void *opaque, USBPortOps *ops, int speedmask);
+ void usb_port_location(USBPort *downstream, USBPort *upstream, int portnr);
+ void usb_unregister_port(USBBus *bus, USBPort *port);
++int usb_claim_port(USBDevice *dev);
++void usb_release_port(USBDevice *dev);
+ int usb_device_attach(USBDevice *dev);
+ int usb_device_detach(USBDevice *dev);
+ int usb_device_delete_addr(int busnr, int addr);
+diff --git a/trace-events b/trace-events
+index e6f8c37..201cb49 100644
+--- a/trace-events
++++ b/trace-events
+@@ -209,6 +209,12 @@ disable sun4m_iommu_page_get_flags(uint64_t pa, uint64_t iopte, uint32_t ret) "g
+ disable sun4m_iommu_translate_pa(uint64_t addr, uint64_t pa, uint32_t iopte) "xlate dva %"PRIx64" => pa %"PRIx64" iopte = %x"
+ disable sun4m_iommu_bad_addr(uint64_t addr) "bad addr %"PRIx64""
+
++# hw/usb-bus.c
++usb_port_claim(int bus, const char *port) "bus %d, port %s"
++usb_port_attach(int bus, const char *port) "bus %d, port %s"
++usb_port_detach(int bus, const char *port) "bus %d, port %s"
++usb_port_release(int bus, const char *port) "bus %d, port %s"
++
+ # hw/usb-ehci.c
+ disable usb_ehci_reset(void) "=== RESET ==="
+ disable usb_ehci_mmio_readl(uint32_t addr, const char *str, uint32_t val) "rd mmio %04x [%s] = %x"
+--
+1.5.6.5
+
Modified: pve-qemu-kvm/trunk/debian/patches/series
===================================================================
--- pve-qemu-kvm/trunk/debian/patches/series 2011-10-12 04:32:05 UTC (rev 6560)
+++ pve-qemu-kvm/trunk/debian/patches/series 2011-10-14 14:34:48 UTC (rev 6561)
@@ -8,3 +8,10 @@
use-local-linux-kvm-h.diff
fr-ca-keymap-corrections.diff
msix-eventfd-fix.patch
+0001-usb-host-reapurb-error-report-fix.patch
+0002-usb-host-fix-halted-endpoints.patch
+0003-usb-host-fix-configuration-tracking.patch
+0004-usb-host-endpoint-table-fixup.patch
+0005-usb-ehci-handle-siTDs.patch
+0006-usb-fix-use-after-free.patch
+0007-usb-claim-port-at-device-initialization-time.patch
More information about the pve-devel
mailing list