From dbbf01958e777b6f03fc4ab425879f84800b9cda Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 27 Sep 2012 17:25:44 +0200 Subject: usb-redir: Change usbredir_open_chardev into usbredir_create_parser As we need to create the parser at more places. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/redirect.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'hw') diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index b10241a..5e0f98d 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -862,15 +862,11 @@ static void usbredir_chardev_close_bh(void *opaque) } } -static void usbredir_chardev_open(USBRedirDevice *dev) +static void usbredir_create_parser(USBRedirDevice *dev) { uint32_t caps[USB_REDIR_CAPS_SIZE] = { 0, }; int flags = 0; - /* Make sure any pending closes are handled (no-op if none pending) */ - usbredir_chardev_close_bh(dev); - qemu_bh_cancel(dev->chardev_close_bh); - DPRINTF("creating usbredirparser\n"); dev->parser = qemu_oom_check(usbredirparser_create()); @@ -982,7 +978,10 @@ static void usbredir_chardev_event(void *opaque, int event) switch (event) { case CHR_EVENT_OPENED: DPRINTF("chardev open\n"); - usbredir_chardev_open(dev); + /* Make sure any pending closes are handled (no-op if none pending) */ + usbredir_chardev_close_bh(dev); + qemu_bh_cancel(dev->chardev_close_bh); + usbredir_create_parser(dev); break; case CHR_EVENT_CLOSED: DPRINTF("chardev close\n"); -- cgit v1.1 From 5c16f767813602fbf57414e2a11057e252e0d422 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 27 Sep 2012 17:25:45 +0200 Subject: usb-redir: Don't make migration fail in none seamless case Instead simple disconnect the device like host redirection does on migration. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/redirect.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'hw') diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 5e0f98d..2283565 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -1614,12 +1614,17 @@ static int usbredir_get_parser(QEMUFile *f, void *priv, size_t unused) } /* - * Our chardev should be open already at this point, otherwise - * the usbredir channel will be broken (ie spice without seamless) + * If our chardev is not open already at this point the usbredir connection + * has been broken (non seamless migration, or restore from disk). + * + * In this case create a temporary parser to receive the migration data, + * and schedule the close_bh to report the device as disconnected to the + * guest and to destroy the parser again. */ if (dev->parser == NULL) { - ERROR("get_parser called with closed chardev, failing migration\n"); - return -1; + WARNING("usb-redir connection broken during migration\n"); + usbredir_create_parser(dev); + qemu_bh_schedule(dev->chardev_close_bh); } data = g_malloc(len); -- cgit v1.1 From 883bca776daa43111e9c39008f0038f7c62ae723 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 10 Oct 2012 15:50:36 +0200 Subject: uhci: Raise interrupt when requested even for non active tds According to the spec we must raise an interrupt when one is requested even for non active tds. Linux depends on this, for bulk transfers it runs an inactivity timer to work around a bug in early uhci revisions, when we take longer then 200 ms to process a packet, this timer goes of, and as part of the handling Linux then unlinks the qh, and relinks it after the frindex has increased by atleast 1, the problem is Linux only checks for the frindex increases on an interrupt, and we don't send that, causing the qh to go inactive for more then 32 frames, at which point we consider the packet cancelled. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-uhci.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'hw') diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index cdc8bc3..c2f08e3 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -826,8 +826,16 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, USBEndpoint *ep; /* Is active ? */ - if (!(td->ctrl & TD_CTRL_ACTIVE)) + if (!(td->ctrl & TD_CTRL_ACTIVE)) { + /* + * ehci11d spec page 22: "Even if the Active bit in the TD is already + * cleared when the TD is fetched ... an IOC interrupt is generated" + */ + if (td->ctrl & TD_CTRL_IOC) { + *int_mask |= 0x01; + } return TD_RESULT_NEXT_QH; + } async = uhci_async_find_td(s, addr, td); if (async) { -- cgit v1.1