Merge remote-tracking branch 'origin/master' into f17

Conflicts:
	qemu.spec
This commit is contained in:
Hans de Goede 2012-03-12 16:37:34 +01:00
commit ed047fd061
23 changed files with 1892 additions and 1 deletions

View File

@ -0,0 +1,35 @@
From 959f57d34f11daf0da6f73541243934f39dfb2b2 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Fri, 13 Jan 2012 14:26:26 +0100
Subject: [PATCH 119/140] usb-ehci: Clear the portstatus powner bit on device
disconnect
According to the EHCI spec port ownerhsip should revert to the EHCI controller
on device disconnect. This fixes the problem of a port getting stuck on USB 1
when using redirection and plugging in a USB 2 device after a USB 1 device
has been redirected.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
hw/usb-ehci.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index a946e1d..69bcc4b 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -764,6 +764,11 @@ static void ehci_detach(USBPort *port)
USBPort *companion = s->companion_ports[port->index];
companion->ops->detach(companion);
companion->dev = NULL;
+ /*
+ * EHCI spec 4.2.2: "When a disconnect occurs... On the event,
+ * the port ownership is returned immediately to the EHCI controller."
+ */
+ *portsc &= ~PORTSC_POWNER;
return;
}
--
1.7.9.3

View File

@ -0,0 +1,263 @@
From bcc4748db3e991fbaa032fe9c0726288a8f1008d Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Thu, 12 Jan 2012 16:54:04 +0100
Subject: [PATCH 120/140] usb-redir: Add the posibility to filter out certain
devices from redirecion
This patch adds the posibility to filter out certain devices from redirecion.
To use this pass the filter property to -device usb-redir. The filter
property takes a string consisting of filter rules, the format for a rule is:
<class>:<vendor>:<product>:<version>:<allow>
-1 can be used to allow any value for a field.
Muliple rules can be concatonated using | as a separator. Note that if
a device matches none of the passed in rules, redirecting it will not be
allowed!
Example:
-device usb-redir,filter='-1:0x0781:0x5567:-1:0|0x08:-1:-1:-1:1'
This example will deny the Sandisk Cruzer Blade being redirected, as it
has a usb id of 0781:5567, it will allow any other usb mass storage devices,
and it will deny any other devices (the default for devices not matching any
of the rules.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
configure | 2 +-
usb-redir.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++++------
2 files changed, 106 insertions(+), 11 deletions(-)
diff --git a/configure b/configure
index 7ecf44e..c7e37df 100755
--- a/configure
+++ b/configure
@@ -2541,7 +2541,7 @@ fi
# check for usbredirparser for usb network redirection support
if test "$usb_redir" != "no" ; then
- if $pkg_config libusbredirparser >/dev/null 2>&1 ; then
+ if $pkg_config --atleast-version=0.3.3 libusbredirparser >/dev/null 2>&1 ; then
usb_redir="yes"
usb_redir_cflags=$($pkg_config --cflags libusbredirparser 2>/dev/null)
usb_redir_libs=$($pkg_config --libs libusbredirparser 2>/dev/null)
diff --git a/usb-redir.c b/usb-redir.c
index 6e92f14..85f40d6 100644
--- a/usb-redir.c
+++ b/usb-redir.c
@@ -34,6 +34,7 @@
#include <sys/ioctl.h>
#include <signal.h>
#include <usbredirparser.h>
+#include <usbredirfilter.h>
#include "hw/usb.h"
@@ -72,6 +73,7 @@ struct USBRedirDevice {
/* Properties */
CharDriverState *cs;
uint8_t debug;
+ char *filter_str;
/* Data passed from chardev the fd_read cb to the usbredirparser read cb */
const uint8_t *read_buf;
int read_buf_size;
@@ -84,6 +86,11 @@ struct USBRedirDevice {
struct endp_data endpoint[MAX_ENDPOINTS];
uint32_t packet_id;
QTAILQ_HEAD(, AsyncURB) asyncq;
+ /* Data for device filtering */
+ struct usb_redir_device_connect_header device_info;
+ struct usb_redir_interface_info_header interface_info;
+ struct usbredirfilter_rule *filter_rules;
+ int filter_rules_count;
};
struct AsyncURB {
@@ -790,6 +797,7 @@ static int usbredir_handle_control(USBDevice *udev, USBPacket *p,
static void usbredir_open_close_bh(void *opaque)
{
USBRedirDevice *dev = opaque;
+ uint32_t caps[USB_REDIR_CAPS_SIZE] = { 0, };
usbredir_device_disconnect(dev);
@@ -820,7 +828,9 @@ static void usbredir_open_close_bh(void *opaque)
dev->parser->interrupt_packet_func = usbredir_interrupt_packet;
dev->read_buf = NULL;
dev->read_buf_size = 0;
- usbredirparser_init(dev->parser, VERSION, NULL, 0, 0);
+
+ usbredirparser_caps_set_cap(caps, usb_redir_cap_connect_device_version);
+ usbredirparser_init(dev->parser, VERSION, caps, USB_REDIR_CAPS_SIZE, 0);
usbredirparser_do_write(dev->parser);
}
}
@@ -908,6 +918,17 @@ static int usbredir_initfn(USBDevice *udev)
return -1;
}
+ if (dev->filter_str) {
+ i = usbredirfilter_string_to_rules(dev->filter_str, ":", "|",
+ &dev->filter_rules,
+ &dev->filter_rules_count);
+ if (i) {
+ qerror_report(QERR_INVALID_PARAMETER_VALUE, "filter",
+ "a usb device filter string");
+ return -1;
+ }
+ }
+
dev->open_close_bh = qemu_bh_new(usbredir_open_close_bh, dev);
dev->attach_timer = qemu_new_timer_ms(vm_clock, usbredir_do_attach, dev);
@@ -956,6 +977,44 @@ static void usbredir_handle_destroy(USBDevice *udev)
if (dev->parser) {
usbredirparser_destroy(dev->parser);
}
+
+ free(dev->filter_rules);
+}
+
+static int usbredir_check_filter(USBRedirDevice *dev)
+{
+ if (dev->interface_info.interface_count == 0) {
+ ERROR("No interface info for device\n");
+ return -1;
+ }
+
+ if (dev->filter_rules) {
+ if (!usbredirparser_peer_has_cap(dev->parser,
+ usb_redir_cap_connect_device_version)) {
+ ERROR("Device filter specified and peer does not have the "
+ "connect_device_version capability\n");
+ return -1;
+ }
+
+ if (usbredirfilter_check(
+ dev->filter_rules,
+ dev->filter_rules_count,
+ dev->device_info.device_class,
+ dev->device_info.device_subclass,
+ dev->device_info.device_protocol,
+ dev->interface_info.interface_class,
+ dev->interface_info.interface_subclass,
+ dev->interface_info.interface_protocol,
+ dev->interface_info.interface_count,
+ dev->device_info.vendor_id,
+ dev->device_info.product_id,
+ dev->device_info.device_version_bcd,
+ 0) != 0) {
+ return -1;
+ }
+ }
+
+ return 0;
}
/*
@@ -984,6 +1043,7 @@ static void usbredir_device_connect(void *priv,
struct usb_redir_device_connect_header *device_connect)
{
USBRedirDevice *dev = priv;
+ const char *speed;
if (qemu_timer_pending(dev->attach_timer) || dev->dev.attached) {
ERROR("Received device connect while already connected\n");
@@ -992,26 +1052,48 @@ static void usbredir_device_connect(void *priv,
switch (device_connect->speed) {
case usb_redir_speed_low:
- DPRINTF("attaching low speed device\n");
+ speed = "low speed";
dev->dev.speed = USB_SPEED_LOW;
break;
case usb_redir_speed_full:
- DPRINTF("attaching full speed device\n");
+ speed = "full speed";
dev->dev.speed = USB_SPEED_FULL;
break;
case usb_redir_speed_high:
- DPRINTF("attaching high speed device\n");
+ speed = "high speed";
dev->dev.speed = USB_SPEED_HIGH;
break;
case usb_redir_speed_super:
- DPRINTF("attaching super speed device\n");
+ speed = "super speed";
dev->dev.speed = USB_SPEED_SUPER;
break;
default:
- DPRINTF("attaching unknown speed device, assuming full speed\n");
+ speed = "unknown speed";
dev->dev.speed = USB_SPEED_FULL;
}
+
+ if (usbredirparser_peer_has_cap(dev->parser,
+ usb_redir_cap_connect_device_version)) {
+ INFO("attaching %s device %04x:%04x version %d.%d class %02x\n",
+ speed, device_connect->vendor_id, device_connect->product_id,
+ device_connect->device_version_bcd >> 8,
+ device_connect->device_version_bcd & 0xff,
+ device_connect->device_class);
+ } else {
+ INFO("attaching %s device %04x:%04x class %02x\n", speed,
+ device_connect->vendor_id, device_connect->product_id,
+ device_connect->device_class);
+ }
+
dev->dev.speedmask = (1 << dev->dev.speed);
+ dev->device_info = *device_connect;
+
+ if (usbredir_check_filter(dev)) {
+ WARNING("Device %04x:%04x rejected by device filter, not attaching\n",
+ device_connect->vendor_id, device_connect->product_id);
+ return;
+ }
+
qemu_mod_timer(dev->attach_timer, dev->next_attach_time);
}
@@ -1038,15 +1120,27 @@ static void usbredir_device_disconnect(void *priv)
for (i = 0; i < MAX_ENDPOINTS; i++) {
QTAILQ_INIT(&dev->endpoint[i].bufpq);
}
+ dev->interface_info.interface_count = 0;
}
static void usbredir_interface_info(void *priv,
struct usb_redir_interface_info_header *interface_info)
{
- /* The intention is to allow specifying acceptable interface classes
- for redirection on the cmdline and in the future verify this here,
- and disconnect (or never connect) the device if a not accepted
- interface class is detected */
+ USBRedirDevice *dev = priv;
+
+ dev->interface_info = *interface_info;
+
+ /*
+ * If we receive interface info after the device has already been
+ * connected (ie on a set_config), re-check the filter.
+ */
+ if (qemu_timer_pending(dev->attach_timer) || dev->dev.attached) {
+ if (usbredir_check_filter(dev)) {
+ ERROR("Device no longer matches filter after interface info "
+ "change, disconnecting!\n");
+ usbredir_device_disconnect(dev);
+ }
+ }
}
static void usbredir_ep_info(void *priv,
@@ -1356,6 +1450,7 @@ static struct USBDeviceInfo usbredir_dev_info = {
.qdev.props = (Property[]) {
DEFINE_PROP_CHR("chardev", USBRedirDevice, cs),
DEFINE_PROP_UINT8("debug", USBRedirDevice, debug, 0),
+ DEFINE_PROP_STRING("filter", USBRedirDevice, filter_str),
DEFINE_PROP_END_OF_LIST(),
},
};
--
1.7.9.3

View File

@ -0,0 +1,33 @@
From 6c13e7b9448b10d966bb99c00c5120678ccd2a3f Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Sat, 18 Feb 2012 09:12:14 +0100
Subject: [PATCH 121/140] usb-redir: Fix printing of device version
The device version is in bcd format, which requires some special handling to
print.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
usb-redir.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/usb-redir.c b/usb-redir.c
index 85f40d6..9b804e9 100644
--- a/usb-redir.c
+++ b/usb-redir.c
@@ -1076,8 +1076,10 @@ static void usbredir_device_connect(void *priv,
usb_redir_cap_connect_device_version)) {
INFO("attaching %s device %04x:%04x version %d.%d class %02x\n",
speed, device_connect->vendor_id, device_connect->product_id,
- device_connect->device_version_bcd >> 8,
- device_connect->device_version_bcd & 0xff,
+ ((device_connect->device_version_bcd & 0xf000) >> 12) * 10 +
+ ((device_connect->device_version_bcd & 0x0f00) >> 8),
+ ((device_connect->device_version_bcd & 0x00f0) >> 4) * 10 +
+ ((device_connect->device_version_bcd & 0x000f) >> 0),
device_connect->device_class);
} else {
INFO("attaching %s device %04x:%04x class %02x\n", speed,
--
1.7.9.3

View File

@ -0,0 +1,64 @@
From 49a01afb24b925de97074d093fb072bb7de470f9 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Sat, 18 Feb 2012 09:18:57 +0100
Subject: [PATCH 122/140] usb-redir: Always clear device state on filter
reject
Always call usbredir_device_disconnect() when usbredir_check_filter() fails
to clean up all the device state (ie received endpoint info).
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
usb-redir.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/usb-redir.c b/usb-redir.c
index 9b804e9..fe3b0a3 100644
--- a/usb-redir.c
+++ b/usb-redir.c
@@ -985,7 +985,7 @@ static int usbredir_check_filter(USBRedirDevice *dev)
{
if (dev->interface_info.interface_count == 0) {
ERROR("No interface info for device\n");
- return -1;
+ goto error;
}
if (dev->filter_rules) {
@@ -993,7 +993,7 @@ static int usbredir_check_filter(USBRedirDevice *dev)
usb_redir_cap_connect_device_version)) {
ERROR("Device filter specified and peer does not have the "
"connect_device_version capability\n");
- return -1;
+ goto error;
}
if (usbredirfilter_check(
@@ -1010,11 +1010,15 @@ static int usbredir_check_filter(USBRedirDevice *dev)
dev->device_info.product_id,
dev->device_info.device_version_bcd,
0) != 0) {
- return -1;
+ goto error;
}
}
return 0;
+
+error:
+ usbredir_device_disconnect(dev);
+ return -1;
}
/*
@@ -1140,7 +1144,6 @@ static void usbredir_interface_info(void *priv,
if (usbredir_check_filter(dev)) {
ERROR("Device no longer matches filter after interface info "
"change, disconnecting!\n");
- usbredir_device_disconnect(dev);
}
}
}
--
1.7.9.3

View File

@ -0,0 +1,93 @@
From f04315d9210f22e5d7317f1cfb3c076fb93b3c08 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Sun, 19 Feb 2012 09:58:03 +0100
Subject: [PATCH 123/140] usb-redir: Let the usb-host know about our device
filtering
libusbredirparser-0.3.4 adds 2 new packets which allows us to notify
the usb-host:
-about the usb device filter we have (if any), so that it knows not the even
try to redirect certain devices
-when we reject a device based on filtering (in case it tries anyways)
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
configure | 2 +-
usb-redir.c | 20 ++++++++++++++++++++
2 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/configure b/configure
index c7e37df..a4848a4 100755
--- a/configure
+++ b/configure
@@ -2541,7 +2541,7 @@ fi
# check for usbredirparser for usb network redirection support
if test "$usb_redir" != "no" ; then
- if $pkg_config --atleast-version=0.3.3 libusbredirparser >/dev/null 2>&1 ; then
+ if $pkg_config --atleast-version=0.3.4 libusbredirparser >/dev/null 2>&1 ; then
usb_redir="yes"
usb_redir_cflags=$($pkg_config --cflags libusbredirparser 2>/dev/null)
usb_redir_libs=$($pkg_config --libs libusbredirparser 2>/dev/null)
diff --git a/usb-redir.c b/usb-redir.c
index fe3b0a3..d10d8de 100644
--- a/usb-redir.c
+++ b/usb-redir.c
@@ -106,6 +106,7 @@ struct AsyncURB {
QTAILQ_ENTRY(AsyncURB)next;
};
+static void usbredir_hello(void *priv, struct usb_redir_hello_header *h);
static void usbredir_device_connect(void *priv,
struct usb_redir_device_connect_header *device_connect);
static void usbredir_device_disconnect(void *priv);
@@ -812,6 +813,7 @@ static void usbredir_open_close_bh(void *opaque)
dev->parser->log_func = usbredir_log;
dev->parser->read_func = usbredir_read;
dev->parser->write_func = usbredir_write;
+ dev->parser->hello_func = usbredir_hello;
dev->parser->device_connect_func = usbredir_device_connect;
dev->parser->device_disconnect_func = usbredir_device_disconnect;
dev->parser->interface_info_func = usbredir_interface_info;
@@ -830,6 +832,7 @@ static void usbredir_open_close_bh(void *opaque)
dev->read_buf_size = 0;
usbredirparser_caps_set_cap(caps, usb_redir_cap_connect_device_version);
+ usbredirparser_caps_set_cap(caps, usb_redir_cap_filter);
usbredirparser_init(dev->parser, VERSION, caps, USB_REDIR_CAPS_SIZE, 0);
usbredirparser_do_write(dev->parser);
}
@@ -1018,6 +1021,10 @@ static int usbredir_check_filter(USBRedirDevice *dev)
error:
usbredir_device_disconnect(dev);
+ if (usbredirparser_peer_has_cap(dev->parser, usb_redir_cap_filter)) {
+ usbredirparser_send_filter_reject(dev->parser);
+ usbredirparser_do_write(dev->parser);
+ }
return -1;
}
@@ -1043,6 +1050,19 @@ static int usbredir_handle_status(USBRedirDevice *dev,
}
}
+static void usbredir_hello(void *priv, struct usb_redir_hello_header *h)
+{
+ USBRedirDevice *dev = priv;
+
+ /* Try to send the filter info now that we've the usb-host's caps */
+ if (usbredirparser_peer_has_cap(dev->parser, usb_redir_cap_filter) &&
+ dev->filter_rules) {
+ usbredirparser_send_filter_filter(dev->parser, dev->filter_rules,
+ dev->filter_rules_count);
+ usbredirparser_do_write(dev->parser);
+ }
+}
+
static void usbredir_device_connect(void *priv,
struct usb_redir_device_connect_header *device_connect)
{
--
1.7.9.3

View File

@ -0,0 +1,42 @@
From 91338d1b4df14f7454d1b52200d2ae4eb957fa72 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Sun, 26 Feb 2012 15:28:51 +0100
Subject: [PATCH 124/140] usb-redir: Limit return values returned by iso
packets
The usbredir protocol uses a status of usb_redir_stall to indicate that
an iso data stream has stopped (ie because the urbs failed on resubmit),
but iso packets should never return a result of USB_RET_STALL, since iso
endpoints cannot stall. So instead simply always return USB_RET_NAK on
iso stream errors.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
usb-redir.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/usb-redir.c b/usb-redir.c
index d10d8de..c76e55d 100644
--- a/usb-redir.c
+++ b/usb-redir.c
@@ -441,7 +441,7 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
/* Check iso_error for stream errors, otherwise its an underrun */
status = dev->endpoint[EP2I(ep)].iso_error;
dev->endpoint[EP2I(ep)].iso_error = 0;
- return usbredir_handle_status(dev, status, 0);
+ return status ? USB_RET_NAK : 0;
}
DPRINTF2("iso-token-in ep %02X status %d len %d queue-size: %d\n", ep,
isop->status, isop->len, dev->endpoint[EP2I(ep)].bufpq_size);
@@ -449,7 +449,7 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
status = isop->status;
if (status != usb_redir_success) {
bufp_free(dev, isop, ep);
- return usbredir_handle_status(dev, status, 0);
+ return USB_RET_NAK;
}
len = isop->len;
--
1.7.9.3

View File

@ -0,0 +1,33 @@
From ddb24b5063e3b4c90295bd4ddaab3bfc428ae79b Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Sun, 26 Feb 2012 15:51:50 +0100
Subject: [PATCH 125/140] usb-redir: Return USB_RET_NAK when we've no data for
an interrupt endpoint
We should return USB_RET_NAK, rather then a 0 sized packet, when we've no data
for an interrupt IN endpoint.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
usb-redir.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/usb-redir.c b/usb-redir.c
index c76e55d..629c87d 100644
--- a/usb-redir.c
+++ b/usb-redir.c
@@ -558,7 +558,10 @@ static int usbredir_handle_interrupt_data(USBRedirDevice *dev,
/* Check interrupt_error for stream errors */
status = dev->endpoint[EP2I(ep)].interrupt_error;
dev->endpoint[EP2I(ep)].interrupt_error = 0;
- return usbredir_handle_status(dev, status, 0);
+ if (status) {
+ return usbredir_handle_status(dev, status, 0);
+ }
+ return USB_RET_NAK;
}
DPRINTF("interrupt-token-in ep %02X status %d len %d\n", ep,
intp->status, intp->len);
--
1.7.9.3

View File

@ -0,0 +1,64 @@
From 7a3acb928b617b33605c779e7df05c2c896844b1 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Mon, 20 Feb 2012 16:27:47 +0100
Subject: [PATCH 126/140] usb-ehci: Handle ISO packets failing with an error
other then NAK
Before this patch the ehci code was not checking for any other errors other
then USB_RET_NAK. This causes 2 problems:
1) Other errors are not reported to the guest.
2) When transactions with the ITD_XACT_IOC bit set completing with another
error would not result in USBSTS_INT getting set.
I hit this problem when unplugging devices while iso data was streaming from
the device to the guest. When this happens it takes a while for the guest to
process the unplugging and remove ISO transactions from the ehci schedule, in
the mean time these transactions would complete with a result of USB_RET_NODEV,
which was not handled. This lead to the Linux guest's usb subsystem "hanging",
that is it would no longer see new usb devices getting plugged in and running
for example lsusb would lead to a stuck (D state) lsusb process. This patch
fixes this.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
hw/usb-ehci.c | 22 +++++++++++++++++++---
1 file changed, 19 insertions(+), 3 deletions(-)
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index 69bcc4b..a6b6ae5 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -1512,11 +1512,27 @@ static int ehci_process_itd(EHCIState *ehci,
/* IN */
set_field(&itd->transact[i], ret, ITD_XACT_LENGTH);
}
-
- if (itd->transact[i] & ITD_XACT_IOC) {
- ehci_record_interrupt(ehci, USBSTS_INT);
+ } else {
+ switch (ret) {
+ default:
+ fprintf(stderr, "Unexpected iso usb result: %d\n", ret);
+ /* Fall through */
+ case USB_RET_NODEV:
+ /* 3.3.2: XACTERR is only allowed on IN transactions */
+ if (dir) {
+ itd->transact[i] |= ITD_XACT_XACTERR;
+ ehci_record_interrupt(ehci, USBSTS_ERRINT);
+ }
+ break;
+ case USB_RET_BABBLE:
+ itd->transact[i] |= ITD_XACT_BABBLE;
+ ehci_record_interrupt(ehci, USBSTS_ERRINT);
+ break;
}
}
+ if (itd->transact[i] & ITD_XACT_IOC) {
+ ehci_record_interrupt(ehci, USBSTS_INT);
+ }
itd->transact[i] &= ~ITD_XACT_ACTIVE;
}
}
--
1.7.9.3

View File

@ -0,0 +1,61 @@
From 82e500c24a026323e0b8b869e227cc68b179fb11 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Mon, 27 Feb 2012 11:44:52 +0100
Subject: [PATCH 127/140] usb-ehci: Never follow table entries with the T-bit
set
Before this patch the T-bit was not checked in 2 places, while it should be.
Once we properly check the T-bit everywhere we no longer need the weird
entry < 0x1000 and entry > 0x1000 checks, so this patch removes them.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
hw/usb-ehci.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index a6b6ae5..37076a9 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -1596,8 +1596,7 @@ static int ehci_state_fetchentry(EHCIState *ehci, int async)
int again = 0;
uint32_t entry = ehci_get_fetch_addr(ehci, async);
- if (entry < 0x1000) {
- DPRINTF("fetchentry: entry invalid (0x%08x)\n", entry);
+ if (NLPTR_TBIT(entry)) {
ehci_set_state(ehci, async, EST_ACTIVE);
goto out;
}
@@ -1705,7 +1704,8 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
if (q->qh.token & QTD_TOKEN_HALT) {
ehci_set_state(ehci, async, EST_HORIZONTALQH);
- } else if ((q->qh.token & QTD_TOKEN_ACTIVE) && (q->qh.current_qtd > 0x1000)) {
+ } else if ((q->qh.token & QTD_TOKEN_ACTIVE) &&
+ (NLPTR_TBIT(q->qh.current_qtd) == 0)) {
q->qtdaddr = q->qh.current_qtd;
ehci_set_state(ehci, async, EST_FETCHQTD);
@@ -1784,7 +1784,6 @@ static int ehci_state_advqueue(EHCIQueue *q, int async)
* want data and alt-next qTD is valid
*/
if (((q->qh.token & QTD_TOKEN_TBYTES_MASK) != 0) &&
- (q->qh.altnext_qtd > 0x1000) &&
(NLPTR_TBIT(q->qh.altnext_qtd) == 0)) {
q->qtdaddr = q->qh.altnext_qtd;
ehci_set_state(q->ehci, async, EST_FETCHQTD);
@@ -1792,8 +1791,7 @@ static int ehci_state_advqueue(EHCIQueue *q, int async)
/*
* next qTD is valid
*/
- } else if ((q->qh.next_qtd > 0x1000) &&
- (NLPTR_TBIT(q->qh.next_qtd) == 0)) {
+ } else if (NLPTR_TBIT(q->qh.next_qtd) == 0) {
q->qtdaddr = q->qh.next_qtd;
ehci_set_state(q->ehci, async, EST_FETCHQTD);
--
1.7.9.3

View File

@ -0,0 +1,219 @@
From 0f1e5b8d4f36de8b6b1301740226c9858b5a0318 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Tue, 28 Feb 2012 16:34:38 +0100
Subject: [PATCH 128/140] usb-ehci: split our qh queue into async and periodic
queues
qhs can be part of both the async and the periodic schedule, as is shown
in later patches in this series it is useful to keep track of the qhs on
a per schedule basis.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
hw/usb-ehci.c | 62 ++++++++++++++++++++++++++++++++++-----------------------
1 file changed, 37 insertions(+), 25 deletions(-)
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index 37076a9..980cce3 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -347,7 +347,6 @@ enum async_state {
struct EHCIQueue {
EHCIState *ehci;
QTAILQ_ENTRY(EHCIQueue) next;
- bool async_schedule;
uint32_t seen;
uint64_t ts;
@@ -367,6 +366,8 @@ struct EHCIQueue {
int usb_status;
};
+typedef QTAILQ_HEAD(EHCIQueueHead, EHCIQueue) EHCIQueueHead;
+
struct EHCIState {
PCIDevice dev;
USBBus bus;
@@ -410,7 +411,8 @@ struct EHCIState {
USBPort ports[NB_PORTS];
USBPort *companion_ports[NB_PORTS];
uint32_t usbsts_pending;
- QTAILQ_HEAD(, EHCIQueue) queues;
+ EHCIQueueHead aqueues;
+ EHCIQueueHead pqueues;
uint32_t a_fetch_addr; // which address to look at next
uint32_t p_fetch_addr; // which address to look at next
@@ -660,31 +662,34 @@ static void ehci_trace_sitd(EHCIState *s, target_phys_addr_t addr,
static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, int async)
{
+ EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
EHCIQueue *q;
q = g_malloc0(sizeof(*q));
q->ehci = ehci;
- q->async_schedule = async;
- QTAILQ_INSERT_HEAD(&ehci->queues, q, next);
+ QTAILQ_INSERT_HEAD(head, q, next);
trace_usb_ehci_queue_action(q, "alloc");
return q;
}
-static void ehci_free_queue(EHCIQueue *q)
+static void ehci_free_queue(EHCIQueue *q, int async)
{
+ EHCIQueueHead *head = async ? &q->ehci->aqueues : &q->ehci->pqueues;
trace_usb_ehci_queue_action(q, "free");
if (q->async == EHCI_ASYNC_INFLIGHT) {
usb_cancel_packet(&q->packet);
}
- QTAILQ_REMOVE(&q->ehci->queues, q, next);
+ QTAILQ_REMOVE(head, q, next);
g_free(q);
}
-static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr)
+static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr,
+ int async)
{
+ EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
EHCIQueue *q;
- QTAILQ_FOREACH(q, &ehci->queues, next) {
+ QTAILQ_FOREACH(q, head, next) {
if (addr == q->qhaddr) {
return q;
}
@@ -692,11 +697,12 @@ static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr)
return NULL;
}
-static void ehci_queues_rip_unused(EHCIState *ehci)
+static void ehci_queues_rip_unused(EHCIState *ehci, int async)
{
+ EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
EHCIQueue *q, *tmp;
- QTAILQ_FOREACH_SAFE(q, &ehci->queues, next, tmp) {
+ QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
if (q->seen) {
q->seen = 0;
q->ts = ehci->last_run_ns;
@@ -706,28 +712,30 @@ static void ehci_queues_rip_unused(EHCIState *ehci)
/* allow 0.25 sec idle */
continue;
}
- ehci_free_queue(q);
+ ehci_free_queue(q, async);
}
}
-static void ehci_queues_rip_device(EHCIState *ehci, USBDevice *dev)
+static void ehci_queues_rip_device(EHCIState *ehci, USBDevice *dev, int async)
{
+ EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
EHCIQueue *q, *tmp;
- QTAILQ_FOREACH_SAFE(q, &ehci->queues, next, tmp) {
+ QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
if (q->packet.owner != dev) {
continue;
}
- ehci_free_queue(q);
+ ehci_free_queue(q, async);
}
}
-static void ehci_queues_rip_all(EHCIState *ehci)
+static void ehci_queues_rip_all(EHCIState *ehci, int async)
{
+ EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
EHCIQueue *q, *tmp;
- QTAILQ_FOREACH_SAFE(q, &ehci->queues, next, tmp) {
- ehci_free_queue(q);
+ QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
+ ehci_free_queue(q, async);
}
}
@@ -772,7 +780,8 @@ static void ehci_detach(USBPort *port)
return;
}
- ehci_queues_rip_device(s, port->dev);
+ ehci_queues_rip_device(s, port->dev, 0);
+ ehci_queues_rip_device(s, port->dev, 1);
*portsc &= ~(PORTSC_CONNECT|PORTSC_PED);
*portsc |= PORTSC_CSC;
@@ -792,7 +801,8 @@ static void ehci_child_detach(USBPort *port, USBDevice *child)
return;
}
- ehci_queues_rip_device(s, child);
+ ehci_queues_rip_device(s, child, 0);
+ ehci_queues_rip_device(s, child, 1);
}
static void ehci_wakeup(USBPort *port)
@@ -890,7 +900,8 @@ static void ehci_reset(void *opaque)
usb_send_msg(devs[i], USB_MSG_RESET);
}
}
- ehci_queues_rip_all(s);
+ ehci_queues_rip_all(s, 0);
+ ehci_queues_rip_all(s, 1);
}
static uint32_t ehci_mem_readb(void *ptr, target_phys_addr_t addr)
@@ -1554,7 +1565,7 @@ static int ehci_state_waitlisthead(EHCIState *ehci, int async)
ehci_set_usbsts(ehci, USBSTS_REC);
}
- ehci_queues_rip_unused(ehci);
+ ehci_queues_rip_unused(ehci, async);
/* Find the head of the list (4.9.1.1) */
for(i = 0; i < MAX_QH; i++) {
@@ -1641,7 +1652,7 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
int reload;
entry = ehci_get_fetch_addr(ehci, async);
- q = ehci_find_queue_by_qh(ehci, entry);
+ q = ehci_find_queue_by_qh(ehci, entry, async);
if (NULL == q) {
q = ehci_alloc_queue(ehci, async);
}
@@ -2092,7 +2103,7 @@ static void ehci_advance_state(EHCIState *ehci,
static void ehci_advance_async_state(EHCIState *ehci)
{
- int async = 1;
+ const int async = 1;
switch(ehci_get_state(ehci, async)) {
case EST_INACTIVE:
@@ -2149,7 +2160,7 @@ static void ehci_advance_periodic_state(EHCIState *ehci)
{
uint32_t entry;
uint32_t list;
- int async = 0;
+ const int async = 0;
// 4.6
@@ -2366,7 +2377,8 @@ static int usb_ehci_initfn(PCIDevice *dev)
}
s->frame_timer = qemu_new_timer_ns(vm_clock, ehci_frame_timer, s);
- QTAILQ_INIT(&s->queues);
+ QTAILQ_INIT(&s->aqueues);
+ QTAILQ_INIT(&s->pqueues);
qemu_register_reset(ehci_reset, s);
--
1.7.9.3

View File

@ -0,0 +1,42 @@
From 320063f7165c5a5f9ddd5a09a4663bc1a81f5bd6 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Fri, 2 Mar 2012 13:52:44 +0100
Subject: [PATCH 129/140] usb-ehci: always call ehci_queues_rip_unused for
period queues
Before this patch USB 2 devices with interrupt endpoints were not working
properly. The problem is that to avoid loops we stop processing as soon
as we encounter a queue-head (qh) we've already seen since qhs can be linked
in a circular fashion, this is tracked by the seen flag in our qh struct.
The resetting of the seen flag is done from ehci_queues_rip_unused which
before this patch was only called when executing the statemachine for the
async schedule.
But packets for interrupt endpoints are part of the periodic schedule! So what
would happen is that when there were no ctrl or bulk packets for a USB 2
device with an interrupt endpoint, the async schedule would become non
active, then ehci_queues_rip_unused would no longer get called and when
processing the qhs for the interrupt endpoints from the periodic schedule
their seen bit would still be 1 and they would be skipped.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
hw/usb-ehci.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index 980cce3..422afc8 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -2195,6 +2195,7 @@ static void ehci_advance_periodic_state(EHCIState *ehci)
ehci_set_fetch_addr(ehci, async,entry);
ehci_set_state(ehci, async, EST_FETCHENTRY);
ehci_advance_state(ehci, async);
+ ehci_queues_rip_unused(ehci, async, 0);
break;
default:
--
1.7.9.3

View File

@ -0,0 +1,115 @@
From 35562fb521547e081e732453a6395fc00d9ee9e4 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Thu, 1 Mar 2012 15:20:17 +0100
Subject: [PATCH 130/140] usb-ehci: Drop cached qhs when the doorbell gets
rung
The purpose of the IAAD bit / the doorbell is to make the ehci controller
forget about cached qhs, this is mainly used when cancelling transactions,
the qh is unlinked from the async schedule and then the doorbell gets rung,
once the doorbell is acked by the controller the hcd knows that the qh is
no longer in use and that it can do something else with the memory, such
as re-use it for a new qh! But we keep our struct representing this qh around
for circa 250 ms. This allows for a (mightily large) race window where the
following could happen:
-hcd submits a qh at address 0xdeadbeef
-our ehci code sees the qh, sends a request to a usb-device, gets a result
of USB_RET_ASYNC, sets the async_state of the qh to EHCI_ASYNC_INFLIGHT
-hcd unlinks the qh at address 0xdeadbeef
-hcd rings the doorbell, wait for us to ack it
-hcd re-uses the qh at address 0xdeadbeef
-our ehci code sees the qh, looks in the async_queue, sees there already is
a qh at address 0xdeadbeef there with async_state of EHCI_ASYNC_INFLIGHT,
does nothing
-the *original* (which the hcd thinks it has cancelled) transaction finishes
-our ehci code sees the qh on yet another pass through the async list,
looks in the async_queue, sees there already is a qh at address 0xdeadbeef
there with async_state of EHCI_ASYNC_COMPLETED, and finished the transaction
with the results of the *original* transaction.
Not good (tm), this patch fixes this race by removing all qhs which have not
been seen during the last cycle through the async list immidiately when the
doorbell is rung.
Note this patch does not fix any actually observed problem, but upon
reading of the EHCI spec it became apparent to me that the above race could
happen and the usb-ehci behavior from before this patch is not good.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
hw/usb-ehci.c | 31 ++++++++++++++++---------------
1 file changed, 16 insertions(+), 15 deletions(-)
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index 422afc8..b8ba483 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -697,7 +697,7 @@ static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr,
return NULL;
}
-static void ehci_queues_rip_unused(EHCIState *ehci, int async)
+static void ehci_queues_rip_unused(EHCIState *ehci, int async, int flush)
{
EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
EHCIQueue *q, *tmp;
@@ -708,7 +708,7 @@ static void ehci_queues_rip_unused(EHCIState *ehci, int async)
q->ts = ehci->last_run_ns;
continue;
}
- if (ehci->last_run_ns < q->ts + 250000000) {
+ if (!flush && ehci->last_run_ns < q->ts + 250000000) {
/* allow 0.25 sec idle */
continue;
}
@@ -1565,7 +1565,7 @@ static int ehci_state_waitlisthead(EHCIState *ehci, int async)
ehci_set_usbsts(ehci, USBSTS_REC);
}
- ehci_queues_rip_unused(ehci, async);
+ ehci_queues_rip_unused(ehci, async, 0);
/* Find the head of the list (4.9.1.1) */
for(i = 0; i < MAX_QH; i++) {
@@ -2121,18 +2121,7 @@ static void ehci_advance_async_state(EHCIState *ehci)
break;
}
- /* If the doorbell is set, the guest wants to make a change to the
- * schedule. The host controller needs to release cached data.
- * (section 4.8.2)
- */
- if (ehci->usbcmd & USBCMD_IAAD) {
- DPRINTF("ASYNC: doorbell request acknowledged\n");
- ehci->usbcmd &= ~USBCMD_IAAD;
- ehci_set_interrupt(ehci, USBSTS_IAA);
- break;
- }
-
- /* make sure guest has acknowledged */
+ /* make sure guest has acknowledged the doorbell interrupt */
/* TO-DO: is this really needed? */
if (ehci->usbsts & USBSTS_IAA) {
DPRINTF("IAA status bit still set.\n");
@@ -2146,6 +2135,18 @@ static void ehci_advance_async_state(EHCIState *ehci)
ehci_set_state(ehci, async, EST_WAITLISTHEAD);
ehci_advance_state(ehci, async);
+
+ /* If the doorbell is set, the guest wants to make a change to the
+ * schedule. The host controller needs to release cached data.
+ * (section 4.8.2)
+ */
+ if (ehci->usbcmd & USBCMD_IAAD) {
+ /* Remove all unseen qhs from the async qhs queue */
+ ehci_queues_rip_unused(ehci, async, 1);
+ DPRINTF("ASYNC: doorbell request acknowledged\n");
+ ehci->usbcmd &= ~USBCMD_IAAD;
+ ehci_set_interrupt(ehci, USBSTS_IAA);
+ }
break;
default:
--
1.7.9.3

View File

@ -0,0 +1,44 @@
From cbb6384d32c4926822ba9216992253deef9ef3b5 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Fri, 2 Mar 2012 11:02:04 +0100
Subject: [PATCH 131/140] usb-ehci: Rip the queues when the async or period
schedule is halted
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
hw/usb-ehci.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index b8ba483..11eded7 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -1054,7 +1054,8 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
if (!(val & USBCMD_RUNSTOP) && (s->usbcmd & USBCMD_RUNSTOP)) {
qemu_del_timer(s->frame_timer);
- // TODO - should finish out some stuff before setting halt
+ ehci_queues_rip_all(s, 0);
+ ehci_queues_rip_all(s, 1);
ehci_set_usbsts(s, USBSTS_HALT);
}
@@ -2116,6 +2117,7 @@ static void ehci_advance_async_state(EHCIState *ehci)
case EST_ACTIVE:
if ( !(ehci->usbcmd & USBCMD_ASE)) {
+ ehci_queues_rip_all(ehci, async);
ehci_clear_usbsts(ehci, USBSTS_ASS);
ehci_set_state(ehci, async, EST_INACTIVE);
break;
@@ -2176,6 +2178,7 @@ static void ehci_advance_periodic_state(EHCIState *ehci)
case EST_ACTIVE:
if ( !(ehci->frindex & 7) && !(ehci->usbcmd & USBCMD_PSE)) {
+ ehci_queues_rip_all(ehci, async);
ehci_clear_usbsts(ehci, USBSTS_PSS);
ehci_set_state(ehci, async, EST_INACTIVE);
break;
--
1.7.9.3

View File

@ -0,0 +1,33 @@
From 73a9969c47459ee208d6247999823f2a36ee51fe Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Thu, 1 Mar 2012 16:34:56 +0100
Subject: [PATCH 132/140] usb-ehci: Any packet completion except for NAK
should set the interrupt
As clearly stated in the 2.3.2 of the EHCI spec, any time USBERRINT get
sets then if the td has its IOC bit set USBINT should be set as well.
This means that for any status except for USB_RET_NAK we should set
USBINT if the IOC bit is set.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
hw/usb-ehci.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index 11eded7..bc5f591 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -1338,7 +1338,7 @@ err:
q->qh.token ^= QTD_TOKEN_DTOGGLE;
q->qh.token &= ~QTD_TOKEN_ACTIVE;
- if ((q->usb_status >= 0) && (q->qh.token & QTD_TOKEN_IOC)) {
+ if ((q->usb_status != USB_RET_NAK) && (q->qh.token & QTD_TOKEN_IOC)) {
ehci_record_interrupt(q->ehci, USBSTS_INT);
}
}
--
1.7.9.3

View File

@ -0,0 +1,72 @@
From 6e6bfa88ae3867afd8258b43e3c05cba2585ee37 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Thu, 1 Mar 2012 21:43:56 +0100
Subject: [PATCH 133/140] usb-ehci: Fix cerr tracking
cerr should only be decremented on errors which cause XactErr to be set, and
when that happens the failing transaction should be retried until cerr reaches
0 and only then should USBSTS_ERRINT be set (and inactive cleared and
USBSTS_INT set if requested).
Since we don't have any hardware level errors (and in case of redirection
the real hardware has already retried), re-trying makes no sense, so
immediately set cerr to 0 on errors which set XactErr.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
hw/usb-ehci.c | 19 ++++++-------------
1 file changed, 6 insertions(+), 13 deletions(-)
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index bc5f591..a3d5c11 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -1269,7 +1269,7 @@ static void ehci_async_complete_packet(USBPort *port, USBPacket *packet)
static void ehci_execute_complete(EHCIQueue *q)
{
- int c_err, reload;
+ int reload;
assert(q->async != EHCI_ASYNC_INFLIGHT);
q->async = EHCI_ASYNC_NONE;
@@ -1278,15 +1278,10 @@ static void ehci_execute_complete(EHCIQueue *q)
q->qhaddr, q->qh.next, q->qtdaddr, q->usb_status);
if (q->usb_status < 0) {
-err:
- /* TO-DO: put this is in a function that can be invoked below as well */
- c_err = get_field(q->qh.token, QTD_TOKEN_CERR);
- c_err--;
- set_field(&q->qh.token, c_err, QTD_TOKEN_CERR);
-
switch(q->usb_status) {
case USB_RET_NODEV:
q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_XACTERR);
+ set_field(&q->qh.token, 0, QTD_TOKEN_CERR);
ehci_record_interrupt(q->ehci, USBSTS_ERRINT);
break;
case USB_RET_STALL:
@@ -1314,15 +1309,13 @@ err:
assert(0);
break;
}
+ } else if ((q->usb_status > q->tbytes) && (q->pid == USB_TOKEN_IN)) {
+ q->usb_status = USB_RET_BABBLE;
+ q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_BABBLE);
+ ehci_record_interrupt(q->ehci, USBSTS_ERRINT);
} else {
- // DPRINTF("Short packet condition\n");
// TODO check 4.12 for splits
- if ((q->usb_status > q->tbytes) && (q->pid == USB_TOKEN_IN)) {
- q->usb_status = USB_RET_BABBLE;
- goto err;
- }
-
if (q->tbytes && q->pid == USB_TOKEN_IN) {
q->tbytes -= q->usb_status;
} else {
--
1.7.9.3

View File

@ -0,0 +1,78 @@
From 6177c3610b6416a7200ae6c6985f01fccdbdc7e5 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Thu, 1 Mar 2012 23:11:13 +0100
Subject: [PATCH 134/140] usb-ehci: Remove dead nakcnt code
This patch removes 2 bits of dead nakcnt code:
1) usb_ehci_execute calls ehci_qh_do_overlay which does:
nakcnt = reload;
and then has a block of code which is conditional on:
if (reload && !nakcnt) {
which ofcourse is never true now as nakcnt == reload.
2) ehci_state_fetchqh does:
nakcnt = reload;
but before nakcnt is ever used ehci_state_fetchqh is always followed
by a ehci_qh_do_overlay call which also does:
nakcnt = reload;
So doing this from ehci_state_fetchqh is redundant.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
hw/usb-ehci.c | 20 --------------------
1 file changed, 20 deletions(-)
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index a3d5c11..92cdf2a 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -1643,7 +1643,6 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
{
uint32_t entry;
EHCIQueue *q;
- int reload;
entry = ehci_get_fetch_addr(ehci, async);
q = ehci_find_queue_by_qh(ehci, entry, async);
@@ -1701,11 +1700,6 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
}
#endif
- reload = get_field(q->qh.epchar, QH_EPCHAR_RL);
- if (reload) {
- set_field(&q->qh.altnext_qtd, reload, QH_ALTNEXT_NAKCNT);
- }
-
if (q->qh.token & QTD_TOKEN_HALT) {
ehci_set_state(ehci, async, EST_HORIZONTALQH);
@@ -1865,25 +1859,11 @@ static void ehci_flush_qh(EHCIQueue *q)
static int ehci_state_execute(EHCIQueue *q, int async)
{
int again = 0;
- int reload, nakcnt;
- int smask;
if (ehci_qh_do_overlay(q) != 0) {
return -1;
}
- smask = get_field(q->qh.epcap, QH_EPCAP_SMASK);
-
- if (!smask) {
- reload = get_field(q->qh.epchar, QH_EPCHAR_RL);
- nakcnt = get_field(q->qh.altnext_qtd, QH_ALTNEXT_NAKCNT);
- if (reload && !nakcnt) {
- ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
- again = 1;
- goto out;
- }
- }
-
// TODO verify enough time remains in the uframe as in 4.4.1.1
// TODO write back ptr to async list when done or out of time
// TODO Windows does not seem to ever set the MULT field
--
1.7.9.3

View File

@ -0,0 +1,120 @@
From 2d9b6cb9bd00ede47635dc4db413f647143d5a1d Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Thu, 1 Mar 2012 23:55:11 +0100
Subject: [PATCH 135/140] usb-ehci: Fix and simplify nakcnt handling
The nakcnt code in ehci_execute_complete() marked transactions as finished
when a packet completed with a result of USB_RET_NAK, but USB_RET_NAK
means that the device cannot receive / send data at that time and that
the transaction should be retried later, which is also what the usb-uhci
and usb-ohci code does.
Note that there already was some special code in place to handle this
for interrupt endpoints in the form of doing a return from
ehci_execute_complete() when reload == 0, but that for bulk transactions
this was not handled correctly (where as for example the usb-ccid device does
return USB_RET_NAK for bulk packets).
Besides that the code in ehci_execute_complete() decrement nakcnt by 1
on a packet result of USB_RET_NAK, but
-since the transaction got marked as finished,
nakcnt would never be decremented again
-there is no code checking for nakcnt becoming 0
-there is no use in re-trying the transaction within the same usb frame /
usb-ehci frame-timer call, since the status of emulated devices won't change
as long as the usb-ehci frame-timer is running
So we should simply set the nakcnt to 0 when we get a USB_RET_NAK, thus
claiming that we've tried reload times (or as many times as possible if
reload is 0).
Besides the code in ehci_execute_complete() handling USB_RET_NAK there
was also code handling it in ehci_state_executing(), which calls
ehci_execute_complete(), and then does its own handling on top of the handling
in ehci_execute_complete(), this code would decrement nakcnt *again* (if not
already 0), or restore the reload value (which was never changed) on success.
Since the double decrement was wrong to begin with, and is no longer needed
now that we set nakcnt directly to 0 on USB_RET_NAK, and the restore of reload
is not needed either, this patch simply removes all nakcnt handling from
ehci_state_executing().
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
hw/usb-ehci.c | 32 ++++----------------------------
1 file changed, 4 insertions(+), 28 deletions(-)
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index 92cdf2a..aa6fae5 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -1269,8 +1269,6 @@ static void ehci_async_complete_packet(USBPort *port, USBPacket *packet)
static void ehci_execute_complete(EHCIQueue *q)
{
- int reload;
-
assert(q->async != EHCI_ASYNC_INFLIGHT);
q->async = EHCI_ASYNC_NONE;
@@ -1289,16 +1287,8 @@ static void ehci_execute_complete(EHCIQueue *q)
ehci_record_interrupt(q->ehci, USBSTS_ERRINT);
break;
case USB_RET_NAK:
- /* 4.10.3 */
- reload = get_field(q->qh.epchar, QH_EPCHAR_RL);
- if ((q->pid == USB_TOKEN_IN) && reload) {
- int nakcnt = get_field(q->qh.altnext_qtd, QH_ALTNEXT_NAKCNT);
- nakcnt--;
- set_field(&q->qh.altnext_qtd, nakcnt, QH_ALTNEXT_NAKCNT);
- } else if (!reload) {
- return;
- }
- break;
+ set_field(&q->qh.altnext_qtd, 0, QH_ALTNEXT_NAKCNT);
+ return; /* We're not done yet with this transaction */
case USB_RET_BABBLE:
q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_BABBLE);
ehci_record_interrupt(q->ehci, USBSTS_ERRINT);
@@ -1331,7 +1321,7 @@ static void ehci_execute_complete(EHCIQueue *q)
q->qh.token ^= QTD_TOKEN_DTOGGLE;
q->qh.token &= ~QTD_TOKEN_ACTIVE;
- if ((q->usb_status != USB_RET_NAK) && (q->qh.token & QTD_TOKEN_IOC)) {
+ if (q->qh.token & QTD_TOKEN_IOC) {
ehci_record_interrupt(q->ehci, USBSTS_INT);
}
}
@@ -1905,7 +1895,6 @@ out:
static int ehci_state_executing(EHCIQueue *q, int async)
{
int again = 0;
- int reload, nakcnt;
ehci_execute_complete(q);
if (q->usb_status == USB_RET_ASYNC) {
@@ -1925,21 +1914,8 @@ static int ehci_state_executing(EHCIQueue *q, int async)
// counter decrements to 0
}
- reload = get_field(q->qh.epchar, QH_EPCHAR_RL);
- if (reload) {
- nakcnt = get_field(q->qh.altnext_qtd, QH_ALTNEXT_NAKCNT);
- if (q->usb_status == USB_RET_NAK) {
- if (nakcnt) {
- nakcnt--;
- }
- } else {
- nakcnt = reload;
- }
- set_field(&q->qh.altnext_qtd, nakcnt, QH_ALTNEXT_NAKCNT);
- }
-
/* 4.10.5 */
- if ((q->usb_status == USB_RET_NAK) || (q->qh.token & QTD_TOKEN_ACTIVE)) {
+ if (q->usb_status == USB_RET_NAK) {
ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
} else {
ehci_set_state(q->ehci, async, EST_WRITEBACK);
--
1.7.9.3

View File

@ -0,0 +1,114 @@
From 0e6cd6e6da3d0648204526e8ebd79047f48d009a Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Fri, 2 Mar 2012 00:36:50 +0100
Subject: [PATCH 136/140] usb-ehci: Remove dead isoch_pause code
I see no value in keeping this around, so lets delete it.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
hw/usb-ehci.c | 60 +++++++++++++++------------------------------------------
1 file changed, 15 insertions(+), 45 deletions(-)
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index aa6fae5..72c3f2a 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -419,7 +419,6 @@ struct EHCIState {
USBPacket ipacket;
QEMUSGList isgl;
- int isoch_pause;
uint64_t last_run_ns;
};
@@ -886,7 +885,6 @@ static void ehci_reset(void *opaque)
s->astate = EST_INACTIVE;
s->pstate = EST_INACTIVE;
- s->isoch_pause = -1;
s->attach_poll_counter = 0;
for(i = 0; i < NB_PORTS; i++) {
@@ -1468,46 +1466,7 @@ static int ehci_process_itd(EHCIState *ehci,
usb_packet_unmap(&ehci->ipacket);
qemu_sglist_destroy(&ehci->isgl);
-#if 0
- /* In isoch, there is no facility to indicate a NAK so let's
- * instead just complete a zero-byte transaction. Setting
- * DBERR seems too draconian.
- */
-
- if (ret == USB_RET_NAK) {
- if (ehci->isoch_pause > 0) {
- DPRINTF("ISOCH: received a NAK but paused so returning\n");
- ehci->isoch_pause--;
- return 0;
- } else if (ehci->isoch_pause == -1) {
- DPRINTF("ISOCH: recv NAK & isoch pause inactive, setting\n");
- // Pause frindex for up to 50 msec waiting for data from
- // remote
- ehci->isoch_pause = 50;
- return 0;
- } else {
- DPRINTF("ISOCH: isoch pause timeout! return 0\n");
- ret = 0;
- }
- } else {
- DPRINTF("ISOCH: received ACK, clearing pause\n");
- ehci->isoch_pause = -1;
- }
-#else
- if (ret == USB_RET_NAK) {
- ret = 0;
- }
-#endif
-
- if (ret >= 0) {
- if (!dir) {
- /* OUT */
- set_field(&itd->transact[i], len - ret, ITD_XACT_LENGTH);
- } else {
- /* IN */
- set_field(&itd->transact[i], ret, ITD_XACT_LENGTH);
- }
- } else {
+ if (ret < 0) {
switch (ret) {
default:
fprintf(stderr, "Unexpected iso usb result: %d\n", ret);
@@ -1523,6 +1482,19 @@ static int ehci_process_itd(EHCIState *ehci,
itd->transact[i] |= ITD_XACT_BABBLE;
ehci_record_interrupt(ehci, USBSTS_ERRINT);
break;
+ case USB_RET_NAK:
+ /* no data for us, so do a zero-length transfer */
+ ret = 0;
+ break;
+ }
+ }
+ if (ret >= 0) {
+ if (!dir) {
+ /* OUT */
+ set_field(&itd->transact[i], len - ret, ITD_XACT_LENGTH);
+ } else {
+ /* IN */
+ set_field(&itd->transact[i], ret, ITD_XACT_LENGTH);
}
}
if (itd->transact[i] & ITD_XACT_IOC) {
@@ -2176,9 +2148,7 @@ static void ehci_frame_timer(void *opaque)
for (i = 0; i < frames; i++) {
if ( !(ehci->usbsts & USBSTS_HALT)) {
- if (ehci->isoch_pause <= 0) {
- ehci->frindex += 8;
- }
+ ehci->frindex += 8;
if (ehci->frindex > 0x00001fff) {
ehci->frindex = 0;
--
1.7.9.3

View File

@ -0,0 +1,70 @@
From 9726556968aef62213b80bd4e351a4f7f721f941 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Thu, 1 Mar 2012 17:22:14 +0100
Subject: [PATCH 137/140] usb: return BABBLE rather then NAK when we receive
too much data
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
usb-linux.c | 8 +++++++-
usb-redir.c | 4 ++--
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/usb-linux.c b/usb-linux.c
index ab4c693..b2d70f9 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -390,6 +390,10 @@ static void async_complete(void *opaque)
p->result = USB_RET_STALL;
break;
+ case -EOVERFLOW:
+ p->result = USB_RET_BABBLE;
+ break;
+
default:
p->result = USB_RET_NAK;
break;
@@ -718,6 +722,8 @@ static int urb_status_to_usb_ret(int status)
switch (status) {
case -EPIPE:
return USB_RET_STALL;
+ case -EOVERFLOW:
+ return USB_RET_BABBLE;
default:
return USB_RET_NAK;
}
@@ -755,7 +761,7 @@ static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
} else if (aurb[i].urb.iso_frame_desc[j].actual_length
> p->iov.size) {
printf("husb: received iso data is larger then packet\n");
- len = USB_RET_NAK;
+ len = USB_RET_BABBLE;
/* All good copy data over */
} else {
len = aurb[i].urb.iso_frame_desc[j].actual_length;
diff --git a/usb-redir.c b/usb-redir.c
index 629c87d..61860ef 100644
--- a/usb-redir.c
+++ b/usb-redir.c
@@ -457,7 +457,7 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
ERROR("received iso data is larger then packet ep %02X (%d > %d)\n",
ep, len, (int)p->iov.size);
bufp_free(dev, isop, ep);
- return USB_RET_NAK;
+ return USB_RET_BABBLE;
}
usb_packet_copy(p, isop->data, len);
bufp_free(dev, isop, ep);
@@ -576,7 +576,7 @@ static int usbredir_handle_interrupt_data(USBRedirDevice *dev,
if (len > p->iov.size) {
ERROR("received int data is larger then packet ep %02X\n", ep);
bufp_free(dev, intp, ep);
- return USB_RET_NAK;
+ return USB_RET_BABBLE;
}
usb_packet_copy(p, intp->data, len);
bufp_free(dev, intp, ep);
--
1.7.9.3

View File

@ -0,0 +1,167 @@
From 2a6bbdddc2aca6af038c42054c3d3a7b09e5ac3a Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Fri, 2 Mar 2012 00:26:23 +0100
Subject: [PATCH 138/140] usb: add USB_RET_IOERROR
We already have USB_RET_NAK, but that means that a device does not want
to send/receive right now. But with host / network redirection we can
actually have a transaction fail due to some io error, rather then ie
the device just not having any data atm.
This patch adds a new error code named USB_RET_IOERROR for this, and uses
it were appropriate.
Notes:
-Currently all usb-controllers handle this the same as NODEV, but that
may change in the future, OHCI could indicate a CRC error instead for example.
-This patch does not touch hw/usb-musb.c, that is because the code in there
handles STALL and NAK specially and has a if status < 0 generic catch all
for all other errors
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
hw/usb-ehci.c | 2 ++
hw/usb-ohci.c | 2 ++
hw/usb-uhci.c | 1 +
hw/usb.h | 11 ++++++-----
usb-linux.c | 4 ++--
usb-redir.c | 9 ++++++---
6 files changed, 19 insertions(+), 10 deletions(-)
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index 72c3f2a..ba1b9da 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -1275,6 +1275,7 @@ static void ehci_execute_complete(EHCIQueue *q)
if (q->usb_status < 0) {
switch(q->usb_status) {
+ case USB_RET_IOERROR:
case USB_RET_NODEV:
q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_XACTERR);
set_field(&q->qh.token, 0, QTD_TOKEN_CERR);
@@ -1471,6 +1472,7 @@ static int ehci_process_itd(EHCIState *ehci,
default:
fprintf(stderr, "Unexpected iso usb result: %d\n", ret);
/* Fall through */
+ case USB_RET_IOERROR:
case USB_RET_NODEV:
/* 3.3.2: XACTERR is only allowed on IN transactions */
if (dir) {
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index c2981c5..d805497 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -828,6 +828,7 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
OHCI_CC_DATAUNDERRUN);
} else {
switch (ret) {
+ case USB_RET_IOERROR:
case USB_RET_NODEV:
OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
OHCI_CC_DEVICENOTRESPONDING);
@@ -1051,6 +1052,7 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DATAUNDERRUN);
} else {
switch (ret) {
+ case USB_RET_IOERROR:
case USB_RET_NODEV:
OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DEVICENOTRESPONDING);
case USB_RET_NAK:
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index f9e3ea5..a994943 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -751,6 +751,7 @@ out:
break;
return 1;
+ case USB_RET_IOERROR:
case USB_RET_NODEV:
default:
break;
diff --git a/hw/usb.h b/hw/usb.h
index c6e1870..4010e12 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -41,11 +41,12 @@
#define USB_MSG_DETACH 0x101
#define USB_MSG_RESET 0x102
-#define USB_RET_NODEV (-1)
-#define USB_RET_NAK (-2)
-#define USB_RET_STALL (-3)
-#define USB_RET_BABBLE (-4)
-#define USB_RET_ASYNC (-5)
+#define USB_RET_NODEV (-1)
+#define USB_RET_NAK (-2)
+#define USB_RET_STALL (-3)
+#define USB_RET_BABBLE (-4)
+#define USB_RET_IOERROR (-5)
+#define USB_RET_ASYNC (-6)
#define USB_SPEED_LOW 0
#define USB_SPEED_FULL 1
diff --git a/usb-linux.c b/usb-linux.c
index b2d70f9..9f13d1e 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -395,7 +395,7 @@ static void async_complete(void *opaque)
break;
default:
- p->result = USB_RET_NAK;
+ p->result = USB_RET_IOERROR;
break;
}
@@ -725,7 +725,7 @@ static int urb_status_to_usb_ret(int status)
case -EOVERFLOW:
return USB_RET_BABBLE;
default:
- return USB_RET_NAK;
+ return USB_RET_IOERROR;
}
}
diff --git a/usb-redir.c b/usb-redir.c
index 61860ef..f64443e 100644
--- a/usb-redir.c
+++ b/usb-redir.c
@@ -441,7 +441,7 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
/* Check iso_error for stream errors, otherwise its an underrun */
status = dev->endpoint[EP2I(ep)].iso_error;
dev->endpoint[EP2I(ep)].iso_error = 0;
- return status ? USB_RET_NAK : 0;
+ return status ? USB_RET_IOERROR : 0;
}
DPRINTF2("iso-token-in ep %02X status %d len %d queue-size: %d\n", ep,
isop->status, isop->len, dev->endpoint[EP2I(ep)].bufpq_size);
@@ -449,7 +449,7 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
status = isop->status;
if (status != usb_redir_success) {
bufp_free(dev, isop, ep);
- return USB_RET_NAK;
+ return USB_RET_IOERROR;
}
len = isop->len;
@@ -1045,11 +1045,14 @@ static int usbredir_handle_status(USBRedirDevice *dev,
return USB_RET_STALL;
case usb_redir_cancelled:
WARNING("returning cancelled packet to HC?\n");
+ return USB_RET_NAK;
case usb_redir_inval:
+ WARNING("got invalid param error from usb-host?\n");
+ return USB_RET_NAK;
case usb_redir_ioerror:
case usb_redir_timeout:
default:
- return USB_RET_NAK;
+ return USB_RET_IOERROR;
}
}
--
1.7.9.3

View File

@ -0,0 +1,40 @@
From 21946e621f14553b72cde7fae221ae390a427eac Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Thu, 23 Feb 2012 13:24:00 +0000
Subject: [PATCH 139/140] usb-ehci: fix reset
Two reset fixes:
* pick up s->usbcmd value after ehci_reset call to make sure it
keeps the reset value and doesn't get rubbish filled in when
val is written back to the mmio register array later on.
* make sure the frame timer is zapped on reset.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb-ehci.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index ba1b9da..ad0f6e1 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -900,6 +900,7 @@ static void ehci_reset(void *opaque)
}
ehci_queues_rip_all(s, 0);
ehci_queues_rip_all(s, 1);
+ qemu_del_timer(s->frame_timer);
}
static uint32_t ehci_mem_readb(void *ptr, target_phys_addr_t addr)
@@ -1059,7 +1060,7 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
if (val & USBCMD_HCRESET) {
ehci_reset(s);
- val &= ~USBCMD_HCRESET;
+ val = s->usbcmd;
}
/* not supporting dynamic frame list size at the moment */
--
1.7.9.3

View File

@ -0,0 +1,42 @@
From 985b7cfbd45960bb74a13ad8044765a8e35f2251 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Sun, 4 Mar 2012 12:41:11 +0100
Subject: [PATCH 140/140] usb-ehci: sanity-check iso xfers
This patch adds a sanity check to itd processing to make sure the
endpoint addressed by the guest is actually an iso endpoint. Also
verify that usb drivers don't return USB_RET_ASYNC which is illegal for
iso xfers.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(Cherry picked from: aa0568ff2559d7717f4684af6a83d0bd1a125f56)
[qemu-kvm-1.0: we don't track ep types on RHEL-6 like we do upstream, so we
cannot check if an itd is pointing to a non iso ep in advance, but we do still
need to make sure that we never handle an iso xfer async. So check if the
device does want to handle it async, and if so cancel the xfer and treat it as
a NAK, like upstream does when the ep type check fails.]
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
hw/usb-ehci.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index ad0f6e1..b5d7037 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -1485,6 +1485,10 @@ static int ehci_process_itd(EHCIState *ehci,
itd->transact[i] |= ITD_XACT_BABBLE;
ehci_record_interrupt(ehci, USBSTS_ERRINT);
break;
+ case USB_RET_ASYNC:
+ /* ISO endpoints are never ASYNC, not an iso endpoint? */
+ usb_cancel_packet(&ehci->ipacket);
+ /* Treat this as a NAK (fall through) */
case USB_RET_NAK:
/* no data for us, so do a zero-length transfer */
ret = 0;
--
1.7.9.3

View File

@ -1,7 +1,7 @@
Summary: QEMU is a FAST! processor emulator
Name: qemu
Version: 1.0
Release: 6%{?dist}
Release: 7%{?dist}
# Epoch because we pushed a qemu-1.0 package
Epoch: 2
License: GPLv2+ and LGPLv2+ and BSD
@ -86,6 +86,28 @@ Patch115: 0115-spice-qemu-char.c-remove-intermediate-buffer.patch
Patch116: 0116-usb-redir-Add-flow-control-support.patch
Patch117: 0117-virtio-serial-bus-replay-guest_open-on-migration.patch
Patch118: 0118-char-Disable-write-callback-if-throttled-chardev-is-.patch
Patch119: 0119-usb-ehci-Clear-the-portstatus-powner-bit-on-device-d.patch
Patch120: 0120-usb-redir-Add-the-posibility-to-filter-out-certain-d.patch
Patch121: 0121-usb-redir-Fix-printing-of-device-version.patch
Patch122: 0122-usb-redir-Always-clear-device-state-on-filter-reject.patch
Patch123: 0123-usb-redir-Let-the-usb-host-know-about-our-device-fil.patch
Patch124: 0124-usb-redir-Limit-return-values-returned-by-iso-packet.patch
Patch125: 0125-usb-redir-Return-USB_RET_NAK-when-we-ve-no-data-for-.patch
Patch126: 0126-usb-ehci-Handle-ISO-packets-failing-with-an-error-ot.patch
Patch127: 0127-usb-ehci-Never-follow-table-entries-with-the-T-bit-s.patch
Patch128: 0128-usb-ehci-split-our-qh-queue-into-async-and-periodic-.patch
Patch129: 0129-usb-ehci-always-call-ehci_queues_rip_unused-for-peri.patch
Patch130: 0130-usb-ehci-Drop-cached-qhs-when-the-doorbell-gets-rung.patch
Patch131: 0131-usb-ehci-Rip-the-queues-when-the-async-or-period-sch.patch
Patch132: 0132-usb-ehci-Any-packet-completion-except-for-NAK-should.patch
Patch133: 0133-usb-ehci-Fix-cerr-tracking.patch
Patch134: 0134-usb-ehci-Remove-dead-nakcnt-code.patch
Patch135: 0135-usb-ehci-Fix-and-simplify-nakcnt-handling.patch
Patch136: 0136-usb-ehci-Remove-dead-isoch_pause-code.patch
Patch137: 0137-usb-return-BABBLE-rather-then-NAK-when-we-receive-to.patch
Patch138: 0138-usb-add-USB_RET_IOERROR.patch
Patch139: 0139-usb-ehci-fix-reset.patch
Patch140: 0140-usb-ehci-sanity-check-iso-xfers.patch
# General bug fixes
Patch201: Fix_save-restore_of_in-kernel_i8259.patch
@ -382,6 +404,28 @@ such as kvm_stat.
%patch116 -p1
%patch117 -p1
%patch118 -p1
%patch119 -p1
%patch120 -p1
%patch121 -p1
%patch122 -p1
%patch123 -p1
%patch124 -p1
%patch125 -p1
%patch126 -p1
%patch127 -p1
%patch128 -p1
%patch129 -p1
%patch130 -p1
%patch131 -p1
%patch132 -p1
%patch133 -p1
%patch134 -p1
%patch135 -p1
%patch136 -p1
%patch137 -p1
%patch138 -p1
%patch139 -p1
%patch140 -p1
%patch201 -p1
@ -768,6 +812,9 @@ fi
%{_mandir}/man1/qemu-img.1*
%changelog
* Fri Mar 9 2012 Hans de Goede <hdegoede@redhat.com> - 2:1.0-7
- Add a whole bunch of USB bugfixes from upstream
* Mon Feb 13 2012 Daniel P. Berrange <berrange@redhat.com> - 2:1.0-6
- Add many more missing BRs for misc QEMU features
- Enable running of test suite during build