diff --git a/0111-usb-redir-Add-flow-control-support.patch b/0111-usb-redir-Add-flow-control-support.patch
index 3edcd1a..76b5ca5 100644
--- a/0111-usb-redir-Add-flow-control-support.patch
+++ b/0111-usb-redir-Add-flow-control-support.patch
@@ -41,7 +41,7 @@ index ecb2cd4..1460515 100644
  }
  
  /*
-@@ -892,10 +902,22 @@ static void usbredir_chardev_event(void *opaque, int event)
+@@ -892,10 +902,18 @@ static void usbredir_chardev_event(void *opaque, int event)
      }
  }
  
@@ -49,10 +49,6 @@ index ecb2cd4..1460515 100644
 +{
 +    USBRedirDevice *dev = opaque;
 +
-+    if (dev->parser == NULL) {
-+        /* usbredir_open_close_bh hasn't handled the open event yet */
-+        return;
-+    }
 +    usbredirparser_do_write(dev->parser);
 +}
 +
diff --git a/0215-qxl-dont-update-invalid-area.patch b/0215-qxl-dont-update-invalid-area.patch
deleted file mode 100644
index 8739272..0000000
--- a/0215-qxl-dont-update-invalid-area.patch
+++ /dev/null
@@ -1,41 +0,0 @@
-From 6f1652c4412ab60c7f456100143c519d124a895c Mon Sep 17 00:00:00 2001
-From: Dunrong Huang <riegamaths@gmail.com>
-Date: Fri, 31 Aug 2012 00:44:44 +0800
-Subject: [PATCH 215/215] qxl: dont update invalid area
-
-This patch fixes the following error:
-
-$ ~/usr/bin/qemu-system-x86_64 -enable-kvm -m 1024 -spice port=5900,disable-ticketing -vga qxl -cdrom ~/Images/linuxmint-13-mate-dvd-32bit.iso
-(/home/mathslinux/usr/bin/qemu-system-x86_64:10068): SpiceWorker-CRITICAL **: red_worker.c:4599:red_update_area: condition `area->left >= 0 && area->top >= 0 && area->left < area->right && area->top < area->bottom' failed
-Aborted
-
-spice server terminates QEMU process if we pass invalid area to it,
-so dont update those invalid areas.
-
-Signed-off-by: Dunrong Huang <riegamaths@gmail.com>
-Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
----
- hw/qxl.c | 7 +++++++
- 1 file changed, 7 insertions(+)
-
-diff --git a/hw/qxl.c b/hw/qxl.c
-index b726c19..045432e 100644
---- a/hw/qxl.c
-+++ b/hw/qxl.c
-@@ -1470,6 +1470,13 @@ async_common:
-             return;
-         }
- 
-+        if (update.left < 0 || update.top < 0 || update.left >= update.right ||
-+            update.top >= update.bottom) {
-+            qxl_set_guest_bug(d, "QXL_IO_UPDATE_AREA: "
-+                              "invalid area(%d,%d,%d,%d)\n", update.left,
-+                              update.right, update.top, update.bottom);
-+            break;
-+        }
-         if (async == QXL_ASYNC) {
-             cookie = qxl_cookie_new(QXL_COOKIE_TYPE_IO,
-                                     QXL_IO_UPDATE_AREA_ASYNC);
--- 
-1.7.12
-
diff --git a/0215-spice-switch-to-queue-for-vga-mode-updates.patch b/0215-spice-switch-to-queue-for-vga-mode-updates.patch
new file mode 100644
index 0000000..9bd3562
--- /dev/null
+++ b/0215-spice-switch-to-queue-for-vga-mode-updates.patch
@@ -0,0 +1,138 @@
+From 20b7c4b95c7f0c93000a68779e9cb9e63cff68da Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Wed, 5 Sep 2012 08:25:08 +0200
+Subject: [PATCH 215/293] spice: switch to queue for vga mode updates
+
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+---
+ hw/qxl.c           |  6 +++---
+ ui/spice-display.c | 25 ++++++++++++++-----------
+ ui/spice-display.h |  3 ++-
+ 3 files changed, 19 insertions(+), 15 deletions(-)
+
+diff --git a/hw/qxl.c b/hw/qxl.c
+index b726c19..833cd77 100644
+--- a/hw/qxl.c
++++ b/hw/qxl.c
+@@ -597,9 +597,9 @@ static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
+     case QXL_MODE_VGA:
+         ret = false;
+         qemu_mutex_lock(&qxl->ssd.lock);
+-        if (qxl->ssd.update != NULL) {
+-            update = qxl->ssd.update;
+-            qxl->ssd.update = NULL;
++        update = QTAILQ_FIRST(&qxl->ssd.updates);
++        if (update != NULL) {
++            QTAILQ_REMOVE(&qxl->ssd.updates, update, next);
+             *ext = update->ext;
+             ret = true;
+         }
+diff --git a/ui/spice-display.c b/ui/spice-display.c
+index 99bc665..59c5fd7 100644
+--- a/ui/spice-display.c
++++ b/ui/spice-display.c
+@@ -164,7 +164,7 @@ int qemu_spice_display_is_running(SimpleSpiceDisplay *ssd)
+ #endif
+ }
+ 
+-static SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd)
++static void qemu_spice_create_update(SimpleSpiceDisplay *ssd)
+ {
+     SimpleSpiceUpdate *update;
+     QXLDrawable *drawable;
+@@ -175,7 +175,7 @@ static SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd)
+     struct timespec time_space;
+ 
+     if (qemu_spice_rect_is_empty(&ssd->dirty)) {
+-        return NULL;
++        return;
+     };
+ 
+     trace_qemu_spice_create_update(
+@@ -239,7 +239,7 @@ static SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd)
+     cmd->data = (uintptr_t)drawable;
+ 
+     memset(&ssd->dirty, 0, sizeof(ssd->dirty));
+-    return update;
++    QTAILQ_INSERT_TAIL(&ssd->updates, update, next);
+ }
+ 
+ /*
+@@ -315,6 +315,7 @@ void qemu_spice_display_init_common(SimpleSpiceDisplay *ssd, DisplayState *ds)
+ {
+     ssd->ds = ds;
+     qemu_mutex_init(&ssd->lock);
++    QTAILQ_INIT(&ssd->updates);
+     ssd->mouse_x = -1;
+     ssd->mouse_y = -1;
+     if (ssd->num_surfaces == 0) {
+@@ -345,6 +346,8 @@ void qemu_spice_display_update(SimpleSpiceDisplay *ssd,
+ 
+ void qemu_spice_display_resize(SimpleSpiceDisplay *ssd)
+ {
++    SimpleSpiceUpdate *update;
++
+     dprint(1, "%s:\n", __FUNCTION__);
+ 
+     memset(&ssd->dirty, 0, sizeof(ssd->dirty));
+@@ -352,9 +355,9 @@ void qemu_spice_display_resize(SimpleSpiceDisplay *ssd)
+     ssd->conv = NULL;
+ 
+     qemu_mutex_lock(&ssd->lock);
+-    if (ssd->update != NULL) {
+-        qemu_spice_destroy_update(ssd, ssd->update);
+-        ssd->update = NULL;
++    while ((update = QTAILQ_FIRST(&ssd->updates)) != NULL) {
++        QTAILQ_REMOVE(&ssd->updates, update, next);
++        qemu_spice_destroy_update(ssd, update);
+     }
+     qemu_mutex_unlock(&ssd->lock);
+     qemu_spice_destroy_host_primary(ssd);
+@@ -384,8 +387,8 @@ void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd)
+     vga_hw_update();
+ 
+     qemu_mutex_lock(&ssd->lock);
+-    if (ssd->update == NULL) {
+-        ssd->update = qemu_spice_create_update(ssd);
++    if (QTAILQ_EMPTY(&ssd->updates)) {
++        qemu_spice_create_update(ssd);
+         ssd->notify++;
+     }
+     qemu_spice_cursor_refresh_unlocked(ssd);
+@@ -442,9 +445,9 @@ static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
+     dprint(3, "%s:\n", __FUNCTION__);
+ 
+     qemu_mutex_lock(&ssd->lock);
+-    if (ssd->update != NULL) {
+-        update = ssd->update;
+-        ssd->update = NULL;
++    update = QTAILQ_FIRST(&ssd->updates);
++    if (update != NULL) {
++        QTAILQ_REMOVE(&ssd->updates, update, next);
+         *ext = update->ext;
+         ret = true;
+     }
+diff --git a/ui/spice-display.h b/ui/spice-display.h
+index 512ab78..3fcb6fe 100644
+--- a/ui/spice-display.h
++++ b/ui/spice-display.h
+@@ -92,7 +92,7 @@ struct SimpleSpiceDisplay {
+      * to them must be protected by the lock.
+      */
+     QemuMutex lock;
+-    SimpleSpiceUpdate *update;
++    QTAILQ_HEAD(, SimpleSpiceUpdate) updates;
+     QEMUCursor *cursor;
+     int mouse_x, mouse_y;
+ };
+@@ -102,6 +102,7 @@ struct SimpleSpiceUpdate {
+     QXLImage image;
+     QXLCommandExt ext;
+     uint8_t *bitmap;
++    QTAILQ_ENTRY(SimpleSpiceUpdate) next;
+ };
+ 
+ int qemu_spice_rect_is_empty(const QXLRect* r);
+-- 
+1.7.12
+
diff --git a/0216-qxl-Ignore-set_client_capabilities-pre-post-migrate.patch b/0216-qxl-Ignore-set_client_capabilities-pre-post-migrate.patch
deleted file mode 100644
index 3391970..0000000
--- a/0216-qxl-Ignore-set_client_capabilities-pre-post-migrate.patch
+++ /dev/null
@@ -1,41 +0,0 @@
-From 68d246d6a904e0a851c521a08a18187598e1c696 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Fri, 7 Sep 2012 21:29:22 +0200
-Subject: [PATCH] qxl: Ignore set_client_capabilities pre/post migrate
-
-The recent introduction of set_client_capabilities has broken
-(seamless) migration by trying to call qxl_send_events pre (seamless
-incoming) and post (*) migration, triggering the following assert:
-qxl_send_events: Assertion `qemu_spice_display_is_running(&d->ssd)' failed.
-
-The solution is easy, pre migration the guest will have already received
-the client caps on the migration source side, and post migration there no
-longer is a guest, so we can simply ignore the set_client_capabilities call
-in both those scenarios.
-
-*) Post migration, so not fatal for to the migration itself, but still a crash
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- hw/qxl.c | 5 +++++
- 1 file changed, 5 insertions(+)
-
-diff --git a/hw/qxl.c b/hw/qxl.c
-index 045432e..1b400f1 100644
---- a/hw/qxl.c
-+++ b/hw/qxl.c
-@@ -953,6 +953,11 @@ static void interface_set_client_capabilities(QXLInstance *sin,
- {
-     PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
- 
-+    if (runstate_check(RUN_STATE_INMIGRATE) ||
-+        runstate_check(RUN_STATE_POSTMIGRATE)) {
-+        return;
-+    }
-+
-     qxl->shadow_rom.client_present = client_present;
-     memcpy(qxl->shadow_rom.client_capabilities, caps, sizeof(caps));
-     qxl->rom->client_present = client_present;
--- 
-1.7.12
-
diff --git a/0216-spice-split-qemu_spice_create_update.patch b/0216-spice-split-qemu_spice_create_update.patch
new file mode 100644
index 0000000..711382c
--- /dev/null
+++ b/0216-spice-split-qemu_spice_create_update.patch
@@ -0,0 +1,94 @@
+From a754b60d7602dae18120ab014735927058e89983 Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Wed, 5 Sep 2012 08:52:23 +0200
+Subject: [PATCH 216/293] spice: split qemu_spice_create_update
+
+Creating one function which creates a single update for a given
+rectangle.  And one (for now) pretty simple wrapper around it to
+queue up screen updates for the dirty region.
+
+[ v2: also update bounding box ]
+
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+---
+ ui/spice-display.c | 31 ++++++++++++++++++-------------
+ 1 file changed, 18 insertions(+), 13 deletions(-)
+
+diff --git a/ui/spice-display.c b/ui/spice-display.c
+index 59c5fd7..6f68f28 100644
+--- a/ui/spice-display.c
++++ b/ui/spice-display.c
+@@ -164,7 +164,8 @@ int qemu_spice_display_is_running(SimpleSpiceDisplay *ssd)
+ #endif
+ }
+ 
+-static void qemu_spice_create_update(SimpleSpiceDisplay *ssd)
++static void qemu_spice_create_one_update(SimpleSpiceDisplay *ssd,
++                                         QXLRect *rect)
+ {
+     SimpleSpiceUpdate *update;
+     QXLDrawable *drawable;
+@@ -174,24 +175,20 @@ static void qemu_spice_create_update(SimpleSpiceDisplay *ssd)
+     int by, bw, bh;
+     struct timespec time_space;
+ 
+-    if (qemu_spice_rect_is_empty(&ssd->dirty)) {
+-        return;
+-    };
+-
+     trace_qemu_spice_create_update(
+-           ssd->dirty.left, ssd->dirty.right,
+-           ssd->dirty.top, ssd->dirty.bottom);
++           rect->left, rect->right,
++           rect->top, rect->bottom);
+ 
+     update   = g_malloc0(sizeof(*update));
+     drawable = &update->drawable;
+     image    = &update->image;
+     cmd      = &update->ext.cmd;
+ 
+-    bw       = ssd->dirty.right - ssd->dirty.left;
+-    bh       = ssd->dirty.bottom - ssd->dirty.top;
++    bw       = rect->right - rect->left;
++    bh       = rect->bottom - rect->top;
+     update->bitmap = g_malloc(bw * bh * 4);
+ 
+-    drawable->bbox            = ssd->dirty;
++    drawable->bbox            = *rect;
+     drawable->clip.type       = SPICE_CLIP_TYPE_NONE;
+     drawable->effect          = QXL_EFFECT_OPAQUE;
+     drawable->release_info.id = (uintptr_t)update;
+@@ -226,8 +223,8 @@ static void qemu_spice_create_update(SimpleSpiceDisplay *ssd)
+     }
+ 
+     src = ds_get_data(ssd->ds) +
+-        ssd->dirty.top * ds_get_linesize(ssd->ds) +
+-        ssd->dirty.left * ds_get_bytes_per_pixel(ssd->ds);
++        rect->top * ds_get_linesize(ssd->ds) +
++        rect->left * ds_get_bytes_per_pixel(ssd->ds);
+     dst = update->bitmap;
+     for (by = 0; by < bh; by++) {
+         qemu_pf_conv_run(ssd->conv, dst, src, bw);
+@@ -238,10 +235,18 @@ static void qemu_spice_create_update(SimpleSpiceDisplay *ssd)
+     cmd->type = QXL_CMD_DRAW;
+     cmd->data = (uintptr_t)drawable;
+ 
+-    memset(&ssd->dirty, 0, sizeof(ssd->dirty));
+     QTAILQ_INSERT_TAIL(&ssd->updates, update, next);
+ }
+ 
++static void qemu_spice_create_update(SimpleSpiceDisplay *ssd)
++{
++    if (qemu_spice_rect_is_empty(&ssd->dirty)) {
++        return;
++    };
++    qemu_spice_create_one_update(ssd, &ssd->dirty);
++    memset(&ssd->dirty, 0, sizeof(ssd->dirty));
++}
++
+ /*
+  * Called from spice server thread context (via interface_release_ressource)
+  * We do *not* hold the global qemu mutex here, so extra care is needed
+-- 
+1.7.12
+
diff --git a/0217-spice-add-screen-mirror.patch b/0217-spice-add-screen-mirror.patch
new file mode 100644
index 0000000..5898ba8
--- /dev/null
+++ b/0217-spice-add-screen-mirror.patch
@@ -0,0 +1,98 @@
+From d7080640a03a1c7739eb730eaec0c63e7e12cdb6 Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Wed, 5 Sep 2012 09:35:57 +0200
+Subject: [PATCH 217/293] spice: add screen mirror
+
+Create a screen mirror, keep there a copy of the most recent update
+passed on to spice-server.
+
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+---
+ ui/spice-display.c | 32 ++++++++++++++++++++++----------
+ ui/spice-display.h |  1 +
+ 2 files changed, 23 insertions(+), 10 deletions(-)
+
+diff --git a/ui/spice-display.c b/ui/spice-display.c
+index 6f68f28..973cd53 100644
+--- a/ui/spice-display.c
++++ b/ui/spice-display.c
+@@ -171,8 +171,8 @@ static void qemu_spice_create_one_update(SimpleSpiceDisplay *ssd,
+     QXLDrawable *drawable;
+     QXLImage *image;
+     QXLCommand *cmd;
+-    uint8_t *src, *dst;
+-    int by, bw, bh;
++    uint8_t *src, *mirror, *dst;
++    int by, bw, bh, offset, bytes;
+     struct timespec time_space;
+ 
+     trace_qemu_spice_create_update(
+@@ -216,19 +216,18 @@ static void qemu_spice_create_one_update(SimpleSpiceDisplay *ssd,
+     image->bitmap.palette = 0;
+     image->bitmap.format = SPICE_BITMAP_FMT_32BIT;
+ 
+-    if (ssd->conv == NULL) {
+-        PixelFormat dst = qemu_default_pixelformat(32);
+-        ssd->conv = qemu_pf_conv_get(&dst, &ssd->ds->surface->pf);
+-        assert(ssd->conv);
+-    }
+-
+-    src = ds_get_data(ssd->ds) +
++    offset =
+         rect->top * ds_get_linesize(ssd->ds) +
+         rect->left * ds_get_bytes_per_pixel(ssd->ds);
++    bytes = ds_get_bytes_per_pixel(ssd->ds) * bw;
++    src = ds_get_data(ssd->ds) + offset;
++    mirror = ssd->ds_mirror + offset;
+     dst = update->bitmap;
+     for (by = 0; by < bh; by++) {
+-        qemu_pf_conv_run(ssd->conv, dst, src, bw);
++        memcpy(mirror, src, bytes);
++        qemu_pf_conv_run(ssd->conv, dst, mirror, bw);
+         src += ds_get_linesize(ssd->ds);
++        mirror += ds_get_linesize(ssd->ds);
+         dst += image->bitmap.stride;
+     }
+ 
+@@ -243,6 +242,17 @@ static void qemu_spice_create_update(SimpleSpiceDisplay *ssd)
+     if (qemu_spice_rect_is_empty(&ssd->dirty)) {
+         return;
+     };
++
++    if (ssd->conv == NULL) {
++        PixelFormat dst = qemu_default_pixelformat(32);
++        ssd->conv = qemu_pf_conv_get(&dst, &ssd->ds->surface->pf);
++        assert(ssd->conv);
++    }
++    if (ssd->ds_mirror == NULL) {
++        int size = ds_get_height(ssd->ds) * ds_get_linesize(ssd->ds);
++        ssd->ds_mirror = g_malloc0(size);
++    }
++
+     qemu_spice_create_one_update(ssd, &ssd->dirty);
+     memset(&ssd->dirty, 0, sizeof(ssd->dirty));
+ }
+@@ -358,6 +368,8 @@ void qemu_spice_display_resize(SimpleSpiceDisplay *ssd)
+     memset(&ssd->dirty, 0, sizeof(ssd->dirty));
+     qemu_pf_conv_put(ssd->conv);
+     ssd->conv = NULL;
++    g_free(ssd->ds_mirror);
++    ssd->ds_mirror = NULL;
+ 
+     qemu_mutex_lock(&ssd->lock);
+     while ((update = QTAILQ_FIRST(&ssd->updates)) != NULL) {
+diff --git a/ui/spice-display.h b/ui/spice-display.h
+index 3fcb6fe..dea41c1 100644
+--- a/ui/spice-display.h
++++ b/ui/spice-display.h
+@@ -72,6 +72,7 @@ typedef struct SimpleSpiceUpdate SimpleSpiceUpdate;
+ 
+ struct SimpleSpiceDisplay {
+     DisplayState *ds;
++    uint8_t *ds_mirror;
+     void *buf;
+     int bufsize;
+     QXLWorker *worker;
+-- 
+1.7.12
+
diff --git a/0218-spice-send-updates-only-for-changed-screen-content.patch b/0218-spice-send-updates-only-for-changed-screen-content.patch
new file mode 100644
index 0000000..5b63fec
--- /dev/null
+++ b/0218-spice-send-updates-only-for-changed-screen-content.patch
@@ -0,0 +1,93 @@
+From e503ba260e585c9ee56f44ae5b8da51643776369 Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Wed, 5 Sep 2012 10:41:42 +0200
+Subject: [PATCH 218/293] spice: send updates only for changed screen content
+
+when creating screen updates go compare the current guest screen
+against the mirror (which holds the most recent update sent), then
+only create updates for the screen areas which did actually change.
+
+[ v2: drop redundant qemu_spice_create_one_update call ]
+
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+---
+ ui/spice-display.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 55 insertions(+), 1 deletion(-)
+
+diff --git a/ui/spice-display.c b/ui/spice-display.c
+index 973cd53..d062765 100644
+--- a/ui/spice-display.c
++++ b/ui/spice-display.c
+@@ -239,6 +239,13 @@ static void qemu_spice_create_one_update(SimpleSpiceDisplay *ssd,
+ 
+ static void qemu_spice_create_update(SimpleSpiceDisplay *ssd)
+ {
++    static const int blksize = 32;
++    int blocks = (ds_get_width(ssd->ds) + blksize - 1) / blksize;
++    int dirty_top[blocks];
++    int y, yoff, x, xoff, blk, bw;
++    int bpp = ds_get_bytes_per_pixel(ssd->ds);
++    uint8_t *guest, *mirror;
++
+     if (qemu_spice_rect_is_empty(&ssd->dirty)) {
+         return;
+     };
+@@ -253,7 +260,54 @@ static void qemu_spice_create_update(SimpleSpiceDisplay *ssd)
+         ssd->ds_mirror = g_malloc0(size);
+     }
+ 
+-    qemu_spice_create_one_update(ssd, &ssd->dirty);
++    for (blk = 0; blk < blocks; blk++) {
++        dirty_top[blk] = -1;
++    }
++
++    guest = ds_get_data(ssd->ds);
++    mirror = ssd->ds_mirror;
++    for (y = ssd->dirty.top; y < ssd->dirty.bottom; y++) {
++        yoff = y * ds_get_linesize(ssd->ds);
++        for (x = ssd->dirty.left; x < ssd->dirty.right; x += blksize) {
++            xoff = x * bpp;
++            blk = x / blksize;
++            bw = MIN(blksize, ssd->dirty.right - x);
++            if (memcmp(guest + yoff + xoff,
++                       mirror + yoff + xoff,
++                       bw * bpp) == 0) {
++                if (dirty_top[blk] != -1) {
++                    QXLRect update = {
++                        .top    = dirty_top[blk],
++                        .bottom = y,
++                        .left   = x,
++                        .right  = x + bw,
++                    };
++                    qemu_spice_create_one_update(ssd, &update);
++                    dirty_top[blk] = -1;
++                }
++            } else {
++                if (dirty_top[blk] == -1) {
++                    dirty_top[blk] = y;
++                }
++            }
++        }
++    }
++
++    for (x = ssd->dirty.left; x < ssd->dirty.right; x += blksize) {
++        blk = x / blksize;
++        bw = MIN(blksize, ssd->dirty.right - x);
++        if (dirty_top[blk] != -1) {
++            QXLRect update = {
++                .top    = dirty_top[blk],
++                .bottom = ssd->dirty.bottom,
++                .left   = x,
++                .right  = x + bw,
++            };
++            qemu_spice_create_one_update(ssd, &update);
++            dirty_top[blk] = -1;
++        }
++    }
++
+     memset(&ssd->dirty, 0, sizeof(ssd->dirty));
+ }
+ 
+-- 
+1.7.12
+
diff --git a/0219-qxl-dont-update-invalid-area.patch b/0219-qxl-dont-update-invalid-area.patch
new file mode 100644
index 0000000..8739272
--- /dev/null
+++ b/0219-qxl-dont-update-invalid-area.patch
@@ -0,0 +1,41 @@
+From 6f1652c4412ab60c7f456100143c519d124a895c Mon Sep 17 00:00:00 2001
+From: Dunrong Huang <riegamaths@gmail.com>
+Date: Fri, 31 Aug 2012 00:44:44 +0800
+Subject: [PATCH 215/215] qxl: dont update invalid area
+
+This patch fixes the following error:
+
+$ ~/usr/bin/qemu-system-x86_64 -enable-kvm -m 1024 -spice port=5900,disable-ticketing -vga qxl -cdrom ~/Images/linuxmint-13-mate-dvd-32bit.iso
+(/home/mathslinux/usr/bin/qemu-system-x86_64:10068): SpiceWorker-CRITICAL **: red_worker.c:4599:red_update_area: condition `area->left >= 0 && area->top >= 0 && area->left < area->right && area->top < area->bottom' failed
+Aborted
+
+spice server terminates QEMU process if we pass invalid area to it,
+so dont update those invalid areas.
+
+Signed-off-by: Dunrong Huang <riegamaths@gmail.com>
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+---
+ hw/qxl.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/hw/qxl.c b/hw/qxl.c
+index b726c19..045432e 100644
+--- a/hw/qxl.c
++++ b/hw/qxl.c
+@@ -1470,6 +1470,13 @@ async_common:
+             return;
+         }
+ 
++        if (update.left < 0 || update.top < 0 || update.left >= update.right ||
++            update.top >= update.bottom) {
++            qxl_set_guest_bug(d, "QXL_IO_UPDATE_AREA: "
++                              "invalid area(%d,%d,%d,%d)\n", update.left,
++                              update.right, update.top, update.bottom);
++            break;
++        }
+         if (async == QXL_ASYNC) {
+             cookie = qxl_cookie_new(QXL_COOKIE_TYPE_IO,
+                                     QXL_IO_UPDATE_AREA_ASYNC);
+-- 
+1.7.12
+
diff --git a/0220-qxl-Ignore-set_client_capabilities-pre-post-migrate.patch b/0220-qxl-Ignore-set_client_capabilities-pre-post-migrate.patch
new file mode 100644
index 0000000..3391970
--- /dev/null
+++ b/0220-qxl-Ignore-set_client_capabilities-pre-post-migrate.patch
@@ -0,0 +1,41 @@
+From 68d246d6a904e0a851c521a08a18187598e1c696 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Fri, 7 Sep 2012 21:29:22 +0200
+Subject: [PATCH] qxl: Ignore set_client_capabilities pre/post migrate
+
+The recent introduction of set_client_capabilities has broken
+(seamless) migration by trying to call qxl_send_events pre (seamless
+incoming) and post (*) migration, triggering the following assert:
+qxl_send_events: Assertion `qemu_spice_display_is_running(&d->ssd)' failed.
+
+The solution is easy, pre migration the guest will have already received
+the client caps on the migration source side, and post migration there no
+longer is a guest, so we can simply ignore the set_client_capabilities call
+in both those scenarios.
+
+*) Post migration, so not fatal for to the migration itself, but still a crash
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ hw/qxl.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/hw/qxl.c b/hw/qxl.c
+index 045432e..1b400f1 100644
+--- a/hw/qxl.c
++++ b/hw/qxl.c
+@@ -953,6 +953,11 @@ static void interface_set_client_capabilities(QXLInstance *sin,
+ {
+     PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
+ 
++    if (runstate_check(RUN_STATE_INMIGRATE) ||
++        runstate_check(RUN_STATE_POSTMIGRATE)) {
++        return;
++    }
++
+     qxl->shadow_rom.client_present = client_present;
+     memcpy(qxl->shadow_rom.client_capabilities, caps, sizeof(caps));
+     qxl->rom->client_present = client_present;
+-- 
+1.7.12
+
diff --git a/0221-qxl-better-cleanup-for-surface-destroy.patch b/0221-qxl-better-cleanup-for-surface-destroy.patch
new file mode 100644
index 0000000..d24e093
--- /dev/null
+++ b/0221-qxl-better-cleanup-for-surface-destroy.patch
@@ -0,0 +1,32 @@
+From 2315ba0b57785d788828e6871e528c9ab368068f Mon Sep 17 00:00:00 2001
+From: Uri Lublin <uril@redhat.com>
+Date: Tue, 11 Sep 2012 10:09:58 +0300
+Subject: [PATCH 221/293] qxl: better cleanup for surface destroy
+
+Add back a call to qxl_spice_destroy_surface_wait_complete() in qxl_spice_destroy_surface_wait(),
+that was removed by commit c480bb7da465186b84d8427e068ef7502e47ffbf
+
+It is needed to complete surface-removal cleanup, for non async.
+For async, qxl_spice_destroy_surface_wait_complete is called upon operation completion.
+
+Signed-off-by: Uri Lublin <uril@redhat.com>
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+---
+ hw/qxl.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/hw/qxl.c b/hw/qxl.c
+index 144a002..9f06f5e 100644
+--- a/hw/qxl.c
++++ b/hw/qxl.c
+@@ -201,6 +201,7 @@ static void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id,
+         spice_qxl_destroy_surface_async(&qxl->ssd.qxl, id, (uintptr_t)cookie);
+     } else {
+         qxl->ssd.worker->destroy_surface_wait(qxl->ssd.worker, id);
++        qxl_spice_destroy_surface_wait_complete(qxl, id);
+     }
+ }
+ 
+-- 
+1.7.12
+
diff --git a/0222-hw-qxl-tracing-fixes.patch b/0222-hw-qxl-tracing-fixes.patch
new file mode 100644
index 0000000..2feba9d
--- /dev/null
+++ b/0222-hw-qxl-tracing-fixes.patch
@@ -0,0 +1,96 @@
+From b1b9a04abd4cc461e507091fadea866788d4a60a Mon Sep 17 00:00:00 2001
+From: Alon Levy <alevy@redhat.com>
+Date: Wed, 12 Sep 2012 16:13:26 +0300
+Subject: [PATCH 222/293] hw/qxl: tracing fixes
+
+Add two new trace events:
+qxl_send_events(int qid, uint32_t events) "%d %d"
+qxl_set_guest_bug(int qid) "%d"
+
+Change qxl_io_unexpected_vga_mode parameters to be equivalent to those
+of qxl_io_write for easier grouping under a single systemtap probe.
+
+Change d to qxl in one place.
+
+Signed-off-by: Alon Levy <alevy@redhat.com>
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+---
+ hw/qxl.c     | 8 +++++---
+ trace-events | 6 ++++--
+ 2 files changed, 9 insertions(+), 5 deletions(-)
+
+diff --git a/hw/qxl.c b/hw/qxl.c
+index 9f06f5e..360f4f6 100644
+--- a/hw/qxl.c
++++ b/hw/qxl.c
+@@ -141,6 +141,7 @@ static void qxl_ring_set_dirty(PCIQXLDevice *qxl);
+ 
+ void qxl_set_guest_bug(PCIQXLDevice *qxl, const char *msg, ...)
+ {
++    trace_qxl_set_guest_bug(qxl->id);
+     qxl_send_events(qxl, QXL_INTERRUPT_ERROR);
+     qxl->guest_bug = 1;
+     if (qxl->guestdebug) {
+@@ -1408,7 +1409,7 @@ static void ioport_write(void *opaque, target_phys_addr_t addr,
+             break;
+         }
+         trace_qxl_io_unexpected_vga_mode(d->id,
+-            io_port, io_port_to_string(io_port));
++            addr, val, io_port_to_string(io_port));
+         /* be nice to buggy guest drivers */
+         if (io_port >= QXL_IO_UPDATE_AREA_ASYNC &&
+             io_port < QXL_IO_RANGE_SIZE) {
+@@ -1607,9 +1608,9 @@ cancel_async:
+ static uint64_t ioport_read(void *opaque, target_phys_addr_t addr,
+                             unsigned size)
+ {
+-    PCIQXLDevice *d = opaque;
++    PCIQXLDevice *qxl = opaque;
+ 
+-    trace_qxl_io_read_unexpected(d->id);
++    trace_qxl_io_read_unexpected(qxl->id);
+     return 0xff;
+ }
+ 
+@@ -1639,6 +1640,7 @@ static void qxl_send_events(PCIQXLDevice *d, uint32_t events)
+     uint32_t old_pending;
+     uint32_t le_events = cpu_to_le32(events);
+ 
++    trace_qxl_send_events(d->id, events);
+     assert(qemu_spice_display_is_running(&d->ssd));
+     old_pending = __sync_fetch_and_or(&d->ram->int_pending, le_events);
+     if ((old_pending & le_events) == le_events) {
+diff --git a/trace-events b/trace-events
+index 8fcbc50..42dfb93 100644
+--- a/trace-events
++++ b/trace-events
+@@ -925,7 +925,7 @@ qxl_interface_update_area_complete_overflow(int qid, int max) "%d max=%d"
+ qxl_interface_update_area_complete_schedule_bh(int qid, uint32_t num_dirty) "%d #dirty=%d"
+ qxl_io_destroy_primary_ignored(int qid, const char *mode) "%d %s"
+ qxl_io_read_unexpected(int qid) "%d"
+-qxl_io_unexpected_vga_mode(int qid, uint32_t io_port, const char *desc) "%d 0x%x (%s)"
++qxl_io_unexpected_vga_mode(int qid, uint64_t addr, uint64_t val, const char *desc) "%d 0x%"PRIx64"=%"PRIu64" (%s)"
+ qxl_io_write(int qid, const char *mode, uint64_t addr, uint64_t val, unsigned size, int async) "%d %s addr=%"PRIu64 " val=%"PRIu64" size=%u async=%d"
+ qxl_memslot_add_guest(int qid, uint32_t slot_id, uint64_t guest_start, uint64_t guest_end) "%d %u: guest phys 0x%"PRIx64 " - 0x%" PRIx64
+ qxl_post_load(int qid, const char *mode) "%d %s"
+@@ -956,7 +956,7 @@ qxl_spice_destroy_surfaces(int qid, int async) "%d async=%d"
+ qxl_spice_destroy_surface_wait_complete(int qid, uint32_t id) "%d sid=%d"
+ qxl_spice_destroy_surface_wait(int qid, uint32_t id, int async) "%d sid=%d async=%d"
+ qxl_spice_flush_surfaces_async(int qid, uint32_t surface_count, uint32_t num_free_res) "%d s#=%d, res#=%d"
+-qxl_spice_monitors_config(int id) "%d"
++qxl_spice_monitors_config(int qid) "%d"
+ qxl_spice_loadvm_commands(int qid, void *ext, uint32_t count) "%d ext=%p count=%d"
+ qxl_spice_oom(int qid) "%d"
+ qxl_spice_reset_cursor(int qid) "%d"
+@@ -965,6 +965,8 @@ qxl_spice_reset_memslots(int qid) "%d"
+ qxl_spice_update_area(int qid, uint32_t surface_id, uint32_t left, uint32_t right, uint32_t top, uint32_t bottom) "%d sid=%d [%d,%d,%d,%d]"
+ qxl_spice_update_area_rest(int qid, uint32_t num_dirty_rects, uint32_t clear_dirty_region) "%d #d=%d clear=%d"
+ qxl_surfaces_dirty(int qid, int surface, int offset, int size) "%d surface=%d offset=%d size=%d"
++qxl_send_events(int qid, uint32_t events) "%d %d"
++qxl_set_guest_bug(int qid) "%d"
+ 
+ # hw/qxl-render.c
+ qxl_render_blit_guest_primary_initialized(void) ""
+-- 
+1.7.12
+
diff --git a/0223-qxl-add-trace-event-for-QXL_IO_LOG.patch b/0223-qxl-add-trace-event-for-QXL_IO_LOG.patch
new file mode 100644
index 0000000..84982fa
--- /dev/null
+++ b/0223-qxl-add-trace-event-for-QXL_IO_LOG.patch
@@ -0,0 +1,39 @@
+From f4cebc3d7a15ecccf61809c35242427e2c2e6713 Mon Sep 17 00:00:00 2001
+From: Alon Levy <alevy@redhat.com>
+Date: Wed, 12 Sep 2012 16:13:27 +0300
+Subject: [PATCH 223/293] qxl: add trace-event for QXL_IO_LOG
+
+Signed-off-by: Alon Levy <alevy@redhat.com>
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+---
+ hw/qxl.c     | 1 +
+ trace-events | 1 +
+ 2 files changed, 2 insertions(+)
+
+diff --git a/hw/qxl.c b/hw/qxl.c
+index 360f4f6..1ef117a 100644
+--- a/hw/qxl.c
++++ b/hw/qxl.c
+@@ -1515,6 +1515,7 @@ async_common:
+         qxl_set_mode(d, val, 0);
+         break;
+     case QXL_IO_LOG:
++        trace_qxl_io_log(d->id, d->ram->log_buf);
+         if (d->guestdebug) {
+             fprintf(stderr, "qxl/guest-%d: %" PRId64 ": %s", d->id,
+                     qemu_get_clock_ns(vm_clock), d->ram->log_buf);
+diff --git a/trace-events b/trace-events
+index 42dfb93..0ce69d6 100644
+--- a/trace-events
++++ b/trace-events
+@@ -924,6 +924,7 @@ qxl_interface_update_area_complete_rest(int qid, uint32_t num_updated_rects) "%d
+ qxl_interface_update_area_complete_overflow(int qid, int max) "%d max=%d"
+ qxl_interface_update_area_complete_schedule_bh(int qid, uint32_t num_dirty) "%d #dirty=%d"
+ qxl_io_destroy_primary_ignored(int qid, const char *mode) "%d %s"
++qxl_io_log(int qid, const uint8_t *str) "%d %s"
+ qxl_io_read_unexpected(int qid) "%d"
+ qxl_io_unexpected_vga_mode(int qid, uint64_t addr, uint64_t val, const char *desc) "%d 0x%"PRIx64"=%"PRIu64" (%s)"
+ qxl_io_write(int qid, const char *mode, uint64_t addr, uint64_t val, unsigned size, int async) "%d %s addr=%"PRIu64 " val=%"PRIu64" size=%u async=%d"
+-- 
+1.7.12
+
diff --git a/0224-hw-qxl-support-client-monitor-configuration-via-devi.patch b/0224-hw-qxl-support-client-monitor-configuration-via-devi.patch
new file mode 100644
index 0000000..56cd1e1
--- /dev/null
+++ b/0224-hw-qxl-support-client-monitor-configuration-via-devi.patch
@@ -0,0 +1,182 @@
+From 3ad6b56cb328a01150fc9a61ee7f4300af2a0912 Mon Sep 17 00:00:00 2001
+From: Alon Levy <alevy@redhat.com>
+Date: Wed, 12 Sep 2012 16:13:28 +0300
+Subject: [PATCH 224/293] hw/qxl: support client monitor configuration via
+ device
+
+Until now we used only the agent to change the monitor count and each
+monitor resolution. This patch introduces the qemu part of using the
+device as the mediator instead of the agent via virtio-serial.
+
+Spice (>=0.11.5) calls the new QXLInterface::client_monitors_config,
+which returns wether the interrupt is enabled, and if so and given a non
+NULL monitors config will
+generate an interrupt QXL_INTERRUPT_CLIENT_MONITORS_CONFIG with crc
+checksum for the guest to verify a second call hasn't interfered.
+
+The maximal number of monitors is limited on the QXLRom to 64.
+
+Signed-off-by: Alon Levy <alevy@redhat.com>
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+---
+ configure    |  7 ++++++
+ hw/qxl.c     | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ trace-events |  6 ++++-
+ 3 files changed, 91 insertions(+), 1 deletion(-)
+
+diff --git a/configure b/configure
+index 0bfef84..ebe8b1c 100755
+--- a/configure
++++ b/configure
+@@ -2716,6 +2716,9 @@ EOF
+     if $pkg_config --atleast-version=0.12.0 spice-protocol >/dev/null 2>&1; then
+         spice_qxl_io_monitors_config_async="yes"
+     fi
++    if $pkg_config --atleast-version=0.12.2 spice-protocol > /dev/null 2>&1; then
++        spice_qxl_client_monitors_config="yes"
++    fi
+   else
+     if test "$spice" = "yes" ; then
+       feature_not_found "spice"
+@@ -3457,6 +3460,10 @@ if test "$spice_qxl_io_monitors_config_async" = "yes" ; then
+   echo "CONFIG_QXL_IO_MONITORS_CONFIG_ASYNC=y" >> $config_host_mak
+ fi
+ 
++if test "$spice_qxl_client_monitors_config" = "yes" ; then
++  echo "CONFIG_QXL_CLIENT_MONITORS_CONFIG=y" >> $config_host_mak
++fi
++
+ if test "$smartcard" = "yes" ; then
+   echo "CONFIG_SMARTCARD=y" >> $config_host_mak
+ fi
+diff --git a/hw/qxl.c b/hw/qxl.c
+index 1ef117a..0695872 100644
+--- a/hw/qxl.c
++++ b/hw/qxl.c
+@@ -18,6 +18,8 @@
+  * along with this program; if not, see <http://www.gnu.org/licenses/>.
+  */
+ 
++#include <zlib.h>
++
+ #include "qemu-common.h"
+ #include "qemu-timer.h"
+ #include "qemu-queue.h"
+@@ -971,6 +973,79 @@ static void interface_set_client_capabilities(QXLInstance *sin,
+ 
+ #endif
+ 
++#if defined(CONFIG_QXL_CLIENT_MONITORS_CONFIG) \
++    && SPICE_SERVER_VERSION >= 0x000b05
++
++static uint32_t qxl_crc32(const uint8_t *p, unsigned len)
++{
++    /*
++     * zlib xors the seed with 0xffffffff, and xors the result
++     * again with 0xffffffff; Both are not done with linux's crc32,
++     * which we want to be compatible with, so undo that.
++     */
++    return crc32(0xffffffff, p, len) ^ 0xffffffff;
++}
++
++/* called from main context only */
++static int interface_client_monitors_config(QXLInstance *sin,
++                                        VDAgentMonitorsConfig *monitors_config)
++{
++    PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
++    QXLRom *rom = memory_region_get_ram_ptr(&qxl->rom_bar);
++    int i;
++
++    /*
++     * Older windows drivers set int_mask to 0 when their ISR is called,
++     * then later set it to ~0. So it doesn't relate to the actual interrupts
++     * handled. However, they are old, so clearly they don't support this
++     * interrupt
++     */
++    if (qxl->ram->int_mask == 0 || qxl->ram->int_mask == ~0 ||
++        !(qxl->ram->int_mask & QXL_INTERRUPT_CLIENT_MONITORS_CONFIG)) {
++        trace_qxl_client_monitors_config_unsupported_by_guest(qxl->id,
++                                                            qxl->ram->int_mask,
++                                                            monitors_config);
++        return 0;
++    }
++    if (!monitors_config) {
++        return 1;
++    }
++    memset(&rom->client_monitors_config, 0,
++           sizeof(rom->client_monitors_config));
++    rom->client_monitors_config.count = monitors_config->num_of_monitors;
++    /* monitors_config->flags ignored */
++    if (rom->client_monitors_config.count >=
++            ARRAY_SIZE(rom->client_monitors_config.heads)) {
++        trace_qxl_client_monitors_config_capped(qxl->id,
++                                monitors_config->num_of_monitors,
++                                ARRAY_SIZE(rom->client_monitors_config.heads));
++        rom->client_monitors_config.count =
++            ARRAY_SIZE(rom->client_monitors_config.heads);
++    }
++    for (i = 0 ; i < rom->client_monitors_config.count ; ++i) {
++        VDAgentMonConfig *monitor = &monitors_config->monitors[i];
++        QXLURect *rect = &rom->client_monitors_config.heads[i];
++        /* monitor->depth ignored */
++        rect->left = monitor->x;
++        rect->top = monitor->y;
++        rect->right = monitor->x + monitor->width;
++        rect->bottom = monitor->y + monitor->height;
++    }
++    rom->client_monitors_config_crc = qxl_crc32(
++            (const uint8_t *)&rom->client_monitors_config,
++            sizeof(rom->client_monitors_config));
++    trace_qxl_client_monitors_config_crc(qxl->id,
++            sizeof(rom->client_monitors_config),
++            rom->client_monitors_config_crc);
++
++    trace_qxl_interrupt_client_monitors_config(qxl->id,
++                        rom->client_monitors_config.count,
++                        rom->client_monitors_config.heads);
++    qxl_send_events(qxl, QXL_INTERRUPT_CLIENT_MONITORS_CONFIG);
++    return 1;
++}
++#endif
++
+ static const QXLInterface qxl_interface = {
+     .base.type               = SPICE_INTERFACE_QXL,
+     .base.description        = "qxl gpu",
+@@ -995,6 +1070,10 @@ static const QXLInterface qxl_interface = {
+ #if SPICE_SERVER_VERSION >= 0x000b04
+     .set_client_capabilities = interface_set_client_capabilities,
+ #endif
++#if SPICE_SERVER_VERSION >= 0x000b05 && \
++    defined(CONFIG_QXL_CLIENT_MONITORS_CONFIG)
++    .client_monitors_config = interface_client_monitors_config,
++#endif
+ };
+ 
+ static void qxl_enter_vga_mode(PCIQXLDevice *d)
+diff --git a/trace-events b/trace-events
+index 0ce69d6..1b19988 100644
+--- a/trace-events
++++ b/trace-events
+@@ -924,7 +924,7 @@ qxl_interface_update_area_complete_rest(int qid, uint32_t num_updated_rects) "%d
+ qxl_interface_update_area_complete_overflow(int qid, int max) "%d max=%d"
+ qxl_interface_update_area_complete_schedule_bh(int qid, uint32_t num_dirty) "%d #dirty=%d"
+ qxl_io_destroy_primary_ignored(int qid, const char *mode) "%d %s"
+-qxl_io_log(int qid, const uint8_t *str) "%d %s"
++qxl_io_log(int qid, const uint8_t *log_buf) "%d %s"
+ qxl_io_read_unexpected(int qid) "%d"
+ qxl_io_unexpected_vga_mode(int qid, uint64_t addr, uint64_t val, const char *desc) "%d 0x%"PRIx64"=%"PRIu64" (%s)"
+ qxl_io_write(int qid, const char *mode, uint64_t addr, uint64_t val, unsigned size, int async) "%d %s addr=%"PRIu64 " val=%"PRIu64" size=%u async=%d"
+@@ -968,6 +968,10 @@ qxl_spice_update_area_rest(int qid, uint32_t num_dirty_rects, uint32_t clear_dir
+ qxl_surfaces_dirty(int qid, int surface, int offset, int size) "%d surface=%d offset=%d size=%d"
+ qxl_send_events(int qid, uint32_t events) "%d %d"
+ qxl_set_guest_bug(int qid) "%d"
++qxl_interrupt_client_monitors_config(int qid, int num_heads, void *heads) "%d %d %p"
++qxl_client_monitors_config_unsupported_by_guest(int qid, uint32_t int_mask, void *client_monitors_config) "%d %X %p"
++qxl_client_monitors_config_capped(int qid, int requested, int limit) "%d %d %d"
++qxl_client_monitors_config_crc(int qid, unsigned size, uint32_t crc32) "%d %u %u"
+ 
+ # hw/qxl-render.c
+ qxl_render_blit_guest_primary_initialized(void) ""
+-- 
+1.7.12
+
diff --git a/0332-xhci-drop-buffering.patch b/0332-xhci-drop-buffering.patch
index 1097664..67de840 100644
--- a/0332-xhci-drop-buffering.patch
+++ b/0332-xhci-drop-buffering.patch
@@ -1,7 +1,7 @@
-From ad14386b3f1ccd445afd30d30a343cb9fcf6c0a7 Mon Sep 17 00:00:00 2001
+From ba184fe5a0e63bd40956b456d85a01da13d6183d Mon Sep 17 00:00:00 2001
 From: Gerd Hoffmann <kraxel@redhat.com>
 Date: Fri, 17 Aug 2012 11:04:36 +0200
-Subject: [PATCH 332/366] xhci: drop buffering
+Subject: [PATCH 332/369] xhci: drop buffering
 
 This patch splits the xhci_xfer_data function into three.
 The xhci_xfer_data function used to do does two things:
@@ -21,14 +21,16 @@ The patch also fixes reporting of transaction errors which must be
 reported unconditinally, not only in case the guest asks for it
 using the ISP flag.
 
+[ v2: fix warning ]
+
 Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
 ---
- hw/usb/hcd-xhci.c | 183 +++++++++++++++++++++---------------------------------
+ hw/usb/hcd-xhci.c | 185 +++++++++++++++++++++---------------------------------
  trace-events      |   2 +-
- 2 files changed, 72 insertions(+), 113 deletions(-)
+ 2 files changed, 72 insertions(+), 115 deletions(-)
 
 diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
-index c0a2476..c858b6d 100644
+index c0a2476..446d692 100644
 --- a/hw/usb/hcd-xhci.c
 +++ b/hw/usb/hcd-xhci.c
 @@ -305,6 +305,7 @@ typedef struct XHCIState XHCIState;
@@ -266,7 +268,15 @@ index c0a2476..c858b6d 100644
          xhci_stall_ep(xfer);
          break;
      default:
-@@ -1279,8 +1280,7 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
+@@ -1271,7 +1272,6 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
+ {
+     XHCITRB *trb_setup, *trb_status;
+     uint8_t bmRequestType;
+-    uint16_t wLength;
+     XHCIPort *port;
+     USBDevice *dev;
+     int ret;
+@@ -1279,8 +1279,7 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
      trb_setup = &xfer->trbs[0];
      trb_status = &xfer->trbs[xfer->trb_count-1];
  
@@ -276,10 +286,12 @@ index c0a2476..c858b6d 100644
  
      /* at most one Event Data TRB allowed after STATUS */
      if (TRB_TYPE(*trb_status) == TR_EVDATA && xfer->trb_count > 2) {
-@@ -1311,18 +1311,6 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
-     bmRequestType = trb_setup->parameter;
-     wLength = trb_setup->parameter >> 48;
+@@ -1309,19 +1308,6 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
+     }
  
+     bmRequestType = trb_setup->parameter;
+-    wLength = trb_setup->parameter >> 48;
+-
 -    if (xfer->data && xfer->data_alloced < wLength) {
 -        xfer->data_alloced = 0;
 -        g_free(xfer->data);
@@ -291,11 +303,10 @@ index c0a2476..c858b6d 100644
 -        xfer->data_alloced = wLength;
 -    }
 -    xfer->data_length = wLength;
--
+ 
      port = &xhci->ports[xhci->slots[xfer->slotid-1].port-1];
      dev = xhci_find_device(port, xhci->slots[xfer->slotid-1].devaddr);
-     if (!dev) {
-@@ -1336,9 +1324,6 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
+@@ -1336,9 +1322,6 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
  
      xhci_setup_packet(xfer, dev);
      xfer->packet.parameter = trb_setup->parameter;
@@ -305,7 +316,7 @@ index c0a2476..c858b6d 100644
  
      ret = usb_handle_packet(dev, &xfer->packet);
  
-@@ -1359,16 +1344,6 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx
+@@ -1359,16 +1342,6 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx
  
      xfer->in_xfer = epctx->type>>2;
  
@@ -322,7 +333,7 @@ index c0a2476..c858b6d 100644
      if (epctx->type == ET_ISO_IN || epctx->type == ET_ISO_OUT) {
          xfer->pkts = 1;
      } else {
-@@ -1402,9 +1377,6 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx
+@@ -1402,9 +1375,6 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx
          return -1;
      }
  
@@ -332,7 +343,7 @@ index c0a2476..c858b6d 100644
      ret = usb_handle_packet(dev, &xfer->packet);
  
      xhci_complete_packet(xfer, ret);
-@@ -1416,20 +1388,7 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx
+@@ -1416,20 +1386,7 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx
  
  static int xhci_fire_transfer(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx)
  {
diff --git a/0333-xhci-move-device-lookup-into-xhci_setup_packet.patch b/0333-xhci-move-device-lookup-into-xhci_setup_packet.patch
index 3cde29a..2ac0629 100644
--- a/0333-xhci-move-device-lookup-into-xhci_setup_packet.patch
+++ b/0333-xhci-move-device-lookup-into-xhci_setup_packet.patch
@@ -1,7 +1,7 @@
-From 76d49f5c5abc30f33f5b9288df68d53dba9e10f0 Mon Sep 17 00:00:00 2001
+From e144accdeb05222cf671c3bad142c81c40dbacdb Mon Sep 17 00:00:00 2001
 From: Gerd Hoffmann <kraxel@redhat.com>
 Date: Fri, 24 Aug 2012 14:21:39 +0200
-Subject: [PATCH 333/366] xhci: move device lookup into xhci_setup_packet
+Subject: [PATCH 333/369] xhci: move device lookup into xhci_setup_packet
 
 Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
 ---
@@ -9,7 +9,7 @@ Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
  1 file changed, 38 insertions(+), 36 deletions(-)
 
 diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
-index c858b6d..303e1ac 100644
+index 446d692..c108c9d 100644
 --- a/hw/usb/hcd-xhci.c
 +++ b/hw/usb/hcd-xhci.c
 @@ -1196,13 +1196,38 @@ static void xhci_stall_ep(XHCITransfer *xfer)
@@ -53,7 +53,7 @@ index c858b6d..303e1ac 100644
      usb_packet_setup(&xfer->packet, dir, ep, xfer->trbs[0].addr);
      xhci_xfer_map(xfer);
      DPRINTF("xhci: setup packet pid 0x%x addr %d ep %d\n",
-@@ -1260,21 +1285,11 @@ static int xhci_complete_packet(XHCITransfer *xfer, int ret)
+@@ -1260,20 +1285,10 @@ static int xhci_complete_packet(XHCITransfer *xfer, int ret)
      return 0;
  }
  
@@ -69,15 +69,14 @@ index c858b6d..303e1ac 100644
  {
      XHCITRB *trb_setup, *trb_status;
      uint8_t bmRequestType;
-     uint16_t wLength;
 -    XHCIPort *port;
 -    USBDevice *dev;
      int ret;
  
      trb_setup = &xfer->trbs[0];
-@@ -1311,21 +1326,15 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
+@@ -1309,21 +1324,15 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
+ 
      bmRequestType = trb_setup->parameter;
-     wLength = trb_setup->parameter >> 48;
  
 -    port = &xhci->ports[xhci->slots[xfer->slotid-1].port-1];
 -    dev = xhci_find_device(port, xhci->slots[xfer->slotid-1].devaddr);
@@ -101,7 +100,7 @@ index c858b6d..303e1ac 100644
  
      xhci_complete_packet(xfer, ret);
      if (!xfer->running_async && !xfer->running_retry) {
-@@ -1336,8 +1345,6 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
+@@ -1334,8 +1343,6 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
  
  static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx)
  {
@@ -110,7 +109,7 @@ index c858b6d..303e1ac 100644
      int ret;
  
      DPRINTF("xhci_submit(slotid=%d,epid=%d)\n", xfer->slotid, xfer->epid);
-@@ -1350,16 +1357,6 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx
+@@ -1348,16 +1355,6 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx
          xfer->pkts = 0;
      }
  
@@ -127,7 +126,7 @@ index c858b6d..303e1ac 100644
      switch(epctx->type) {
      case ET_INTR_OUT:
      case ET_INTR_IN:
-@@ -1377,7 +1374,10 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx
+@@ -1375,7 +1372,10 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx
          return -1;
      }
  
@@ -139,7 +138,7 @@ index c858b6d..303e1ac 100644
  
      xhci_complete_packet(xfer, ret);
      if (!xfer->running_async && !xfer->running_retry) {
-@@ -1420,7 +1420,9 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid
+@@ -1418,7 +1418,9 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid
  
          trace_usb_xhci_xfer_retry(xfer);
          assert(xfer->running_retry);
diff --git a/0355-ehci-switch-to-new-style-memory-ops.patch b/0355-ehci-switch-to-new-style-memory-ops.patch
deleted file mode 100644
index 78e6b4f..0000000
--- a/0355-ehci-switch-to-new-style-memory-ops.patch
+++ /dev/null
@@ -1,367 +0,0 @@
-From 538ee859ae415782e5be3b4a07e7db655cf70aa2 Mon Sep 17 00:00:00 2001
-From: Gerd Hoffmann <kraxel@redhat.com>
-Date: Thu, 6 Sep 2012 11:24:51 +0200
-Subject: [PATCH 355/366] ehci: switch to new-style memory ops
-
-Also register different memory regions for capabilities,
-operational registers and port status registers.  Create
-separate tracepoints for operational regs and port status
-regs.  Ditch a bunch of sanity checks because the memory
-core will do this for us now.
-
-Offloading the byte, word and dword access handling to the
-memory core also has the side effect of fixing ehci register
-access on bigendian hosts.
-
-Cc: David Gibson <david@gibson.dropbear.id.au>
-Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
----
- hw/usb/hcd-ehci.c | 173 ++++++++++++++++++++++++++----------------------------
- trace-events      |   9 ++-
- 2 files changed, 90 insertions(+), 92 deletions(-)
-
-diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
-index 2f3e9c0..f5ba8e1 100644
---- a/hw/usb/hcd-ehci.c
-+++ b/hw/usb/hcd-ehci.c
-@@ -389,6 +389,9 @@ struct EHCIState {
-     USBBus bus;
-     qemu_irq irq;
-     MemoryRegion mem;
-+    MemoryRegion mem_caps;
-+    MemoryRegion mem_opreg;
-+    MemoryRegion mem_ports;
-     int companion_count;
- 
-     /* properties */
-@@ -398,10 +401,10 @@ struct EHCIState {
-      *  EHCI spec version 1.0 Section 2.3
-      *  Host Controller Operational Registers
-      */
-+    uint8_t caps[OPREGBASE];
-     union {
--        uint8_t mmio[MMIO_SIZE];
-+        uint32_t opreg[(PORTSC_BEGIN-OPREGBASE)/sizeof(uint32_t)];
-         struct {
--            uint8_t cap[OPREGBASE];
-             uint32_t usbcmd;
-             uint32_t usbsts;
-             uint32_t usbintr;
-@@ -411,9 +414,9 @@ struct EHCIState {
-             uint32_t asynclistaddr;
-             uint32_t notused[9];
-             uint32_t configflag;
--            uint32_t portsc[NB_PORTS];
-         };
-     };
-+    uint32_t portsc[NB_PORTS];
- 
-     /*
-      *  Internal states, shadow registers, etc
-@@ -471,22 +474,12 @@ static const char *ehci_state_names[] = {
- };
- 
- static const char *ehci_mmio_names[] = {
--    [CAPLENGTH]         = "CAPLENGTH",
--    [HCIVERSION]        = "HCIVERSION",
--    [HCSPARAMS]         = "HCSPARAMS",
--    [HCCPARAMS]         = "HCCPARAMS",
-     [USBCMD]            = "USBCMD",
-     [USBSTS]            = "USBSTS",
-     [USBINTR]           = "USBINTR",
-     [FRINDEX]           = "FRINDEX",
-     [PERIODICLISTBASE]  = "P-LIST BASE",
-     [ASYNCLISTADDR]     = "A-LIST ADDR",
--    [PORTSC_BEGIN]      = "PORTSC #0",
--    [PORTSC_BEGIN + 4]  = "PORTSC #1",
--    [PORTSC_BEGIN + 8]  = "PORTSC #2",
--    [PORTSC_BEGIN + 12] = "PORTSC #3",
--    [PORTSC_BEGIN + 16] = "PORTSC #4",
--    [PORTSC_BEGIN + 20] = "PORTSC #5",
-     [CONFIGFLAG]        = "CONFIGFLAG",
- };
- 
-@@ -509,7 +502,8 @@ static const char *state2str(uint32_t state)
- 
- static const char *addr2str(target_phys_addr_t addr)
- {
--    return nr2str(ehci_mmio_names, ARRAY_SIZE(ehci_mmio_names), addr);
-+    return nr2str(ehci_mmio_names, ARRAY_SIZE(ehci_mmio_names),
-+                  addr + OPREGBASE);
- }
- 
- static void ehci_trace_usbsts(uint32_t mask, int state)
-@@ -1018,7 +1012,7 @@ static int ehci_register_companion(USBBus *bus, USBPort *ports[],
-     }
- 
-     s->companion_count++;
--    s->mmio[0x05] = (s->companion_count << 4) | portcount;
-+    s->caps[0x05] = (s->companion_count << 4) | portcount;
- 
-     return 0;
- }
-@@ -1063,7 +1057,8 @@ static void ehci_reset(void *opaque)
-         }
-     }
- 
--    memset(&s->mmio[OPREGBASE], 0x00, MMIO_SIZE - OPREGBASE);
-+    memset(&s->opreg, 0x00, sizeof(s->opreg));
-+    memset(&s->portsc, 0x00, sizeof(s->portsc));
- 
-     s->usbcmd = NB_MAXINTRATE << USBCMD_ITC_SH;
-     s->usbsts = USBSTS_HALT;
-@@ -1090,50 +1085,35 @@ static void ehci_reset(void *opaque)
-     qemu_bh_cancel(s->async_bh);
- }
- 
--static uint32_t ehci_mem_readb(void *ptr, target_phys_addr_t addr)
-+static uint64_t ehci_caps_read(void *ptr, target_phys_addr_t addr,
-+                               unsigned size)
- {
-     EHCIState *s = ptr;
--    uint32_t val;
--
--    val = s->mmio[addr];
--
--    return val;
-+    return s->caps[addr];
- }
- 
--static uint32_t ehci_mem_readw(void *ptr, target_phys_addr_t addr)
-+static uint64_t ehci_opreg_read(void *ptr, target_phys_addr_t addr,
-+                                unsigned size)
- {
-     EHCIState *s = ptr;
-     uint32_t val;
- 
--    val = s->mmio[addr] | (s->mmio[addr+1] << 8);
--
-+    val = s->opreg[addr >> 2];
-+    trace_usb_ehci_opreg_read(addr + OPREGBASE, addr2str(addr), val);
-     return val;
- }
- 
--static uint32_t ehci_mem_readl(void *ptr, target_phys_addr_t addr)
-+static uint64_t ehci_port_read(void *ptr, target_phys_addr_t addr,
-+                               unsigned size)
- {
-     EHCIState *s = ptr;
-     uint32_t val;
- 
--    val = s->mmio[addr] | (s->mmio[addr+1] << 8) |
--          (s->mmio[addr+2] << 16) | (s->mmio[addr+3] << 24);
--
--    trace_usb_ehci_mmio_readl(addr, addr2str(addr), val);
-+    val = s->portsc[addr >> 2];
-+    trace_usb_ehci_portsc_read(addr + PORTSC_BEGIN, addr >> 2, val);
-     return val;
- }
- 
--static void ehci_mem_writeb(void *ptr, target_phys_addr_t addr, uint32_t val)
--{
--    fprintf(stderr, "EHCI doesn't handle byte writes to MMIO\n");
--    exit(1);
--}
--
--static void ehci_mem_writew(void *ptr, target_phys_addr_t addr, uint32_t val)
--{
--    fprintf(stderr, "EHCI doesn't handle 16-bit writes to MMIO\n");
--    exit(1);
--}
--
- static void handle_port_owner_write(EHCIState *s, int port, uint32_t owner)
- {
-     USBDevice *dev = s->ports[port].dev;
-@@ -1162,11 +1142,17 @@ static void handle_port_owner_write(EHCIState *s, int port, uint32_t owner)
-     }
- }
- 
--static void handle_port_status_write(EHCIState *s, int port, uint32_t val)
-+static void ehci_port_write(void *ptr, target_phys_addr_t addr,
-+                            uint64_t val, unsigned size)
- {
-+    EHCIState *s = ptr;
-+    int port = addr >> 2;
-     uint32_t *portsc = &s->portsc[port];
-+    uint32_t old = *portsc;
-     USBDevice *dev = s->ports[port].dev;
- 
-+    trace_usb_ehci_portsc_write(addr + PORTSC_BEGIN, addr >> 2, val);
-+
-     /* Clear rwc bits */
-     *portsc &= ~(val & PORTSC_RWC_MASK);
-     /* The guest may clear, but not set the PED bit */
-@@ -1198,39 +1184,20 @@ static void handle_port_status_write(EHCIState *s, int port, uint32_t val)
- 
-     *portsc &= ~PORTSC_RO_MASK;
-     *portsc |= val;
-+    trace_usb_ehci_portsc_change(addr + PORTSC_BEGIN, addr >> 2, *portsc, old);
- }
- 
--static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
-+static void ehci_opreg_write(void *ptr, target_phys_addr_t addr,
-+                             uint64_t val, unsigned size)
- {
-     EHCIState *s = ptr;
--    uint32_t *mmio = (uint32_t *)(&s->mmio[addr]);
-+    uint32_t *mmio = s->opreg + (addr >> 2);
-     uint32_t old = *mmio;
-     int i;
- 
--    trace_usb_ehci_mmio_writel(addr, addr2str(addr), val);
--
--    /* Only aligned reads are allowed on OHCI */
--    if (addr & 3) {
--        fprintf(stderr, "usb-ehci: Mis-aligned write to addr 0x"
--                TARGET_FMT_plx "\n", addr);
--        return;
--    }
--
--    if (addr >= PORTSC && addr < PORTSC + 4 * NB_PORTS) {
--        handle_port_status_write(s, (addr-PORTSC)/4, val);
--        trace_usb_ehci_mmio_change(addr, addr2str(addr), *mmio, old);
--        return;
--    }
--
--    if (addr < OPREGBASE) {
--        fprintf(stderr, "usb-ehci: write attempt to read-only register"
--                TARGET_FMT_plx "\n", addr);
--        return;
--    }
--
-+    trace_usb_ehci_opreg_write(addr + OPREGBASE, addr2str(addr), val);
- 
--    /* Do any register specific pre-write processing here.  */
--    switch(addr) {
-+    switch (addr + OPREGBASE) {
-     case USBCMD:
-         if (val & USBCMD_HCRESET) {
-             ehci_reset(s);
-@@ -1241,7 +1208,7 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
-         /* not supporting dynamic frame list size at the moment */
-         if ((val & USBCMD_FLS) && !(s->usbcmd & USBCMD_FLS)) {
-             fprintf(stderr, "attempt to set frame list size -- value %d\n",
--                    val & USBCMD_FLS);
-+                    (int)val & USBCMD_FLS);
-             val &= ~USBCMD_FLS;
-         }
- 
-@@ -1308,7 +1275,7 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
-     }
- 
-     *mmio = val;
--    trace_usb_ehci_mmio_change(addr, addr2str(addr), *mmio, old);
-+    trace_usb_ehci_opreg_change(addr + OPREGBASE, addr2str(addr), *mmio, old);
- }
- 
- 
-@@ -2520,11 +2487,28 @@ static void ehci_async_bh(void *opaque)
-     ehci_advance_async_state(ehci);
- }
- 
--static const MemoryRegionOps ehci_mem_ops = {
--    .old_mmio = {
--        .read = { ehci_mem_readb, ehci_mem_readw, ehci_mem_readl },
--        .write = { ehci_mem_writeb, ehci_mem_writew, ehci_mem_writel },
--    },
-+static const MemoryRegionOps ehci_mmio_caps_ops = {
-+    .read = ehci_caps_read,
-+    .valid.min_access_size = 1,
-+    .valid.max_access_size = 4,
-+    .impl.min_access_size = 1,
-+    .impl.max_access_size = 1,
-+    .endianness = DEVICE_LITTLE_ENDIAN,
-+};
-+
-+static const MemoryRegionOps ehci_mmio_opreg_ops = {
-+    .read = ehci_opreg_read,
-+    .write = ehci_opreg_write,
-+    .valid.min_access_size = 4,
-+    .valid.max_access_size = 4,
-+    .endianness = DEVICE_LITTLE_ENDIAN,
-+};
-+
-+static const MemoryRegionOps ehci_mmio_port_ops = {
-+    .read = ehci_port_read,
-+    .write = ehci_port_write,
-+    .valid.min_access_size = 4,
-+    .valid.max_access_size = 4,
-     .endianness = DEVICE_LITTLE_ENDIAN,
- };
- 
-@@ -2681,19 +2665,19 @@ static int usb_ehci_initfn(PCIDevice *dev)
-     pci_conf[0x6e] = 0x00;
-     pci_conf[0x6f] = 0xc0;  // USBLEFCTLSTS
- 
--    // 2.2 host controller interface version
--    s->mmio[0x00] = (uint8_t) OPREGBASE;
--    s->mmio[0x01] = 0x00;
--    s->mmio[0x02] = 0x00;
--    s->mmio[0x03] = 0x01;        // HC version
--    s->mmio[0x04] = NB_PORTS;    // Number of downstream ports
--    s->mmio[0x05] = 0x00;        // No companion ports at present
--    s->mmio[0x06] = 0x00;
--    s->mmio[0x07] = 0x00;
--    s->mmio[0x08] = 0x80;        // We can cache whole frame, not 64-bit capable
--    s->mmio[0x09] = 0x68;        // EECP
--    s->mmio[0x0a] = 0x00;
--    s->mmio[0x0b] = 0x00;
-+    /* 2.2 host controller interface version */
-+    s->caps[0x00] = (uint8_t) OPREGBASE;
-+    s->caps[0x01] = 0x00;
-+    s->caps[0x02] = 0x00;
-+    s->caps[0x03] = 0x01;        /* HC version */
-+    s->caps[0x04] = NB_PORTS;    /* Number of downstream ports */
-+    s->caps[0x05] = 0x00;        /* No companion ports at present */
-+    s->caps[0x06] = 0x00;
-+    s->caps[0x07] = 0x00;
-+    s->caps[0x08] = 0x80;        /* We can cache whole frame, no 64-bit */
-+    s->caps[0x09] = 0x68;        /* EECP */
-+    s->caps[0x0a] = 0x00;
-+    s->caps[0x0b] = 0x00;
- 
-     s->irq = s->dev.irq[3];
- 
-@@ -2712,7 +2696,18 @@ static int usb_ehci_initfn(PCIDevice *dev)
- 
-     qemu_register_reset(ehci_reset, s);
- 
--    memory_region_init_io(&s->mem, &ehci_mem_ops, s, "ehci", MMIO_SIZE);
-+    memory_region_init(&s->mem, "ehci", MMIO_SIZE);
-+    memory_region_init_io(&s->mem_caps, &ehci_mmio_caps_ops, s,
-+                          "capabilities", OPREGBASE);
-+    memory_region_init_io(&s->mem_opreg, &ehci_mmio_opreg_ops, s,
-+                          "operational", PORTSC_BEGIN - OPREGBASE);
-+    memory_region_init_io(&s->mem_ports, &ehci_mmio_port_ops, s,
-+                          "ports", PORTSC_END - PORTSC_BEGIN);
-+
-+    memory_region_add_subregion(&s->mem, 0,            &s->mem_caps);
-+    memory_region_add_subregion(&s->mem, OPREGBASE,    &s->mem_opreg);
-+    memory_region_add_subregion(&s->mem, PORTSC_BEGIN, &s->mem_ports);
-+
-     pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mem);
- 
-     return 0;
-diff --git a/trace-events b/trace-events
-index b25ae1c..a58b0b7 100644
---- a/trace-events
-+++ b/trace-events
-@@ -243,9 +243,12 @@ usb_port_release(int bus, const char *port) "bus %d, port %s"
- 
- # hw/usb/hcd-ehci.c
- usb_ehci_reset(void) "=== RESET ==="
--usb_ehci_mmio_readl(uint32_t addr, const char *str, uint32_t val) "rd mmio %04x [%s] = %x"
--usb_ehci_mmio_writel(uint32_t addr, const char *str, uint32_t val) "wr mmio %04x [%s] = %x"
--usb_ehci_mmio_change(uint32_t addr, const char *str, uint32_t new, uint32_t old) "ch mmio %04x [%s] = %x (old: %x)"
-+usb_ehci_opreg_read(uint32_t addr, const char *str, uint32_t val) "rd mmio %04x [%s] = %x"
-+usb_ehci_opreg_write(uint32_t addr, const char *str, uint32_t val) "wr mmio %04x [%s] = %x"
-+usb_ehci_opreg_change(uint32_t addr, const char *str, uint32_t new, uint32_t old) "ch mmio %04x [%s] = %x (old: %x)"
-+usb_ehci_portsc_read(uint32_t addr, uint32_t port, uint32_t val) "rd mmio %04x [port %d] = %x"
-+usb_ehci_portsc_write(uint32_t addr, uint32_t port, uint32_t val) "wr mmio %04x [port %d] = %x"
-+usb_ehci_portsc_change(uint32_t addr, uint32_t port, uint32_t new, uint32_t old) "ch mmio %04x [port %d] = %x (old: %x)"
- usb_ehci_usbsts(const char *sts, int state) "usbsts %s %d"
- usb_ehci_state(const char *schedule, const char *state) "%s schedule %s"
- usb_ehci_qh_ptrs(void *q, uint32_t addr, uint32_t nxt, uint32_t c_qtd, uint32_t n_qtd, uint32_t a_qtd) "q %p - QH @ %08x: next %08x qtds %08x,%08x,%08x"
--- 
-1.7.12
-
diff --git a/0355-usb-host-allow-emulated-non-async-control-requests-w.patch b/0355-usb-host-allow-emulated-non-async-control-requests-w.patch
new file mode 100644
index 0000000..752582f
--- /dev/null
+++ b/0355-usb-host-allow-emulated-non-async-control-requests-w.patch
@@ -0,0 +1,37 @@
+From 487e24442148aa659a53f69db394642a7d93c3c6 Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Thu, 6 Sep 2012 12:03:41 +0200
+Subject: [PATCH 357/366] usb-host: allow emulated (non-async) control
+ requests without USBPacket
+
+xhci needs this for USB_REQ_SET_ADDRESS due to the way
+usb addressing is handled by the xhci hardware.
+
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+---
+ hw/usb/host-linux.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/hw/usb/host-linux.c b/hw/usb/host-linux.c
+index 8df9207..44f1a64 100644
+--- a/hw/usb/host-linux.c
++++ b/hw/usb/host-linux.c
+@@ -1045,7 +1045,6 @@ static int usb_host_handle_control(USBDevice *dev, USBPacket *p,
+ 
+     /* Note request is (bRequestType << 8) | bRequest */
+     trace_usb_host_req_control(s->bus_num, s->addr, p, request, value, index);
+-    assert(p->result == 0);
+ 
+     switch (request) {
+     case DeviceOutRequest | USB_REQ_SET_ADDRESS:
+@@ -1074,6 +1073,7 @@ static int usb_host_handle_control(USBDevice *dev, USBPacket *p,
+     }
+ 
+     /* The rest are asynchronous */
++    assert(p && p->result == 0);
+ 
+     if (length > sizeof(dev->data_buf)) {
+         fprintf(stderr, "husb: ctrl buffer too small (%d > %zu)\n",
+-- 
+1.7.12
+
diff --git a/0356-ehci-switch-to-new-style-memory-ops.patch b/0356-ehci-switch-to-new-style-memory-ops.patch
new file mode 100644
index 0000000..78e6b4f
--- /dev/null
+++ b/0356-ehci-switch-to-new-style-memory-ops.patch
@@ -0,0 +1,367 @@
+From 538ee859ae415782e5be3b4a07e7db655cf70aa2 Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Thu, 6 Sep 2012 11:24:51 +0200
+Subject: [PATCH 355/366] ehci: switch to new-style memory ops
+
+Also register different memory regions for capabilities,
+operational registers and port status registers.  Create
+separate tracepoints for operational regs and port status
+regs.  Ditch a bunch of sanity checks because the memory
+core will do this for us now.
+
+Offloading the byte, word and dword access handling to the
+memory core also has the side effect of fixing ehci register
+access on bigendian hosts.
+
+Cc: David Gibson <david@gibson.dropbear.id.au>
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+---
+ hw/usb/hcd-ehci.c | 173 ++++++++++++++++++++++++++----------------------------
+ trace-events      |   9 ++-
+ 2 files changed, 90 insertions(+), 92 deletions(-)
+
+diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
+index 2f3e9c0..f5ba8e1 100644
+--- a/hw/usb/hcd-ehci.c
++++ b/hw/usb/hcd-ehci.c
+@@ -389,6 +389,9 @@ struct EHCIState {
+     USBBus bus;
+     qemu_irq irq;
+     MemoryRegion mem;
++    MemoryRegion mem_caps;
++    MemoryRegion mem_opreg;
++    MemoryRegion mem_ports;
+     int companion_count;
+ 
+     /* properties */
+@@ -398,10 +401,10 @@ struct EHCIState {
+      *  EHCI spec version 1.0 Section 2.3
+      *  Host Controller Operational Registers
+      */
++    uint8_t caps[OPREGBASE];
+     union {
+-        uint8_t mmio[MMIO_SIZE];
++        uint32_t opreg[(PORTSC_BEGIN-OPREGBASE)/sizeof(uint32_t)];
+         struct {
+-            uint8_t cap[OPREGBASE];
+             uint32_t usbcmd;
+             uint32_t usbsts;
+             uint32_t usbintr;
+@@ -411,9 +414,9 @@ struct EHCIState {
+             uint32_t asynclistaddr;
+             uint32_t notused[9];
+             uint32_t configflag;
+-            uint32_t portsc[NB_PORTS];
+         };
+     };
++    uint32_t portsc[NB_PORTS];
+ 
+     /*
+      *  Internal states, shadow registers, etc
+@@ -471,22 +474,12 @@ static const char *ehci_state_names[] = {
+ };
+ 
+ static const char *ehci_mmio_names[] = {
+-    [CAPLENGTH]         = "CAPLENGTH",
+-    [HCIVERSION]        = "HCIVERSION",
+-    [HCSPARAMS]         = "HCSPARAMS",
+-    [HCCPARAMS]         = "HCCPARAMS",
+     [USBCMD]            = "USBCMD",
+     [USBSTS]            = "USBSTS",
+     [USBINTR]           = "USBINTR",
+     [FRINDEX]           = "FRINDEX",
+     [PERIODICLISTBASE]  = "P-LIST BASE",
+     [ASYNCLISTADDR]     = "A-LIST ADDR",
+-    [PORTSC_BEGIN]      = "PORTSC #0",
+-    [PORTSC_BEGIN + 4]  = "PORTSC #1",
+-    [PORTSC_BEGIN + 8]  = "PORTSC #2",
+-    [PORTSC_BEGIN + 12] = "PORTSC #3",
+-    [PORTSC_BEGIN + 16] = "PORTSC #4",
+-    [PORTSC_BEGIN + 20] = "PORTSC #5",
+     [CONFIGFLAG]        = "CONFIGFLAG",
+ };
+ 
+@@ -509,7 +502,8 @@ static const char *state2str(uint32_t state)
+ 
+ static const char *addr2str(target_phys_addr_t addr)
+ {
+-    return nr2str(ehci_mmio_names, ARRAY_SIZE(ehci_mmio_names), addr);
++    return nr2str(ehci_mmio_names, ARRAY_SIZE(ehci_mmio_names),
++                  addr + OPREGBASE);
+ }
+ 
+ static void ehci_trace_usbsts(uint32_t mask, int state)
+@@ -1018,7 +1012,7 @@ static int ehci_register_companion(USBBus *bus, USBPort *ports[],
+     }
+ 
+     s->companion_count++;
+-    s->mmio[0x05] = (s->companion_count << 4) | portcount;
++    s->caps[0x05] = (s->companion_count << 4) | portcount;
+ 
+     return 0;
+ }
+@@ -1063,7 +1057,8 @@ static void ehci_reset(void *opaque)
+         }
+     }
+ 
+-    memset(&s->mmio[OPREGBASE], 0x00, MMIO_SIZE - OPREGBASE);
++    memset(&s->opreg, 0x00, sizeof(s->opreg));
++    memset(&s->portsc, 0x00, sizeof(s->portsc));
+ 
+     s->usbcmd = NB_MAXINTRATE << USBCMD_ITC_SH;
+     s->usbsts = USBSTS_HALT;
+@@ -1090,50 +1085,35 @@ static void ehci_reset(void *opaque)
+     qemu_bh_cancel(s->async_bh);
+ }
+ 
+-static uint32_t ehci_mem_readb(void *ptr, target_phys_addr_t addr)
++static uint64_t ehci_caps_read(void *ptr, target_phys_addr_t addr,
++                               unsigned size)
+ {
+     EHCIState *s = ptr;
+-    uint32_t val;
+-
+-    val = s->mmio[addr];
+-
+-    return val;
++    return s->caps[addr];
+ }
+ 
+-static uint32_t ehci_mem_readw(void *ptr, target_phys_addr_t addr)
++static uint64_t ehci_opreg_read(void *ptr, target_phys_addr_t addr,
++                                unsigned size)
+ {
+     EHCIState *s = ptr;
+     uint32_t val;
+ 
+-    val = s->mmio[addr] | (s->mmio[addr+1] << 8);
+-
++    val = s->opreg[addr >> 2];
++    trace_usb_ehci_opreg_read(addr + OPREGBASE, addr2str(addr), val);
+     return val;
+ }
+ 
+-static uint32_t ehci_mem_readl(void *ptr, target_phys_addr_t addr)
++static uint64_t ehci_port_read(void *ptr, target_phys_addr_t addr,
++                               unsigned size)
+ {
+     EHCIState *s = ptr;
+     uint32_t val;
+ 
+-    val = s->mmio[addr] | (s->mmio[addr+1] << 8) |
+-          (s->mmio[addr+2] << 16) | (s->mmio[addr+3] << 24);
+-
+-    trace_usb_ehci_mmio_readl(addr, addr2str(addr), val);
++    val = s->portsc[addr >> 2];
++    trace_usb_ehci_portsc_read(addr + PORTSC_BEGIN, addr >> 2, val);
+     return val;
+ }
+ 
+-static void ehci_mem_writeb(void *ptr, target_phys_addr_t addr, uint32_t val)
+-{
+-    fprintf(stderr, "EHCI doesn't handle byte writes to MMIO\n");
+-    exit(1);
+-}
+-
+-static void ehci_mem_writew(void *ptr, target_phys_addr_t addr, uint32_t val)
+-{
+-    fprintf(stderr, "EHCI doesn't handle 16-bit writes to MMIO\n");
+-    exit(1);
+-}
+-
+ static void handle_port_owner_write(EHCIState *s, int port, uint32_t owner)
+ {
+     USBDevice *dev = s->ports[port].dev;
+@@ -1162,11 +1142,17 @@ static void handle_port_owner_write(EHCIState *s, int port, uint32_t owner)
+     }
+ }
+ 
+-static void handle_port_status_write(EHCIState *s, int port, uint32_t val)
++static void ehci_port_write(void *ptr, target_phys_addr_t addr,
++                            uint64_t val, unsigned size)
+ {
++    EHCIState *s = ptr;
++    int port = addr >> 2;
+     uint32_t *portsc = &s->portsc[port];
++    uint32_t old = *portsc;
+     USBDevice *dev = s->ports[port].dev;
+ 
++    trace_usb_ehci_portsc_write(addr + PORTSC_BEGIN, addr >> 2, val);
++
+     /* Clear rwc bits */
+     *portsc &= ~(val & PORTSC_RWC_MASK);
+     /* The guest may clear, but not set the PED bit */
+@@ -1198,39 +1184,20 @@ static void handle_port_status_write(EHCIState *s, int port, uint32_t val)
+ 
+     *portsc &= ~PORTSC_RO_MASK;
+     *portsc |= val;
++    trace_usb_ehci_portsc_change(addr + PORTSC_BEGIN, addr >> 2, *portsc, old);
+ }
+ 
+-static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
++static void ehci_opreg_write(void *ptr, target_phys_addr_t addr,
++                             uint64_t val, unsigned size)
+ {
+     EHCIState *s = ptr;
+-    uint32_t *mmio = (uint32_t *)(&s->mmio[addr]);
++    uint32_t *mmio = s->opreg + (addr >> 2);
+     uint32_t old = *mmio;
+     int i;
+ 
+-    trace_usb_ehci_mmio_writel(addr, addr2str(addr), val);
+-
+-    /* Only aligned reads are allowed on OHCI */
+-    if (addr & 3) {
+-        fprintf(stderr, "usb-ehci: Mis-aligned write to addr 0x"
+-                TARGET_FMT_plx "\n", addr);
+-        return;
+-    }
+-
+-    if (addr >= PORTSC && addr < PORTSC + 4 * NB_PORTS) {
+-        handle_port_status_write(s, (addr-PORTSC)/4, val);
+-        trace_usb_ehci_mmio_change(addr, addr2str(addr), *mmio, old);
+-        return;
+-    }
+-
+-    if (addr < OPREGBASE) {
+-        fprintf(stderr, "usb-ehci: write attempt to read-only register"
+-                TARGET_FMT_plx "\n", addr);
+-        return;
+-    }
+-
++    trace_usb_ehci_opreg_write(addr + OPREGBASE, addr2str(addr), val);
+ 
+-    /* Do any register specific pre-write processing here.  */
+-    switch(addr) {
++    switch (addr + OPREGBASE) {
+     case USBCMD:
+         if (val & USBCMD_HCRESET) {
+             ehci_reset(s);
+@@ -1241,7 +1208,7 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
+         /* not supporting dynamic frame list size at the moment */
+         if ((val & USBCMD_FLS) && !(s->usbcmd & USBCMD_FLS)) {
+             fprintf(stderr, "attempt to set frame list size -- value %d\n",
+-                    val & USBCMD_FLS);
++                    (int)val & USBCMD_FLS);
+             val &= ~USBCMD_FLS;
+         }
+ 
+@@ -1308,7 +1275,7 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
+     }
+ 
+     *mmio = val;
+-    trace_usb_ehci_mmio_change(addr, addr2str(addr), *mmio, old);
++    trace_usb_ehci_opreg_change(addr + OPREGBASE, addr2str(addr), *mmio, old);
+ }
+ 
+ 
+@@ -2520,11 +2487,28 @@ static void ehci_async_bh(void *opaque)
+     ehci_advance_async_state(ehci);
+ }
+ 
+-static const MemoryRegionOps ehci_mem_ops = {
+-    .old_mmio = {
+-        .read = { ehci_mem_readb, ehci_mem_readw, ehci_mem_readl },
+-        .write = { ehci_mem_writeb, ehci_mem_writew, ehci_mem_writel },
+-    },
++static const MemoryRegionOps ehci_mmio_caps_ops = {
++    .read = ehci_caps_read,
++    .valid.min_access_size = 1,
++    .valid.max_access_size = 4,
++    .impl.min_access_size = 1,
++    .impl.max_access_size = 1,
++    .endianness = DEVICE_LITTLE_ENDIAN,
++};
++
++static const MemoryRegionOps ehci_mmio_opreg_ops = {
++    .read = ehci_opreg_read,
++    .write = ehci_opreg_write,
++    .valid.min_access_size = 4,
++    .valid.max_access_size = 4,
++    .endianness = DEVICE_LITTLE_ENDIAN,
++};
++
++static const MemoryRegionOps ehci_mmio_port_ops = {
++    .read = ehci_port_read,
++    .write = ehci_port_write,
++    .valid.min_access_size = 4,
++    .valid.max_access_size = 4,
+     .endianness = DEVICE_LITTLE_ENDIAN,
+ };
+ 
+@@ -2681,19 +2665,19 @@ static int usb_ehci_initfn(PCIDevice *dev)
+     pci_conf[0x6e] = 0x00;
+     pci_conf[0x6f] = 0xc0;  // USBLEFCTLSTS
+ 
+-    // 2.2 host controller interface version
+-    s->mmio[0x00] = (uint8_t) OPREGBASE;
+-    s->mmio[0x01] = 0x00;
+-    s->mmio[0x02] = 0x00;
+-    s->mmio[0x03] = 0x01;        // HC version
+-    s->mmio[0x04] = NB_PORTS;    // Number of downstream ports
+-    s->mmio[0x05] = 0x00;        // No companion ports at present
+-    s->mmio[0x06] = 0x00;
+-    s->mmio[0x07] = 0x00;
+-    s->mmio[0x08] = 0x80;        // We can cache whole frame, not 64-bit capable
+-    s->mmio[0x09] = 0x68;        // EECP
+-    s->mmio[0x0a] = 0x00;
+-    s->mmio[0x0b] = 0x00;
++    /* 2.2 host controller interface version */
++    s->caps[0x00] = (uint8_t) OPREGBASE;
++    s->caps[0x01] = 0x00;
++    s->caps[0x02] = 0x00;
++    s->caps[0x03] = 0x01;        /* HC version */
++    s->caps[0x04] = NB_PORTS;    /* Number of downstream ports */
++    s->caps[0x05] = 0x00;        /* No companion ports at present */
++    s->caps[0x06] = 0x00;
++    s->caps[0x07] = 0x00;
++    s->caps[0x08] = 0x80;        /* We can cache whole frame, no 64-bit */
++    s->caps[0x09] = 0x68;        /* EECP */
++    s->caps[0x0a] = 0x00;
++    s->caps[0x0b] = 0x00;
+ 
+     s->irq = s->dev.irq[3];
+ 
+@@ -2712,7 +2696,18 @@ static int usb_ehci_initfn(PCIDevice *dev)
+ 
+     qemu_register_reset(ehci_reset, s);
+ 
+-    memory_region_init_io(&s->mem, &ehci_mem_ops, s, "ehci", MMIO_SIZE);
++    memory_region_init(&s->mem, "ehci", MMIO_SIZE);
++    memory_region_init_io(&s->mem_caps, &ehci_mmio_caps_ops, s,
++                          "capabilities", OPREGBASE);
++    memory_region_init_io(&s->mem_opreg, &ehci_mmio_opreg_ops, s,
++                          "operational", PORTSC_BEGIN - OPREGBASE);
++    memory_region_init_io(&s->mem_ports, &ehci_mmio_port_ops, s,
++                          "ports", PORTSC_END - PORTSC_BEGIN);
++
++    memory_region_add_subregion(&s->mem, 0,            &s->mem_caps);
++    memory_region_add_subregion(&s->mem, OPREGBASE,    &s->mem_opreg);
++    memory_region_add_subregion(&s->mem, PORTSC_BEGIN, &s->mem_ports);
++
+     pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mem);
+ 
+     return 0;
+diff --git a/trace-events b/trace-events
+index b25ae1c..a58b0b7 100644
+--- a/trace-events
++++ b/trace-events
+@@ -243,9 +243,12 @@ usb_port_release(int bus, const char *port) "bus %d, port %s"
+ 
+ # hw/usb/hcd-ehci.c
+ usb_ehci_reset(void) "=== RESET ==="
+-usb_ehci_mmio_readl(uint32_t addr, const char *str, uint32_t val) "rd mmio %04x [%s] = %x"
+-usb_ehci_mmio_writel(uint32_t addr, const char *str, uint32_t val) "wr mmio %04x [%s] = %x"
+-usb_ehci_mmio_change(uint32_t addr, const char *str, uint32_t new, uint32_t old) "ch mmio %04x [%s] = %x (old: %x)"
++usb_ehci_opreg_read(uint32_t addr, const char *str, uint32_t val) "rd mmio %04x [%s] = %x"
++usb_ehci_opreg_write(uint32_t addr, const char *str, uint32_t val) "wr mmio %04x [%s] = %x"
++usb_ehci_opreg_change(uint32_t addr, const char *str, uint32_t new, uint32_t old) "ch mmio %04x [%s] = %x (old: %x)"
++usb_ehci_portsc_read(uint32_t addr, uint32_t port, uint32_t val) "rd mmio %04x [port %d] = %x"
++usb_ehci_portsc_write(uint32_t addr, uint32_t port, uint32_t val) "wr mmio %04x [port %d] = %x"
++usb_ehci_portsc_change(uint32_t addr, uint32_t port, uint32_t new, uint32_t old) "ch mmio %04x [port %d] = %x (old: %x)"
+ usb_ehci_usbsts(const char *sts, int state) "usbsts %s %d"
+ usb_ehci_state(const char *schedule, const char *state) "%s schedule %s"
+ usb_ehci_qh_ptrs(void *q, uint32_t addr, uint32_t nxt, uint32_t c_qtd, uint32_t n_qtd, uint32_t a_qtd) "q %p - QH @ %08x: next %08x qtds %08x,%08x,%08x"
+-- 
+1.7.12
+
diff --git a/0356-xhci-drop-unused-wlength.patch b/0356-xhci-drop-unused-wlength.patch
deleted file mode 100644
index 7bc3008..0000000
--- a/0356-xhci-drop-unused-wlength.patch
+++ /dev/null
@@ -1,33 +0,0 @@
-From 0b32fd99ab948db3b4cac32562272095a2594f4c Mon Sep 17 00:00:00 2001
-From: Gerd Hoffmann <kraxel@redhat.com>
-Date: Thu, 6 Sep 2012 11:55:06 +0200
-Subject: [PATCH 356/366] xhci: drop unused wlength
-
-Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
----
- hw/usb/hcd-xhci.c | 2 --
- 1 file changed, 2 deletions(-)
-
-diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
-index 2918e64..e0ca690 100644
---- a/hw/usb/hcd-xhci.c
-+++ b/hw/usb/hcd-xhci.c
-@@ -1505,7 +1505,6 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
- {
-     XHCITRB *trb_setup, *trb_status;
-     uint8_t bmRequestType;
--    uint16_t wLength;
-     int ret;
- 
-     trb_setup = &xfer->trbs[0];
-@@ -1540,7 +1539,6 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
-     }
- 
-     bmRequestType = trb_setup->parameter;
--    wLength = trb_setup->parameter >> 48;
- 
-     xfer->in_xfer = bmRequestType & USB_DIR_IN;
-     xfer->iso_xfer = false;
--- 
-1.7.12
-
diff --git a/0357-ehci-Fix-interrupts-stopping-when-Interrupt-Threshol.patch b/0357-ehci-Fix-interrupts-stopping-when-Interrupt-Threshol.patch
new file mode 100644
index 0000000..803ab11
--- /dev/null
+++ b/0357-ehci-Fix-interrupts-stopping-when-Interrupt-Threshol.patch
@@ -0,0 +1,34 @@
+From 2ebb3309738501fcc9e8da807866fa4225bb5e91 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Mon, 10 Sep 2012 11:44:08 +0200
+Subject: [PATCH 357/369] ehci: Fix interrupts stopping when Interrupt
+ Threshold Control is 8
+
+If Interrupt Threshold Control is 8 or a multiple of 8, then
+s->usbsts_frindex can become exactly 0x4000, at which point
+(s->usbsts_frindex > s->frindex) will never become true, as
+s->usbsts_frindex will not be lowered / reset in this case.
+
+This patch fixes this.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ hw/usb/hcd-ehci.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
+index f5ba8e1..54273d7 100644
+--- a/hw/usb/hcd-ehci.c
++++ b/hw/usb/hcd-ehci.c
+@@ -2413,7 +2413,7 @@ static void ehci_update_frindex(EHCIState *ehci, int frames)
+         if (ehci->frindex == 0x00004000) {
+             ehci_raise_irq(ehci, USBSTS_FLR);
+             ehci->frindex = 0;
+-            if (ehci->usbsts_frindex > 0x00004000) {
++            if (ehci->usbsts_frindex >= 0x00004000) {
+                 ehci->usbsts_frindex -= 0x00004000;
+             } else {
+                 ehci->usbsts_frindex = 0;
+-- 
+1.7.12
+
diff --git a/0357-usb-host-allow-emulated-non-async-control-requests-w.patch b/0357-usb-host-allow-emulated-non-async-control-requests-w.patch
deleted file mode 100644
index 752582f..0000000
--- a/0357-usb-host-allow-emulated-non-async-control-requests-w.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-From 487e24442148aa659a53f69db394642a7d93c3c6 Mon Sep 17 00:00:00 2001
-From: Gerd Hoffmann <kraxel@redhat.com>
-Date: Thu, 6 Sep 2012 12:03:41 +0200
-Subject: [PATCH 357/366] usb-host: allow emulated (non-async) control
- requests without USBPacket
-
-xhci needs this for USB_REQ_SET_ADDRESS due to the way
-usb addressing is handled by the xhci hardware.
-
-Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
----
- hw/usb/host-linux.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/hw/usb/host-linux.c b/hw/usb/host-linux.c
-index 8df9207..44f1a64 100644
---- a/hw/usb/host-linux.c
-+++ b/hw/usb/host-linux.c
-@@ -1045,7 +1045,6 @@ static int usb_host_handle_control(USBDevice *dev, USBPacket *p,
- 
-     /* Note request is (bRequestType << 8) | bRequest */
-     trace_usb_host_req_control(s->bus_num, s->addr, p, request, value, index);
--    assert(p->result == 0);
- 
-     switch (request) {
-     case DeviceOutRequest | USB_REQ_SET_ADDRESS:
-@@ -1074,6 +1073,7 @@ static int usb_host_handle_control(USBDevice *dev, USBPacket *p,
-     }
- 
-     /* The rest are asynchronous */
-+    assert(p && p->result == 0);
- 
-     if (length > sizeof(dev->data_buf)) {
-         fprintf(stderr, "husb: ctrl buffer too small (%d > %zu)\n",
--- 
-1.7.12
-
diff --git a/0358-ehci-Don-t-process-too-much-frames-in-1-timer-tick-v.patch b/0358-ehci-Don-t-process-too-much-frames-in-1-timer-tick-v.patch
new file mode 100644
index 0000000..9608c63
--- /dev/null
+++ b/0358-ehci-Don-t-process-too-much-frames-in-1-timer-tick-v.patch
@@ -0,0 +1,57 @@
+From d1034a88fdd8ad693a5cc2cb75af946e1562ff09 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Mon, 10 Sep 2012 12:38:21 +0200
+Subject: [PATCH 358/369] ehci: Don't process too much frames in 1 timer tick
+ (v2)
+
+The Linux ehci isoc scheduling code fills the entire schedule ahead of
+time minus 80 frames. If we make a large jump in where we are in the
+schedule, ie 40 frames, then the scheduler all of a sudden will only have
+40 frames left to work in, causing it to fail packet submissions
+with error -27 (-EFBIG).
+
+Changes in v2:
+-Don't hardcode a maximum number of frames to process in one tick, instead:
+ -Process a minimum number of frames to ensure we do eventually catch up
+ -Stop (after the minimum number) when the guest has requested an irq
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ hw/usb/hcd-ehci.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
+index 54273d7..6ce727c 100644
+--- a/hw/usb/hcd-ehci.c
++++ b/hw/usb/hcd-ehci.c
+@@ -139,6 +139,7 @@
+ #define NB_PORTS         6        // Number of downstream ports
+ #define BUFF_SIZE        5*4096   // Max bytes to transfer per transaction
+ #define MAX_QH           100      // Max allowable queue heads in a chain
++#define MIN_FR_PER_TICK  3        // Min frames to process when catching up
+ 
+ /*  Internal periodic / asynchronous schedule state machine states
+  */
+@@ -2448,6 +2449,19 @@ static void ehci_frame_timer(void *opaque)
+         }
+ 
+         for (i = 0; i < frames; i++) {
++            /* 
++             * If we're running behind schedule, we should not catch up
++             * too fast, as that will make some guests unhappy:
++             * 1) We must process a minimum of MIN_FR_PER_TICK frames,
++             *    otherwise we will never catch up
++             * 2) Process frames until the guest has requested an irq (IOC)
++             */
++            if (i >= MIN_FR_PER_TICK) {
++                ehci_commit_irq(ehci);
++                if ((ehci->usbsts & USBINTR_MASK) & ehci->usbintr) {
++                    break;
++                }
++            }
+             ehci_update_frindex(ehci, 1);
+             ehci_advance_periodic_state(ehci);
+             ehci->last_run_ns += FRAME_TIMER_NS;
+-- 
+1.7.12
+
diff --git a/0358-ehci-Don-t-set-seen-to-0-when-removing-unseen-queue-.patch b/0358-ehci-Don-t-set-seen-to-0-when-removing-unseen-queue-.patch
deleted file mode 100644
index f40d17b..0000000
--- a/0358-ehci-Don-t-set-seen-to-0-when-removing-unseen-queue-.patch
+++ /dev/null
@@ -1,101 +0,0 @@
-From 833eeda8129b2cf4955a34600b60c01e00652526 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Wed, 5 Sep 2012 12:13:41 +0200
-Subject: [PATCH 358/366] ehci: Don't set seen to 0 when removing unseen
- queue-heads
-
-When removing unseen queue-heads from the async queue list, we should not
-set the seen flag to 0, as this may cause them to be removed by
-ehci_queues_rip_unused() during the next call to ehci_advance_async_state()
-if the timer is late or running at a low frequency.
-
-Note:
-1) This *may* have caused the instant unlink / relinks described in commit
-   9bc3a3a216e2689bfcdd36c3e079333bbdbf3ba0
-
-2) Rather then putting more if-s inside ehci_queues_rip_unused, this patch
-   instead introduces a new ehci_queues_rip_unseen function.
-
-3) This patch also makes it save to call ehci_queues_rip_unseen() multiple
-   times, which gets used in the folluw up patch titled:
-   "ehci: Walk async schedule before and after migration"
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- hw/usb/hcd-ehci.c | 24 ++++++++++++++++++------
- 1 file changed, 18 insertions(+), 6 deletions(-)
-
-diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
-index f5ba8e1..6f48132 100644
---- a/hw/usb/hcd-ehci.c
-+++ b/hw/usb/hcd-ehci.c
-@@ -847,10 +847,10 @@ static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr,
-     return NULL;
- }
- 
--static void ehci_queues_rip_unused(EHCIState *ehci, int async, int flush)
-+static void ehci_queues_rip_unused(EHCIState *ehci, int async)
- {
-     EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
--    const char *warn = (async && !flush) ? "guest unlinked busy QH" : NULL;
-+    const char *warn = async ? "guest unlinked busy QH" : NULL;
-     uint64_t maxage = FRAME_TIMER_NS * ehci->maxframes * 4;
-     EHCIQueue *q, *tmp;
- 
-@@ -860,13 +860,25 @@ static void ehci_queues_rip_unused(EHCIState *ehci, int async, int flush)
-             q->ts = ehci->last_run_ns;
-             continue;
-         }
--        if (!flush && ehci->last_run_ns < q->ts + maxage) {
-+        if (ehci->last_run_ns < q->ts + maxage) {
-             continue;
-         }
-         ehci_free_queue(q, warn);
-     }
- }
- 
-+static void ehci_queues_rip_unseen(EHCIState *ehci, int async)
-+{
-+    EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
-+    EHCIQueue *q, *tmp;
-+
-+    QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
-+        if (!q->seen) {
-+            ehci_free_queue(q, NULL);
-+        }
-+    }
-+}
-+
- static void ehci_queues_rip_device(EHCIState *ehci, USBDevice *dev, int async)
- {
-     EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
-@@ -1699,7 +1711,7 @@ static int ehci_state_waitlisthead(EHCIState *ehci,  int async)
-         ehci_set_usbsts(ehci, USBSTS_REC);
-     }
- 
--    ehci_queues_rip_unused(ehci, async, 0);
-+    ehci_queues_rip_unused(ehci, async);
- 
-     /*  Find the head of the list (4.9.1.1) */
-     for(i = 0; i < MAX_QH; i++) {
-@@ -2331,7 +2343,7 @@ static void ehci_advance_async_state(EHCIState *ehci)
-          */
-         if (ehci->usbcmd & USBCMD_IAAD) {
-             /* Remove all unseen qhs from the async qhs queue */
--            ehci_queues_rip_unused(ehci, async, 1);
-+            ehci_queues_rip_unseen(ehci, async);
-             trace_usb_ehci_doorbell_ack();
-             ehci->usbcmd &= ~USBCMD_IAAD;
-             ehci_raise_irq(ehci, USBSTS_IAA);
-@@ -2384,7 +2396,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);
-+        ehci_queues_rip_unused(ehci, async);
-         break;
- 
-     default:
--- 
-1.7.12
-
diff --git a/0359-configure-usbredir-fixes.patch b/0359-configure-usbredir-fixes.patch
new file mode 100644
index 0000000..ff0454b
--- /dev/null
+++ b/0359-configure-usbredir-fixes.patch
@@ -0,0 +1,33 @@
+From 31bb27a1393168657cb53deff12d4b58601e4d72 Mon Sep 17 00:00:00 2001
+From: Aurelien Jarno <aurelien@aurel32.net>
+Date: Tue, 11 Sep 2012 18:57:58 +0000
+Subject: [PATCH 359/369] configure: usbredir fixes
+
+usbredir is only used by system emulation, so add the libraries to
+libs_softmmu instead of LIBS.
+
+Cc: Michael Tokarev <mjt@tls.msk.ru>
+Cc: Gerd Hoffmann <kraxel@redhat.com>
+Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+---
+ configure | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/configure b/configure
+index 25c406f..d63530a 100755
+--- a/configure
++++ b/configure
+@@ -2770,7 +2770,7 @@ if test "$usb_redir" != "no" ; then
+         usb_redir_cflags=$($pkg_config --cflags libusbredirparser 2>/dev/null)
+         usb_redir_libs=$($pkg_config --libs libusbredirparser 2>/dev/null)
+         QEMU_CFLAGS="$QEMU_CFLAGS $usb_redir_cflags"
+-        LIBS="$LIBS $usb_redir_libs"
++        libs_softmmu="$libs_softmmu $usb_redir_libs"
+     else
+         if test "$usb_redir" = "yes"; then
+             feature_not_found "usb-redir"
+-- 
+1.7.12
+
diff --git a/0359-ehci-Walk-async-schedule-before-and-after-migration.patch b/0359-ehci-Walk-async-schedule-before-and-after-migration.patch
deleted file mode 100644
index 3c2bf54..0000000
--- a/0359-ehci-Walk-async-schedule-before-and-after-migration.patch
+++ /dev/null
@@ -1,66 +0,0 @@
-From fec70ddafe1632f40608ef6917760a7f946f278a Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Wed, 5 Sep 2012 12:07:10 +0200
-Subject: [PATCH 359/366] ehci: Walk async schedule before and after migration
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- hw/usb/hcd-ehci.c | 28 ++++++++++++++++++++++++++++
- 1 file changed, 28 insertions(+)
-
-diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
-index 6f48132..30d2b56 100644
---- a/hw/usb/hcd-ehci.c
-+++ b/hw/usb/hcd-ehci.c
-@@ -34,6 +34,7 @@
- #include "monitor.h"
- #include "trace.h"
- #include "dma.h"
-+#include "sysemu.h"
- 
- #define EHCI_DEBUG   0
- 
-@@ -2558,6 +2559,32 @@ static int usb_ehci_post_load(void *opaque, int version_id)
-     return 0;
- }
- 
-+static void usb_ehci_vm_state_change(void *opaque, int running, RunState state)
-+{
-+    EHCIState *ehci = opaque;
-+
-+    /*
-+     * We don't migrate the EHCIQueue-s, instead we rebuild them for the
-+     * schedule in guest memory. We must do the rebuilt ASAP, so that
-+     * USB-devices which have async handled packages have a packet in the
-+     * ep queue to match the completion with.
-+     */
-+    if (state == RUN_STATE_RUNNING) {
-+        ehci_advance_async_state(ehci);
-+    }
-+
-+    /*
-+     * The schedule rebuilt from guest memory could cause the migration dest
-+     * to miss a QH unlink, and fail to cancel packets, since the unlinked QH
-+     * will never have existed on the destination. Therefor we must flush the
-+     * async schedule on savevm to catch any not yet noticed unlinks.
-+     */
-+    if (state == RUN_STATE_SAVE_VM) {
-+        ehci_advance_async_state(ehci);
-+        ehci_queues_rip_unseen(ehci, 1);
-+    }
-+}
-+
- static const VMStateDescription vmstate_ehci = {
-     .name        = "ehci",
-     .version_id  = 2,
-@@ -2707,6 +2734,7 @@ static int usb_ehci_initfn(PCIDevice *dev)
-     usb_packet_init(&s->ipacket);
- 
-     qemu_register_reset(ehci_reset, s);
-+    qemu_add_vm_change_state_handler(usb_ehci_vm_state_change, s);
- 
-     memory_region_init(&s->mem, "ehci", MMIO_SIZE);
-     memory_region_init_io(&s->mem_caps, &ehci_mmio_caps_ops, s,
--- 
-1.7.12
-
diff --git a/0360-ehci-Don-t-process-too-much-frames-in-1-timer-tick.patch b/0360-ehci-Don-t-process-too-much-frames-in-1-timer-tick.patch
deleted file mode 100644
index fb0fe6b..0000000
--- a/0360-ehci-Don-t-process-too-much-frames-in-1-timer-tick.patch
+++ /dev/null
@@ -1,49 +0,0 @@
-From d2901e4798cb106d5b265aa4e3ae05c06bf2bd1c Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Thu, 6 Sep 2012 17:10:48 +0200
-Subject: [PATCH 360/366] ehci: Don't process too much frames in 1 timer tick
-
-The Linux ehci isoc scheduling code fills the entire schedule ahead of
-time minus 80 frames. If we make a large jump in where we are in the
-schedule, ie 40 frames, then the scheduler all of a sudden will only have
-40 frames left to work in, causing it to fail packet submissions
-with error -27 (-EFBIG).
-
-Note at first I had MAX_FR_PER_TICK set to 8, which works well with newer
-Linux guest kernels, but not with older ones (such as the RHEL-6 kernel).
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- hw/usb/hcd-ehci.c | 9 +++++++++
- 1 file changed, 9 insertions(+)
-
-diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
-index 30d2b56..5398544 100644
---- a/hw/usb/hcd-ehci.c
-+++ b/hw/usb/hcd-ehci.c
-@@ -140,6 +140,7 @@
- #define NB_PORTS         6        // Number of downstream ports
- #define BUFF_SIZE        5*4096   // Max bytes to transfer per transaction
- #define MAX_QH           100      // Max allowable queue heads in a chain
-+#define MAX_FR_PER_TICK  4        /* Max frames to process in one timer tick */
- 
- /*  Internal periodic / asynchronous schedule state machine states
-  */
-@@ -2460,6 +2461,14 @@ static void ehci_frame_timer(void *opaque)
-             DPRINTF("WARNING - EHCI skipped %d frames\n", skipped_frames);
-         }
- 
-+        /*
-+         * Processing too much frames at once causes the Linux EHCI isoc
-+         * scheduling code to fail packet re-submissions with -EFBIG.
-+         */
-+        if (frames > MAX_FR_PER_TICK) {
-+            frames = MAX_FR_PER_TICK;
-+        }
-+
-         for (i = 0; i < frames; i++) {
-             ehci_update_frindex(ehci, 1);
-             ehci_advance_periodic_state(ehci);
--- 
-1.7.12
-
diff --git a/0360-ehci-Don-t-set-seen-to-0-when-removing-unseen-queue-.patch b/0360-ehci-Don-t-set-seen-to-0-when-removing-unseen-queue-.patch
new file mode 100644
index 0000000..f40d17b
--- /dev/null
+++ b/0360-ehci-Don-t-set-seen-to-0-when-removing-unseen-queue-.patch
@@ -0,0 +1,101 @@
+From 833eeda8129b2cf4955a34600b60c01e00652526 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Wed, 5 Sep 2012 12:13:41 +0200
+Subject: [PATCH 358/366] ehci: Don't set seen to 0 when removing unseen
+ queue-heads
+
+When removing unseen queue-heads from the async queue list, we should not
+set the seen flag to 0, as this may cause them to be removed by
+ehci_queues_rip_unused() during the next call to ehci_advance_async_state()
+if the timer is late or running at a low frequency.
+
+Note:
+1) This *may* have caused the instant unlink / relinks described in commit
+   9bc3a3a216e2689bfcdd36c3e079333bbdbf3ba0
+
+2) Rather then putting more if-s inside ehci_queues_rip_unused, this patch
+   instead introduces a new ehci_queues_rip_unseen function.
+
+3) This patch also makes it save to call ehci_queues_rip_unseen() multiple
+   times, which gets used in the folluw up patch titled:
+   "ehci: Walk async schedule before and after migration"
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ hw/usb/hcd-ehci.c | 24 ++++++++++++++++++------
+ 1 file changed, 18 insertions(+), 6 deletions(-)
+
+diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
+index f5ba8e1..6f48132 100644
+--- a/hw/usb/hcd-ehci.c
++++ b/hw/usb/hcd-ehci.c
+@@ -847,10 +847,10 @@ static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr,
+     return NULL;
+ }
+ 
+-static void ehci_queues_rip_unused(EHCIState *ehci, int async, int flush)
++static void ehci_queues_rip_unused(EHCIState *ehci, int async)
+ {
+     EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
+-    const char *warn = (async && !flush) ? "guest unlinked busy QH" : NULL;
++    const char *warn = async ? "guest unlinked busy QH" : NULL;
+     uint64_t maxage = FRAME_TIMER_NS * ehci->maxframes * 4;
+     EHCIQueue *q, *tmp;
+ 
+@@ -860,13 +860,25 @@ static void ehci_queues_rip_unused(EHCIState *ehci, int async, int flush)
+             q->ts = ehci->last_run_ns;
+             continue;
+         }
+-        if (!flush && ehci->last_run_ns < q->ts + maxage) {
++        if (ehci->last_run_ns < q->ts + maxage) {
+             continue;
+         }
+         ehci_free_queue(q, warn);
+     }
+ }
+ 
++static void ehci_queues_rip_unseen(EHCIState *ehci, int async)
++{
++    EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
++    EHCIQueue *q, *tmp;
++
++    QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
++        if (!q->seen) {
++            ehci_free_queue(q, NULL);
++        }
++    }
++}
++
+ static void ehci_queues_rip_device(EHCIState *ehci, USBDevice *dev, int async)
+ {
+     EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
+@@ -1699,7 +1711,7 @@ static int ehci_state_waitlisthead(EHCIState *ehci,  int async)
+         ehci_set_usbsts(ehci, USBSTS_REC);
+     }
+ 
+-    ehci_queues_rip_unused(ehci, async, 0);
++    ehci_queues_rip_unused(ehci, async);
+ 
+     /*  Find the head of the list (4.9.1.1) */
+     for(i = 0; i < MAX_QH; i++) {
+@@ -2331,7 +2343,7 @@ static void ehci_advance_async_state(EHCIState *ehci)
+          */
+         if (ehci->usbcmd & USBCMD_IAAD) {
+             /* Remove all unseen qhs from the async qhs queue */
+-            ehci_queues_rip_unused(ehci, async, 1);
++            ehci_queues_rip_unseen(ehci, async);
+             trace_usb_ehci_doorbell_ack();
+             ehci->usbcmd &= ~USBCMD_IAAD;
+             ehci_raise_irq(ehci, USBSTS_IAA);
+@@ -2384,7 +2396,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);
++        ehci_queues_rip_unused(ehci, async);
+         break;
+ 
+     default:
+-- 
+1.7.12
+
diff --git a/0361-ehci-Walk-async-schedule-before-and-after-migration.patch b/0361-ehci-Walk-async-schedule-before-and-after-migration.patch
new file mode 100644
index 0000000..3c2bf54
--- /dev/null
+++ b/0361-ehci-Walk-async-schedule-before-and-after-migration.patch
@@ -0,0 +1,66 @@
+From fec70ddafe1632f40608ef6917760a7f946f278a Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Wed, 5 Sep 2012 12:07:10 +0200
+Subject: [PATCH 359/366] ehci: Walk async schedule before and after migration
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ hw/usb/hcd-ehci.c | 28 ++++++++++++++++++++++++++++
+ 1 file changed, 28 insertions(+)
+
+diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
+index 6f48132..30d2b56 100644
+--- a/hw/usb/hcd-ehci.c
++++ b/hw/usb/hcd-ehci.c
+@@ -34,6 +34,7 @@
+ #include "monitor.h"
+ #include "trace.h"
+ #include "dma.h"
++#include "sysemu.h"
+ 
+ #define EHCI_DEBUG   0
+ 
+@@ -2558,6 +2559,32 @@ static int usb_ehci_post_load(void *opaque, int version_id)
+     return 0;
+ }
+ 
++static void usb_ehci_vm_state_change(void *opaque, int running, RunState state)
++{
++    EHCIState *ehci = opaque;
++
++    /*
++     * We don't migrate the EHCIQueue-s, instead we rebuild them for the
++     * schedule in guest memory. We must do the rebuilt ASAP, so that
++     * USB-devices which have async handled packages have a packet in the
++     * ep queue to match the completion with.
++     */
++    if (state == RUN_STATE_RUNNING) {
++        ehci_advance_async_state(ehci);
++    }
++
++    /*
++     * The schedule rebuilt from guest memory could cause the migration dest
++     * to miss a QH unlink, and fail to cancel packets, since the unlinked QH
++     * will never have existed on the destination. Therefor we must flush the
++     * async schedule on savevm to catch any not yet noticed unlinks.
++     */
++    if (state == RUN_STATE_SAVE_VM) {
++        ehci_advance_async_state(ehci);
++        ehci_queues_rip_unseen(ehci, 1);
++    }
++}
++
+ static const VMStateDescription vmstate_ehci = {
+     .name        = "ehci",
+     .version_id  = 2,
+@@ -2707,6 +2734,7 @@ static int usb_ehci_initfn(PCIDevice *dev)
+     usb_packet_init(&s->ipacket);
+ 
+     qemu_register_reset(ehci_reset, s);
++    qemu_add_vm_change_state_handler(usb_ehci_vm_state_change, s);
+ 
+     memory_region_init(&s->mem, "ehci", MMIO_SIZE);
+     memory_region_init_io(&s->mem_caps, &ehci_mmio_caps_ops, s,
+-- 
+1.7.12
+
diff --git a/0361-usb-redir-Change-cancelled-packet-code-into-a-generi.patch b/0361-usb-redir-Change-cancelled-packet-code-into-a-generi.patch
deleted file mode 100644
index 2efd733..0000000
--- a/0361-usb-redir-Change-cancelled-packet-code-into-a-generi.patch
+++ /dev/null
@@ -1,184 +0,0 @@
-From efbf5d06a89ec7b329d2aa15d3a6ea023b63c646 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Tue, 4 Sep 2012 14:18:34 +0200
-Subject: [PATCH 361/365] usb-redir: Change cancelled packet code into a
- generic packet-id queue
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- hw/usb/redirect.c | 102 +++++++++++++++++++++++++++++++++++++-----------------
- 1 file changed, 71 insertions(+), 31 deletions(-)
-
-diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
-index 9cbcddb..08776d9 100644
---- a/hw/usb/redirect.c
-+++ b/hw/usb/redirect.c
-@@ -43,7 +43,6 @@
- #define EP2I(ep_address) (((ep_address & 0x80) >> 3) | (ep_address & 0x0f))
- #define I2EP(i) (((i & 0x10) << 3) | (i & 0x0f))
- 
--typedef struct Cancelled Cancelled;
- typedef struct USBRedirDevice USBRedirDevice;
- 
- /* Struct to hold buffered packets (iso or int input packets) */
-@@ -69,6 +68,18 @@ struct endp_data {
-     int bufpq_target_size;
- };
- 
-+struct PacketIdQueueEntry {
-+    uint64_t id;
-+    QTAILQ_ENTRY(PacketIdQueueEntry)next;
-+};
-+
-+struct PacketIdQueue {
-+    USBRedirDevice *dev;
-+    const char *name;
-+    QTAILQ_HEAD(, PacketIdQueueEntry) head;
-+    int size;
-+};
-+
- struct USBRedirDevice {
-     USBDevice dev;
-     /* Properties */
-@@ -86,7 +97,7 @@ struct USBRedirDevice {
-     int64_t next_attach_time;
-     struct usbredirparser *parser;
-     struct endp_data endpoint[MAX_ENDPOINTS];
--    QTAILQ_HEAD(, Cancelled) cancelled;
-+    struct PacketIdQueue cancelled;
-     /* Data for device filtering */
-     struct usb_redir_device_connect_header device_info;
-     struct usb_redir_interface_info_header interface_info;
-@@ -94,11 +105,6 @@ struct USBRedirDevice {
-     int filter_rules_count;
- };
- 
--struct Cancelled {
--    uint64_t id;
--    QTAILQ_ENTRY(Cancelled)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);
-@@ -249,37 +255,75 @@ static int usbredir_write(void *priv, uint8_t *data, int count)
-  * Cancelled and buffered packets helpers
-  */
- 
--static void usbredir_cancel_packet(USBDevice *udev, USBPacket *p)
-+static void packet_id_queue_init(struct PacketIdQueue *q,
-+    USBRedirDevice *dev, const char *name)
- {
--    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
--    Cancelled *c;
-+    q->dev = dev;
-+    q->name = name;
-+    QTAILQ_INIT(&q->head);
-+    q->size = 0;
-+}
-+
-+static void packet_id_queue_add(struct PacketIdQueue *q, uint64_t id)
-+{
-+    USBRedirDevice *dev = q->dev;
-+    struct PacketIdQueueEntry *e;
-+
-+    DPRINTF("adding packet id %"PRIu64" to %s queue\n", id, q->name);
-+
-+    e = g_malloc0(sizeof(struct PacketIdQueueEntry));
-+    e->id = id;
-+    QTAILQ_INSERT_TAIL(&q->head, e, next);
-+    q->size++;
-+}
-+
-+static int packet_id_queue_remove(struct PacketIdQueue *q, uint64_t id)
-+{
-+    USBRedirDevice *dev = q->dev;
-+    struct PacketIdQueueEntry *e;
-+
-+    QTAILQ_FOREACH(e, &q->head, next) {
-+        if (e->id == id) {
-+            DPRINTF("removing packet id %"PRIu64" from %s queue\n",
-+                    id, q->name);
-+            QTAILQ_REMOVE(&q->head, e, next);
-+            q->size--;
-+            g_free(e);
-+            return 1;
-+        }
-+    }
-+    return 0;
-+}
-+
-+static void packet_id_queue_empty(struct PacketIdQueue *q)
-+{
-+    USBRedirDevice *dev = q->dev;
-+    struct PacketIdQueueEntry *e, *next_e;
- 
--    DPRINTF("cancel packet id %"PRIu64"\n", p->id);
-+    DPRINTF("removing %d packet-ids from %s queue\n", q->size, q->name);
- 
--    c = g_malloc0(sizeof(Cancelled));
--    c->id = p->id;
--    QTAILQ_INSERT_TAIL(&dev->cancelled, c, next);
-+    QTAILQ_FOREACH_SAFE(e, &q->head, next, next_e) {
-+        QTAILQ_REMOVE(&q->head, e, next);
-+        g_free(e);
-+    }
-+    q->size = 0;
-+}
- 
-+static void usbredir_cancel_packet(USBDevice *udev, USBPacket *p)
-+{
-+    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
-+
-+    packet_id_queue_add(&dev->cancelled, p->id);
-     usbredirparser_send_cancel_data_packet(dev->parser, p->id);
-     usbredirparser_do_write(dev->parser);
- }
- 
- static int usbredir_is_cancelled(USBRedirDevice *dev, uint64_t id)
- {
--    Cancelled *c;
--
-     if (!dev->dev.attached) {
-         return 1; /* Treat everything as cancelled after a disconnect */
-     }
--
--    QTAILQ_FOREACH(c, &dev->cancelled, next) {
--        if (c->id == id) {
--            QTAILQ_REMOVE(&dev->cancelled, c, next);
--            g_free(c);
--            return 1;
--        }
--    }
--    return 0;
-+    return packet_id_queue_remove(&dev->cancelled, id);
- }
- 
- static USBPacket *usbredir_find_packet_by_id(USBRedirDevice *dev,
-@@ -942,7 +986,7 @@ static int usbredir_initfn(USBDevice *udev)
-     dev->chardev_close_bh = qemu_bh_new(usbredir_chardev_close_bh, dev);
-     dev->attach_timer = qemu_new_timer_ms(vm_clock, usbredir_do_attach, dev);
- 
--    QTAILQ_INIT(&dev->cancelled);
-+    packet_id_queue_init(&dev->cancelled, dev, "cancelled");
-     for (i = 0; i < MAX_ENDPOINTS; i++) {
-         QTAILQ_INIT(&dev->endpoint[i].bufpq);
-     }
-@@ -960,13 +1004,9 @@ static int usbredir_initfn(USBDevice *udev)
- 
- static void usbredir_cleanup_device_queues(USBRedirDevice *dev)
- {
--    Cancelled *c, *next_c;
-     int i;
- 
--    QTAILQ_FOREACH_SAFE(c, &dev->cancelled, next, next_c) {
--        QTAILQ_REMOVE(&dev->cancelled, c, next);
--        g_free(c);
--    }
-+    packet_id_queue_empty(&dev->cancelled);
-     for (i = 0; i < MAX_ENDPOINTS; i++) {
-         usbredir_free_bufpq(dev, I2EP(i));
-     }
--- 
-1.7.12
-
diff --git a/0362-usb-redir-Add-an-already_in_flight-packet-id-queue.patch b/0362-usb-redir-Add-an-already_in_flight-packet-id-queue.patch
deleted file mode 100644
index 10c9aa3..0000000
--- a/0362-usb-redir-Add-an-already_in_flight-packet-id-queue.patch
+++ /dev/null
@@ -1,119 +0,0 @@
-From b422d151d0861ed346bed7cddb410a6b4c67711b Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Tue, 4 Sep 2012 17:03:54 +0200
-Subject: [PATCH 362/365] usb-redir: Add an already_in_flight packet-id queue
-
-After a live migration, the usb-hcd will re-queue all packets by
-walking over the schedule in the guest memory again, but requests which
-were encountered on the migration source before will already be in flight,
-so these should *not* be re-send to the usbredir-host.
-
-This patch adds an already in flight packet ud queue, which will be filled by
-the source before migration and then moved over to the migration dest, any
-async handled packets are then checked against this queue to avoid sending
-the same packet to the usbredir-host twice.
-
-Signed-off-by: Hans de Goede <hdegoede@redhat,com>
----
- hw/usb/redirect.c | 43 +++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 43 insertions(+)
-
-diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
-index 08776d9..1c8edd3 100644
---- a/hw/usb/redirect.c
-+++ b/hw/usb/redirect.c
-@@ -98,6 +98,7 @@ struct USBRedirDevice {
-     struct usbredirparser *parser;
-     struct endp_data endpoint[MAX_ENDPOINTS];
-     struct PacketIdQueue cancelled;
-+    struct PacketIdQueue already_in_flight;
-     /* Data for device filtering */
-     struct usb_redir_device_connect_header device_info;
-     struct usb_redir_interface_info_header interface_info;
-@@ -326,6 +327,34 @@ static int usbredir_is_cancelled(USBRedirDevice *dev, uint64_t id)
-     return packet_id_queue_remove(&dev->cancelled, id);
- }
- 
-+static void usbredir_fill_already_in_flight_from_ep(USBRedirDevice *dev,
-+    struct USBEndpoint *ep)
-+{
-+    static USBPacket *p;
-+
-+    QTAILQ_FOREACH(p, &ep->queue, queue) {
-+        packet_id_queue_add(&dev->already_in_flight, p->id);
-+    }
-+}
-+
-+static void usbredir_fill_already_in_flight(USBRedirDevice *dev)
-+{
-+    int ep;
-+    struct USBDevice *udev = &dev->dev;
-+
-+    usbredir_fill_already_in_flight_from_ep(dev, &udev->ep_ctl);
-+
-+    for (ep = 0; ep < USB_MAX_ENDPOINTS; ep++) {
-+        usbredir_fill_already_in_flight_from_ep(dev, &udev->ep_in[ep]);
-+        usbredir_fill_already_in_flight_from_ep(dev, &udev->ep_out[ep]);
-+    }
-+}
-+
-+static int usbredir_already_in_flight(USBRedirDevice *dev, uint64_t id)
-+{
-+    return packet_id_queue_remove(&dev->already_in_flight, id);
-+}
-+
- static USBPacket *usbredir_find_packet_by_id(USBRedirDevice *dev,
-     uint8_t ep, uint64_t id)
- {
-@@ -541,6 +570,10 @@ static int usbredir_handle_bulk_data(USBRedirDevice *dev, USBPacket *p,
- 
-     DPRINTF("bulk-out ep %02X len %zd id %"PRIu64"\n", ep, p->iov.size, p->id);
- 
-+    if (usbredir_already_in_flight(dev, p->id)) {
-+        return USB_RET_ASYNC;
-+    }
-+
-     bulk_packet.endpoint  = ep;
-     bulk_packet.length    = p->iov.size;
-     bulk_packet.stream_id = 0;
-@@ -621,6 +654,10 @@ static int usbredir_handle_interrupt_data(USBRedirDevice *dev,
-         DPRINTF("interrupt-out ep %02X len %zd id %"PRIu64"\n", ep,
-                 p->iov.size, p->id);
- 
-+        if (usbredir_already_in_flight(dev, p->id)) {
-+            return USB_RET_ASYNC;
-+        }
-+
-         interrupt_packet.endpoint  = ep;
-         interrupt_packet.length    = p->iov.size;
- 
-@@ -763,6 +800,10 @@ static int usbredir_handle_control(USBDevice *udev, USBPacket *p,
-     USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
-     struct usb_redir_control_packet_header control_packet;
- 
-+    if (usbredir_already_in_flight(dev, p->id)) {
-+        return USB_RET_ASYNC;
-+    }
-+
-     /* Special cases for certain standard device requests */
-     switch (request) {
-     case DeviceOutRequest | USB_REQ_SET_ADDRESS:
-@@ -987,6 +1028,7 @@ static int usbredir_initfn(USBDevice *udev)
-     dev->attach_timer = qemu_new_timer_ms(vm_clock, usbredir_do_attach, dev);
- 
-     packet_id_queue_init(&dev->cancelled, dev, "cancelled");
-+    packet_id_queue_init(&dev->already_in_flight, dev, "already-in-flight");
-     for (i = 0; i < MAX_ENDPOINTS; i++) {
-         QTAILQ_INIT(&dev->endpoint[i].bufpq);
-     }
-@@ -1007,6 +1049,7 @@ static void usbredir_cleanup_device_queues(USBRedirDevice *dev)
-     int i;
- 
-     packet_id_queue_empty(&dev->cancelled);
-+    packet_id_queue_empty(&dev->already_in_flight);
-     for (i = 0; i < MAX_ENDPOINTS; i++) {
-         usbredir_free_bufpq(dev, I2EP(i));
-     }
--- 
-1.7.12
-
diff --git a/0362-usb-redir-Change-cancelled-packet-code-into-a-generi.patch b/0362-usb-redir-Change-cancelled-packet-code-into-a-generi.patch
new file mode 100644
index 0000000..2efd733
--- /dev/null
+++ b/0362-usb-redir-Change-cancelled-packet-code-into-a-generi.patch
@@ -0,0 +1,184 @@
+From efbf5d06a89ec7b329d2aa15d3a6ea023b63c646 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Tue, 4 Sep 2012 14:18:34 +0200
+Subject: [PATCH 361/365] usb-redir: Change cancelled packet code into a
+ generic packet-id queue
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ hw/usb/redirect.c | 102 +++++++++++++++++++++++++++++++++++++-----------------
+ 1 file changed, 71 insertions(+), 31 deletions(-)
+
+diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
+index 9cbcddb..08776d9 100644
+--- a/hw/usb/redirect.c
++++ b/hw/usb/redirect.c
+@@ -43,7 +43,6 @@
+ #define EP2I(ep_address) (((ep_address & 0x80) >> 3) | (ep_address & 0x0f))
+ #define I2EP(i) (((i & 0x10) << 3) | (i & 0x0f))
+ 
+-typedef struct Cancelled Cancelled;
+ typedef struct USBRedirDevice USBRedirDevice;
+ 
+ /* Struct to hold buffered packets (iso or int input packets) */
+@@ -69,6 +68,18 @@ struct endp_data {
+     int bufpq_target_size;
+ };
+ 
++struct PacketIdQueueEntry {
++    uint64_t id;
++    QTAILQ_ENTRY(PacketIdQueueEntry)next;
++};
++
++struct PacketIdQueue {
++    USBRedirDevice *dev;
++    const char *name;
++    QTAILQ_HEAD(, PacketIdQueueEntry) head;
++    int size;
++};
++
+ struct USBRedirDevice {
+     USBDevice dev;
+     /* Properties */
+@@ -86,7 +97,7 @@ struct USBRedirDevice {
+     int64_t next_attach_time;
+     struct usbredirparser *parser;
+     struct endp_data endpoint[MAX_ENDPOINTS];
+-    QTAILQ_HEAD(, Cancelled) cancelled;
++    struct PacketIdQueue cancelled;
+     /* Data for device filtering */
+     struct usb_redir_device_connect_header device_info;
+     struct usb_redir_interface_info_header interface_info;
+@@ -94,11 +105,6 @@ struct USBRedirDevice {
+     int filter_rules_count;
+ };
+ 
+-struct Cancelled {
+-    uint64_t id;
+-    QTAILQ_ENTRY(Cancelled)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);
+@@ -249,37 +255,75 @@ static int usbredir_write(void *priv, uint8_t *data, int count)
+  * Cancelled and buffered packets helpers
+  */
+ 
+-static void usbredir_cancel_packet(USBDevice *udev, USBPacket *p)
++static void packet_id_queue_init(struct PacketIdQueue *q,
++    USBRedirDevice *dev, const char *name)
+ {
+-    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
+-    Cancelled *c;
++    q->dev = dev;
++    q->name = name;
++    QTAILQ_INIT(&q->head);
++    q->size = 0;
++}
++
++static void packet_id_queue_add(struct PacketIdQueue *q, uint64_t id)
++{
++    USBRedirDevice *dev = q->dev;
++    struct PacketIdQueueEntry *e;
++
++    DPRINTF("adding packet id %"PRIu64" to %s queue\n", id, q->name);
++
++    e = g_malloc0(sizeof(struct PacketIdQueueEntry));
++    e->id = id;
++    QTAILQ_INSERT_TAIL(&q->head, e, next);
++    q->size++;
++}
++
++static int packet_id_queue_remove(struct PacketIdQueue *q, uint64_t id)
++{
++    USBRedirDevice *dev = q->dev;
++    struct PacketIdQueueEntry *e;
++
++    QTAILQ_FOREACH(e, &q->head, next) {
++        if (e->id == id) {
++            DPRINTF("removing packet id %"PRIu64" from %s queue\n",
++                    id, q->name);
++            QTAILQ_REMOVE(&q->head, e, next);
++            q->size--;
++            g_free(e);
++            return 1;
++        }
++    }
++    return 0;
++}
++
++static void packet_id_queue_empty(struct PacketIdQueue *q)
++{
++    USBRedirDevice *dev = q->dev;
++    struct PacketIdQueueEntry *e, *next_e;
+ 
+-    DPRINTF("cancel packet id %"PRIu64"\n", p->id);
++    DPRINTF("removing %d packet-ids from %s queue\n", q->size, q->name);
+ 
+-    c = g_malloc0(sizeof(Cancelled));
+-    c->id = p->id;
+-    QTAILQ_INSERT_TAIL(&dev->cancelled, c, next);
++    QTAILQ_FOREACH_SAFE(e, &q->head, next, next_e) {
++        QTAILQ_REMOVE(&q->head, e, next);
++        g_free(e);
++    }
++    q->size = 0;
++}
+ 
++static void usbredir_cancel_packet(USBDevice *udev, USBPacket *p)
++{
++    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
++
++    packet_id_queue_add(&dev->cancelled, p->id);
+     usbredirparser_send_cancel_data_packet(dev->parser, p->id);
+     usbredirparser_do_write(dev->parser);
+ }
+ 
+ static int usbredir_is_cancelled(USBRedirDevice *dev, uint64_t id)
+ {
+-    Cancelled *c;
+-
+     if (!dev->dev.attached) {
+         return 1; /* Treat everything as cancelled after a disconnect */
+     }
+-
+-    QTAILQ_FOREACH(c, &dev->cancelled, next) {
+-        if (c->id == id) {
+-            QTAILQ_REMOVE(&dev->cancelled, c, next);
+-            g_free(c);
+-            return 1;
+-        }
+-    }
+-    return 0;
++    return packet_id_queue_remove(&dev->cancelled, id);
+ }
+ 
+ static USBPacket *usbredir_find_packet_by_id(USBRedirDevice *dev,
+@@ -942,7 +986,7 @@ static int usbredir_initfn(USBDevice *udev)
+     dev->chardev_close_bh = qemu_bh_new(usbredir_chardev_close_bh, dev);
+     dev->attach_timer = qemu_new_timer_ms(vm_clock, usbredir_do_attach, dev);
+ 
+-    QTAILQ_INIT(&dev->cancelled);
++    packet_id_queue_init(&dev->cancelled, dev, "cancelled");
+     for (i = 0; i < MAX_ENDPOINTS; i++) {
+         QTAILQ_INIT(&dev->endpoint[i].bufpq);
+     }
+@@ -960,13 +1004,9 @@ static int usbredir_initfn(USBDevice *udev)
+ 
+ static void usbredir_cleanup_device_queues(USBRedirDevice *dev)
+ {
+-    Cancelled *c, *next_c;
+     int i;
+ 
+-    QTAILQ_FOREACH_SAFE(c, &dev->cancelled, next, next_c) {
+-        QTAILQ_REMOVE(&dev->cancelled, c, next);
+-        g_free(c);
+-    }
++    packet_id_queue_empty(&dev->cancelled);
+     for (i = 0; i < MAX_ENDPOINTS; i++) {
+         usbredir_free_bufpq(dev, I2EP(i));
+     }
+-- 
+1.7.12
+
diff --git a/0363-usb-redir-Add-an-already_in_flight-packet-id-queue.patch b/0363-usb-redir-Add-an-already_in_flight-packet-id-queue.patch
new file mode 100644
index 0000000..10c9aa3
--- /dev/null
+++ b/0363-usb-redir-Add-an-already_in_flight-packet-id-queue.patch
@@ -0,0 +1,119 @@
+From b422d151d0861ed346bed7cddb410a6b4c67711b Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Tue, 4 Sep 2012 17:03:54 +0200
+Subject: [PATCH 362/365] usb-redir: Add an already_in_flight packet-id queue
+
+After a live migration, the usb-hcd will re-queue all packets by
+walking over the schedule in the guest memory again, but requests which
+were encountered on the migration source before will already be in flight,
+so these should *not* be re-send to the usbredir-host.
+
+This patch adds an already in flight packet ud queue, which will be filled by
+the source before migration and then moved over to the migration dest, any
+async handled packets are then checked against this queue to avoid sending
+the same packet to the usbredir-host twice.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat,com>
+---
+ hw/usb/redirect.c | 43 +++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 43 insertions(+)
+
+diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
+index 08776d9..1c8edd3 100644
+--- a/hw/usb/redirect.c
++++ b/hw/usb/redirect.c
+@@ -98,6 +98,7 @@ struct USBRedirDevice {
+     struct usbredirparser *parser;
+     struct endp_data endpoint[MAX_ENDPOINTS];
+     struct PacketIdQueue cancelled;
++    struct PacketIdQueue already_in_flight;
+     /* Data for device filtering */
+     struct usb_redir_device_connect_header device_info;
+     struct usb_redir_interface_info_header interface_info;
+@@ -326,6 +327,34 @@ static int usbredir_is_cancelled(USBRedirDevice *dev, uint64_t id)
+     return packet_id_queue_remove(&dev->cancelled, id);
+ }
+ 
++static void usbredir_fill_already_in_flight_from_ep(USBRedirDevice *dev,
++    struct USBEndpoint *ep)
++{
++    static USBPacket *p;
++
++    QTAILQ_FOREACH(p, &ep->queue, queue) {
++        packet_id_queue_add(&dev->already_in_flight, p->id);
++    }
++}
++
++static void usbredir_fill_already_in_flight(USBRedirDevice *dev)
++{
++    int ep;
++    struct USBDevice *udev = &dev->dev;
++
++    usbredir_fill_already_in_flight_from_ep(dev, &udev->ep_ctl);
++
++    for (ep = 0; ep < USB_MAX_ENDPOINTS; ep++) {
++        usbredir_fill_already_in_flight_from_ep(dev, &udev->ep_in[ep]);
++        usbredir_fill_already_in_flight_from_ep(dev, &udev->ep_out[ep]);
++    }
++}
++
++static int usbredir_already_in_flight(USBRedirDevice *dev, uint64_t id)
++{
++    return packet_id_queue_remove(&dev->already_in_flight, id);
++}
++
+ static USBPacket *usbredir_find_packet_by_id(USBRedirDevice *dev,
+     uint8_t ep, uint64_t id)
+ {
+@@ -541,6 +570,10 @@ static int usbredir_handle_bulk_data(USBRedirDevice *dev, USBPacket *p,
+ 
+     DPRINTF("bulk-out ep %02X len %zd id %"PRIu64"\n", ep, p->iov.size, p->id);
+ 
++    if (usbredir_already_in_flight(dev, p->id)) {
++        return USB_RET_ASYNC;
++    }
++
+     bulk_packet.endpoint  = ep;
+     bulk_packet.length    = p->iov.size;
+     bulk_packet.stream_id = 0;
+@@ -621,6 +654,10 @@ static int usbredir_handle_interrupt_data(USBRedirDevice *dev,
+         DPRINTF("interrupt-out ep %02X len %zd id %"PRIu64"\n", ep,
+                 p->iov.size, p->id);
+ 
++        if (usbredir_already_in_flight(dev, p->id)) {
++            return USB_RET_ASYNC;
++        }
++
+         interrupt_packet.endpoint  = ep;
+         interrupt_packet.length    = p->iov.size;
+ 
+@@ -763,6 +800,10 @@ static int usbredir_handle_control(USBDevice *udev, USBPacket *p,
+     USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
+     struct usb_redir_control_packet_header control_packet;
+ 
++    if (usbredir_already_in_flight(dev, p->id)) {
++        return USB_RET_ASYNC;
++    }
++
+     /* Special cases for certain standard device requests */
+     switch (request) {
+     case DeviceOutRequest | USB_REQ_SET_ADDRESS:
+@@ -987,6 +1028,7 @@ static int usbredir_initfn(USBDevice *udev)
+     dev->attach_timer = qemu_new_timer_ms(vm_clock, usbredir_do_attach, dev);
+ 
+     packet_id_queue_init(&dev->cancelled, dev, "cancelled");
++    packet_id_queue_init(&dev->already_in_flight, dev, "already-in-flight");
+     for (i = 0; i < MAX_ENDPOINTS; i++) {
+         QTAILQ_INIT(&dev->endpoint[i].bufpq);
+     }
+@@ -1007,6 +1049,7 @@ static void usbredir_cleanup_device_queues(USBRedirDevice *dev)
+     int i;
+ 
+     packet_id_queue_empty(&dev->cancelled);
++    packet_id_queue_empty(&dev->already_in_flight);
+     for (i = 0; i < MAX_ENDPOINTS; i++) {
+         usbredir_free_bufpq(dev, I2EP(i));
+     }
+-- 
+1.7.12
+
diff --git a/0363-usb-redir-Store-max_packet_size-in-endp_data.patch b/0363-usb-redir-Store-max_packet_size-in-endp_data.patch
deleted file mode 100644
index 16f05d3..0000000
--- a/0363-usb-redir-Store-max_packet_size-in-endp_data.patch
+++ /dev/null
@@ -1,38 +0,0 @@
-From c9917c910cf59e2407bbf51770724c5ec17d9cd1 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Thu, 6 Sep 2012 20:52:36 +0200
-Subject: [PATCH 363/365] usb-redir: Store max_packet_size in endp_data
-
-So that we've a place to migrate it to / from to allow restoring it after
-migration.
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- hw/usb/redirect.c | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
-diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
-index 1c8edd3..d8568ae 100644
---- a/hw/usb/redirect.c
-+++ b/hw/usb/redirect.c
-@@ -57,6 +57,7 @@ struct endp_data {
-     uint8_t type;
-     uint8_t interval;
-     uint8_t interface; /* bInterfaceNumber this ep belongs to */
-+    uint16_t max_packet_size; /* In bytes, not wMaxPacketSize format !! */
-     uint8_t iso_started;
-     uint8_t iso_error; /* For reporting iso errors to the HC */
-     uint8_t interrupt_started;
-@@ -1305,7 +1306,8 @@ static void usbredir_ep_info(void *priv,
-         usb_ep->ifnum = dev->endpoint[i].interface;
-         if (usbredirparser_peer_has_cap(dev->parser,
-                                      usb_redir_cap_ep_info_max_packet_size)) {
--            usb_ep->max_packet_size = ep_info->max_packet_size[i];
-+            dev->endpoint[i].max_packet_size =
-+                usb_ep->max_packet_size = ep_info->max_packet_size[i];
-         }
-         if (ep_info->type[i] == usb_redir_type_bulk) {
-             usb_ep->pipeline = true;
--- 
-1.7.12
-
diff --git a/0364-usb-redir-Add-support-for-migration.patch b/0364-usb-redir-Add-support-for-migration.patch
deleted file mode 100644
index bcbbaab..0000000
--- a/0364-usb-redir-Add-support-for-migration.patch
+++ /dev/null
@@ -1,429 +0,0 @@
-From 0d733a1280bdaba402c6efbfae116408d7c81bb0 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Wed, 5 Sep 2012 09:21:44 +0200
-Subject: [PATCH 364/365] usb-redir: Add support for migration
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- hw/usb/redirect.c | 349 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
- 1 file changed, 346 insertions(+), 3 deletions(-)
-
-diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
-index d8568ae..812096e 100644
---- a/hw/usb/redirect.c
-+++ b/hw/usb/redirect.c
-@@ -65,8 +65,8 @@ struct endp_data {
-     uint8_t bufpq_prefilled;
-     uint8_t bufpq_dropping_packets;
-     QTAILQ_HEAD(, buf_packet) bufpq;
--    int bufpq_size;
--    int bufpq_target_size;
-+    int32_t bufpq_size;
-+    int32_t bufpq_target_size;
- };
- 
- struct PacketIdQueueEntry {
-@@ -241,6 +241,11 @@ static int usbredir_write(void *priv, uint8_t *data, int count)
-         return 0;
-     }
- 
-+    /* Don't send new data to the chardev until our state is fully synced */
-+    if (!runstate_check(RUN_STATE_RUNNING)) {
-+        return 0;
-+    }
-+
-     r = qemu_chr_fe_write(dev->cs, data, count);
- 
-     if (r < 0) {
-@@ -868,6 +873,7 @@ static void usbredir_chardev_open(USBRedirDevice *dev)
- {
-     uint32_t caps[USB_REDIR_CAPS_SIZE] = { 0, };
-     char version[32];
-+    int flags = 0;
- 
-     /* Make sure any pending closes are handled (no-op if none pending) */
-     usbredir_chardev_close_bh(dev);
-@@ -903,7 +909,12 @@ static void usbredir_chardev_open(USBRedirDevice *dev)
-     usbredirparser_caps_set_cap(caps, usb_redir_cap_filter);
-     usbredirparser_caps_set_cap(caps, usb_redir_cap_ep_info_max_packet_size);
-     usbredirparser_caps_set_cap(caps, usb_redir_cap_64bits_ids);
--    usbredirparser_init(dev->parser, version, caps, USB_REDIR_CAPS_SIZE, 0);
-+
-+    if (runstate_check(RUN_STATE_INMIGRATE)) {
-+        flags |= usbredirparser_fl_no_hello;
-+    }
-+    usbredirparser_init(dev->parser, version, caps, USB_REDIR_CAPS_SIZE,
-+                        flags);
-     usbredirparser_do_write(dev->parser);
- }
- 
-@@ -949,6 +960,11 @@ static int usbredir_chardev_can_read(void *opaque)
-         return 0;
-     }
- 
-+    /* Don't read new data from the chardev until our state is fully synced */
-+    if (!runstate_check(RUN_STATE_RUNNING)) {
-+        return 0;
-+    }
-+
-     /* usbredir_parser_do_read will consume *all* data we give it */
-     return 1024 * 1024;
- }
-@@ -1004,6 +1020,15 @@ static const QemuChrHandlers usbredir_chr_handlers = {
-  * init + destroy
-  */
- 
-+static void usbredir_vm_state_change(void *priv, int running, RunState state)
-+{
-+    USBRedirDevice *dev = priv;
-+
-+    if (state == RUN_STATE_RUNNING && dev->parser != NULL) {
-+        usbredirparser_do_write(dev->parser); /* Flush any pending writes */
-+    }
-+}
-+
- static int usbredir_initfn(USBDevice *udev)
- {
-     USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
-@@ -1041,6 +1066,7 @@ static int usbredir_initfn(USBDevice *udev)
-     qemu_chr_fe_open(dev->cs);
-     qemu_chr_add_handlers(dev->cs, &usbredir_chr_handlers, dev);
- 
-+    qemu_add_vm_change_state_handler(usbredir_vm_state_change, dev);
-     add_boot_device_path(dev->bootindex, &udev->qdev, NULL);
-     return 0;
- }
-@@ -1530,6 +1556,322 @@ static void usbredir_interrupt_packet(void *priv, uint64_t id,
-     }
- }
- 
-+/*
-+ * Migration code
-+ */
-+
-+static void usbredir_pre_save(void *priv)
-+{
-+    USBRedirDevice *dev = priv;
-+
-+    usbredir_fill_already_in_flight(dev);
-+}
-+
-+static int usbredir_post_load(void *priv, int version_id)
-+{
-+    USBRedirDevice *dev = priv;
-+    struct USBEndpoint *usb_ep;
-+    int i;
-+
-+    switch (dev->device_info.speed) {
-+    case usb_redir_speed_low:
-+        dev->dev.speed = USB_SPEED_LOW;
-+        break;
-+    case usb_redir_speed_full:
-+        dev->dev.speed = USB_SPEED_FULL;
-+        break;
-+    case usb_redir_speed_high:
-+        dev->dev.speed = USB_SPEED_HIGH;
-+        break;
-+    case usb_redir_speed_super:
-+        dev->dev.speed = USB_SPEED_SUPER;
-+        break;
-+    default:
-+        dev->dev.speed = USB_SPEED_FULL;
-+    }
-+    dev->dev.speedmask = (1 << dev->dev.speed);
-+
-+    for (i = 0; i < MAX_ENDPOINTS; i++) {
-+        usb_ep = usb_ep_get(&dev->dev,
-+                            (i & 0x10) ? USB_TOKEN_IN : USB_TOKEN_OUT,
-+                            i & 0x0f);
-+        usb_ep->type = dev->endpoint[i].type;
-+        usb_ep->ifnum = dev->endpoint[i].interface;
-+        usb_ep->max_packet_size = dev->endpoint[i].max_packet_size;
-+        if (dev->endpoint[i].type == usb_redir_type_bulk) {
-+            usb_ep->pipeline = true;
-+        }
-+    }
-+    return 0;
-+}
-+
-+/* For usbredirparser migration */
-+static void usbredir_put_parser(QEMUFile *f, void *priv, size_t unused)
-+{
-+    USBRedirDevice *dev = priv;
-+    uint8_t *data;
-+    int len;
-+
-+    if (dev->parser == NULL) {
-+        qemu_put_be32(f, 0);
-+        return;
-+    }
-+
-+    usbredirparser_serialize(dev->parser, &data, &len);
-+    qemu_oom_check(data);
-+
-+    qemu_put_be32(f, len);
-+    qemu_put_buffer(f, data, len);
-+
-+    free(data);
-+}
-+
-+static int usbredir_get_parser(QEMUFile *f, void *priv, size_t unused)
-+{
-+    USBRedirDevice *dev = priv;
-+    uint8_t *data;
-+    int len, ret;
-+
-+    len = qemu_get_be32(f);
-+    if (len == 0) {
-+        return 0;
-+    }
-+
-+    /*
-+     * Our chardev should be open already at this point, otherwise
-+     * the usbredir channel will be broken (ie spice without seamless)
-+     */
-+    if (dev->parser == NULL) {
-+        ERROR("get_parser called with closed chardev, failing migration\n");
-+        return -1;
-+    }
-+
-+    data = g_malloc(len);
-+    qemu_get_buffer(f, data, len);
-+
-+    ret = usbredirparser_unserialize(dev->parser, data, len);
-+
-+    g_free(data);
-+
-+    return ret;
-+}
-+
-+static const VMStateInfo usbredir_parser_vmstate_info = {
-+    .name = "usb-redir-parser",
-+    .put  = usbredir_put_parser,
-+    .get  = usbredir_get_parser,
-+};
-+
-+
-+/* For buffered packets (iso/irq) queue migration */
-+static void usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused)
-+{
-+    struct endp_data *endp = priv;
-+    struct buf_packet *bufp;
-+    int remain = endp->bufpq_size;
-+
-+    qemu_put_be32(f, endp->bufpq_size);
-+    QTAILQ_FOREACH(bufp, &endp->bufpq, next) {
-+        qemu_put_be32(f, bufp->len);
-+        qemu_put_be32(f, bufp->status);
-+        qemu_put_buffer(f, bufp->data, bufp->len);
-+        remain--;
-+    }
-+    assert(remain == 0);
-+}
-+
-+static int usbredir_get_bufpq(QEMUFile *f, void *priv, size_t unused)
-+{
-+    struct endp_data *endp = priv;
-+    struct buf_packet *bufp;
-+    int i;
-+
-+    endp->bufpq_size = qemu_get_be32(f);
-+    for (i = 0; i < endp->bufpq_size; i++) {
-+        bufp = g_malloc(sizeof(struct buf_packet));
-+        bufp->len = qemu_get_be32(f);
-+        bufp->status = qemu_get_be32(f);
-+        bufp->data = qemu_oom_check(malloc(bufp->len)); /* regular malloc! */
-+        qemu_get_buffer(f, bufp->data, bufp->len);
-+        QTAILQ_INSERT_TAIL(&endp->bufpq, bufp, next);
-+    }
-+    return 0;
-+}
-+
-+static const VMStateInfo usbredir_ep_bufpq_vmstate_info = {
-+    .name = "usb-redir-bufpq",
-+    .put  = usbredir_put_bufpq,
-+    .get  = usbredir_get_bufpq,
-+};
-+
-+
-+/* For endp_data migration */
-+static const VMStateDescription usbredir_ep_vmstate = {
-+    .name = "usb-redir-ep",
-+    .version_id = 1,
-+    .minimum_version_id = 1,
-+    .fields = (VMStateField []) {
-+        VMSTATE_UINT8(type, struct endp_data),
-+        VMSTATE_UINT8(interval, struct endp_data),
-+        VMSTATE_UINT8(interface, struct endp_data),
-+        VMSTATE_UINT16(max_packet_size, struct endp_data),
-+        VMSTATE_UINT8(iso_started, struct endp_data),
-+        VMSTATE_UINT8(iso_error, struct endp_data),
-+        VMSTATE_UINT8(interrupt_started, struct endp_data),
-+        VMSTATE_UINT8(interrupt_error, struct endp_data),
-+        VMSTATE_UINT8(bufpq_prefilled, struct endp_data),
-+        VMSTATE_UINT8(bufpq_dropping_packets, struct endp_data),
-+        {
-+            .name         = "bufpq",
-+            .version_id   = 0,
-+            .field_exists = NULL,
-+            .size         = 0,
-+            .info         = &usbredir_ep_bufpq_vmstate_info,
-+            .flags        = VMS_SINGLE,
-+            .offset       = 0,
-+        },
-+        VMSTATE_INT32(bufpq_target_size, struct endp_data),
-+        VMSTATE_END_OF_LIST()
-+    }
-+};
-+
-+
-+/* For PacketIdQueue migration */
-+static void usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused)
-+{
-+    struct PacketIdQueue *q = priv;
-+    USBRedirDevice *dev = q->dev;
-+    struct PacketIdQueueEntry *e;
-+    int remain = q->size;
-+
-+    DPRINTF("put_packet_id_q %s size %d\n", q->name, q->size);
-+    qemu_put_be32(f, q->size);
-+    QTAILQ_FOREACH(e, &q->head, next) {
-+        qemu_put_be64(f, e->id);
-+        remain--;
-+    }
-+    assert(remain == 0);
-+}
-+
-+static int usbredir_get_packet_id_q(QEMUFile *f, void *priv, size_t unused)
-+{
-+    struct PacketIdQueue *q = priv;
-+    USBRedirDevice *dev = q->dev;
-+    int i, size;
-+    uint64_t id;
-+
-+    size = qemu_get_be32(f);
-+    DPRINTF("get_packet_id_q %s size %d\n", q->name, size);
-+    for (i = 0; i < size; i++) {
-+        id = qemu_get_be64(f);
-+        packet_id_queue_add(q, id);
-+    }
-+    assert(q->size == size);
-+    return 0;
-+}
-+
-+static const VMStateInfo usbredir_ep_packet_id_q_vmstate_info = {
-+    .name = "usb-redir-packet-id-q",
-+    .put  = usbredir_put_packet_id_q,
-+    .get  = usbredir_get_packet_id_q,
-+};
-+
-+static const VMStateDescription usbredir_ep_packet_id_queue_vmstate = {
-+    .name = "usb-redir-packet-id-queue",
-+    .version_id = 1,
-+    .minimum_version_id = 1,
-+    .fields = (VMStateField []) {
-+        {
-+            .name         = "queue",
-+            .version_id   = 0,
-+            .field_exists = NULL,
-+            .size         = 0,
-+            .info         = &usbredir_ep_packet_id_q_vmstate_info,
-+            .flags        = VMS_SINGLE,
-+            .offset       = 0,
-+        },
-+        VMSTATE_END_OF_LIST()
-+    }
-+};
-+
-+
-+/* For usb_redir_device_connect_header migration */
-+static const VMStateDescription usbredir_device_info_vmstate = {
-+    .name = "usb-redir-device-info",
-+    .version_id = 1,
-+    .minimum_version_id = 1,
-+    .fields = (VMStateField []) {
-+        VMSTATE_UINT8(speed, struct usb_redir_device_connect_header),
-+        VMSTATE_UINT8(device_class, struct usb_redir_device_connect_header),
-+        VMSTATE_UINT8(device_subclass, struct usb_redir_device_connect_header),
-+        VMSTATE_UINT8(device_protocol, struct usb_redir_device_connect_header),
-+        VMSTATE_UINT16(vendor_id, struct usb_redir_device_connect_header),
-+        VMSTATE_UINT16(product_id, struct usb_redir_device_connect_header),
-+        VMSTATE_UINT16(device_version_bcd,
-+                       struct usb_redir_device_connect_header),
-+        VMSTATE_END_OF_LIST()
-+    }
-+};
-+
-+
-+/* For usb_redir_interface_info_header migration */
-+static const VMStateDescription usbredir_interface_info_vmstate = {
-+    .name = "usb-redir-interface-info",
-+    .version_id = 1,
-+    .minimum_version_id = 1,
-+    .fields = (VMStateField []) {
-+        VMSTATE_UINT32(interface_count,
-+                       struct usb_redir_interface_info_header),
-+        VMSTATE_UINT8_ARRAY(interface,
-+                            struct usb_redir_interface_info_header, 32),
-+        VMSTATE_UINT8_ARRAY(interface_class,
-+                            struct usb_redir_interface_info_header, 32),
-+        VMSTATE_UINT8_ARRAY(interface_subclass,
-+                            struct usb_redir_interface_info_header, 32),
-+        VMSTATE_UINT8_ARRAY(interface_protocol,
-+                            struct usb_redir_interface_info_header, 32),
-+        VMSTATE_END_OF_LIST()
-+    }
-+};
-+
-+
-+/* And finally the USBRedirDevice vmstate itself */
-+static const VMStateDescription usbredir_vmstate = {
-+    .name = "usb-redir",
-+    .version_id = 1,
-+    .minimum_version_id = 1,
-+    .pre_save = usbredir_pre_save,
-+    .post_load = usbredir_post_load,
-+    .fields = (VMStateField []) {
-+        VMSTATE_USB_DEVICE(dev, USBRedirDevice),
-+        VMSTATE_TIMER(attach_timer, USBRedirDevice),
-+        {
-+            .name         = "parser",
-+            .version_id   = 0,
-+            .field_exists = NULL,
-+            .size         = 0,
-+            .info         = &usbredir_parser_vmstate_info,
-+            .flags        = VMS_SINGLE,
-+            .offset       = 0,
-+        },
-+        VMSTATE_STRUCT_ARRAY(endpoint, USBRedirDevice, MAX_ENDPOINTS, 1,
-+                             usbredir_ep_vmstate, struct endp_data),
-+        VMSTATE_STRUCT(cancelled, USBRedirDevice, 1,
-+                       usbredir_ep_packet_id_queue_vmstate,
-+                       struct PacketIdQueue),
-+        VMSTATE_STRUCT(already_in_flight, USBRedirDevice, 1,
-+                       usbredir_ep_packet_id_queue_vmstate,
-+                       struct PacketIdQueue),
-+        VMSTATE_STRUCT(device_info, USBRedirDevice, 1,
-+                       usbredir_device_info_vmstate,
-+                       struct usb_redir_device_connect_header),
-+        VMSTATE_STRUCT(interface_info, USBRedirDevice, 1,
-+                       usbredir_interface_info_vmstate,
-+                       struct usb_redir_interface_info_header),
-+        VMSTATE_END_OF_LIST()
-+    }
-+};
-+
- static Property usbredir_properties[] = {
-     DEFINE_PROP_CHR("chardev", USBRedirDevice, cs),
-     DEFINE_PROP_UINT8("debug", USBRedirDevice, debug, 0),
-@@ -1550,6 +1892,7 @@ static void usbredir_class_initfn(ObjectClass *klass, void *data)
-     uc->handle_reset   = usbredir_handle_reset;
-     uc->handle_data    = usbredir_handle_data;
-     uc->handle_control = usbredir_handle_control;
-+    dc->vmsd           = &usbredir_vmstate;
-     dc->props          = usbredir_properties;
- }
- 
--- 
-1.7.12
-
diff --git a/0364-usb-redir-Store-max_packet_size-in-endp_data.patch b/0364-usb-redir-Store-max_packet_size-in-endp_data.patch
new file mode 100644
index 0000000..16f05d3
--- /dev/null
+++ b/0364-usb-redir-Store-max_packet_size-in-endp_data.patch
@@ -0,0 +1,38 @@
+From c9917c910cf59e2407bbf51770724c5ec17d9cd1 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Thu, 6 Sep 2012 20:52:36 +0200
+Subject: [PATCH 363/365] usb-redir: Store max_packet_size in endp_data
+
+So that we've a place to migrate it to / from to allow restoring it after
+migration.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ hw/usb/redirect.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
+index 1c8edd3..d8568ae 100644
+--- a/hw/usb/redirect.c
++++ b/hw/usb/redirect.c
+@@ -57,6 +57,7 @@ struct endp_data {
+     uint8_t type;
+     uint8_t interval;
+     uint8_t interface; /* bInterfaceNumber this ep belongs to */
++    uint16_t max_packet_size; /* In bytes, not wMaxPacketSize format !! */
+     uint8_t iso_started;
+     uint8_t iso_error; /* For reporting iso errors to the HC */
+     uint8_t interrupt_started;
+@@ -1305,7 +1306,8 @@ static void usbredir_ep_info(void *priv,
+         usb_ep->ifnum = dev->endpoint[i].interface;
+         if (usbredirparser_peer_has_cap(dev->parser,
+                                      usb_redir_cap_ep_info_max_packet_size)) {
+-            usb_ep->max_packet_size = ep_info->max_packet_size[i];
++            dev->endpoint[i].max_packet_size =
++                usb_ep->max_packet_size = ep_info->max_packet_size[i];
+         }
+         if (ep_info->type[i] == usb_redir_type_bulk) {
+             usb_ep->pipeline = true;
+-- 
+1.7.12
+
diff --git a/0365-usb-redir-Add-chardev-open-close-debug-logging.patch b/0365-usb-redir-Add-chardev-open-close-debug-logging.patch
deleted file mode 100644
index 4e2f75d..0000000
--- a/0365-usb-redir-Add-chardev-open-close-debug-logging.patch
+++ /dev/null
@@ -1,54 +0,0 @@
-From 3efd9345ea643cf6f15776425213a92a442dd217 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Wed, 5 Sep 2012 15:56:57 +0200
-Subject: [PATCH 365/365] usb-redir: Add chardev open / close debug logging
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- hw/usb/redirect.c | 6 ++++++
- 1 file changed, 6 insertions(+)
-
-diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
-index 812096e..b03c412 100644
---- a/hw/usb/redirect.c
-+++ b/hw/usb/redirect.c
-@@ -864,6 +864,7 @@ static void usbredir_chardev_close_bh(void *opaque)
-     usbredir_device_disconnect(dev);
- 
-     if (dev->parser) {
-+        DPRINTF("destroying usbredirparser\n");
-         usbredirparser_destroy(dev->parser);
-         dev->parser = NULL;
-     }
-@@ -879,6 +880,8 @@ static void usbredir_chardev_open(USBRedirDevice *dev)
-     usbredir_chardev_close_bh(dev);
-     qemu_bh_cancel(dev->chardev_close_bh);
- 
-+    DPRINTF("creating usbredirparser\n");
-+
-     strcpy(version, "qemu usb-redir guest ");
-     pstrcat(version, sizeof(version), qemu_get_version());
- 
-@@ -990,9 +993,11 @@ static void usbredir_chardev_event(void *opaque, int event)
- 
-     switch (event) {
-     case CHR_EVENT_OPENED:
-+        DPRINTF("chardev open\n");
-         usbredir_chardev_open(dev);
-         break;
-     case CHR_EVENT_CLOSED:
-+        DPRINTF("chardev close\n");
-         qemu_bh_schedule(dev->chardev_close_bh);
-         break;
-     }
-@@ -1255,6 +1260,7 @@ static void usbredir_device_disconnect(void *priv)
-     qemu_del_timer(dev->attach_timer);
- 
-     if (dev->dev.attached) {
-+        DPRINTF("detaching device\n");
-         usb_device_detach(&dev->dev);
-         /*
-          * Delay next usb device attach to give the guest a chance to see
--- 
-1.7.12
-
diff --git a/0365-usb-redir-Add-support-for-migration.patch b/0365-usb-redir-Add-support-for-migration.patch
new file mode 100644
index 0000000..bcbbaab
--- /dev/null
+++ b/0365-usb-redir-Add-support-for-migration.patch
@@ -0,0 +1,429 @@
+From 0d733a1280bdaba402c6efbfae116408d7c81bb0 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Wed, 5 Sep 2012 09:21:44 +0200
+Subject: [PATCH 364/365] usb-redir: Add support for migration
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ hw/usb/redirect.c | 349 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 346 insertions(+), 3 deletions(-)
+
+diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
+index d8568ae..812096e 100644
+--- a/hw/usb/redirect.c
++++ b/hw/usb/redirect.c
+@@ -65,8 +65,8 @@ struct endp_data {
+     uint8_t bufpq_prefilled;
+     uint8_t bufpq_dropping_packets;
+     QTAILQ_HEAD(, buf_packet) bufpq;
+-    int bufpq_size;
+-    int bufpq_target_size;
++    int32_t bufpq_size;
++    int32_t bufpq_target_size;
+ };
+ 
+ struct PacketIdQueueEntry {
+@@ -241,6 +241,11 @@ static int usbredir_write(void *priv, uint8_t *data, int count)
+         return 0;
+     }
+ 
++    /* Don't send new data to the chardev until our state is fully synced */
++    if (!runstate_check(RUN_STATE_RUNNING)) {
++        return 0;
++    }
++
+     r = qemu_chr_fe_write(dev->cs, data, count);
+ 
+     if (r < 0) {
+@@ -868,6 +873,7 @@ static void usbredir_chardev_open(USBRedirDevice *dev)
+ {
+     uint32_t caps[USB_REDIR_CAPS_SIZE] = { 0, };
+     char version[32];
++    int flags = 0;
+ 
+     /* Make sure any pending closes are handled (no-op if none pending) */
+     usbredir_chardev_close_bh(dev);
+@@ -903,7 +909,12 @@ static void usbredir_chardev_open(USBRedirDevice *dev)
+     usbredirparser_caps_set_cap(caps, usb_redir_cap_filter);
+     usbredirparser_caps_set_cap(caps, usb_redir_cap_ep_info_max_packet_size);
+     usbredirparser_caps_set_cap(caps, usb_redir_cap_64bits_ids);
+-    usbredirparser_init(dev->parser, version, caps, USB_REDIR_CAPS_SIZE, 0);
++
++    if (runstate_check(RUN_STATE_INMIGRATE)) {
++        flags |= usbredirparser_fl_no_hello;
++    }
++    usbredirparser_init(dev->parser, version, caps, USB_REDIR_CAPS_SIZE,
++                        flags);
+     usbredirparser_do_write(dev->parser);
+ }
+ 
+@@ -949,6 +960,11 @@ static int usbredir_chardev_can_read(void *opaque)
+         return 0;
+     }
+ 
++    /* Don't read new data from the chardev until our state is fully synced */
++    if (!runstate_check(RUN_STATE_RUNNING)) {
++        return 0;
++    }
++
+     /* usbredir_parser_do_read will consume *all* data we give it */
+     return 1024 * 1024;
+ }
+@@ -1004,6 +1020,15 @@ static const QemuChrHandlers usbredir_chr_handlers = {
+  * init + destroy
+  */
+ 
++static void usbredir_vm_state_change(void *priv, int running, RunState state)
++{
++    USBRedirDevice *dev = priv;
++
++    if (state == RUN_STATE_RUNNING && dev->parser != NULL) {
++        usbredirparser_do_write(dev->parser); /* Flush any pending writes */
++    }
++}
++
+ static int usbredir_initfn(USBDevice *udev)
+ {
+     USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
+@@ -1041,6 +1066,7 @@ static int usbredir_initfn(USBDevice *udev)
+     qemu_chr_fe_open(dev->cs);
+     qemu_chr_add_handlers(dev->cs, &usbredir_chr_handlers, dev);
+ 
++    qemu_add_vm_change_state_handler(usbredir_vm_state_change, dev);
+     add_boot_device_path(dev->bootindex, &udev->qdev, NULL);
+     return 0;
+ }
+@@ -1530,6 +1556,322 @@ static void usbredir_interrupt_packet(void *priv, uint64_t id,
+     }
+ }
+ 
++/*
++ * Migration code
++ */
++
++static void usbredir_pre_save(void *priv)
++{
++    USBRedirDevice *dev = priv;
++
++    usbredir_fill_already_in_flight(dev);
++}
++
++static int usbredir_post_load(void *priv, int version_id)
++{
++    USBRedirDevice *dev = priv;
++    struct USBEndpoint *usb_ep;
++    int i;
++
++    switch (dev->device_info.speed) {
++    case usb_redir_speed_low:
++        dev->dev.speed = USB_SPEED_LOW;
++        break;
++    case usb_redir_speed_full:
++        dev->dev.speed = USB_SPEED_FULL;
++        break;
++    case usb_redir_speed_high:
++        dev->dev.speed = USB_SPEED_HIGH;
++        break;
++    case usb_redir_speed_super:
++        dev->dev.speed = USB_SPEED_SUPER;
++        break;
++    default:
++        dev->dev.speed = USB_SPEED_FULL;
++    }
++    dev->dev.speedmask = (1 << dev->dev.speed);
++
++    for (i = 0; i < MAX_ENDPOINTS; i++) {
++        usb_ep = usb_ep_get(&dev->dev,
++                            (i & 0x10) ? USB_TOKEN_IN : USB_TOKEN_OUT,
++                            i & 0x0f);
++        usb_ep->type = dev->endpoint[i].type;
++        usb_ep->ifnum = dev->endpoint[i].interface;
++        usb_ep->max_packet_size = dev->endpoint[i].max_packet_size;
++        if (dev->endpoint[i].type == usb_redir_type_bulk) {
++            usb_ep->pipeline = true;
++        }
++    }
++    return 0;
++}
++
++/* For usbredirparser migration */
++static void usbredir_put_parser(QEMUFile *f, void *priv, size_t unused)
++{
++    USBRedirDevice *dev = priv;
++    uint8_t *data;
++    int len;
++
++    if (dev->parser == NULL) {
++        qemu_put_be32(f, 0);
++        return;
++    }
++
++    usbredirparser_serialize(dev->parser, &data, &len);
++    qemu_oom_check(data);
++
++    qemu_put_be32(f, len);
++    qemu_put_buffer(f, data, len);
++
++    free(data);
++}
++
++static int usbredir_get_parser(QEMUFile *f, void *priv, size_t unused)
++{
++    USBRedirDevice *dev = priv;
++    uint8_t *data;
++    int len, ret;
++
++    len = qemu_get_be32(f);
++    if (len == 0) {
++        return 0;
++    }
++
++    /*
++     * Our chardev should be open already at this point, otherwise
++     * the usbredir channel will be broken (ie spice without seamless)
++     */
++    if (dev->parser == NULL) {
++        ERROR("get_parser called with closed chardev, failing migration\n");
++        return -1;
++    }
++
++    data = g_malloc(len);
++    qemu_get_buffer(f, data, len);
++
++    ret = usbredirparser_unserialize(dev->parser, data, len);
++
++    g_free(data);
++
++    return ret;
++}
++
++static const VMStateInfo usbredir_parser_vmstate_info = {
++    .name = "usb-redir-parser",
++    .put  = usbredir_put_parser,
++    .get  = usbredir_get_parser,
++};
++
++
++/* For buffered packets (iso/irq) queue migration */
++static void usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused)
++{
++    struct endp_data *endp = priv;
++    struct buf_packet *bufp;
++    int remain = endp->bufpq_size;
++
++    qemu_put_be32(f, endp->bufpq_size);
++    QTAILQ_FOREACH(bufp, &endp->bufpq, next) {
++        qemu_put_be32(f, bufp->len);
++        qemu_put_be32(f, bufp->status);
++        qemu_put_buffer(f, bufp->data, bufp->len);
++        remain--;
++    }
++    assert(remain == 0);
++}
++
++static int usbredir_get_bufpq(QEMUFile *f, void *priv, size_t unused)
++{
++    struct endp_data *endp = priv;
++    struct buf_packet *bufp;
++    int i;
++
++    endp->bufpq_size = qemu_get_be32(f);
++    for (i = 0; i < endp->bufpq_size; i++) {
++        bufp = g_malloc(sizeof(struct buf_packet));
++        bufp->len = qemu_get_be32(f);
++        bufp->status = qemu_get_be32(f);
++        bufp->data = qemu_oom_check(malloc(bufp->len)); /* regular malloc! */
++        qemu_get_buffer(f, bufp->data, bufp->len);
++        QTAILQ_INSERT_TAIL(&endp->bufpq, bufp, next);
++    }
++    return 0;
++}
++
++static const VMStateInfo usbredir_ep_bufpq_vmstate_info = {
++    .name = "usb-redir-bufpq",
++    .put  = usbredir_put_bufpq,
++    .get  = usbredir_get_bufpq,
++};
++
++
++/* For endp_data migration */
++static const VMStateDescription usbredir_ep_vmstate = {
++    .name = "usb-redir-ep",
++    .version_id = 1,
++    .minimum_version_id = 1,
++    .fields = (VMStateField []) {
++        VMSTATE_UINT8(type, struct endp_data),
++        VMSTATE_UINT8(interval, struct endp_data),
++        VMSTATE_UINT8(interface, struct endp_data),
++        VMSTATE_UINT16(max_packet_size, struct endp_data),
++        VMSTATE_UINT8(iso_started, struct endp_data),
++        VMSTATE_UINT8(iso_error, struct endp_data),
++        VMSTATE_UINT8(interrupt_started, struct endp_data),
++        VMSTATE_UINT8(interrupt_error, struct endp_data),
++        VMSTATE_UINT8(bufpq_prefilled, struct endp_data),
++        VMSTATE_UINT8(bufpq_dropping_packets, struct endp_data),
++        {
++            .name         = "bufpq",
++            .version_id   = 0,
++            .field_exists = NULL,
++            .size         = 0,
++            .info         = &usbredir_ep_bufpq_vmstate_info,
++            .flags        = VMS_SINGLE,
++            .offset       = 0,
++        },
++        VMSTATE_INT32(bufpq_target_size, struct endp_data),
++        VMSTATE_END_OF_LIST()
++    }
++};
++
++
++/* For PacketIdQueue migration */
++static void usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused)
++{
++    struct PacketIdQueue *q = priv;
++    USBRedirDevice *dev = q->dev;
++    struct PacketIdQueueEntry *e;
++    int remain = q->size;
++
++    DPRINTF("put_packet_id_q %s size %d\n", q->name, q->size);
++    qemu_put_be32(f, q->size);
++    QTAILQ_FOREACH(e, &q->head, next) {
++        qemu_put_be64(f, e->id);
++        remain--;
++    }
++    assert(remain == 0);
++}
++
++static int usbredir_get_packet_id_q(QEMUFile *f, void *priv, size_t unused)
++{
++    struct PacketIdQueue *q = priv;
++    USBRedirDevice *dev = q->dev;
++    int i, size;
++    uint64_t id;
++
++    size = qemu_get_be32(f);
++    DPRINTF("get_packet_id_q %s size %d\n", q->name, size);
++    for (i = 0; i < size; i++) {
++        id = qemu_get_be64(f);
++        packet_id_queue_add(q, id);
++    }
++    assert(q->size == size);
++    return 0;
++}
++
++static const VMStateInfo usbredir_ep_packet_id_q_vmstate_info = {
++    .name = "usb-redir-packet-id-q",
++    .put  = usbredir_put_packet_id_q,
++    .get  = usbredir_get_packet_id_q,
++};
++
++static const VMStateDescription usbredir_ep_packet_id_queue_vmstate = {
++    .name = "usb-redir-packet-id-queue",
++    .version_id = 1,
++    .minimum_version_id = 1,
++    .fields = (VMStateField []) {
++        {
++            .name         = "queue",
++            .version_id   = 0,
++            .field_exists = NULL,
++            .size         = 0,
++            .info         = &usbredir_ep_packet_id_q_vmstate_info,
++            .flags        = VMS_SINGLE,
++            .offset       = 0,
++        },
++        VMSTATE_END_OF_LIST()
++    }
++};
++
++
++/* For usb_redir_device_connect_header migration */
++static const VMStateDescription usbredir_device_info_vmstate = {
++    .name = "usb-redir-device-info",
++    .version_id = 1,
++    .minimum_version_id = 1,
++    .fields = (VMStateField []) {
++        VMSTATE_UINT8(speed, struct usb_redir_device_connect_header),
++        VMSTATE_UINT8(device_class, struct usb_redir_device_connect_header),
++        VMSTATE_UINT8(device_subclass, struct usb_redir_device_connect_header),
++        VMSTATE_UINT8(device_protocol, struct usb_redir_device_connect_header),
++        VMSTATE_UINT16(vendor_id, struct usb_redir_device_connect_header),
++        VMSTATE_UINT16(product_id, struct usb_redir_device_connect_header),
++        VMSTATE_UINT16(device_version_bcd,
++                       struct usb_redir_device_connect_header),
++        VMSTATE_END_OF_LIST()
++    }
++};
++
++
++/* For usb_redir_interface_info_header migration */
++static const VMStateDescription usbredir_interface_info_vmstate = {
++    .name = "usb-redir-interface-info",
++    .version_id = 1,
++    .minimum_version_id = 1,
++    .fields = (VMStateField []) {
++        VMSTATE_UINT32(interface_count,
++                       struct usb_redir_interface_info_header),
++        VMSTATE_UINT8_ARRAY(interface,
++                            struct usb_redir_interface_info_header, 32),
++        VMSTATE_UINT8_ARRAY(interface_class,
++                            struct usb_redir_interface_info_header, 32),
++        VMSTATE_UINT8_ARRAY(interface_subclass,
++                            struct usb_redir_interface_info_header, 32),
++        VMSTATE_UINT8_ARRAY(interface_protocol,
++                            struct usb_redir_interface_info_header, 32),
++        VMSTATE_END_OF_LIST()
++    }
++};
++
++
++/* And finally the USBRedirDevice vmstate itself */
++static const VMStateDescription usbredir_vmstate = {
++    .name = "usb-redir",
++    .version_id = 1,
++    .minimum_version_id = 1,
++    .pre_save = usbredir_pre_save,
++    .post_load = usbredir_post_load,
++    .fields = (VMStateField []) {
++        VMSTATE_USB_DEVICE(dev, USBRedirDevice),
++        VMSTATE_TIMER(attach_timer, USBRedirDevice),
++        {
++            .name         = "parser",
++            .version_id   = 0,
++            .field_exists = NULL,
++            .size         = 0,
++            .info         = &usbredir_parser_vmstate_info,
++            .flags        = VMS_SINGLE,
++            .offset       = 0,
++        },
++        VMSTATE_STRUCT_ARRAY(endpoint, USBRedirDevice, MAX_ENDPOINTS, 1,
++                             usbredir_ep_vmstate, struct endp_data),
++        VMSTATE_STRUCT(cancelled, USBRedirDevice, 1,
++                       usbredir_ep_packet_id_queue_vmstate,
++                       struct PacketIdQueue),
++        VMSTATE_STRUCT(already_in_flight, USBRedirDevice, 1,
++                       usbredir_ep_packet_id_queue_vmstate,
++                       struct PacketIdQueue),
++        VMSTATE_STRUCT(device_info, USBRedirDevice, 1,
++                       usbredir_device_info_vmstate,
++                       struct usb_redir_device_connect_header),
++        VMSTATE_STRUCT(interface_info, USBRedirDevice, 1,
++                       usbredir_interface_info_vmstate,
++                       struct usb_redir_interface_info_header),
++        VMSTATE_END_OF_LIST()
++    }
++};
++
+ static Property usbredir_properties[] = {
+     DEFINE_PROP_CHR("chardev", USBRedirDevice, cs),
+     DEFINE_PROP_UINT8("debug", USBRedirDevice, debug, 0),
+@@ -1550,6 +1892,7 @@ static void usbredir_class_initfn(ObjectClass *klass, void *data)
+     uc->handle_reset   = usbredir_handle_reset;
+     uc->handle_data    = usbredir_handle_data;
+     uc->handle_control = usbredir_handle_control;
++    dc->vmsd           = &usbredir_vmstate;
+     dc->props          = usbredir_properties;
+ }
+ 
+-- 
+1.7.12
+
diff --git a/0366-usb-redir-Add-chardev-open-close-debug-logging.patch b/0366-usb-redir-Add-chardev-open-close-debug-logging.patch
new file mode 100644
index 0000000..4e2f75d
--- /dev/null
+++ b/0366-usb-redir-Add-chardev-open-close-debug-logging.patch
@@ -0,0 +1,54 @@
+From 3efd9345ea643cf6f15776425213a92a442dd217 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Wed, 5 Sep 2012 15:56:57 +0200
+Subject: [PATCH 365/365] usb-redir: Add chardev open / close debug logging
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ hw/usb/redirect.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
+index 812096e..b03c412 100644
+--- a/hw/usb/redirect.c
++++ b/hw/usb/redirect.c
+@@ -864,6 +864,7 @@ static void usbredir_chardev_close_bh(void *opaque)
+     usbredir_device_disconnect(dev);
+ 
+     if (dev->parser) {
++        DPRINTF("destroying usbredirparser\n");
+         usbredirparser_destroy(dev->parser);
+         dev->parser = NULL;
+     }
+@@ -879,6 +880,8 @@ static void usbredir_chardev_open(USBRedirDevice *dev)
+     usbredir_chardev_close_bh(dev);
+     qemu_bh_cancel(dev->chardev_close_bh);
+ 
++    DPRINTF("creating usbredirparser\n");
++
+     strcpy(version, "qemu usb-redir guest ");
+     pstrcat(version, sizeof(version), qemu_get_version());
+ 
+@@ -990,9 +993,11 @@ static void usbredir_chardev_event(void *opaque, int event)
+ 
+     switch (event) {
+     case CHR_EVENT_OPENED:
++        DPRINTF("chardev open\n");
+         usbredir_chardev_open(dev);
+         break;
+     case CHR_EVENT_CLOSED:
++        DPRINTF("chardev close\n");
+         qemu_bh_schedule(dev->chardev_close_bh);
+         break;
+     }
+@@ -1255,6 +1260,7 @@ static void usbredir_device_disconnect(void *priv)
+     qemu_del_timer(dev->attach_timer);
+ 
+     if (dev->dev.attached) {
++        DPRINTF("detaching device\n");
+         usb_device_detach(&dev->dev);
+         /*
+          * Delay next usb device attach to give the guest a chance to see
+-- 
+1.7.12
+
diff --git a/0367-usb-redir-Revert-usb-redir-part-of-commit-93bfef4c.patch b/0367-usb-redir-Revert-usb-redir-part-of-commit-93bfef4c.patch
new file mode 100644
index 0000000..8a1b518
--- /dev/null
+++ b/0367-usb-redir-Revert-usb-redir-part-of-commit-93bfef4c.patch
@@ -0,0 +1,63 @@
+From 786657ed32cb68ae5cd4d099e6ea3f36290bcbcb Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Mon, 10 Sep 2012 13:49:46 +0200
+Subject: [PATCH 367/369] usb-redir: Revert usb-redir part of commit 93bfef4c
+
+Commit 93bfef4c6e4b23caea9d51e1099d06433d8835a4 makes qemu-devices
+which report the qemu version string to the guest in some way use a
+qemu_get_version function which reports a machine-specific version string.
+
+However usb-redir does not expose the qemu version to the guest, only to
+the usbredir-host as part of the initial handshake. This can then be logged
+on the usbredir-host side for debugging purposes and is otherwise completely
+unused! For debugging purposes it is important to have the real qemu version
+in there, rather then the machine-specific version.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ hw/usb/redirect.c | 8 +++-----
+ 1 file changed, 3 insertions(+), 5 deletions(-)
+
+diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
+index 86c0398..78e93a7 100644
+--- a/hw/usb/redirect.c
++++ b/hw/usb/redirect.c
+@@ -142,6 +142,8 @@ static void usbredir_interrupt_packet(void *priv, uint64_t id,
+ static int usbredir_handle_status(USBRedirDevice *dev,
+                                        int status, int actual_len);
+ 
++#define VERSION "qemu usb-redir guest " QEMU_VERSION
++
+ /*
+  * Logging stuff
+  */
+@@ -873,7 +875,6 @@ static void usbredir_chardev_close_bh(void *opaque)
+ static void usbredir_chardev_open(USBRedirDevice *dev)
+ {
+     uint32_t caps[USB_REDIR_CAPS_SIZE] = { 0, };
+-    char version[32];
+     int flags = 0;
+ 
+     /* Make sure any pending closes are handled (no-op if none pending) */
+@@ -882,9 +883,6 @@ static void usbredir_chardev_open(USBRedirDevice *dev)
+ 
+     DPRINTF("creating usbredirparser\n");
+ 
+-    strcpy(version, "qemu usb-redir guest ");
+-    pstrcat(version, sizeof(version), qemu_get_version());
+-
+     dev->parser = qemu_oom_check(usbredirparser_create());
+     dev->parser->priv = dev;
+     dev->parser->log_func = usbredir_log;
+@@ -916,7 +914,7 @@ static void usbredir_chardev_open(USBRedirDevice *dev)
+     if (runstate_check(RUN_STATE_INMIGRATE)) {
+         flags |= usbredirparser_fl_no_hello;
+     }
+-    usbredirparser_init(dev->parser, version, caps, USB_REDIR_CAPS_SIZE,
++    usbredirparser_init(dev->parser, VERSION, caps, USB_REDIR_CAPS_SIZE,
+                         flags);
+     usbredirparser_do_write(dev->parser);
+ }
+-- 
+1.7.12
+
diff --git a/0368-uhci-Don-t-queue-up-packets-after-one-with-the-SPD-f.patch b/0368-uhci-Don-t-queue-up-packets-after-one-with-the-SPD-f.patch
new file mode 100644
index 0000000..af350d9
--- /dev/null
+++ b/0368-uhci-Don-t-queue-up-packets-after-one-with-the-SPD-f.patch
@@ -0,0 +1,44 @@
+From 41f5d67c0649d74b505edc2a874c91148355eb25 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Wed, 12 Sep 2012 13:30:51 +0200
+Subject: [PATCH 368/369] uhci: Don't queue up packets after one with the SPD
+ flag set
+
+Don't queue up packets after a packet with the SPD (short packet detect)
+flag set. Since we won't know if the packet will actually be short until it
+has completed, and if it is short we should stop the queue.
+
+This fixes a miniature photoframe emulating a USB cdrom with the windows
+software for it not working.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ hw/usb/hcd-uhci.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
+index c7c8786..cdc8bc3 100644
+--- a/hw/usb/hcd-uhci.c
++++ b/hw/usb/hcd-uhci.c
+@@ -1000,6 +1000,9 @@ static void uhci_fill_queue(UHCIState *s, UHCI_TD *td)
+         }
+         assert(ret == TD_RESULT_ASYNC_START);
+         assert(int_mask == 0);
++        if (ptd.ctrl & TD_CTRL_SPD) {
++            break;
++        }
+         plink = ptd.link;
+     }
+ }
+@@ -1097,7 +1100,7 @@ static void uhci_process_frame(UHCIState *s)
+ 
+         case TD_RESULT_ASYNC_START:
+             trace_usb_uhci_td_async(curr_qh & ~0xf, link & ~0xf);
+-            if (is_valid(td.link)) {
++            if (is_valid(td.link) && !(td.ctrl & TD_CTRL_SPD)) {
+                 uhci_fill_queue(s, &td);
+             }
+             link = curr_qh ? qh.link : td.link;
+-- 
+1.7.12
+
diff --git a/0369-ehci-Fix-interrupt-packet-MULT-handling.patch b/0369-ehci-Fix-interrupt-packet-MULT-handling.patch
new file mode 100644
index 0000000..3105ad9
--- /dev/null
+++ b/0369-ehci-Fix-interrupt-packet-MULT-handling.patch
@@ -0,0 +1,131 @@
+From 074e4dddddec4456026e211163e0d8d5c9bfaf0c Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Thu, 20 Sep 2012 16:55:02 +0200
+Subject: [PATCH 369/369] ehci: Fix interrupt packet MULT handling
+
+There are several issues with our handling of the MULT epcap field
+of interrupt qhs, which this patch fixes.
+
+1) When we don't execute a transaction because of the transaction counter
+being 0, p->async stays EHCI_ASYNC_NONE, and the next time we process the
+same qtd we hit an assert in ehci_state_fetchqtd because of this. Even though
+I believe that this is caused by 3 below, this patch still removes the assert,
+as that can still happen without 3, when multiple packets are queued for the
+same interrupt ep.
+
+2) We only *check* the transaction counter from ehci_state_execute, any
+packets queued up by fill_queue bypass this check. This is fixed by not calling
+fill_queue for interrupt packets.
+
+3) Some versions of Windows set the MULT field of the qh to 0, which is a
+clear violation of the EHCI spec, but still they do it. This means that we
+will never execute a qtd for these, making interrupt ep-s on USB-2 devices
+not work, and after recent changes, triggering 1).
+
+So far we've stored the transaction counter in our copy of the mult field,
+but with this beginnig at 0 already when dealing with these version of windows
+this won't work. So this patch adds a transact_ctr field to our qh struct,
+and sets this to the MULT field value on fetchqh. When the MULT field value
+is 0, we set it to 4. Assuming that windows gets way with setting it to 0,
+by the actual hardware going horizontal on a 1 -> 0 transition, which will
+give it 4 transactions (MULT goes from 0 - 3).
+
+Note that we cannot stop on detecting the 1 -> 0 transition, as our decrement
+of the transaction counter, and checking for it are done in 2 different places.
+
+Reported-by: Shawn Starr <shawn.starr@rogers.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ hw/usb/hcd-ehci.c | 39 +++++++++++++++++++--------------------
+ 1 file changed, 19 insertions(+), 20 deletions(-)
+
+diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
+index 48a1b09..3acd881a 100644
+--- a/hw/usb/hcd-ehci.c
++++ b/hw/usb/hcd-ehci.c
+@@ -373,6 +373,7 @@ struct EHCIQueue {
+     uint32_t seen;
+     uint64_t ts;
+     int async;
++    int transact_ctr;
+ 
+     /* cached data from guest - needs to be flushed
+      * when guest removes an entry (doorbell, handshake sequence)
+@@ -1837,6 +1838,10 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
+     }
+     q->qh = qh;
+ 
++    q->transact_ctr = get_field(q->qh.epcap, QH_EPCAP_MULT);
++    if (q->transact_ctr == 0) /* Guest bug in some versions of windows */
++        q->transact_ctr = 4;
++
+     if (q->dev == NULL) {
+         q->dev = ehci_find_device(q->ehci, devaddr);
+     }
+@@ -2014,11 +2019,8 @@ static int ehci_state_fetchqtd(EHCIQueue *q)
+     } else if (p != NULL) {
+         switch (p->async) {
+         case EHCI_ASYNC_NONE:
+-            /* Should never happen packet should at least be initialized */
+-            assert(0);
+-            break;
+         case EHCI_ASYNC_INITIALIZED:
+-            /* Previously nacked packet (likely interrupt ep) */
++            /* Not yet executed (MULT), or previously nacked (int) packet */
+             ehci_set_state(q->ehci, q->async, EST_EXECUTE);
+             break;
+         case EHCI_ASYNC_INFLIGHT:
+@@ -2107,15 +2109,12 @@ static int ehci_state_execute(EHCIQueue *q)
+ 
+     // 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
+ 
+-    if (!q->async) {
+-        int transactCtr = get_field(q->qh.epcap, QH_EPCAP_MULT);
+-        if (!transactCtr) {
+-            ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
+-            again = 1;
+-            goto out;
+-        }
++    /* 4.10.3, bottom of page 82, go horizontal on transaction counter == 0 */
++    if (!q->async && q->transact_ctr == 0) {
++        ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
++        again = 1;
++        goto out;
+     }
+ 
+     if (q->async) {
+@@ -2132,7 +2131,11 @@ static int ehci_state_execute(EHCIQueue *q)
+         trace_usb_ehci_packet_action(p->queue, p, "async");
+         p->async = EHCI_ASYNC_INFLIGHT;
+         ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
+-        again = (ehci_fill_queue(p) == USB_RET_PROCERR) ? -1 : 1;
++        if (q->async) {
++            again = (ehci_fill_queue(p) == USB_RET_PROCERR) ? -1 : 1;
++        } else {
++            again = 1;
++        }
+         goto out;
+     }
+ 
+@@ -2152,13 +2155,9 @@ static int ehci_state_executing(EHCIQueue *q)
+ 
+     ehci_execute_complete(q);
+ 
+-    // 4.10.3
+-    if (!q->async) {
+-        int transactCtr = get_field(q->qh.epcap, QH_EPCAP_MULT);
+-        transactCtr--;
+-        set_field(&q->qh.epcap, transactCtr, QH_EPCAP_MULT);
+-        // 4.10.3, bottom of page 82, should exit this state when transaction
+-        // counter decrements to 0
++    /* 4.10.3 */
++    if (!q->async && q->transact_ctr > 0) {
++        q->transact_ctr--;
+     }
+ 
+     /* 4.10.5 */
+-- 
+1.7.12
+
diff --git a/qemu.spec b/qemu.spec
index cdb6fae..e06b79e 100644
--- a/qemu.spec
+++ b/qemu.spec
@@ -39,7 +39,7 @@
 Summary: QEMU is a FAST! processor emulator
 Name: qemu
 Version: 1.2.0
-Release: 8%{?dist}
+Release: 9%{?dist}
 # Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped
 Epoch: 2
 License: GPLv2+ and LGPLv2+ and BSD
@@ -116,8 +116,16 @@ Patch211: 0211-configure-print-spice-protocol-and-spice-server-vers.patch
 Patch212: 0212-spice-make-number-of-surfaces-runtime-configurable.patch
 Patch213: 0213-qxl-Add-set_client_capabilities-interface-to-QXLInte.patch
 Patch214: 0214-Remove-ifdef-QXL_COMMAND_FLAG_COMPAT_16BPP.patch
-Patch215: 0215-qxl-dont-update-invalid-area.patch
-Patch216: 0216-qxl-Ignore-set_client_capabilities-pre-post-migrate.patch
+Patch215: 0215-spice-switch-to-queue-for-vga-mode-updates.patch
+Patch216: 0216-spice-split-qemu_spice_create_update.patch
+Patch217: 0217-spice-add-screen-mirror.patch
+Patch218: 0218-spice-send-updates-only-for-changed-screen-content.patch
+Patch219: 0219-qxl-dont-update-invalid-area.patch
+Patch220: 0220-qxl-Ignore-set_client_capabilities-pre-post-migrate.patch
+Patch221: 0221-qxl-better-cleanup-for-surface-destroy.patch
+Patch222: 0222-hw-qxl-tracing-fixes.patch
+Patch223: 0223-qxl-add-trace-event-for-QXL_IO_LOG.patch
+Patch224: 0224-hw-qxl-support-client-monitor-configuration-via-devi.patch
 
 # Ugh, ton of USB bugfixes / preparation patches for usb-redir
 # live-migration which did not make 1.2.0 :|
@@ -176,20 +184,23 @@ Patch0351: 0351-xhci-pick-target-interrupter.patch
 Patch0352: 0352-xhci-support-multiple-interrupters.patch
 Patch0353: 0353-xhci-kill-xhci_mem_-read-write-dispatcher-functions.patch
 Patch0354: 0354-xhci-allow-bytewise-capability-register-reads.patch
-Patch0355: 0355-ehci-switch-to-new-style-memory-ops.patch
-Patch0356: 0356-xhci-drop-unused-wlength.patch
-Patch0357: 0357-usb-host-allow-emulated-non-async-control-requests-w.patch
-
+Patch0355: 0355-usb-host-allow-emulated-non-async-control-requests-w.patch
+Patch0356: 0356-ehci-switch-to-new-style-memory-ops.patch
+Patch0357: 0357-ehci-Fix-interrupts-stopping-when-Interrupt-Threshol.patch
+Patch0358: 0358-ehci-Don-t-process-too-much-frames-in-1-timer-tick-v.patch
+Patch0359: 0359-configure-usbredir-fixes.patch
+Patch0360: 0360-ehci-Don-t-set-seen-to-0-when-removing-unseen-queue-.patch
+Patch0361: 0361-ehci-Walk-async-schedule-before-and-after-migration.patch
+Patch0362: 0362-usb-redir-Change-cancelled-packet-code-into-a-generi.patch
+Patch0363: 0363-usb-redir-Add-an-already_in_flight-packet-id-queue.patch
+Patch0364: 0364-usb-redir-Store-max_packet_size-in-endp_data.patch
+Patch0365: 0365-usb-redir-Add-support-for-migration.patch
+Patch0366: 0366-usb-redir-Add-chardev-open-close-debug-logging.patch
+Patch0367: 0367-usb-redir-Revert-usb-redir-part-of-commit-93bfef4c.patch
+Patch0368: 0368-uhci-Don-t-queue-up-packets-after-one-with-the-SPD-f.patch
 # And the last few ehci fixes + the actual usb-redir live migration code
 # Not yet upstream but should get there real soon
-Patch0358: 0358-ehci-Don-t-set-seen-to-0-when-removing-unseen-queue-.patch
-Patch0359: 0359-ehci-Walk-async-schedule-before-and-after-migration.patch
-Patch0360: 0360-ehci-Don-t-process-too-much-frames-in-1-timer-tick.patch
-Patch0361: 0361-usb-redir-Change-cancelled-packet-code-into-a-generi.patch
-Patch0362: 0362-usb-redir-Add-an-already_in_flight-packet-id-queue.patch
-Patch0363: 0363-usb-redir-Store-max_packet_size-in-endp_data.patch
-Patch0364: 0364-usb-redir-Add-support-for-migration.patch
-Patch0365: 0365-usb-redir-Add-chardev-open-close-debug-logging.patch
+Patch0369: 0369-ehci-Fix-interrupt-packet-MULT-handling.patch
 
 # Revert c3767ed0eb5d0.
 # NOT upstream (hopefully will be soon).
@@ -510,6 +521,14 @@ such as kvm_stat.
 %patch214 -p1
 %patch215 -p1
 %patch216 -p1
+%patch217 -p1
+%patch218 -p1
+%patch219 -p1
+%patch220 -p1
+%patch221 -p1
+%patch222 -p1
+%patch223 -p1
+%patch224 -p1
 
 %patch301 -p1
 %patch302 -p1
@@ -576,6 +595,10 @@ such as kvm_stat.
 %patch363 -p1
 %patch364 -p1
 %patch365 -p1
+%patch366 -p1
+%patch367 -p1
+%patch368 -p1
+%patch369 -p1
 
 %patch900 -p1
 
@@ -1046,6 +1069,9 @@ fi
 %{_mandir}/man1/qemu-img.1*
 
 %changelog
+* Thu Sep 20 2012 Hans de Goede <hdegoede@redhat.com> - 2:1.2.0-9
+- Sync USB and Spice patchsets with upstream
+
 * Sun Sep 16 2012 Richard W.M. Jones <rjones@redhat.com> - 2:1.2.0-8
 - Use 'global' instead of 'define', and underscore in definition name,
   n-v-r, and 'dist' tag of SLOF, all to fix RHBZ#855252.