|
|
5544c1 |
From b89a0cc1ec9dbe30cbe002f12d487a52950da166 Mon Sep 17 00:00:00 2001
|
|
Hans de Goede |
c8dfc6 |
From: Hans de Goede <hdegoede@redhat.com>
|
|
Hans de Goede |
c8dfc6 |
Date: Thu, 23 Aug 2012 16:37:19 +0200
|
|
|
5544c1 |
Subject: [PATCH] usb-redir: Don't delay handling of open events to a bottom
|
|
|
5544c1 |
half
|
|
Hans de Goede |
c8dfc6 |
|
|
Hans de Goede |
c8dfc6 |
There is no need for this, and doing so means that a backend trying to
|
|
Hans de Goede |
c8dfc6 |
write immediately after an open event will see qemu_chr_be_can_write
|
|
Hans de Goede |
c8dfc6 |
returning 0, which not all backends handle well as there is no wakeup
|
|
Hans de Goede |
c8dfc6 |
mechanism to detect when the frontend does become writable.
|
|
Hans de Goede |
c8dfc6 |
|
|
Hans de Goede |
c8dfc6 |
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
|
Hans de Goede |
c8dfc6 |
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
|
|
5544c1 |
(cherry picked from commit ed9873bfbf145c084d039baab08c63b9d67e7bd3)
|
|
|
5544c1 |
|
|
|
5544c1 |
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
|
|
Hans de Goede |
c8dfc6 |
---
|
|
Hans de Goede |
c8dfc6 |
hw/usb/redirect.c | 100 +++++++++++++++++++++++++++++-------------------------
|
|
Hans de Goede |
c8dfc6 |
1 file changed, 53 insertions(+), 47 deletions(-)
|
|
Hans de Goede |
c8dfc6 |
|
|
Hans de Goede |
c8dfc6 |
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
|
|
|
5544c1 |
index 7f3719b..5cc3334 100644
|
|
Hans de Goede |
c8dfc6 |
--- a/hw/usb/redirect.c
|
|
Hans de Goede |
c8dfc6 |
+++ b/hw/usb/redirect.c
|
|
Hans de Goede |
c8dfc6 |
@@ -79,8 +79,8 @@ struct USBRedirDevice {
|
|
Hans de Goede |
c8dfc6 |
/* Data passed from chardev the fd_read cb to the usbredirparser read cb */
|
|
Hans de Goede |
c8dfc6 |
const uint8_t *read_buf;
|
|
Hans de Goede |
c8dfc6 |
int read_buf_size;
|
|
Hans de Goede |
c8dfc6 |
- /* For async handling of open/close */
|
|
Hans de Goede |
c8dfc6 |
- QEMUBH *open_close_bh;
|
|
Hans de Goede |
c8dfc6 |
+ /* For async handling of close */
|
|
Hans de Goede |
c8dfc6 |
+ QEMUBH *chardev_close_bh;
|
|
Hans de Goede |
c8dfc6 |
/* To delay the usb attach in case of quick chardev close + open */
|
|
Hans de Goede |
c8dfc6 |
QEMUTimer *attach_timer;
|
|
Hans de Goede |
c8dfc6 |
int64_t next_attach_time;
|
|
|
5544c1 |
@@ -784,18 +784,11 @@ static int usbredir_handle_control(USBDevice *udev, USBPacket *p,
|
|
Hans de Goede |
c8dfc6 |
* from within the USBDevice data / control packet callbacks and doing a
|
|
Hans de Goede |
c8dfc6 |
* usb_detach from within these callbacks is not a good idea.
|
|
Hans de Goede |
c8dfc6 |
*
|
|
Hans de Goede |
c8dfc6 |
- * So we use a bh handler to take care of close events. We also handle
|
|
Hans de Goede |
c8dfc6 |
- * open events from this callback to make sure that a close directly followed
|
|
Hans de Goede |
c8dfc6 |
- * by an open gets handled in the right order.
|
|
Hans de Goede |
c8dfc6 |
+ * So we use a bh handler to take care of close events.
|
|
Hans de Goede |
c8dfc6 |
*/
|
|
Hans de Goede |
c8dfc6 |
-static void usbredir_open_close_bh(void *opaque)
|
|
Hans de Goede |
c8dfc6 |
+static void usbredir_chardev_close_bh(void *opaque)
|
|
Hans de Goede |
c8dfc6 |
{
|
|
Hans de Goede |
c8dfc6 |
USBRedirDevice *dev = opaque;
|
|
Hans de Goede |
c8dfc6 |
- uint32_t caps[USB_REDIR_CAPS_SIZE] = { 0, };
|
|
Hans de Goede |
c8dfc6 |
- char version[32];
|
|
Hans de Goede |
c8dfc6 |
-
|
|
Hans de Goede |
c8dfc6 |
- strcpy(version, "qemu usb-redir guest ");
|
|
Hans de Goede |
c8dfc6 |
- pstrcat(version, sizeof(version), qemu_get_version());
|
|
Hans de Goede |
c8dfc6 |
|
|
Hans de Goede |
c8dfc6 |
usbredir_device_disconnect(dev);
|
|
Hans de Goede |
c8dfc6 |
|
|
|
5544c1 |
@@ -803,36 +796,47 @@ static void usbredir_open_close_bh(void *opaque)
|
|
Hans de Goede |
c8dfc6 |
usbredirparser_destroy(dev->parser);
|
|
Hans de Goede |
c8dfc6 |
dev->parser = NULL;
|
|
Hans de Goede |
c8dfc6 |
}
|
|
Hans de Goede |
c8dfc6 |
+}
|
|
Hans de Goede |
c8dfc6 |
|
|
Hans de Goede |
c8dfc6 |
- if (dev->cs->opened) {
|
|
Hans de Goede |
c8dfc6 |
- dev->parser = qemu_oom_check(usbredirparser_create());
|
|
Hans de Goede |
c8dfc6 |
- dev->parser->priv = dev;
|
|
Hans de Goede |
c8dfc6 |
- dev->parser->log_func = usbredir_log;
|
|
Hans de Goede |
c8dfc6 |
- dev->parser->read_func = usbredir_read;
|
|
Hans de Goede |
c8dfc6 |
- dev->parser->write_func = usbredir_write;
|
|
Hans de Goede |
c8dfc6 |
- dev->parser->hello_func = usbredir_hello;
|
|
Hans de Goede |
c8dfc6 |
- dev->parser->device_connect_func = usbredir_device_connect;
|
|
Hans de Goede |
c8dfc6 |
- dev->parser->device_disconnect_func = usbredir_device_disconnect;
|
|
Hans de Goede |
c8dfc6 |
- dev->parser->interface_info_func = usbredir_interface_info;
|
|
Hans de Goede |
c8dfc6 |
- dev->parser->ep_info_func = usbredir_ep_info;
|
|
Hans de Goede |
c8dfc6 |
- dev->parser->configuration_status_func = usbredir_configuration_status;
|
|
Hans de Goede |
c8dfc6 |
- dev->parser->alt_setting_status_func = usbredir_alt_setting_status;
|
|
Hans de Goede |
c8dfc6 |
- dev->parser->iso_stream_status_func = usbredir_iso_stream_status;
|
|
Hans de Goede |
c8dfc6 |
- dev->parser->interrupt_receiving_status_func =
|
|
Hans de Goede |
c8dfc6 |
- usbredir_interrupt_receiving_status;
|
|
Hans de Goede |
c8dfc6 |
- dev->parser->bulk_streams_status_func = usbredir_bulk_streams_status;
|
|
Hans de Goede |
c8dfc6 |
- dev->parser->control_packet_func = usbredir_control_packet;
|
|
Hans de Goede |
c8dfc6 |
- dev->parser->bulk_packet_func = usbredir_bulk_packet;
|
|
Hans de Goede |
c8dfc6 |
- dev->parser->iso_packet_func = usbredir_iso_packet;
|
|
Hans de Goede |
c8dfc6 |
- dev->parser->interrupt_packet_func = usbredir_interrupt_packet;
|
|
Hans de Goede |
c8dfc6 |
- dev->read_buf = NULL;
|
|
Hans de Goede |
c8dfc6 |
- dev->read_buf_size = 0;
|
|
Hans de Goede |
c8dfc6 |
+static void usbredir_chardev_open(USBRedirDevice *dev)
|
|
Hans de Goede |
c8dfc6 |
+{
|
|
Hans de Goede |
c8dfc6 |
+ uint32_t caps[USB_REDIR_CAPS_SIZE] = { 0, };
|
|
Hans de Goede |
c8dfc6 |
+ char version[32];
|
|
Hans de Goede |
c8dfc6 |
|
|
Hans de Goede |
c8dfc6 |
- usbredirparser_caps_set_cap(caps, usb_redir_cap_connect_device_version);
|
|
Hans de Goede |
c8dfc6 |
- usbredirparser_caps_set_cap(caps, usb_redir_cap_filter);
|
|
Hans de Goede |
c8dfc6 |
- usbredirparser_init(dev->parser, version, caps, USB_REDIR_CAPS_SIZE, 0);
|
|
Hans de Goede |
c8dfc6 |
- usbredirparser_do_write(dev->parser);
|
|
Hans de Goede |
c8dfc6 |
- }
|
|
Hans de Goede |
c8dfc6 |
+ /* Make sure any pending closes are handled (no-op if none pending) */
|
|
Hans de Goede |
c8dfc6 |
+ usbredir_chardev_close_bh(dev);
|
|
Hans de Goede |
c8dfc6 |
+ qemu_bh_cancel(dev->chardev_close_bh);
|
|
Hans de Goede |
c8dfc6 |
+
|
|
Hans de Goede |
c8dfc6 |
+ strcpy(version, "qemu usb-redir guest ");
|
|
Hans de Goede |
c8dfc6 |
+ pstrcat(version, sizeof(version), qemu_get_version());
|
|
Hans de Goede |
c8dfc6 |
+
|
|
Hans de Goede |
c8dfc6 |
+ dev->parser = qemu_oom_check(usbredirparser_create());
|
|
Hans de Goede |
c8dfc6 |
+ dev->parser->priv = dev;
|
|
Hans de Goede |
c8dfc6 |
+ dev->parser->log_func = usbredir_log;
|
|
Hans de Goede |
c8dfc6 |
+ dev->parser->read_func = usbredir_read;
|
|
Hans de Goede |
c8dfc6 |
+ dev->parser->write_func = usbredir_write;
|
|
Hans de Goede |
c8dfc6 |
+ dev->parser->hello_func = usbredir_hello;
|
|
Hans de Goede |
c8dfc6 |
+ dev->parser->device_connect_func = usbredir_device_connect;
|
|
Hans de Goede |
c8dfc6 |
+ dev->parser->device_disconnect_func = usbredir_device_disconnect;
|
|
Hans de Goede |
c8dfc6 |
+ dev->parser->interface_info_func = usbredir_interface_info;
|
|
Hans de Goede |
c8dfc6 |
+ dev->parser->ep_info_func = usbredir_ep_info;
|
|
Hans de Goede |
c8dfc6 |
+ dev->parser->configuration_status_func = usbredir_configuration_status;
|
|
Hans de Goede |
c8dfc6 |
+ dev->parser->alt_setting_status_func = usbredir_alt_setting_status;
|
|
Hans de Goede |
c8dfc6 |
+ dev->parser->iso_stream_status_func = usbredir_iso_stream_status;
|
|
Hans de Goede |
c8dfc6 |
+ dev->parser->interrupt_receiving_status_func =
|
|
Hans de Goede |
c8dfc6 |
+ usbredir_interrupt_receiving_status;
|
|
Hans de Goede |
c8dfc6 |
+ dev->parser->bulk_streams_status_func = usbredir_bulk_streams_status;
|
|
Hans de Goede |
c8dfc6 |
+ dev->parser->control_packet_func = usbredir_control_packet;
|
|
Hans de Goede |
c8dfc6 |
+ dev->parser->bulk_packet_func = usbredir_bulk_packet;
|
|
Hans de Goede |
c8dfc6 |
+ dev->parser->iso_packet_func = usbredir_iso_packet;
|
|
Hans de Goede |
c8dfc6 |
+ dev->parser->interrupt_packet_func = usbredir_interrupt_packet;
|
|
Hans de Goede |
c8dfc6 |
+ dev->read_buf = NULL;
|
|
Hans de Goede |
c8dfc6 |
+ dev->read_buf_size = 0;
|
|
Hans de Goede |
c8dfc6 |
+
|
|
Hans de Goede |
c8dfc6 |
+ usbredirparser_caps_set_cap(caps, usb_redir_cap_connect_device_version);
|
|
Hans de Goede |
c8dfc6 |
+ usbredirparser_caps_set_cap(caps, usb_redir_cap_filter);
|
|
Hans de Goede |
c8dfc6 |
+ usbredirparser_init(dev->parser, version, caps, USB_REDIR_CAPS_SIZE, 0);
|
|
Hans de Goede |
c8dfc6 |
+ usbredirparser_do_write(dev->parser);
|
|
Hans de Goede |
c8dfc6 |
}
|
|
Hans de Goede |
c8dfc6 |
|
|
Hans de Goede |
c8dfc6 |
static void usbredir_do_attach(void *opaque)
|
|
|
5544c1 |
@@ -856,13 +860,13 @@ static int usbredir_chardev_can_read(void *opaque)
|
|
Hans de Goede |
c8dfc6 |
{
|
|
Hans de Goede |
c8dfc6 |
USBRedirDevice *dev = opaque;
|
|
Hans de Goede |
c8dfc6 |
|
|
Hans de Goede |
c8dfc6 |
- if (dev->parser) {
|
|
Hans de Goede |
c8dfc6 |
- /* usbredir_parser_do_read will consume *all* data we give it */
|
|
Hans de Goede |
c8dfc6 |
- return 1024 * 1024;
|
|
Hans de Goede |
c8dfc6 |
- } else {
|
|
Hans de Goede |
c8dfc6 |
- /* usbredir_open_close_bh hasn't handled the open event yet */
|
|
Hans de Goede |
c8dfc6 |
+ if (!dev->parser) {
|
|
Hans de Goede |
c8dfc6 |
+ WARNING("chardev_can_read called on non open chardev!\n");
|
|
Hans de Goede |
c8dfc6 |
return 0;
|
|
Hans de Goede |
c8dfc6 |
}
|
|
Hans de Goede |
c8dfc6 |
+
|
|
Hans de Goede |
c8dfc6 |
+ /* usbredir_parser_do_read will consume *all* data we give it */
|
|
Hans de Goede |
c8dfc6 |
+ return 1024 * 1024;
|
|
Hans de Goede |
c8dfc6 |
}
|
|
Hans de Goede |
c8dfc6 |
|
|
Hans de Goede |
c8dfc6 |
static void usbredir_chardev_read(void *opaque, const uint8_t *buf, int size)
|
|
|
5544c1 |
@@ -886,8 +890,10 @@ static void usbredir_chardev_event(void *opaque, int event)
|
|
Hans de Goede |
c8dfc6 |
|
|
Hans de Goede |
c8dfc6 |
switch (event) {
|
|
Hans de Goede |
c8dfc6 |
case CHR_EVENT_OPENED:
|
|
Hans de Goede |
c8dfc6 |
+ usbredir_chardev_open(dev);
|
|
Hans de Goede |
c8dfc6 |
+ break;
|
|
Hans de Goede |
c8dfc6 |
case CHR_EVENT_CLOSED:
|
|
Hans de Goede |
c8dfc6 |
- qemu_bh_schedule(dev->open_close_bh);
|
|
Hans de Goede |
c8dfc6 |
+ qemu_bh_schedule(dev->chardev_close_bh);
|
|
Hans de Goede |
c8dfc6 |
break;
|
|
Hans de Goede |
c8dfc6 |
}
|
|
Hans de Goede |
c8dfc6 |
}
|
|
|
5544c1 |
@@ -917,7 +923,7 @@ static int usbredir_initfn(USBDevice *udev)
|
|
Hans de Goede |
c8dfc6 |
}
|
|
Hans de Goede |
c8dfc6 |
}
|
|
Hans de Goede |
c8dfc6 |
|
|
Hans de Goede |
c8dfc6 |
- dev->open_close_bh = qemu_bh_new(usbredir_open_close_bh, dev);
|
|
Hans de Goede |
c8dfc6 |
+ dev->chardev_close_bh = qemu_bh_new(usbredir_chardev_close_bh, dev);
|
|
Hans de Goede |
c8dfc6 |
dev->attach_timer = qemu_new_timer_ms(vm_clock, usbredir_do_attach, dev);
|
|
Hans de Goede |
c8dfc6 |
|
|
Hans de Goede |
c8dfc6 |
QTAILQ_INIT(&dev->asyncq);
|
|
|
5544c1 |
@@ -957,7 +963,7 @@ static void usbredir_handle_destroy(USBDevice *udev)
|
|
Hans de Goede |
c8dfc6 |
qemu_chr_fe_close(dev->cs);
|
|
Hans de Goede |
c8dfc6 |
qemu_chr_delete(dev->cs);
|
|
Hans de Goede |
c8dfc6 |
/* Note must be done after qemu_chr_close, as that causes a close event */
|
|
Hans de Goede |
c8dfc6 |
- qemu_bh_delete(dev->open_close_bh);
|
|
Hans de Goede |
c8dfc6 |
+ qemu_bh_delete(dev->chardev_close_bh);
|
|
Hans de Goede |
c8dfc6 |
|
|
Hans de Goede |
c8dfc6 |
qemu_del_timer(dev->attach_timer);
|
|
Hans de Goede |
c8dfc6 |
qemu_free_timer(dev->attach_timer);
|
|
Hans de Goede |
c8dfc6 |
--
|
|
|
5544c1 |
1.7.12.1
|
|
Hans de Goede |
c8dfc6 |
|