Add a whole bunch of USB bugfixes from upstream
This commit is contained in:
parent
eaebe4482c
commit
1b1995dd67
@ -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
|
||||
|
263
0120-usb-redir-Add-the-posibility-to-filter-out-certain-d.patch
Normal file
263
0120-usb-redir-Add-the-posibility-to-filter-out-certain-d.patch
Normal 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
|
||||
|
33
0121-usb-redir-Fix-printing-of-device-version.patch
Normal file
33
0121-usb-redir-Fix-printing-of-device-version.patch
Normal 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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
219
0128-usb-ehci-split-our-qh-queue-into-async-and-periodic-.patch
Normal file
219
0128-usb-ehci-split-our-qh-queue-into-async-and-periodic-.patch
Normal 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
|
||||
|
@ -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
|
||||
|
115
0130-usb-ehci-Drop-cached-qhs-when-the-doorbell-gets-rung.patch
Normal file
115
0130-usb-ehci-Drop-cached-qhs-when-the-doorbell-gets-rung.patch
Normal 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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
72
0133-usb-ehci-Fix-cerr-tracking.patch
Normal file
72
0133-usb-ehci-Fix-cerr-tracking.patch
Normal 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
|
||||
|
78
0134-usb-ehci-Remove-dead-nakcnt-code.patch
Normal file
78
0134-usb-ehci-Remove-dead-nakcnt-code.patch
Normal 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
|
||||
|
120
0135-usb-ehci-Fix-and-simplify-nakcnt-handling.patch
Normal file
120
0135-usb-ehci-Fix-and-simplify-nakcnt-handling.patch
Normal 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
|
||||
|
114
0136-usb-ehci-Remove-dead-isoch_pause-code.patch
Normal file
114
0136-usb-ehci-Remove-dead-isoch_pause-code.patch
Normal 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
|
||||
|
@ -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
|
||||
|
167
0138-usb-add-USB_RET_IOERROR.patch
Normal file
167
0138-usb-add-USB_RET_IOERROR.patch
Normal 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
|
||||
|
40
0139-usb-ehci-fix-reset.patch
Normal file
40
0139-usb-ehci-fix-reset.patch
Normal 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
|
||||
|
42
0140-usb-ehci-sanity-check-iso-xfers.patch
Normal file
42
0140-usb-ehci-sanity-check-iso-xfers.patch
Normal 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
|
||||
|
49
qemu.spec
49
qemu.spec
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user