diff --git a/0000-libcacard-fix-missing-symbols-in-libcacard.so.patch b/0000-libcacard-fix-missing-symbols-in-libcacard.so.patch
deleted file mode 100644
index b6350c3..0000000
--- a/0000-libcacard-fix-missing-symbols-in-libcacard.so.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From 94afb78477a5b078449e5d48b38e74aac3fa5ac4 Mon Sep 17 00:00:00 2001
-Message-Id: <94afb78477a5b078449e5d48b38e74aac3fa5ac4.1354903384.git.crobinso@redhat.com>
-From: Alon Levy <alevy@redhat.com>
-Date: Wed, 28 Nov 2012 16:38:43 +0200
-Subject: [PATCH] libcacard: fix missing symbols in libcacard.so
-
----
- libcacard/Makefile | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/libcacard/Makefile b/libcacard/Makefile
-index c26aac6..49a9729 100644
---- a/libcacard/Makefile
-+++ b/libcacard/Makefile
-@@ -7,7 +7,7 @@ libcacard_includedir=$(includedir)/cacard
- $(call set-vpath, $(SRC_PATH))
- 
- # objects linked into a shared library, built with libtool with -fPIC if required
--QEMU_OBJS=$(oslib-obj-y) qemu-timer-common.o $(trace-obj-y) $(stub-obj-y)
-+QEMU_OBJS=$(oslib-obj-y) qemu-timer-common.o iov.o cutils.o qemu-user.o $(trace-obj-y) $(stub-obj-y)
- QEMU_OBJS_LIB=$(patsubst %.o,%.lo,$(QEMU_OBJS))
- 
- QEMU_CFLAGS+=-I../
--- 
-1.8.0
-
diff --git a/0001-configure-move-vscclient-binary-under-libcacard.patch b/0001-configure-move-vscclient-binary-under-libcacard.patch
deleted file mode 100644
index 4feb854..0000000
--- a/0001-configure-move-vscclient-binary-under-libcacard.patch
+++ /dev/null
@@ -1,96 +0,0 @@
-From df9d09b15cb4b8397bfe984bf3f54dbb5457d446 Mon Sep 17 00:00:00 2001
-Message-Id: <df9d09b15cb4b8397bfe984bf3f54dbb5457d446.1354903384.git.crobinso@redhat.com>
-In-Reply-To: <94afb78477a5b078449e5d48b38e74aac3fa5ac4.1354903384.git.crobinso@redhat.com>
-References: <94afb78477a5b078449e5d48b38e74aac3fa5ac4.1354903384.git.crobinso@redhat.com>
-From: Alon Levy <alevy@redhat.com>
-Date: Thu, 29 Nov 2012 14:11:19 +0200
-Subject: [PATCH] configure: move vscclient binary under libcacard
-
-build rule is in top level Makefile like other tools.
-
-build rule also exists in libcacard for installation purposes. This was
-fixed in a better way in 1.3.0-rc2
----
- Makefile           |  4 ++--
- Makefile.objs      | 11 ++++++-----
- configure          |  2 +-
- libcacard/Makefile |  6 +++++-
- 4 files changed, 14 insertions(+), 9 deletions(-)
-
-diff --git a/Makefile b/Makefile
-index 9ecbcbb..c2d34a9 100644
---- a/Makefile
-+++ b/Makefile
-@@ -197,8 +197,8 @@ qemu-io$(EXESUF): qemu-io.o cmd.o $(tools-obj-y) $(block-obj-y) libqemustub.a
- 
- qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o
- 
--vscclient$(EXESUF): $(libcacard-y) $(oslib-obj-y) $(trace-obj-y) libcacard/vscclient.o libqemustub.a
--	$(call quiet-command,$(CC) $(LDFLAGS) -o $@ $^ $(libcacard_libs) $(LIBS),"  LINK  $@")
-+libcacard/vscclient$(EXESUF): $(libcacard-y) $(oslib-obj-y) $(trace-obj-y) iov.o cutils.o qemu-user.o libcacard/vscclient.o libqemustub.a
-+libcacard/vscclient$(EXESUF): LIBS += $(libcacard_libs)
- 
- fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o fsdev/virtio-9p-marshal.o oslib-posix.o $(trace-obj-y)
- fsdev/virtfs-proxy-helper$(EXESUF): LIBS += -lcap
-diff --git a/Makefile.objs b/Makefile.objs
-index 3c7abca..140d592 100644
---- a/Makefile.objs
-+++ b/Makefile.objs
-@@ -211,11 +211,12 @@ $(trace-obj-y): $(GENERATED_HEADERS)
- ######################################################################
- # smartcard
- 
--libcacard-y += libcacard/cac.o libcacard/event.o
--libcacard-y += libcacard/vcard.o libcacard/vreader.o
--libcacard-y += libcacard/vcard_emul_nss.o
--libcacard-y += libcacard/vcard_emul_type.o
--libcacard-y += libcacard/card_7816.o
-+libcacard-base-y += cac.o event.o
-+libcacard-base-y += vcard.o vreader.o
-+libcacard-base-y += vcard_emul_nss.o
-+libcacard-base-y += vcard_emul_type.o
-+libcacard-base-y += card_7816.o
-+libcacard-y = $(addprefix libcacard/,$(libcacard-base-y))
- 
- common-obj-$(CONFIG_SMARTCARD_NSS) += $(libcacard-y)
- 
-diff --git a/configure b/configure
-index 994f731..7498e3f 100755
---- a/configure
-+++ b/configure
-@@ -3136,7 +3136,7 @@ if test "$softmmu" = yes ; then
-     fi
-   fi
-   if test "$smartcard_nss" = "yes" ; then
--    tools="vscclient\$(EXESUF) $tools"
-+    tools="libcacard/vscclient\$(EXESUF) $tools"
-   fi
- fi
- 
-diff --git a/libcacard/Makefile b/libcacard/Makefile
-index 49a9729..750713a 100644
---- a/libcacard/Makefile
-+++ b/libcacard/Makefile
-@@ -47,6 +47,10 @@ libcacard.pc: $(libcacard_srcpath)/libcacard.pc.in
- 		< $(libcacard_srcpath)/libcacard.pc.in > libcacard.pc,\
- 	"  GEN   $@")
- 
-+VSCCLIENT_QEMU_OBJS=$(addprefix ../,$(oslib-obj-y) $(trace-obj-y) qemu-timer-common.o iov.o cutils.o qemu-user.o)
-+vscclient$(EXESUF): $(VSCCLIENT_QEMU_OBJS) $(libcacard-base-y) vscclient.o
-+vscclient$(EXESUF): LIBS += $(libcacard_libs)
-+
- .PHONY: install-libcacard
- 
- install-libcacard: libcacard.pc libcacard.la vscclient
-@@ -54,7 +58,7 @@ install-libcacard: libcacard.pc libcacard.la vscclient
- 	$(INSTALL_DIR) "$(DESTDIR)$(libdir)/pkgconfig"
- 	$(INSTALL_DIR) "$(DESTDIR)$(libcacard_includedir)"
- 	$(INSTALL_DIR) "$(DESTDIR)$(bindir)"
--	$(LIBTOOL) --mode=install $(INSTALL_PROG) vscclient "$(DESTDIR)$(bindir)"
-+	$(LIBTOOL) --mode=install $(INSTALL_PROG) vscclient$(EXESUF) "$(DESTDIR)$(bindir)"
- 	$(LIBTOOL) --mode=install $(INSTALL_DATA) libcacard.la "$(DESTDIR)$(libdir)"
- 	$(LIBTOOL) --mode=install $(INSTALL_DATA) libcacard.pc "$(DESTDIR)$(libdir)/pkgconfig"
- 	for inc in *.h; do \
--- 
-1.8.0
-
diff --git a/0001-libcacard-fix-missing-symbols-in-libcacard.so.patch b/0001-libcacard-fix-missing-symbols-in-libcacard.so.patch
new file mode 100644
index 0000000..27e4360
--- /dev/null
+++ b/0001-libcacard-fix-missing-symbols-in-libcacard.so.patch
@@ -0,0 +1,25 @@
+From 94afb78477a5b078449e5d48b38e74aac3fa5ac4 Mon Sep 17 00:00:00 2001
+From: Alon Levy <alevy@redhat.com>
+Date: Wed, 28 Nov 2012 16:38:43 +0200
+Subject: [PATCH] libcacard: fix missing symbols in libcacard.so
+
+---
+ libcacard/Makefile | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/libcacard/Makefile b/libcacard/Makefile
+index c26aac6..49a9729 100644
+--- a/libcacard/Makefile
++++ b/libcacard/Makefile
+@@ -7,7 +7,7 @@ libcacard_includedir=$(includedir)/cacard
+ $(call set-vpath, $(SRC_PATH))
+ 
+ # objects linked into a shared library, built with libtool with -fPIC if required
+-QEMU_OBJS=$(oslib-obj-y) qemu-timer-common.o $(trace-obj-y) $(stub-obj-y)
++QEMU_OBJS=$(oslib-obj-y) qemu-timer-common.o iov.o cutils.o qemu-user.o $(trace-obj-y) $(stub-obj-y)
+ QEMU_OBJS_LIB=$(patsubst %.o,%.lo,$(QEMU_OBJS))
+ 
+ QEMU_CFLAGS+=-I../
+-- 
+1.8.1
+
diff --git a/0002-Fix-migration-from-qemu-kvm-1.2.patch b/0002-Fix-migration-from-qemu-kvm-1.2.patch
deleted file mode 100644
index a04a862..0000000
--- a/0002-Fix-migration-from-qemu-kvm-1.2.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From 633ff09ae5702676d0f33cba80db45ff5bdbde0f Mon Sep 17 00:00:00 2001
-Message-Id: <633ff09ae5702676d0f33cba80db45ff5bdbde0f.1354903384.git.crobinso@redhat.com>
-In-Reply-To: <94afb78477a5b078449e5d48b38e74aac3fa5ac4.1354903384.git.crobinso@redhat.com>
-References: <94afb78477a5b078449e5d48b38e74aac3fa5ac4.1354903384.git.crobinso@redhat.com>
-From: Cole Robinson <crobinso@redhat.com>
-Date: Fri, 7 Dec 2012 12:32:41 -0500
-Subject: [PATCH] Fix migration from qemu-kvm 1.2
-
-As suggested by Marcelo
----
- hw/acpi_piix4.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
-index 519269a..66adc88 100644
---- a/hw/acpi_piix4.c
-+++ b/hw/acpi_piix4.c
-@@ -310,8 +310,8 @@ static int acpi_load_old(QEMUFile *f, void *opaque, int version_id)
-  */
- static const VMStateDescription vmstate_acpi = {
-     .name = "piix4_pm",
--    .version_id = 3,
--    .minimum_version_id = 3,
-+    .version_id = 2,
-+    .minimum_version_id = 2,
-     .minimum_version_id_old = 1,
-     .load_state_old = acpi_load_old,
-     .post_load = vmstate_acpi_post_load,
--- 
-1.8.0
-
diff --git a/0002-configure-move-vscclient-binary-under-libcacard.patch b/0002-configure-move-vscclient-binary-under-libcacard.patch
new file mode 100644
index 0000000..bca69a6
--- /dev/null
+++ b/0002-configure-move-vscclient-binary-under-libcacard.patch
@@ -0,0 +1,93 @@
+From df9d09b15cb4b8397bfe984bf3f54dbb5457d446 Mon Sep 17 00:00:00 2001
+From: Alon Levy <alevy@redhat.com>
+Date: Thu, 29 Nov 2012 14:11:19 +0200
+Subject: [PATCH] configure: move vscclient binary under libcacard
+
+build rule is in top level Makefile like other tools.
+
+build rule also exists in libcacard for installation purposes. This was
+fixed in a better way in 1.3.0-rc2
+---
+ Makefile           |  4 ++--
+ Makefile.objs      | 11 ++++++-----
+ configure          |  2 +-
+ libcacard/Makefile |  6 +++++-
+ 4 files changed, 14 insertions(+), 9 deletions(-)
+
+diff --git a/Makefile b/Makefile
+index 9ecbcbb..c2d34a9 100644
+--- a/Makefile
++++ b/Makefile
+@@ -197,8 +197,8 @@ qemu-io$(EXESUF): qemu-io.o cmd.o $(tools-obj-y) $(block-obj-y) libqemustub.a
+ 
+ qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o
+ 
+-vscclient$(EXESUF): $(libcacard-y) $(oslib-obj-y) $(trace-obj-y) libcacard/vscclient.o libqemustub.a
+-	$(call quiet-command,$(CC) $(LDFLAGS) -o $@ $^ $(libcacard_libs) $(LIBS),"  LINK  $@")
++libcacard/vscclient$(EXESUF): $(libcacard-y) $(oslib-obj-y) $(trace-obj-y) iov.o cutils.o qemu-user.o libcacard/vscclient.o libqemustub.a
++libcacard/vscclient$(EXESUF): LIBS += $(libcacard_libs)
+ 
+ fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o fsdev/virtio-9p-marshal.o oslib-posix.o $(trace-obj-y)
+ fsdev/virtfs-proxy-helper$(EXESUF): LIBS += -lcap
+diff --git a/Makefile.objs b/Makefile.objs
+index 3c7abca..140d592 100644
+--- a/Makefile.objs
++++ b/Makefile.objs
+@@ -211,11 +211,12 @@ $(trace-obj-y): $(GENERATED_HEADERS)
+ ######################################################################
+ # smartcard
+ 
+-libcacard-y += libcacard/cac.o libcacard/event.o
+-libcacard-y += libcacard/vcard.o libcacard/vreader.o
+-libcacard-y += libcacard/vcard_emul_nss.o
+-libcacard-y += libcacard/vcard_emul_type.o
+-libcacard-y += libcacard/card_7816.o
++libcacard-base-y += cac.o event.o
++libcacard-base-y += vcard.o vreader.o
++libcacard-base-y += vcard_emul_nss.o
++libcacard-base-y += vcard_emul_type.o
++libcacard-base-y += card_7816.o
++libcacard-y = $(addprefix libcacard/,$(libcacard-base-y))
+ 
+ common-obj-$(CONFIG_SMARTCARD_NSS) += $(libcacard-y)
+ 
+diff --git a/configure b/configure
+index 994f731..7498e3f 100755
+--- a/configure
++++ b/configure
+@@ -3136,7 +3136,7 @@ if test "$softmmu" = yes ; then
+     fi
+   fi
+   if test "$smartcard_nss" = "yes" ; then
+-    tools="vscclient\$(EXESUF) $tools"
++    tools="libcacard/vscclient\$(EXESUF) $tools"
+   fi
+ fi
+ 
+diff --git a/libcacard/Makefile b/libcacard/Makefile
+index 49a9729..750713a 100644
+--- a/libcacard/Makefile
++++ b/libcacard/Makefile
+@@ -47,6 +47,10 @@ libcacard.pc: $(libcacard_srcpath)/libcacard.pc.in
+ 		< $(libcacard_srcpath)/libcacard.pc.in > libcacard.pc,\
+ 	"  GEN   $@")
+ 
++VSCCLIENT_QEMU_OBJS=$(addprefix ../,$(oslib-obj-y) $(trace-obj-y) qemu-timer-common.o iov.o cutils.o qemu-user.o)
++vscclient$(EXESUF): $(VSCCLIENT_QEMU_OBJS) $(libcacard-base-y) vscclient.o
++vscclient$(EXESUF): LIBS += $(libcacard_libs)
++
+ .PHONY: install-libcacard
+ 
+ install-libcacard: libcacard.pc libcacard.la vscclient
+@@ -54,7 +58,7 @@ install-libcacard: libcacard.pc libcacard.la vscclient
+ 	$(INSTALL_DIR) "$(DESTDIR)$(libdir)/pkgconfig"
+ 	$(INSTALL_DIR) "$(DESTDIR)$(libcacard_includedir)"
+ 	$(INSTALL_DIR) "$(DESTDIR)$(bindir)"
+-	$(LIBTOOL) --mode=install $(INSTALL_PROG) vscclient "$(DESTDIR)$(bindir)"
++	$(LIBTOOL) --mode=install $(INSTALL_PROG) vscclient$(EXESUF) "$(DESTDIR)$(bindir)"
+ 	$(LIBTOOL) --mode=install $(INSTALL_DATA) libcacard.la "$(DESTDIR)$(libdir)"
+ 	$(LIBTOOL) --mode=install $(INSTALL_DATA) libcacard.pc "$(DESTDIR)$(libdir)/pkgconfig"
+ 	for inc in *.h; do \
+-- 
+1.8.1
+
diff --git a/0003-rtc-test-skip-year-2038-overflow-check-in-case-time_.patch b/0003-rtc-test-skip-year-2038-overflow-check-in-case-time_.patch
new file mode 100644
index 0000000..7f9a1c5
--- /dev/null
+++ b/0003-rtc-test-skip-year-2038-overflow-check-in-case-time_.patch
@@ -0,0 +1,29 @@
+From 43eb809a0f98b644cf4a2dd6a257185ad781346c Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Mon, 7 Jan 2013 15:11:52 +0100
+Subject: [PATCH] rtc-test: skip year-2038 overflow check in case time_t is
+ 32bit only
+
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+---
+ tests/rtc-test.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/tests/rtc-test.c b/tests/rtc-test.c
+index 02edbf5..e7123ca 100644
+--- a/tests/rtc-test.c
++++ b/tests/rtc-test.c
+@@ -201,6 +201,10 @@ static void set_year_20xx(void)
+     g_assert_cmpint(cmos_read(RTC_YEAR), ==, 0x11);
+     g_assert_cmpint(cmos_read(RTC_CENTURY), ==, 0x20);
+ 
++    if (sizeof(time_t) == 4) {
++        return;
++    }
++
+     /* Set a date in 2080 to ensure there is no year-2038 overflow.  */
+     cmos_write(RTC_REG_A, 0x76);
+     cmos_write(RTC_YEAR, 0x80);
+-- 
+1.8.1
+
diff --git a/0004-Fix-migration-compat-with-qemu-kvm.patch b/0004-Fix-migration-compat-with-qemu-kvm.patch
new file mode 100644
index 0000000..57852a4
--- /dev/null
+++ b/0004-Fix-migration-compat-with-qemu-kvm.patch
@@ -0,0 +1,70 @@
+From 99c9360e120aa7098952564af5bda76834498442 Mon Sep 17 00:00:00 2001
+From: Cole Robinson <crobinso@redhat.com>
+Date: Mon, 14 Jan 2013 21:49:21 -0500
+Subject: [PATCH] Fix migration compat with qemu-kvm
+
+Outlined here:
+https://lists.gnu.org/archive/html/qemu-devel/2013-01/msg02340.html
+https://lists.gnu.org/archive/html/qemu-devel/2013-01/msg02540.html
+---
+ hw/acpi_piix4.c |  2 +-
+ hw/cirrus_vga.c |  2 +-
+ hw/pc_piix.c    | 16 ----------------
+ 3 files changed, 2 insertions(+), 18 deletions(-)
+
+diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
+index 519269a..785e756 100644
+--- a/hw/acpi_piix4.c
++++ b/hw/acpi_piix4.c
+@@ -311,7 +311,7 @@ static int acpi_load_old(QEMUFile *f, void *opaque, int version_id)
+ static const VMStateDescription vmstate_acpi = {
+     .name = "piix4_pm",
+     .version_id = 3,
+-    .minimum_version_id = 3,
++    .minimum_version_id = 2,
+     .minimum_version_id_old = 1,
+     .load_state_old = acpi_load_old,
+     .post_load = vmstate_acpi_post_load,
+diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
+index 9bef96e..8c94428 100644
+--- a/hw/cirrus_vga.c
++++ b/hw/cirrus_vga.c
+@@ -2975,7 +2975,7 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev)
+ 
+ static Property pci_vga_cirrus_properties[] = {
+     DEFINE_PROP_UINT32("vgamem_mb", struct PCICirrusVGAState,
+-                       cirrus_vga.vga.vram_size_mb, 8),
++                       cirrus_vga.vga.vram_size_mb, 16),
+     DEFINE_PROP_END_OF_LIST(),
+ };
+ 
+diff --git a/hw/pc_piix.c b/hw/pc_piix.c
+index aa3e7f4..ea37ef2 100644
+--- a/hw/pc_piix.c
++++ b/hw/pc_piix.c
+@@ -339,22 +339,6 @@ static QEMUMachine pc_machine_v1_2 = {
+             .property = "param_change",\
+             .value    = "off",\
+         },{\
+-            .driver   = "VGA",\
+-            .property = "vgamem_mb",\
+-            .value    = stringify(8),\
+-        },{\
+-            .driver   = "vmware-svga",\
+-            .property = "vgamem_mb",\
+-            .value    = stringify(8),\
+-        },{\
+-            .driver   = "qxl-vga",\
+-            .property = "vgamem_mb",\
+-            .value    = stringify(8),\
+-        },{\
+-            .driver   = "qxl",\
+-            .property = "vgamem_mb",\
+-            .value    = stringify(8),\
+-        },{\
+             .driver   = "virtio-blk-pci",\
+             .property = "config-wce",\
+             .value    = "off",\
+-- 
+1.8.1
+
diff --git a/0100-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch b/0100-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch
deleted file mode 100644
index 06e63fb..0000000
--- a/0100-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch
+++ /dev/null
@@ -1,58 +0,0 @@
-From 9f0944a25bc1094fa7a74ac9df14e184e2c5c82d Mon Sep 17 00:00:00 2001
-Message-Id: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com>
-From: Amit Shah <amit.shah@redhat.com>
-Date: Mon, 21 Mar 2011 21:57:47 +0100
-Subject: [PATCH] char: Split out tcp socket close code in a separate function
-
-Signed-off-by: Amit Shah <amit.shah@redhat.com>
-Signed-off-by: Cole Robinson <crobinso@redhat.com>
----
- qemu-char.c | 25 ++++++++++++++++---------
- 1 file changed, 16 insertions(+), 9 deletions(-)
-
-diff --git a/qemu-char.c b/qemu-char.c
-index 242b799..77776dc 100644
---- a/qemu-char.c
-+++ b/qemu-char.c
-@@ -2146,6 +2146,21 @@ typedef struct {
- 
- static void tcp_chr_accept(void *opaque);
- 
-+static void tcp_closed(void *opaque)
-+{
-+    CharDriverState *chr = opaque;
-+    TCPCharDriver *s = chr->opaque;
-+
-+    s->connected = 0;
-+    if (s->listen_fd >= 0) {
-+        qemu_set_fd_handler2(s->listen_fd, NULL, tcp_chr_accept, NULL, chr);
-+    }
-+    qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
-+    closesocket(s->fd);
-+    s->fd = -1;
-+    qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
-+}
-+
- static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
- {
-     TCPCharDriver *s = chr->opaque;
-@@ -2304,15 +2319,7 @@ static void tcp_chr_read(void *opaque)
-         len = s->max_size;
-     size = tcp_chr_recv(chr, (void *)buf, len);
-     if (size == 0) {
--        /* connection closed */
--        s->connected = 0;
--        if (s->listen_fd >= 0) {
--            qemu_set_fd_handler2(s->listen_fd, NULL, tcp_chr_accept, NULL, chr);
--        }
--        qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
--        closesocket(s->fd);
--        s->fd = -1;
--        qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
-+        tcp_closed(chr);
-     } else if (size > 0) {
-         if (s->do_telnetopt)
-             tcp_chr_process_IAC_bytes(chr, s, buf, &size);
--- 
-1.8.0
-
diff --git a/0101-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch b/0101-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch
deleted file mode 100644
index 1b2953a..0000000
--- a/0101-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch
+++ /dev/null
@@ -1,1046 +0,0 @@
-From 501ffec04b2b5104ef854624027f0cd769d5d314 Mon Sep 17 00:00:00 2001
-Message-Id: <501ffec04b2b5104ef854624027f0cd769d5d314.1354903384.git.crobinso@redhat.com>
-In-Reply-To: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com>
-References: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com>
-From: Amit Shah <amit.shah@redhat.com>
-Date: Mon, 21 Mar 2011 20:31:45 +0100
-Subject: [PATCH] char: Add a QemuChrHandlers struct to initialise chardev
- handlers
-
-Instead of passing each handler in the qemu_add_handlers() function,
-create a struct of handlers that can be passed to the function instead.
-
-Signed-off-by: Amit Shah <amit.shah@redhat.com>
-Signed-off-by: Cole Robinson <crobinso@redhat.com>
----
- backends/rng-egd.c      | 12 +++++++++---
- gdbstub.c               |  9 +++++++--
- hw/cadence_uart.c       |  9 +++++++--
- hw/ccid-card-passthru.c | 11 +++++++----
- hw/debugcon.c           |  2 +-
- hw/escc.c               |  9 +++++++--
- hw/etraxfs_ser.c        | 13 +++++++++----
- hw/exynos4210_uart.c    |  9 +++++++--
- hw/grlib_apbuart.c      | 12 +++++++-----
- hw/imx_serial.c         |  9 +++++++--
- hw/ivshmem.c            | 28 ++++++++++++++++++++++------
- hw/lm32_juart.c         |  8 +++++++-
- hw/lm32_uart.c          |  8 +++++++-
- hw/mcf_uart.c           |  9 +++++++--
- hw/milkymist-uart.c     |  8 +++++++-
- hw/pl011.c              |  9 +++++++--
- hw/pxa2xx.c             | 13 +++++++++----
- hw/qdev-properties.c    |  2 +-
- hw/s390x/sclpconsole.c  |  9 +++++++--
- hw/serial.c             | 11 ++++++++---
- hw/sh_serial.c          | 12 +++++++++---
- hw/spapr_vty.c          |  8 ++++++--
- hw/strongarm.c          | 12 +++++++-----
- hw/usb/dev-serial.c     | 11 ++++++++---
- hw/usb/redirect.c       |  9 +++++++--
- hw/virtio-console.c     |  9 +++++++--
- hw/xen_console.c        | 16 +++++++++++-----
- hw/xilinx_uartlite.c    | 11 +++++++++--
- monitor.c               | 18 ++++++++++++++----
- net/slirp.c             |  8 ++++++--
- qemu-char.c             | 32 ++++++++++++++++++++++----------
- qemu-char.h             | 13 +++++++++----
- qtest.c                 |  9 ++++++++-
- 33 files changed, 273 insertions(+), 95 deletions(-)
-
-diff --git a/backends/rng-egd.c b/backends/rng-egd.c
-index ad84737..30194be 100644
---- a/backends/rng-egd.c
-+++ b/backends/rng-egd.c
-@@ -133,6 +133,13 @@ static void rng_egd_cancel_requests(RngBackend *b)
-     rng_egd_free_requests(s);
- }
- 
-+static const QemuChrHandlers rng_egd_handlers = {
-+    .fd_can_read = rng_egd_chr_can_read,
-+    .fd_read = rng_egd_chr_read,
-+    .fd_event = NULL,
-+};
-+
-+
- static void rng_egd_opened(RngBackend *b, Error **errp)
- {
-     RngEgd *s = RNG_EGD(b);
-@@ -150,8 +157,7 @@ static void rng_egd_opened(RngBackend *b, Error **errp)
-     }
- 
-     /* FIXME we should resubmit pending requests when the CDS reconnects. */
--    qemu_chr_add_handlers(s->chr, rng_egd_chr_can_read, rng_egd_chr_read,
--                          NULL, s);
-+    qemu_chr_add_handlers(s->chr, &rng_egd_handlers, s);
- }
- 
- static void rng_egd_set_chardev(Object *obj, const char *value, Error **errp)
-@@ -190,7 +196,7 @@ static void rng_egd_finalize(Object *obj)
-     RngEgd *s = RNG_EGD(obj);
- 
-     if (s->chr) {
--        qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, NULL);
-+        qemu_chr_add_handlers(s->chr, NULL, NULL);
-     }
- 
-     g_free(s->chr_name);
-diff --git a/gdbstub.c b/gdbstub.c
-index d02ec75..5d93d20 100644
---- a/gdbstub.c
-+++ b/gdbstub.c
-@@ -2973,6 +2973,12 @@ static void gdb_sigterm_handler(int signal)
- }
- #endif
- 
-+static const QemuChrHandlers gdb_handlers = {
-+    .fd_can_read = gdb_chr_can_receive,
-+    .fd_read = gdb_chr_receive,
-+    .fd_event = gdb_chr_event,
-+};
-+
- int gdbserver_start(const char *device)
- {
-     GDBState *s;
-@@ -3002,8 +3008,7 @@ int gdbserver_start(const char *device)
-         if (!chr)
-             return -1;
- 
--        qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive,
--                              gdb_chr_event, NULL);
-+        qemu_chr_add_handlers(chr, &gdb_handlers, NULL);
-     }
- 
-     s = gdbserver_state;
-diff --git a/hw/cadence_uart.c b/hw/cadence_uart.c
-index 686e617..36ad620 100644
---- a/hw/cadence_uart.c
-+++ b/hw/cadence_uart.c
-@@ -438,6 +438,12 @@ static void cadence_uart_reset(UartState *s)
-     s->rx_wpos = 0;
- }
- 
-+static const QemuChrHandlers cadence_uart_handlers = {
-+    .fd_can_read = uart_can_receive,
-+    .fd_read = uart_receive,
-+    .fd_event = uart_event,
-+};
-+
- static int cadence_uart_init(SysBusDevice *dev)
- {
-     UartState *s = FROM_SYSBUS(UartState, dev);
-@@ -459,8 +465,7 @@ static int cadence_uart_init(SysBusDevice *dev)
-     cadence_uart_reset(s);
- 
-     if (s->chr) {
--        qemu_chr_add_handlers(s->chr, uart_can_receive, uart_receive,
--                              uart_event, s);
-+        qemu_chr_add_handlers(s->chr, &cadence_uart_handlers, s);
-     }
- 
-     return 0;
-diff --git a/hw/ccid-card-passthru.c b/hw/ccid-card-passthru.c
-index bd6c777..fb32107 100644
---- a/hw/ccid-card-passthru.c
-+++ b/hw/ccid-card-passthru.c
-@@ -274,6 +274,12 @@ static const uint8_t *passthru_get_atr(CCIDCardState *base, uint32_t *len)
-     return card->atr;
- }
- 
-+static const QemuChrHandlers passthru_handlers = {
-+    .fd_can_read = ccid_card_vscard_can_read,
-+    .fd_read = ccid_card_vscard_read,
-+    .fd_event = ccid_card_vscard_event,
-+};
-+
- static int passthru_initfn(CCIDCardState *base)
- {
-     PassthruState *card = DO_UPCAST(PassthruState, base, base);
-@@ -282,10 +288,7 @@ static int passthru_initfn(CCIDCardState *base)
-     card->vscard_in_hdr = 0;
-     if (card->cs) {
-         DPRINTF(card, D_INFO, "initing chardev\n");
--        qemu_chr_add_handlers(card->cs,
--            ccid_card_vscard_can_read,
--            ccid_card_vscard_read,
--            ccid_card_vscard_event, card);
-+        qemu_chr_add_handlers(card->cs, &passthru_handlers, card);
-         ccid_card_vscard_send_init(card);
-     } else {
-         error_report("missing chardev");
-diff --git a/hw/debugcon.c b/hw/debugcon.c
-index 14ab326..7887fd2 100644
---- a/hw/debugcon.c
-+++ b/hw/debugcon.c
-@@ -73,7 +73,7 @@ static void debugcon_init_core(DebugconState *s)
-         exit(1);
-     }
- 
--    qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, s);
-+    qemu_chr_add_handlers(s->chr, NULL, s);
- }
- 
- static int debugcon_isa_initfn(ISADevice *dev)
-diff --git a/hw/escc.c b/hw/escc.c
-index a356613..3f26f45 100644
---- a/hw/escc.c
-+++ b/hw/escc.c
-@@ -867,6 +867,12 @@ void slavio_serial_ms_kbd_init(hwaddr base, qemu_irq irq,
-     sysbus_mmio_map(s, 0, base);
- }
- 
-+static const QemuChrHandlers serial_handlers = {
-+    .fd_can_read = serial_can_receive,
-+    .fd_read = serial_receive1,
-+    .fd_event = serial_event,
-+};
-+
- static int escc_init1(SysBusDevice *dev)
- {
-     SerialState *s = FROM_SYSBUS(SerialState, dev);
-@@ -879,8 +885,7 @@ static int escc_init1(SysBusDevice *dev)
-         s->chn[i].chn = 1 - i;
-         s->chn[i].clock = s->frequency / 2;
-         if (s->chn[i].chr) {
--            qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive,
--                                  serial_receive1, serial_event, &s->chn[i]);
-+            qemu_chr_add_handlers(s->chn[i].chr, &serial_handlers, &s->chn[i]);
-         }
-     }
-     s->chn[0].otherchn = &s->chn[1];
-diff --git a/hw/etraxfs_ser.c b/hw/etraxfs_ser.c
-index ee0d72b..64552cc 100644
---- a/hw/etraxfs_ser.c
-+++ b/hw/etraxfs_ser.c
-@@ -208,6 +208,12 @@ static void etraxfs_ser_reset(DeviceState *d)
- 
- }
- 
-+static const QemuChrHandlers serial_handlers = {
-+    .fd_can_read = serial_can_receive,
-+    .fd_read = serial_receive,
-+    .fd_event = serial_event,
-+};
-+
- static int etraxfs_ser_init(SysBusDevice *dev)
- {
-     struct etrax_serial *s = FROM_SYSBUS(typeof (*s), dev);
-@@ -217,10 +223,9 @@ static int etraxfs_ser_init(SysBusDevice *dev)
-     sysbus_init_mmio(dev, &s->mmio);
- 
-     s->chr = qemu_char_get_next_serial();
--    if (s->chr)
--        qemu_chr_add_handlers(s->chr,
--                      serial_can_receive, serial_receive,
--                      serial_event, s);
-+    if (s->chr) {
-+        qemu_chr_add_handlers(s->chr, &serial_handlers, s);
-+    }
-     return 0;
- }
- 
-diff --git a/hw/exynos4210_uart.c b/hw/exynos4210_uart.c
-index 20dcd9f..f2949aa 100644
---- a/hw/exynos4210_uart.c
-+++ b/hw/exynos4210_uart.c
-@@ -625,6 +625,12 @@ DeviceState *exynos4210_uart_create(hwaddr addr,
-     return dev;
- }
- 
-+static const QemuChrHandlers exynos4210_handlers = {
-+    .fd_can_read = exynos4210_uart_can_receive,
-+    .fd_read     = exynos4210_uart_receive,
-+    .fd_event    = exynos4210_uart_event,
-+};
-+
- static int exynos4210_uart_init(SysBusDevice *dev)
- {
-     Exynos4210UartState *s = FROM_SYSBUS(Exynos4210UartState, dev);
-@@ -636,8 +642,7 @@ static int exynos4210_uart_init(SysBusDevice *dev)
- 
-     sysbus_init_irq(dev, &s->irq);
- 
--    qemu_chr_add_handlers(s->chr, exynos4210_uart_can_receive,
--                          exynos4210_uart_receive, exynos4210_uart_event, s);
-+    qemu_chr_add_handlers(s->chr, &exynos4210_handlers, s);
- 
-     return 0;
- }
-diff --git a/hw/grlib_apbuart.c b/hw/grlib_apbuart.c
-index 0865764..fb0e703 100644
---- a/hw/grlib_apbuart.c
-+++ b/hw/grlib_apbuart.c
-@@ -222,15 +222,17 @@ static const MemoryRegionOps grlib_apbuart_ops = {
-     .endianness = DEVICE_NATIVE_ENDIAN,
- };
- 
-+static const QemuChrHandlers grlib_handlers = {
-+    .fd_can_read = grlib_apbuart_can_receive,
-+    .fd_read = grlib_apbuart_receive,
-+    .fd_event = grlib_apbuart_event,
-+};
-+
- static int grlib_apbuart_init(SysBusDevice *dev)
- {
-     UART *uart = FROM_SYSBUS(typeof(*uart), dev);
- 
--    qemu_chr_add_handlers(uart->chr,
--                          grlib_apbuart_can_receive,
--                          grlib_apbuart_receive,
--                          grlib_apbuart_event,
--                          uart);
-+    qemu_chr_add_handlers(uart->chr, &grlib_handlers, uart);
- 
-     sysbus_init_irq(dev, &uart->irq);
- 
-diff --git a/hw/imx_serial.c b/hw/imx_serial.c
-index dcd125f..5347ec8 100644
---- a/hw/imx_serial.c
-+++ b/hw/imx_serial.c
-@@ -381,6 +381,12 @@ static const struct MemoryRegionOps imx_serial_ops = {
-     .endianness = DEVICE_NATIVE_ENDIAN,
- };
- 
-+static const QemuChrHandlers imx_handlers = {
-+    .fd_can_read = imx_can_receive,
-+    .fd_read = imx_receive,
-+    .fd_event = imx_event,
-+};
-+
- static int imx_serial_init(SysBusDevice *dev)
- {
-     IMXSerialState *s = FROM_SYSBUS(IMXSerialState, dev);
-@@ -391,8 +397,7 @@ static int imx_serial_init(SysBusDevice *dev)
-     sysbus_init_irq(dev, &s->irq);
- 
-     if (s->chr) {
--        qemu_chr_add_handlers(s->chr, imx_can_receive, imx_receive,
--                              imx_event, s);
-+        qemu_chr_add_handlers(s->chr, &imx_handlers, s);
-     } else {
-         DPRINTF("No char dev for uart at 0x%lx\n",
-                 (unsigned long)s->iomem.ram_addr);
-diff --git a/hw/ivshmem.c b/hw/ivshmem.c
-index f6dbb21..0e56a97 100644
---- a/hw/ivshmem.c
-+++ b/hw/ivshmem.c
-@@ -274,6 +274,18 @@ static void fake_irqfd(void *opaque, const uint8_t *buf, int size) {
-     msix_notify(pdev, entry->vector);
- }
- 
-+static const QemuChrHandlers ivshmem_handlers = {
-+    .fd_can_read = ivshmem_can_receive,
-+    .fd_read = ivshmem_receive,
-+    .fd_event = ivshmem_event,
-+};
-+
-+static const QemuChrHandlers ivshmem_msi_handlers = {
-+    .fd_can_read = ivshmem_can_receive,
-+    .fd_read = fake_irqfd,
-+    .fd_event = ivshmem_event,
-+};
-+
- static CharDriverState* create_eventfd_chr_device(void * opaque, EventNotifier *n,
-                                                   int vector)
- {
-@@ -294,11 +306,10 @@ static CharDriverState* create_eventfd_chr_device(void * opaque, EventNotifier *
-         s->eventfd_table[vector].pdev = &s->dev;
-         s->eventfd_table[vector].vector = vector;
- 
--        qemu_chr_add_handlers(chr, ivshmem_can_receive, fake_irqfd,
--                      ivshmem_event, &s->eventfd_table[vector]);
-+        qemu_chr_add_handlers(chr, &ivshmem_msi_handlers,
-+                              &s->eventfd_table[vector]);
-     } else {
--        qemu_chr_add_handlers(chr, ivshmem_can_receive, ivshmem_receive,
--                      ivshmem_event, s);
-+        qemu_chr_add_handlers(chr, &ivshmem_handlers, s);
-     }
- 
-     return chr;
-@@ -632,6 +643,12 @@ static void ivshmem_write_config(PCIDevice *pci_dev, uint32_t address,
-     msix_write_config(pci_dev, address, val, len);
- }
- 
-+static const QemuChrHandlers ivshmem_server_handlers = {
-+    .fd_can_read = ivshmem_can_receive,
-+    .fd_read = ivshmem_read,
-+    .fd_event = ivshmem_event,
-+};
-+
- static int pci_ivshmem_init(PCIDevice *dev)
- {
-     IVShmemState *s = DO_UPCAST(IVShmemState, dev, dev);
-@@ -722,8 +739,7 @@ static int pci_ivshmem_init(PCIDevice *dev)
- 
-         s->eventfd_chr = g_malloc0(s->vectors * sizeof(CharDriverState *));
- 
--        qemu_chr_add_handlers(s->server_chr, ivshmem_can_receive, ivshmem_read,
--                     ivshmem_event, s);
-+        qemu_chr_add_handlers(s->server_chr, &ivshmem_server_handlers, s);
-     } else {
-         /* just map the file immediately, we're not using a server */
-         int fd;
-diff --git a/hw/lm32_juart.c b/hw/lm32_juart.c
-index f07ed39..d4daeb8 100644
---- a/hw/lm32_juart.c
-+++ b/hw/lm32_juart.c
-@@ -110,13 +110,19 @@ static void juart_reset(DeviceState *d)
-     s->jrx = 0;
- }
- 
-+static const QemuChrHandlers juart_handlers = {
-+    .fd_can_read = juart_can_rx,
-+    .fd_read = juart_rx,
-+    .fd_event = juart_event,
-+};
-+
- static int lm32_juart_init(SysBusDevice *dev)
- {
-     LM32JuartState *s = FROM_SYSBUS(typeof(*s), dev);
- 
-     s->chr = qemu_char_get_next_serial();
-     if (s->chr) {
--        qemu_chr_add_handlers(s->chr, juart_can_rx, juart_rx, juart_event, s);
-+        qemu_chr_add_handlers(s->chr, &juart_handlers, s);
-     }
- 
-     return 0;
-diff --git a/hw/lm32_uart.c b/hw/lm32_uart.c
-index adb9287..e581bea 100644
---- a/hw/lm32_uart.c
-+++ b/hw/lm32_uart.c
-@@ -243,6 +243,12 @@ static void uart_reset(DeviceState *d)
-     s->regs[R_LSR] = LSR_THRE | LSR_TEMT;
- }
- 
-+static const QemuChrHandlers uart_handlers = {
-+    .fd_can_read = uart_can_rx,
-+    .fd_read = uart_rx,
-+    .fd_event = uart_event,
-+};
-+
- static int lm32_uart_init(SysBusDevice *dev)
- {
-     LM32UartState *s = FROM_SYSBUS(typeof(*s), dev);
-@@ -254,7 +260,7 @@ static int lm32_uart_init(SysBusDevice *dev)
- 
-     s->chr = qemu_char_get_next_serial();
-     if (s->chr) {
--        qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
-+        qemu_chr_add_handlers(s->chr, &uart_handlers, s);
-     }
- 
-     return 0;
-diff --git a/hw/mcf_uart.c b/hw/mcf_uart.c
-index d1655f8..8ead254 100644
---- a/hw/mcf_uart.c
-+++ b/hw/mcf_uart.c
-@@ -272,6 +272,12 @@ static void mcf_uart_receive(void *opaque, const uint8_t *buf, int size)
-     mcf_uart_push_byte(s, buf[0]);
- }
- 
-+static const QemuChrHandlers mcf_uart_handlers = {
-+    .fd_can_read = mcf_uart_can_receive,
-+    .fd_read = mcf_uart_receive,
-+    .fd_event = mcf_uart_event,
-+};
-+
- void *mcf_uart_init(qemu_irq irq, CharDriverState *chr)
- {
-     mcf_uart_state *s;
-@@ -280,8 +286,7 @@ void *mcf_uart_init(qemu_irq irq, CharDriverState *chr)
-     s->chr = chr;
-     s->irq = irq;
-     if (chr) {
--        qemu_chr_add_handlers(chr, mcf_uart_can_receive, mcf_uart_receive,
--                              mcf_uart_event, s);
-+        qemu_chr_add_handlers(chr, &mcf_uart_handlers, s);
-     }
-     mcf_uart_reset(s);
-     return s;
-diff --git a/hw/milkymist-uart.c b/hw/milkymist-uart.c
-index aefa8c7..0c924f2 100644
---- a/hw/milkymist-uart.c
-+++ b/hw/milkymist-uart.c
-@@ -189,6 +189,12 @@ static void milkymist_uart_reset(DeviceState *d)
-     s->regs[R_STAT] = STAT_THRE;
- }
- 
-+static const QemuChrHandlers uart_handlers = {
-+    .fd_can_read = uart_can_rx,
-+    .fd_read = uart_rx,
-+    .fd_event = uart_event,
-+};
-+
- static int milkymist_uart_init(SysBusDevice *dev)
- {
-     MilkymistUartState *s = FROM_SYSBUS(typeof(*s), dev);
-@@ -201,7 +207,7 @@ static int milkymist_uart_init(SysBusDevice *dev)
- 
-     s->chr = qemu_char_get_next_serial();
-     if (s->chr) {
--        qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
-+        qemu_chr_add_handlers(s->chr, &uart_handlers, s);
-     }
- 
-     return 0;
-diff --git a/hw/pl011.c b/hw/pl011.c
-index 1f7ce2f..7f44c55 100644
---- a/hw/pl011.c
-+++ b/hw/pl011.c
-@@ -261,6 +261,12 @@ static const VMStateDescription vmstate_pl011 = {
-     }
- };
- 
-+static const QemuChrHandlers pl011_handlers = {
-+    .fd_can_read = pl011_can_receive,
-+    .fd_read = pl011_receive,
-+    .fd_event = pl011_event,
-+};
-+
- static int pl011_init(SysBusDevice *dev, const unsigned char *id)
- {
-     pl011_state *s = FROM_SYSBUS(pl011_state, dev);
-@@ -276,8 +282,7 @@ static int pl011_init(SysBusDevice *dev, const unsigned char *id)
-     s->cr = 0x300;
-     s->flags = 0x90;
-     if (s->chr) {
--        qemu_chr_add_handlers(s->chr, pl011_can_receive, pl011_receive,
--                              pl011_event, s);
-+        qemu_chr_add_handlers(s->chr, &pl011_handlers, s);
-     }
-     vmstate_register(&dev->qdev, -1, &vmstate_pl011, s);
-     return 0;
-diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
-index e616979..f9ca062 100644
---- a/hw/pxa2xx.c
-+++ b/hw/pxa2xx.c
-@@ -1962,6 +1962,12 @@ static int pxa2xx_fir_load(QEMUFile *f, void *opaque, int version_id)
-     return 0;
- }
- 
-+static const QemuChrHandlers pxa2xx_handlers = {
-+    .fd_can_read = pxa2xx_fir_is_empty,
-+    .fd_read = pxa2xx_fir_rx,
-+    .fd_event = pxa2xx_fir_event,
-+};
-+
- static PXA2xxFIrState *pxa2xx_fir_init(MemoryRegion *sysmem,
-                 hwaddr base,
-                 qemu_irq irq, qemu_irq rx_dma, qemu_irq tx_dma,
-@@ -1980,10 +1986,9 @@ static PXA2xxFIrState *pxa2xx_fir_init(MemoryRegion *sysmem,
-     memory_region_init_io(&s->iomem, &pxa2xx_fir_ops, s, "pxa2xx-fir", 0x1000);
-     memory_region_add_subregion(sysmem, base, &s->iomem);
- 
--    if (chr)
--        qemu_chr_add_handlers(chr, pxa2xx_fir_is_empty,
--                        pxa2xx_fir_rx, pxa2xx_fir_event, s);
--
-+    if (chr) {
-+        qemu_chr_add_handlers(chr, &pxa2xx_handlers, s);
-+    }
-     register_savevm(NULL, "pxa2xx_fir", 0, 0, pxa2xx_fir_save,
-                     pxa2xx_fir_load, s);
- 
-diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
-index 81d901c..9e2b893 100644
---- a/hw/qdev-properties.c
-+++ b/hw/qdev-properties.c
-@@ -550,7 +550,7 @@ static void release_chr(Object *obj, const char *name, void *opaque)
-     CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
- 
-     if (*ptr) {
--        qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL);
-+        qemu_chr_add_handlers(*ptr, NULL, NULL);
-     }
- }
- 
-diff --git a/hw/s390x/sclpconsole.c b/hw/s390x/sclpconsole.c
-index 0ec5623..b3d1d6b 100644
---- a/hw/s390x/sclpconsole.c
-+++ b/hw/s390x/sclpconsole.c
-@@ -240,6 +240,12 @@ static void trigger_ascii_console_data(void *env, int n, int level)
-     sclp_service_interrupt(0);
- }
- 
-+static const QemuChrHandlers sclp_chr_handlers = {
-+    .fd_can_read = chr_can_read,
-+    .fd_read = chr_read,
-+    .fd_event = chr_event,
-+};
-+
- /* qemu object creation and initialization functions */
- 
- /* tell character layer our call-back functions */
-@@ -256,8 +262,7 @@ static int console_init(SCLPEvent *event)
-     console_available = true;
-     event->event_type = SCLP_EVENT_ASCII_CONSOLE_DATA;
-     if (scon->chr) {
--        qemu_chr_add_handlers(scon->chr, chr_can_read,
--                              chr_read, chr_event, scon);
-+        qemu_chr_add_handlers(scon->chr, &sclp_chr_handlers, scon);
-     }
-     scon->irq_read_vt220 = *qemu_allocate_irqs(trigger_ascii_console_data,
-                                                NULL, 1);
-diff --git a/hw/serial.c b/hw/serial.c
-index 60283ea..9134d01 100644
---- a/hw/serial.c
-+++ b/hw/serial.c
-@@ -676,6 +676,12 @@ static void serial_reset(void *opaque)
-     qemu_irq_lower(s->irq);
- }
- 
-+static const QemuChrHandlers serial_handlers = {
-+    .fd_can_read = serial_can_receive1,
-+    .fd_read = serial_receive1,
-+    .fd_event = serial_event,
-+};
-+
- void serial_init_core(SerialState *s)
- {
-     if (!s->chr) {
-@@ -690,13 +696,12 @@ void serial_init_core(SerialState *s)
- 
-     qemu_register_reset(serial_reset, s);
- 
--    qemu_chr_add_handlers(s->chr, serial_can_receive1, serial_receive1,
--                          serial_event, s);
-+    qemu_chr_add_handlers(s->chr, &serial_handlers, s);
- }
- 
- void serial_exit_core(SerialState *s)
- {
--    qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, NULL);
-+    qemu_chr_add_handlers(s->chr, NULL, NULL);
-     qemu_unregister_reset(serial_reset, s);
- }
- 
-diff --git a/hw/sh_serial.c b/hw/sh_serial.c
-index 9da5d08..260185d 100644
---- a/hw/sh_serial.c
-+++ b/hw/sh_serial.c
-@@ -352,6 +352,12 @@ static const MemoryRegionOps sh_serial_ops = {
-     .endianness = DEVICE_NATIVE_ENDIAN,
- };
- 
-+static const QemuChrHandlers sh_serial_handlers = {
-+    .fd_can_read = sh_serial_can_receive1,
-+    .fd_read = sh_serial_receive1,
-+    .fd_event = sh_serial_event,
-+};
-+
- void sh_serial_init(MemoryRegion *sysmem,
-                     hwaddr base, int feat,
-                     uint32_t freq, CharDriverState *chr,
-@@ -396,9 +402,9 @@ void sh_serial_init(MemoryRegion *sysmem,
- 
-     s->chr = chr;
- 
--    if (chr)
--        qemu_chr_add_handlers(chr, sh_serial_can_receive1, sh_serial_receive1,
--			      sh_serial_event, s);
-+    if (chr) {
-+        qemu_chr_add_handlers(chr, &sh_serial_handlers, s);
-+    }
- 
-     s->eri = eri_source;
-     s->rxi = rxi_source;
-diff --git a/hw/spapr_vty.c b/hw/spapr_vty.c
-index 14f862f..9fbe7dd 100644
---- a/hw/spapr_vty.c
-+++ b/hw/spapr_vty.c
-@@ -54,6 +54,11 @@ void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len)
-     qemu_chr_fe_write(dev->chardev, buf, len);
- }
- 
-+static const QemuChrHandlers vty_handlers = {
-+    .fd_can_read = vty_can_receive,
-+    .fd_read = vty_receive,
-+};
-+
- static int spapr_vty_init(VIOsPAPRDevice *sdev)
- {
-     VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)sdev;
-@@ -63,8 +68,7 @@ static int spapr_vty_init(VIOsPAPRDevice *sdev)
-         exit(1);
-     }
- 
--    qemu_chr_add_handlers(dev->chardev, vty_can_receive,
--                          vty_receive, NULL, dev);
-+    qemu_chr_add_handlers(dev->chardev, &vty_handlers, dev);
- 
-     return 0;
- }
-diff --git a/hw/strongarm.c b/hw/strongarm.c
-index 4385515..3567218 100644
---- a/hw/strongarm.c
-+++ b/hw/strongarm.c
-@@ -1199,6 +1199,12 @@ static const MemoryRegionOps strongarm_uart_ops = {
-     .endianness = DEVICE_NATIVE_ENDIAN,
- };
- 
-+static const QemuChrHandlers strongarm_uart_handlers = {
-+    .fd_can_read = strongarm_uart_can_receive,
-+    .fd_read = strongarm_uart_receive,
-+    .fd_event = strongarm_uart_event,
-+};
-+
- static int strongarm_uart_init(SysBusDevice *dev)
- {
-     StrongARMUARTState *s = FROM_SYSBUS(StrongARMUARTState, dev);
-@@ -1211,11 +1217,7 @@ static int strongarm_uart_init(SysBusDevice *dev)
-     s->tx_timer = qemu_new_timer_ns(vm_clock, strongarm_uart_tx, s);
- 
-     if (s->chr) {
--        qemu_chr_add_handlers(s->chr,
--                        strongarm_uart_can_receive,
--                        strongarm_uart_receive,
--                        strongarm_uart_event,
--                        s);
-+        qemu_chr_add_handlers(s->chr, &strongarm_uart_handlers, s);
-     }
- 
-     return 0;
-diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c
-index 99b19df..7307ad2 100644
---- a/hw/usb/dev-serial.c
-+++ b/hw/usb/dev-serial.c
-@@ -414,7 +414,7 @@ static void usb_serial_handle_destroy(USBDevice *dev)
- {
-     USBSerialState *s = (USBSerialState *)dev;
- 
--    qemu_chr_add_handlers(s->cs, NULL, NULL, NULL, NULL);
-+    qemu_chr_add_handlers(s->cs, NULL, NULL);
- }
- 
- static int usb_serial_can_read(void *opaque)
-@@ -478,6 +478,12 @@ static void usb_serial_event(void *opaque, int event)
-     }
- }
- 
-+static const QemuChrHandlers usb_serial_handlers = {
-+    .fd_can_read = usb_serial_can_read,
-+    .fd_read = usb_serial_read,
-+    .fd_event = usb_serial_event,
-+};
-+
- static int usb_serial_initfn(USBDevice *dev)
- {
-     USBSerialState *s = DO_UPCAST(USBSerialState, dev, dev);
-@@ -491,8 +497,7 @@ static int usb_serial_initfn(USBDevice *dev)
-         return -1;
-     }
- 
--    qemu_chr_add_handlers(s->cs, usb_serial_can_read, usb_serial_read,
--                          usb_serial_event, s);
-+    qemu_chr_add_handlers(s->cs, &usb_serial_handlers, s);
-     usb_serial_handle_reset(dev);
- 
-     if (s->cs->opened && !dev->attached) {
-diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
-index 490c90f..c921d2d 100644
---- a/hw/usb/redirect.c
-+++ b/hw/usb/redirect.c
-@@ -1037,6 +1037,12 @@ static void usbredir_chardev_event(void *opaque, int event)
-     }
- }
- 
-+static const QemuChrHandlers usbredir_chr_handlers = {
-+    .fd_can_read = usbredir_chardev_can_read,
-+    .fd_read = usbredir_chardev_read,
-+    .fd_event = usbredir_chardev_event,
-+};
-+
- /*
-  * init + destroy
-  */
-@@ -1088,8 +1094,7 @@ static int usbredir_initfn(USBDevice *udev)
- 
-     /* Let the backend know we are ready */
-     qemu_chr_fe_open(dev->cs);
--    qemu_chr_add_handlers(dev->cs, usbredir_chardev_can_read,
--                          usbredir_chardev_read, usbredir_chardev_event, dev);
-+    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);
-diff --git a/hw/virtio-console.c b/hw/virtio-console.c
-index cffee3d..066590c 100644
---- a/hw/virtio-console.c
-+++ b/hw/virtio-console.c
-@@ -106,6 +106,12 @@ static void chr_event(void *opaque, int event)
-     }
- }
- 
-+static const QemuChrHandlers chr_handlers = {
-+    .fd_can_read = chr_can_read,
-+    .fd_read = chr_read,
-+    .fd_event = chr_event,
-+};
-+
- static int virtconsole_initfn(VirtIOSerialPort *port)
- {
-     VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
-@@ -117,8 +123,7 @@ static int virtconsole_initfn(VirtIOSerialPort *port)
-     }
- 
-     if (vcon->chr) {
--        qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event,
--                              vcon);
-+        qemu_chr_add_handlers(vcon->chr, &chr_handlers, vcon);
-     }
- 
-     return 0;
-diff --git a/hw/xen_console.c b/hw/xen_console.c
-index 9426d73..e9fcadc 100644
---- a/hw/xen_console.c
-+++ b/hw/xen_console.c
-@@ -211,6 +211,11 @@ out:
-     return ret;
- }
- 
-+static const QemuChrHandlers xencons_handlers = {
-+    .fd_can_read = xencons_can_receive,
-+    .fd_read = xencons_receive,
-+};
-+
- static int con_initialise(struct XenDevice *xendev)
- {
-     struct XenConsole *con = container_of(xendev, struct XenConsole, xendev);
-@@ -231,9 +236,9 @@ static int con_initialise(struct XenDevice *xendev)
- 	return -1;
- 
-     xen_be_bind_evtchn(&con->xendev);
--    if (con->chr)
--        qemu_chr_add_handlers(con->chr, xencons_can_receive, xencons_receive,
--                              NULL, con);
-+    if (con->chr) {
-+        qemu_chr_add_handlers(con->chr, &xencons_handlers, con);
-+    }
- 
-     xen_be_printf(xendev, 1, "ring mfn %d, remote port %d, local port %d, limit %zd\n",
- 		  con->ring_ref,
-@@ -250,8 +255,9 @@ static void con_disconnect(struct XenDevice *xendev)
-     if (!xendev->dev) {
-         return;
-     }
--    if (con->chr)
--        qemu_chr_add_handlers(con->chr, NULL, NULL, NULL, NULL);
-+    if (con->chr) {
-+        qemu_chr_add_handlers(con->chr, NULL, NULL);
-+    }
-     xen_be_unbind_evtchn(&con->xendev);
- 
-     if (con->sring) {
-diff --git a/hw/xilinx_uartlite.c b/hw/xilinx_uartlite.c
-index d20fc41..6605fb1 100644
---- a/hw/xilinx_uartlite.c
-+++ b/hw/xilinx_uartlite.c
-@@ -195,6 +195,12 @@ static void uart_event(void *opaque, int event)
- 
- }
- 
-+static const QemuChrHandlers uart_handlers = {
-+    .fd_can_read = uart_can_rx,
-+    .fd_read = uart_rx,
-+    .fd_event = uart_event,
-+};
-+
- static int xilinx_uartlite_init(SysBusDevice *dev)
- {
-     struct xlx_uartlite *s = FROM_SYSBUS(typeof (*s), dev);
-@@ -207,8 +213,9 @@ static int xilinx_uartlite_init(SysBusDevice *dev)
-     sysbus_init_mmio(dev, &s->mmio);
- 
-     s->chr = qemu_char_get_next_serial();
--    if (s->chr)
--        qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
-+    if (s->chr) {
-+        qemu_chr_add_handlers(s->chr, &uart_handlers, s);
-+    }
-     return 0;
- }
- 
-diff --git a/monitor.c b/monitor.c
-index c0e32d6..ce0c90a 100644
---- a/monitor.c
-+++ b/monitor.c
-@@ -4685,6 +4685,18 @@ static void sortcmdlist(void)
-  * End:
-  */
- 
-+static const QemuChrHandlers monitor_handlers = {
-+    .fd_can_read = monitor_can_read,
-+    .fd_read = monitor_read,
-+    .fd_event = monitor_event,
-+};
-+
-+static const QemuChrHandlers monitor_control_handlers = {
-+    .fd_can_read = monitor_can_read,
-+    .fd_read = monitor_control_read,
-+    .fd_event = monitor_control_event,
-+};
-+
- void monitor_init(CharDriverState *chr, int flags)
- {
-     static int is_first_init = 1;
-@@ -4707,14 +4719,12 @@ void monitor_init(CharDriverState *chr, int flags)
-     if (monitor_ctrl_mode(mon)) {
-         mon->mc = g_malloc0(sizeof(MonitorControl));
-         /* Control mode requires special handlers */
--        qemu_chr_add_handlers(chr, monitor_can_read, monitor_control_read,
--                              monitor_control_event, mon);
-+        qemu_chr_add_handlers(chr, &monitor_control_handlers, mon);
-         qemu_chr_fe_set_echo(chr, true);
- 
-         json_message_parser_init(&mon->mc->parser, handle_qmp_command);
-     } else {
--        qemu_chr_add_handlers(chr, monitor_can_read, monitor_read,
--                              monitor_event, mon);
-+        qemu_chr_add_handlers(chr, &monitor_handlers, mon);
-     }
- 
-     QLIST_INSERT_HEAD(&mon_list, mon, entry);
-diff --git a/net/slirp.c b/net/slirp.c
-index afb52c3..07ae92f 100644
---- a/net/slirp.c
-+++ b/net/slirp.c
-@@ -594,6 +594,11 @@ static void guestfwd_read(void *opaque, const uint8_t *buf, int size)
-     slirp_socket_recv(fwd->slirp, fwd->server, fwd->port, buf, size);
- }
- 
-+static const QemuChrHandlers guestfwd_handlers = {
-+    .fd_can_read = guestfwd_can_read,
-+    .fd_read = guestfwd_read,
-+};
-+
- static int slirp_guestfwd(SlirpState *s, const char *config_str,
-                           int legacy_format)
- {
-@@ -659,8 +664,7 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str,
-         fwd->port = port;
-         fwd->slirp = s->slirp;
- 
--        qemu_chr_add_handlers(fwd->hd, guestfwd_can_read, guestfwd_read,
--                              NULL, fwd);
-+        qemu_chr_add_handlers(fwd->hd, &guestfwd_handlers, fwd);
-     }
-     return 0;
- 
-diff --git a/qemu-char.c b/qemu-char.c
-index 77776dc..97247fb 100644
---- a/qemu-char.c
-+++ b/qemu-char.c
-@@ -193,19 +193,26 @@ void qemu_chr_fe_printf(CharDriverState *s, const char *fmt, ...)
-     va_end(ap);
- }
- 
-+static const QemuChrHandlers null_handlers = {
-+    /* All handlers are initialised to NULL */
-+};
-+
- void qemu_chr_add_handlers(CharDriverState *s,
--                           IOCanReadHandler *fd_can_read,
--                           IOReadHandler *fd_read,
--                           IOEventHandler *fd_event,
--                           void *opaque)
-+                           const QemuChrHandlers *handlers, void *opaque)
- {
--    if (!opaque && !fd_can_read && !fd_read && !fd_event) {
-+    if (!s) {
-+        return;
-+    }
-+    if (!opaque && !handlers) {
-         /* chr driver being released. */
-         ++s->avail_connections;
-     }
--    s->chr_can_read = fd_can_read;
--    s->chr_read = fd_read;
--    s->chr_event = fd_event;
-+    if (!handlers) {
-+        handlers = &null_handlers;
-+    }
-+    s->chr_can_read = handlers->fd_can_read;
-+    s->chr_read = handlers->fd_read;
-+    s->chr_event = handlers->fd_event;
-     s->handler_opaque = opaque;
-     if (s->chr_update_read_handler)
-         s->chr_update_read_handler(s);
-@@ -443,6 +450,12 @@ static void mux_chr_event(void *opaque, int event)
-         mux_chr_send_event(d, i, event);
- }
- 
-+static const QemuChrHandlers mux_chr_handlers = {
-+    .fd_can_read = mux_chr_can_read,
-+    .fd_read = mux_chr_read,
-+    .fd_event = mux_chr_event,
-+};
-+
- static void mux_chr_update_read_handler(CharDriverState *chr)
- {
-     MuxDriver *d = chr->opaque;
-@@ -457,8 +470,7 @@ static void mux_chr_update_read_handler(CharDriverState *chr)
-     d->chr_event[d->mux_cnt] = chr->chr_event;
-     /* Fix up the real driver with mux routines */
-     if (d->mux_cnt == 0) {
--        qemu_chr_add_handlers(d->drv, mux_chr_can_read, mux_chr_read,
--                              mux_chr_event, chr);
-+        qemu_chr_add_handlers(d->drv, &mux_chr_handlers, chr);
-     }
-     if (d->focus != -1) {
-         mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_OUT);
-diff --git a/qemu-char.h b/qemu-char.h
-index a121e04..ff206cb 100644
---- a/qemu-char.h
-+++ b/qemu-char.h
-@@ -223,10 +223,15 @@ void qemu_chr_be_write(CharDriverState *s, uint8_t *buf, int len);
-  */
- void qemu_chr_be_event(CharDriverState *s, int event);
- 
--void qemu_chr_add_handlers(CharDriverState *s,
--                           IOCanReadHandler *fd_can_read,
--                           IOReadHandler *fd_read,
--                           IOEventHandler *fd_event,
-+
-+typedef struct QemuChrHandlers {
-+    IOCanReadHandler *fd_can_read;
-+    IOReadHandler *fd_read;
-+    IOHandler *fd_write_unblocked;
-+    IOEventHandler *fd_event;
-+} QemuChrHandlers;
-+
-+void qemu_chr_add_handlers(CharDriverState *s, const QemuChrHandlers *handlers,
-                            void *opaque);
- 
- void qemu_chr_generic_open(CharDriverState *s);
-diff --git a/qtest.c b/qtest.c
-index fbfab4e..4ab5b69 100644
---- a/qtest.c
-+++ b/qtest.c
-@@ -416,6 +416,13 @@ static void qtest_event(void *opaque, int event)
-     }
- }
- 
-+static const QemuChrHandlers test_handlers = {
-+    .fd_can_read = qtest_can_read,
-+    .fd_read = qtest_read,
-+    .fd_event = qtest_event,
-+};
-+
-+
- int qtest_init(void)
- {
-     CharDriverState *chr;
-@@ -425,7 +432,7 @@ int qtest_init(void)
-     configure_icount("0");
-     chr = qemu_chr_new("qtest", qtest_chrdev, NULL);
- 
--    qemu_chr_add_handlers(chr, qtest_can_read, qtest_read, qtest_event, chr);
-+    qemu_chr_add_handlers(chr, &test_handlers, chr);
-     qemu_chr_fe_set_echo(chr, true);
- 
-     inbuf = g_string_new("");
--- 
-1.8.0
-
diff --git a/0101-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch b/0101-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch
new file mode 100644
index 0000000..df59f85
--- /dev/null
+++ b/0101-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch
@@ -0,0 +1,57 @@
+From 973df60b495a87a9cd3b6909d08c148f5fd93691 Mon Sep 17 00:00:00 2001
+From: Amit Shah <amit.shah@redhat.com>
+Date: Mon, 21 Mar 2011 21:57:47 +0100
+Subject: [PATCH] char: Split out tcp socket close code in a separate function
+
+Signed-off-by: Amit Shah <amit.shah@redhat.com>
+Signed-off-by: Cole Robinson <crobinso@redhat.com>
+---
+ qemu-char.c | 25 ++++++++++++++++---------
+ 1 file changed, 16 insertions(+), 9 deletions(-)
+
+diff --git a/qemu-char.c b/qemu-char.c
+index 242b799..77776dc 100644
+--- a/qemu-char.c
++++ b/qemu-char.c
+@@ -2146,6 +2146,21 @@ typedef struct {
+ 
+ static void tcp_chr_accept(void *opaque);
+ 
++static void tcp_closed(void *opaque)
++{
++    CharDriverState *chr = opaque;
++    TCPCharDriver *s = chr->opaque;
++
++    s->connected = 0;
++    if (s->listen_fd >= 0) {
++        qemu_set_fd_handler2(s->listen_fd, NULL, tcp_chr_accept, NULL, chr);
++    }
++    qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
++    closesocket(s->fd);
++    s->fd = -1;
++    qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
++}
++
+ static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+ {
+     TCPCharDriver *s = chr->opaque;
+@@ -2304,15 +2319,7 @@ static void tcp_chr_read(void *opaque)
+         len = s->max_size;
+     size = tcp_chr_recv(chr, (void *)buf, len);
+     if (size == 0) {
+-        /* connection closed */
+-        s->connected = 0;
+-        if (s->listen_fd >= 0) {
+-            qemu_set_fd_handler2(s->listen_fd, NULL, tcp_chr_accept, NULL, chr);
+-        }
+-        qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
+-        closesocket(s->fd);
+-        s->fd = -1;
+-        qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
++        tcp_closed(chr);
+     } else if (size > 0) {
+         if (s->do_telnetopt)
+             tcp_chr_process_IAC_bytes(chr, s, buf, &size);
+-- 
+1.8.1
+
diff --git a/0102-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch b/0102-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch
new file mode 100644
index 0000000..0684934
--- /dev/null
+++ b/0102-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch
@@ -0,0 +1,1043 @@
+From 687d91769e40878f3b8ebb9bdd8ee256a40c97cd Mon Sep 17 00:00:00 2001
+From: Amit Shah <amit.shah@redhat.com>
+Date: Mon, 21 Mar 2011 20:31:45 +0100
+Subject: [PATCH] char: Add a QemuChrHandlers struct to initialise chardev
+ handlers
+
+Instead of passing each handler in the qemu_add_handlers() function,
+create a struct of handlers that can be passed to the function instead.
+
+Signed-off-by: Amit Shah <amit.shah@redhat.com>
+Signed-off-by: Cole Robinson <crobinso@redhat.com>
+---
+ backends/rng-egd.c      | 12 +++++++++---
+ gdbstub.c               |  9 +++++++--
+ hw/cadence_uart.c       |  9 +++++++--
+ hw/ccid-card-passthru.c | 11 +++++++----
+ hw/debugcon.c           |  2 +-
+ hw/escc.c               |  9 +++++++--
+ hw/etraxfs_ser.c        | 13 +++++++++----
+ hw/exynos4210_uart.c    |  9 +++++++--
+ hw/grlib_apbuart.c      | 12 +++++++-----
+ hw/imx_serial.c         |  9 +++++++--
+ hw/ivshmem.c            | 28 ++++++++++++++++++++++------
+ hw/lm32_juart.c         |  8 +++++++-
+ hw/lm32_uart.c          |  8 +++++++-
+ hw/mcf_uart.c           |  9 +++++++--
+ hw/milkymist-uart.c     |  8 +++++++-
+ hw/pl011.c              |  9 +++++++--
+ hw/pxa2xx.c             | 13 +++++++++----
+ hw/qdev-properties.c    |  2 +-
+ hw/s390x/sclpconsole.c  |  9 +++++++--
+ hw/serial.c             | 11 ++++++++---
+ hw/sh_serial.c          | 12 +++++++++---
+ hw/spapr_vty.c          |  8 ++++++--
+ hw/strongarm.c          | 12 +++++++-----
+ hw/usb/dev-serial.c     | 11 ++++++++---
+ hw/usb/redirect.c       |  9 +++++++--
+ hw/virtio-console.c     |  9 +++++++--
+ hw/xen_console.c        | 16 +++++++++++-----
+ hw/xilinx_uartlite.c    | 11 +++++++++--
+ monitor.c               | 18 ++++++++++++++----
+ net/slirp.c             |  8 ++++++--
+ qemu-char.c             | 32 ++++++++++++++++++++++----------
+ qemu-char.h             | 13 +++++++++----
+ qtest.c                 |  9 ++++++++-
+ 33 files changed, 273 insertions(+), 95 deletions(-)
+
+diff --git a/backends/rng-egd.c b/backends/rng-egd.c
+index ad84737..30194be 100644
+--- a/backends/rng-egd.c
++++ b/backends/rng-egd.c
+@@ -133,6 +133,13 @@ static void rng_egd_cancel_requests(RngBackend *b)
+     rng_egd_free_requests(s);
+ }
+ 
++static const QemuChrHandlers rng_egd_handlers = {
++    .fd_can_read = rng_egd_chr_can_read,
++    .fd_read = rng_egd_chr_read,
++    .fd_event = NULL,
++};
++
++
+ static void rng_egd_opened(RngBackend *b, Error **errp)
+ {
+     RngEgd *s = RNG_EGD(b);
+@@ -150,8 +157,7 @@ static void rng_egd_opened(RngBackend *b, Error **errp)
+     }
+ 
+     /* FIXME we should resubmit pending requests when the CDS reconnects. */
+-    qemu_chr_add_handlers(s->chr, rng_egd_chr_can_read, rng_egd_chr_read,
+-                          NULL, s);
++    qemu_chr_add_handlers(s->chr, &rng_egd_handlers, s);
+ }
+ 
+ static void rng_egd_set_chardev(Object *obj, const char *value, Error **errp)
+@@ -190,7 +196,7 @@ static void rng_egd_finalize(Object *obj)
+     RngEgd *s = RNG_EGD(obj);
+ 
+     if (s->chr) {
+-        qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, NULL);
++        qemu_chr_add_handlers(s->chr, NULL, NULL);
+     }
+ 
+     g_free(s->chr_name);
+diff --git a/gdbstub.c b/gdbstub.c
+index d02ec75..5d93d20 100644
+--- a/gdbstub.c
++++ b/gdbstub.c
+@@ -2973,6 +2973,12 @@ static void gdb_sigterm_handler(int signal)
+ }
+ #endif
+ 
++static const QemuChrHandlers gdb_handlers = {
++    .fd_can_read = gdb_chr_can_receive,
++    .fd_read = gdb_chr_receive,
++    .fd_event = gdb_chr_event,
++};
++
+ int gdbserver_start(const char *device)
+ {
+     GDBState *s;
+@@ -3002,8 +3008,7 @@ int gdbserver_start(const char *device)
+         if (!chr)
+             return -1;
+ 
+-        qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive,
+-                              gdb_chr_event, NULL);
++        qemu_chr_add_handlers(chr, &gdb_handlers, NULL);
+     }
+ 
+     s = gdbserver_state;
+diff --git a/hw/cadence_uart.c b/hw/cadence_uart.c
+index 686e617..36ad620 100644
+--- a/hw/cadence_uart.c
++++ b/hw/cadence_uart.c
+@@ -438,6 +438,12 @@ static void cadence_uart_reset(UartState *s)
+     s->rx_wpos = 0;
+ }
+ 
++static const QemuChrHandlers cadence_uart_handlers = {
++    .fd_can_read = uart_can_receive,
++    .fd_read = uart_receive,
++    .fd_event = uart_event,
++};
++
+ static int cadence_uart_init(SysBusDevice *dev)
+ {
+     UartState *s = FROM_SYSBUS(UartState, dev);
+@@ -459,8 +465,7 @@ static int cadence_uart_init(SysBusDevice *dev)
+     cadence_uart_reset(s);
+ 
+     if (s->chr) {
+-        qemu_chr_add_handlers(s->chr, uart_can_receive, uart_receive,
+-                              uart_event, s);
++        qemu_chr_add_handlers(s->chr, &cadence_uart_handlers, s);
+     }
+ 
+     return 0;
+diff --git a/hw/ccid-card-passthru.c b/hw/ccid-card-passthru.c
+index bd6c777..fb32107 100644
+--- a/hw/ccid-card-passthru.c
++++ b/hw/ccid-card-passthru.c
+@@ -274,6 +274,12 @@ static const uint8_t *passthru_get_atr(CCIDCardState *base, uint32_t *len)
+     return card->atr;
+ }
+ 
++static const QemuChrHandlers passthru_handlers = {
++    .fd_can_read = ccid_card_vscard_can_read,
++    .fd_read = ccid_card_vscard_read,
++    .fd_event = ccid_card_vscard_event,
++};
++
+ static int passthru_initfn(CCIDCardState *base)
+ {
+     PassthruState *card = DO_UPCAST(PassthruState, base, base);
+@@ -282,10 +288,7 @@ static int passthru_initfn(CCIDCardState *base)
+     card->vscard_in_hdr = 0;
+     if (card->cs) {
+         DPRINTF(card, D_INFO, "initing chardev\n");
+-        qemu_chr_add_handlers(card->cs,
+-            ccid_card_vscard_can_read,
+-            ccid_card_vscard_read,
+-            ccid_card_vscard_event, card);
++        qemu_chr_add_handlers(card->cs, &passthru_handlers, card);
+         ccid_card_vscard_send_init(card);
+     } else {
+         error_report("missing chardev");
+diff --git a/hw/debugcon.c b/hw/debugcon.c
+index 14ab326..7887fd2 100644
+--- a/hw/debugcon.c
++++ b/hw/debugcon.c
+@@ -73,7 +73,7 @@ static void debugcon_init_core(DebugconState *s)
+         exit(1);
+     }
+ 
+-    qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, s);
++    qemu_chr_add_handlers(s->chr, NULL, s);
+ }
+ 
+ static int debugcon_isa_initfn(ISADevice *dev)
+diff --git a/hw/escc.c b/hw/escc.c
+index a356613..3f26f45 100644
+--- a/hw/escc.c
++++ b/hw/escc.c
+@@ -867,6 +867,12 @@ void slavio_serial_ms_kbd_init(hwaddr base, qemu_irq irq,
+     sysbus_mmio_map(s, 0, base);
+ }
+ 
++static const QemuChrHandlers serial_handlers = {
++    .fd_can_read = serial_can_receive,
++    .fd_read = serial_receive1,
++    .fd_event = serial_event,
++};
++
+ static int escc_init1(SysBusDevice *dev)
+ {
+     SerialState *s = FROM_SYSBUS(SerialState, dev);
+@@ -879,8 +885,7 @@ static int escc_init1(SysBusDevice *dev)
+         s->chn[i].chn = 1 - i;
+         s->chn[i].clock = s->frequency / 2;
+         if (s->chn[i].chr) {
+-            qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive,
+-                                  serial_receive1, serial_event, &s->chn[i]);
++            qemu_chr_add_handlers(s->chn[i].chr, &serial_handlers, &s->chn[i]);
+         }
+     }
+     s->chn[0].otherchn = &s->chn[1];
+diff --git a/hw/etraxfs_ser.c b/hw/etraxfs_ser.c
+index ee0d72b..64552cc 100644
+--- a/hw/etraxfs_ser.c
++++ b/hw/etraxfs_ser.c
+@@ -208,6 +208,12 @@ static void etraxfs_ser_reset(DeviceState *d)
+ 
+ }
+ 
++static const QemuChrHandlers serial_handlers = {
++    .fd_can_read = serial_can_receive,
++    .fd_read = serial_receive,
++    .fd_event = serial_event,
++};
++
+ static int etraxfs_ser_init(SysBusDevice *dev)
+ {
+     struct etrax_serial *s = FROM_SYSBUS(typeof (*s), dev);
+@@ -217,10 +223,9 @@ static int etraxfs_ser_init(SysBusDevice *dev)
+     sysbus_init_mmio(dev, &s->mmio);
+ 
+     s->chr = qemu_char_get_next_serial();
+-    if (s->chr)
+-        qemu_chr_add_handlers(s->chr,
+-                      serial_can_receive, serial_receive,
+-                      serial_event, s);
++    if (s->chr) {
++        qemu_chr_add_handlers(s->chr, &serial_handlers, s);
++    }
+     return 0;
+ }
+ 
+diff --git a/hw/exynos4210_uart.c b/hw/exynos4210_uart.c
+index 20dcd9f..f2949aa 100644
+--- a/hw/exynos4210_uart.c
++++ b/hw/exynos4210_uart.c
+@@ -625,6 +625,12 @@ DeviceState *exynos4210_uart_create(hwaddr addr,
+     return dev;
+ }
+ 
++static const QemuChrHandlers exynos4210_handlers = {
++    .fd_can_read = exynos4210_uart_can_receive,
++    .fd_read     = exynos4210_uart_receive,
++    .fd_event    = exynos4210_uart_event,
++};
++
+ static int exynos4210_uart_init(SysBusDevice *dev)
+ {
+     Exynos4210UartState *s = FROM_SYSBUS(Exynos4210UartState, dev);
+@@ -636,8 +642,7 @@ static int exynos4210_uart_init(SysBusDevice *dev)
+ 
+     sysbus_init_irq(dev, &s->irq);
+ 
+-    qemu_chr_add_handlers(s->chr, exynos4210_uart_can_receive,
+-                          exynos4210_uart_receive, exynos4210_uart_event, s);
++    qemu_chr_add_handlers(s->chr, &exynos4210_handlers, s);
+ 
+     return 0;
+ }
+diff --git a/hw/grlib_apbuart.c b/hw/grlib_apbuart.c
+index 0865764..fb0e703 100644
+--- a/hw/grlib_apbuart.c
++++ b/hw/grlib_apbuart.c
+@@ -222,15 +222,17 @@ static const MemoryRegionOps grlib_apbuart_ops = {
+     .endianness = DEVICE_NATIVE_ENDIAN,
+ };
+ 
++static const QemuChrHandlers grlib_handlers = {
++    .fd_can_read = grlib_apbuart_can_receive,
++    .fd_read = grlib_apbuart_receive,
++    .fd_event = grlib_apbuart_event,
++};
++
+ static int grlib_apbuart_init(SysBusDevice *dev)
+ {
+     UART *uart = FROM_SYSBUS(typeof(*uart), dev);
+ 
+-    qemu_chr_add_handlers(uart->chr,
+-                          grlib_apbuart_can_receive,
+-                          grlib_apbuart_receive,
+-                          grlib_apbuart_event,
+-                          uart);
++    qemu_chr_add_handlers(uart->chr, &grlib_handlers, uart);
+ 
+     sysbus_init_irq(dev, &uart->irq);
+ 
+diff --git a/hw/imx_serial.c b/hw/imx_serial.c
+index dcd125f..5347ec8 100644
+--- a/hw/imx_serial.c
++++ b/hw/imx_serial.c
+@@ -381,6 +381,12 @@ static const struct MemoryRegionOps imx_serial_ops = {
+     .endianness = DEVICE_NATIVE_ENDIAN,
+ };
+ 
++static const QemuChrHandlers imx_handlers = {
++    .fd_can_read = imx_can_receive,
++    .fd_read = imx_receive,
++    .fd_event = imx_event,
++};
++
+ static int imx_serial_init(SysBusDevice *dev)
+ {
+     IMXSerialState *s = FROM_SYSBUS(IMXSerialState, dev);
+@@ -391,8 +397,7 @@ static int imx_serial_init(SysBusDevice *dev)
+     sysbus_init_irq(dev, &s->irq);
+ 
+     if (s->chr) {
+-        qemu_chr_add_handlers(s->chr, imx_can_receive, imx_receive,
+-                              imx_event, s);
++        qemu_chr_add_handlers(s->chr, &imx_handlers, s);
+     } else {
+         DPRINTF("No char dev for uart at 0x%lx\n",
+                 (unsigned long)s->iomem.ram_addr);
+diff --git a/hw/ivshmem.c b/hw/ivshmem.c
+index f6dbb21..0e56a97 100644
+--- a/hw/ivshmem.c
++++ b/hw/ivshmem.c
+@@ -274,6 +274,18 @@ static void fake_irqfd(void *opaque, const uint8_t *buf, int size) {
+     msix_notify(pdev, entry->vector);
+ }
+ 
++static const QemuChrHandlers ivshmem_handlers = {
++    .fd_can_read = ivshmem_can_receive,
++    .fd_read = ivshmem_receive,
++    .fd_event = ivshmem_event,
++};
++
++static const QemuChrHandlers ivshmem_msi_handlers = {
++    .fd_can_read = ivshmem_can_receive,
++    .fd_read = fake_irqfd,
++    .fd_event = ivshmem_event,
++};
++
+ static CharDriverState* create_eventfd_chr_device(void * opaque, EventNotifier *n,
+                                                   int vector)
+ {
+@@ -294,11 +306,10 @@ static CharDriverState* create_eventfd_chr_device(void * opaque, EventNotifier *
+         s->eventfd_table[vector].pdev = &s->dev;
+         s->eventfd_table[vector].vector = vector;
+ 
+-        qemu_chr_add_handlers(chr, ivshmem_can_receive, fake_irqfd,
+-                      ivshmem_event, &s->eventfd_table[vector]);
++        qemu_chr_add_handlers(chr, &ivshmem_msi_handlers,
++                              &s->eventfd_table[vector]);
+     } else {
+-        qemu_chr_add_handlers(chr, ivshmem_can_receive, ivshmem_receive,
+-                      ivshmem_event, s);
++        qemu_chr_add_handlers(chr, &ivshmem_handlers, s);
+     }
+ 
+     return chr;
+@@ -632,6 +643,12 @@ static void ivshmem_write_config(PCIDevice *pci_dev, uint32_t address,
+     msix_write_config(pci_dev, address, val, len);
+ }
+ 
++static const QemuChrHandlers ivshmem_server_handlers = {
++    .fd_can_read = ivshmem_can_receive,
++    .fd_read = ivshmem_read,
++    .fd_event = ivshmem_event,
++};
++
+ static int pci_ivshmem_init(PCIDevice *dev)
+ {
+     IVShmemState *s = DO_UPCAST(IVShmemState, dev, dev);
+@@ -722,8 +739,7 @@ static int pci_ivshmem_init(PCIDevice *dev)
+ 
+         s->eventfd_chr = g_malloc0(s->vectors * sizeof(CharDriverState *));
+ 
+-        qemu_chr_add_handlers(s->server_chr, ivshmem_can_receive, ivshmem_read,
+-                     ivshmem_event, s);
++        qemu_chr_add_handlers(s->server_chr, &ivshmem_server_handlers, s);
+     } else {
+         /* just map the file immediately, we're not using a server */
+         int fd;
+diff --git a/hw/lm32_juart.c b/hw/lm32_juart.c
+index f07ed39..d4daeb8 100644
+--- a/hw/lm32_juart.c
++++ b/hw/lm32_juart.c
+@@ -110,13 +110,19 @@ static void juart_reset(DeviceState *d)
+     s->jrx = 0;
+ }
+ 
++static const QemuChrHandlers juart_handlers = {
++    .fd_can_read = juart_can_rx,
++    .fd_read = juart_rx,
++    .fd_event = juart_event,
++};
++
+ static int lm32_juart_init(SysBusDevice *dev)
+ {
+     LM32JuartState *s = FROM_SYSBUS(typeof(*s), dev);
+ 
+     s->chr = qemu_char_get_next_serial();
+     if (s->chr) {
+-        qemu_chr_add_handlers(s->chr, juart_can_rx, juart_rx, juart_event, s);
++        qemu_chr_add_handlers(s->chr, &juart_handlers, s);
+     }
+ 
+     return 0;
+diff --git a/hw/lm32_uart.c b/hw/lm32_uart.c
+index adb9287..e581bea 100644
+--- a/hw/lm32_uart.c
++++ b/hw/lm32_uart.c
+@@ -243,6 +243,12 @@ static void uart_reset(DeviceState *d)
+     s->regs[R_LSR] = LSR_THRE | LSR_TEMT;
+ }
+ 
++static const QemuChrHandlers uart_handlers = {
++    .fd_can_read = uart_can_rx,
++    .fd_read = uart_rx,
++    .fd_event = uart_event,
++};
++
+ static int lm32_uart_init(SysBusDevice *dev)
+ {
+     LM32UartState *s = FROM_SYSBUS(typeof(*s), dev);
+@@ -254,7 +260,7 @@ static int lm32_uart_init(SysBusDevice *dev)
+ 
+     s->chr = qemu_char_get_next_serial();
+     if (s->chr) {
+-        qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
++        qemu_chr_add_handlers(s->chr, &uart_handlers, s);
+     }
+ 
+     return 0;
+diff --git a/hw/mcf_uart.c b/hw/mcf_uart.c
+index d1655f8..8ead254 100644
+--- a/hw/mcf_uart.c
++++ b/hw/mcf_uart.c
+@@ -272,6 +272,12 @@ static void mcf_uart_receive(void *opaque, const uint8_t *buf, int size)
+     mcf_uart_push_byte(s, buf[0]);
+ }
+ 
++static const QemuChrHandlers mcf_uart_handlers = {
++    .fd_can_read = mcf_uart_can_receive,
++    .fd_read = mcf_uart_receive,
++    .fd_event = mcf_uart_event,
++};
++
+ void *mcf_uart_init(qemu_irq irq, CharDriverState *chr)
+ {
+     mcf_uart_state *s;
+@@ -280,8 +286,7 @@ void *mcf_uart_init(qemu_irq irq, CharDriverState *chr)
+     s->chr = chr;
+     s->irq = irq;
+     if (chr) {
+-        qemu_chr_add_handlers(chr, mcf_uart_can_receive, mcf_uart_receive,
+-                              mcf_uart_event, s);
++        qemu_chr_add_handlers(chr, &mcf_uart_handlers, s);
+     }
+     mcf_uart_reset(s);
+     return s;
+diff --git a/hw/milkymist-uart.c b/hw/milkymist-uart.c
+index aefa8c7..0c924f2 100644
+--- a/hw/milkymist-uart.c
++++ b/hw/milkymist-uart.c
+@@ -189,6 +189,12 @@ static void milkymist_uart_reset(DeviceState *d)
+     s->regs[R_STAT] = STAT_THRE;
+ }
+ 
++static const QemuChrHandlers uart_handlers = {
++    .fd_can_read = uart_can_rx,
++    .fd_read = uart_rx,
++    .fd_event = uart_event,
++};
++
+ static int milkymist_uart_init(SysBusDevice *dev)
+ {
+     MilkymistUartState *s = FROM_SYSBUS(typeof(*s), dev);
+@@ -201,7 +207,7 @@ static int milkymist_uart_init(SysBusDevice *dev)
+ 
+     s->chr = qemu_char_get_next_serial();
+     if (s->chr) {
+-        qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
++        qemu_chr_add_handlers(s->chr, &uart_handlers, s);
+     }
+ 
+     return 0;
+diff --git a/hw/pl011.c b/hw/pl011.c
+index 1f7ce2f..7f44c55 100644
+--- a/hw/pl011.c
++++ b/hw/pl011.c
+@@ -261,6 +261,12 @@ static const VMStateDescription vmstate_pl011 = {
+     }
+ };
+ 
++static const QemuChrHandlers pl011_handlers = {
++    .fd_can_read = pl011_can_receive,
++    .fd_read = pl011_receive,
++    .fd_event = pl011_event,
++};
++
+ static int pl011_init(SysBusDevice *dev, const unsigned char *id)
+ {
+     pl011_state *s = FROM_SYSBUS(pl011_state, dev);
+@@ -276,8 +282,7 @@ static int pl011_init(SysBusDevice *dev, const unsigned char *id)
+     s->cr = 0x300;
+     s->flags = 0x90;
+     if (s->chr) {
+-        qemu_chr_add_handlers(s->chr, pl011_can_receive, pl011_receive,
+-                              pl011_event, s);
++        qemu_chr_add_handlers(s->chr, &pl011_handlers, s);
+     }
+     vmstate_register(&dev->qdev, -1, &vmstate_pl011, s);
+     return 0;
+diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
+index e616979..f9ca062 100644
+--- a/hw/pxa2xx.c
++++ b/hw/pxa2xx.c
+@@ -1962,6 +1962,12 @@ static int pxa2xx_fir_load(QEMUFile *f, void *opaque, int version_id)
+     return 0;
+ }
+ 
++static const QemuChrHandlers pxa2xx_handlers = {
++    .fd_can_read = pxa2xx_fir_is_empty,
++    .fd_read = pxa2xx_fir_rx,
++    .fd_event = pxa2xx_fir_event,
++};
++
+ static PXA2xxFIrState *pxa2xx_fir_init(MemoryRegion *sysmem,
+                 hwaddr base,
+                 qemu_irq irq, qemu_irq rx_dma, qemu_irq tx_dma,
+@@ -1980,10 +1986,9 @@ static PXA2xxFIrState *pxa2xx_fir_init(MemoryRegion *sysmem,
+     memory_region_init_io(&s->iomem, &pxa2xx_fir_ops, s, "pxa2xx-fir", 0x1000);
+     memory_region_add_subregion(sysmem, base, &s->iomem);
+ 
+-    if (chr)
+-        qemu_chr_add_handlers(chr, pxa2xx_fir_is_empty,
+-                        pxa2xx_fir_rx, pxa2xx_fir_event, s);
+-
++    if (chr) {
++        qemu_chr_add_handlers(chr, &pxa2xx_handlers, s);
++    }
+     register_savevm(NULL, "pxa2xx_fir", 0, 0, pxa2xx_fir_save,
+                     pxa2xx_fir_load, s);
+ 
+diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
+index 81d901c..9e2b893 100644
+--- a/hw/qdev-properties.c
++++ b/hw/qdev-properties.c
+@@ -550,7 +550,7 @@ static void release_chr(Object *obj, const char *name, void *opaque)
+     CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
+ 
+     if (*ptr) {
+-        qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL);
++        qemu_chr_add_handlers(*ptr, NULL, NULL);
+     }
+ }
+ 
+diff --git a/hw/s390x/sclpconsole.c b/hw/s390x/sclpconsole.c
+index 0ec5623..b3d1d6b 100644
+--- a/hw/s390x/sclpconsole.c
++++ b/hw/s390x/sclpconsole.c
+@@ -240,6 +240,12 @@ static void trigger_ascii_console_data(void *env, int n, int level)
+     sclp_service_interrupt(0);
+ }
+ 
++static const QemuChrHandlers sclp_chr_handlers = {
++    .fd_can_read = chr_can_read,
++    .fd_read = chr_read,
++    .fd_event = chr_event,
++};
++
+ /* qemu object creation and initialization functions */
+ 
+ /* tell character layer our call-back functions */
+@@ -256,8 +262,7 @@ static int console_init(SCLPEvent *event)
+     console_available = true;
+     event->event_type = SCLP_EVENT_ASCII_CONSOLE_DATA;
+     if (scon->chr) {
+-        qemu_chr_add_handlers(scon->chr, chr_can_read,
+-                              chr_read, chr_event, scon);
++        qemu_chr_add_handlers(scon->chr, &sclp_chr_handlers, scon);
+     }
+     scon->irq_read_vt220 = *qemu_allocate_irqs(trigger_ascii_console_data,
+                                                NULL, 1);
+diff --git a/hw/serial.c b/hw/serial.c
+index 60283ea..9134d01 100644
+--- a/hw/serial.c
++++ b/hw/serial.c
+@@ -676,6 +676,12 @@ static void serial_reset(void *opaque)
+     qemu_irq_lower(s->irq);
+ }
+ 
++static const QemuChrHandlers serial_handlers = {
++    .fd_can_read = serial_can_receive1,
++    .fd_read = serial_receive1,
++    .fd_event = serial_event,
++};
++
+ void serial_init_core(SerialState *s)
+ {
+     if (!s->chr) {
+@@ -690,13 +696,12 @@ void serial_init_core(SerialState *s)
+ 
+     qemu_register_reset(serial_reset, s);
+ 
+-    qemu_chr_add_handlers(s->chr, serial_can_receive1, serial_receive1,
+-                          serial_event, s);
++    qemu_chr_add_handlers(s->chr, &serial_handlers, s);
+ }
+ 
+ void serial_exit_core(SerialState *s)
+ {
+-    qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, NULL);
++    qemu_chr_add_handlers(s->chr, NULL, NULL);
+     qemu_unregister_reset(serial_reset, s);
+ }
+ 
+diff --git a/hw/sh_serial.c b/hw/sh_serial.c
+index 9da5d08..260185d 100644
+--- a/hw/sh_serial.c
++++ b/hw/sh_serial.c
+@@ -352,6 +352,12 @@ static const MemoryRegionOps sh_serial_ops = {
+     .endianness = DEVICE_NATIVE_ENDIAN,
+ };
+ 
++static const QemuChrHandlers sh_serial_handlers = {
++    .fd_can_read = sh_serial_can_receive1,
++    .fd_read = sh_serial_receive1,
++    .fd_event = sh_serial_event,
++};
++
+ void sh_serial_init(MemoryRegion *sysmem,
+                     hwaddr base, int feat,
+                     uint32_t freq, CharDriverState *chr,
+@@ -396,9 +402,9 @@ void sh_serial_init(MemoryRegion *sysmem,
+ 
+     s->chr = chr;
+ 
+-    if (chr)
+-        qemu_chr_add_handlers(chr, sh_serial_can_receive1, sh_serial_receive1,
+-			      sh_serial_event, s);
++    if (chr) {
++        qemu_chr_add_handlers(chr, &sh_serial_handlers, s);
++    }
+ 
+     s->eri = eri_source;
+     s->rxi = rxi_source;
+diff --git a/hw/spapr_vty.c b/hw/spapr_vty.c
+index 14f862f..9fbe7dd 100644
+--- a/hw/spapr_vty.c
++++ b/hw/spapr_vty.c
+@@ -54,6 +54,11 @@ void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len)
+     qemu_chr_fe_write(dev->chardev, buf, len);
+ }
+ 
++static const QemuChrHandlers vty_handlers = {
++    .fd_can_read = vty_can_receive,
++    .fd_read = vty_receive,
++};
++
+ static int spapr_vty_init(VIOsPAPRDevice *sdev)
+ {
+     VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)sdev;
+@@ -63,8 +68,7 @@ static int spapr_vty_init(VIOsPAPRDevice *sdev)
+         exit(1);
+     }
+ 
+-    qemu_chr_add_handlers(dev->chardev, vty_can_receive,
+-                          vty_receive, NULL, dev);
++    qemu_chr_add_handlers(dev->chardev, &vty_handlers, dev);
+ 
+     return 0;
+ }
+diff --git a/hw/strongarm.c b/hw/strongarm.c
+index 4385515..3567218 100644
+--- a/hw/strongarm.c
++++ b/hw/strongarm.c
+@@ -1199,6 +1199,12 @@ static const MemoryRegionOps strongarm_uart_ops = {
+     .endianness = DEVICE_NATIVE_ENDIAN,
+ };
+ 
++static const QemuChrHandlers strongarm_uart_handlers = {
++    .fd_can_read = strongarm_uart_can_receive,
++    .fd_read = strongarm_uart_receive,
++    .fd_event = strongarm_uart_event,
++};
++
+ static int strongarm_uart_init(SysBusDevice *dev)
+ {
+     StrongARMUARTState *s = FROM_SYSBUS(StrongARMUARTState, dev);
+@@ -1211,11 +1217,7 @@ static int strongarm_uart_init(SysBusDevice *dev)
+     s->tx_timer = qemu_new_timer_ns(vm_clock, strongarm_uart_tx, s);
+ 
+     if (s->chr) {
+-        qemu_chr_add_handlers(s->chr,
+-                        strongarm_uart_can_receive,
+-                        strongarm_uart_receive,
+-                        strongarm_uart_event,
+-                        s);
++        qemu_chr_add_handlers(s->chr, &strongarm_uart_handlers, s);
+     }
+ 
+     return 0;
+diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c
+index 99b19df..7307ad2 100644
+--- a/hw/usb/dev-serial.c
++++ b/hw/usb/dev-serial.c
+@@ -414,7 +414,7 @@ static void usb_serial_handle_destroy(USBDevice *dev)
+ {
+     USBSerialState *s = (USBSerialState *)dev;
+ 
+-    qemu_chr_add_handlers(s->cs, NULL, NULL, NULL, NULL);
++    qemu_chr_add_handlers(s->cs, NULL, NULL);
+ }
+ 
+ static int usb_serial_can_read(void *opaque)
+@@ -478,6 +478,12 @@ static void usb_serial_event(void *opaque, int event)
+     }
+ }
+ 
++static const QemuChrHandlers usb_serial_handlers = {
++    .fd_can_read = usb_serial_can_read,
++    .fd_read = usb_serial_read,
++    .fd_event = usb_serial_event,
++};
++
+ static int usb_serial_initfn(USBDevice *dev)
+ {
+     USBSerialState *s = DO_UPCAST(USBSerialState, dev, dev);
+@@ -491,8 +497,7 @@ static int usb_serial_initfn(USBDevice *dev)
+         return -1;
+     }
+ 
+-    qemu_chr_add_handlers(s->cs, usb_serial_can_read, usb_serial_read,
+-                          usb_serial_event, s);
++    qemu_chr_add_handlers(s->cs, &usb_serial_handlers, s);
+     usb_serial_handle_reset(dev);
+ 
+     if (s->cs->opened && !dev->attached) {
+diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
+index 490c90f..c921d2d 100644
+--- a/hw/usb/redirect.c
++++ b/hw/usb/redirect.c
+@@ -1037,6 +1037,12 @@ static void usbredir_chardev_event(void *opaque, int event)
+     }
+ }
+ 
++static const QemuChrHandlers usbredir_chr_handlers = {
++    .fd_can_read = usbredir_chardev_can_read,
++    .fd_read = usbredir_chardev_read,
++    .fd_event = usbredir_chardev_event,
++};
++
+ /*
+  * init + destroy
+  */
+@@ -1088,8 +1094,7 @@ static int usbredir_initfn(USBDevice *udev)
+ 
+     /* Let the backend know we are ready */
+     qemu_chr_fe_open(dev->cs);
+-    qemu_chr_add_handlers(dev->cs, usbredir_chardev_can_read,
+-                          usbredir_chardev_read, usbredir_chardev_event, dev);
++    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);
+diff --git a/hw/virtio-console.c b/hw/virtio-console.c
+index cffee3d..066590c 100644
+--- a/hw/virtio-console.c
++++ b/hw/virtio-console.c
+@@ -106,6 +106,12 @@ static void chr_event(void *opaque, int event)
+     }
+ }
+ 
++static const QemuChrHandlers chr_handlers = {
++    .fd_can_read = chr_can_read,
++    .fd_read = chr_read,
++    .fd_event = chr_event,
++};
++
+ static int virtconsole_initfn(VirtIOSerialPort *port)
+ {
+     VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
+@@ -117,8 +123,7 @@ static int virtconsole_initfn(VirtIOSerialPort *port)
+     }
+ 
+     if (vcon->chr) {
+-        qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event,
+-                              vcon);
++        qemu_chr_add_handlers(vcon->chr, &chr_handlers, vcon);
+     }
+ 
+     return 0;
+diff --git a/hw/xen_console.c b/hw/xen_console.c
+index 9426d73..e9fcadc 100644
+--- a/hw/xen_console.c
++++ b/hw/xen_console.c
+@@ -211,6 +211,11 @@ out:
+     return ret;
+ }
+ 
++static const QemuChrHandlers xencons_handlers = {
++    .fd_can_read = xencons_can_receive,
++    .fd_read = xencons_receive,
++};
++
+ static int con_initialise(struct XenDevice *xendev)
+ {
+     struct XenConsole *con = container_of(xendev, struct XenConsole, xendev);
+@@ -231,9 +236,9 @@ static int con_initialise(struct XenDevice *xendev)
+ 	return -1;
+ 
+     xen_be_bind_evtchn(&con->xendev);
+-    if (con->chr)
+-        qemu_chr_add_handlers(con->chr, xencons_can_receive, xencons_receive,
+-                              NULL, con);
++    if (con->chr) {
++        qemu_chr_add_handlers(con->chr, &xencons_handlers, con);
++    }
+ 
+     xen_be_printf(xendev, 1, "ring mfn %d, remote port %d, local port %d, limit %zd\n",
+ 		  con->ring_ref,
+@@ -250,8 +255,9 @@ static void con_disconnect(struct XenDevice *xendev)
+     if (!xendev->dev) {
+         return;
+     }
+-    if (con->chr)
+-        qemu_chr_add_handlers(con->chr, NULL, NULL, NULL, NULL);
++    if (con->chr) {
++        qemu_chr_add_handlers(con->chr, NULL, NULL);
++    }
+     xen_be_unbind_evtchn(&con->xendev);
+ 
+     if (con->sring) {
+diff --git a/hw/xilinx_uartlite.c b/hw/xilinx_uartlite.c
+index d20fc41..6605fb1 100644
+--- a/hw/xilinx_uartlite.c
++++ b/hw/xilinx_uartlite.c
+@@ -195,6 +195,12 @@ static void uart_event(void *opaque, int event)
+ 
+ }
+ 
++static const QemuChrHandlers uart_handlers = {
++    .fd_can_read = uart_can_rx,
++    .fd_read = uart_rx,
++    .fd_event = uart_event,
++};
++
+ static int xilinx_uartlite_init(SysBusDevice *dev)
+ {
+     struct xlx_uartlite *s = FROM_SYSBUS(typeof (*s), dev);
+@@ -207,8 +213,9 @@ static int xilinx_uartlite_init(SysBusDevice *dev)
+     sysbus_init_mmio(dev, &s->mmio);
+ 
+     s->chr = qemu_char_get_next_serial();
+-    if (s->chr)
+-        qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
++    if (s->chr) {
++        qemu_chr_add_handlers(s->chr, &uart_handlers, s);
++    }
+     return 0;
+ }
+ 
+diff --git a/monitor.c b/monitor.c
+index c0e32d6..ce0c90a 100644
+--- a/monitor.c
++++ b/monitor.c
+@@ -4685,6 +4685,18 @@ static void sortcmdlist(void)
+  * End:
+  */
+ 
++static const QemuChrHandlers monitor_handlers = {
++    .fd_can_read = monitor_can_read,
++    .fd_read = monitor_read,
++    .fd_event = monitor_event,
++};
++
++static const QemuChrHandlers monitor_control_handlers = {
++    .fd_can_read = monitor_can_read,
++    .fd_read = monitor_control_read,
++    .fd_event = monitor_control_event,
++};
++
+ void monitor_init(CharDriverState *chr, int flags)
+ {
+     static int is_first_init = 1;
+@@ -4707,14 +4719,12 @@ void monitor_init(CharDriverState *chr, int flags)
+     if (monitor_ctrl_mode(mon)) {
+         mon->mc = g_malloc0(sizeof(MonitorControl));
+         /* Control mode requires special handlers */
+-        qemu_chr_add_handlers(chr, monitor_can_read, monitor_control_read,
+-                              monitor_control_event, mon);
++        qemu_chr_add_handlers(chr, &monitor_control_handlers, mon);
+         qemu_chr_fe_set_echo(chr, true);
+ 
+         json_message_parser_init(&mon->mc->parser, handle_qmp_command);
+     } else {
+-        qemu_chr_add_handlers(chr, monitor_can_read, monitor_read,
+-                              monitor_event, mon);
++        qemu_chr_add_handlers(chr, &monitor_handlers, mon);
+     }
+ 
+     QLIST_INSERT_HEAD(&mon_list, mon, entry);
+diff --git a/net/slirp.c b/net/slirp.c
+index afb52c3..07ae92f 100644
+--- a/net/slirp.c
++++ b/net/slirp.c
+@@ -594,6 +594,11 @@ static void guestfwd_read(void *opaque, const uint8_t *buf, int size)
+     slirp_socket_recv(fwd->slirp, fwd->server, fwd->port, buf, size);
+ }
+ 
++static const QemuChrHandlers guestfwd_handlers = {
++    .fd_can_read = guestfwd_can_read,
++    .fd_read = guestfwd_read,
++};
++
+ static int slirp_guestfwd(SlirpState *s, const char *config_str,
+                           int legacy_format)
+ {
+@@ -659,8 +664,7 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str,
+         fwd->port = port;
+         fwd->slirp = s->slirp;
+ 
+-        qemu_chr_add_handlers(fwd->hd, guestfwd_can_read, guestfwd_read,
+-                              NULL, fwd);
++        qemu_chr_add_handlers(fwd->hd, &guestfwd_handlers, fwd);
+     }
+     return 0;
+ 
+diff --git a/qemu-char.c b/qemu-char.c
+index 77776dc..97247fb 100644
+--- a/qemu-char.c
++++ b/qemu-char.c
+@@ -193,19 +193,26 @@ void qemu_chr_fe_printf(CharDriverState *s, const char *fmt, ...)
+     va_end(ap);
+ }
+ 
++static const QemuChrHandlers null_handlers = {
++    /* All handlers are initialised to NULL */
++};
++
+ void qemu_chr_add_handlers(CharDriverState *s,
+-                           IOCanReadHandler *fd_can_read,
+-                           IOReadHandler *fd_read,
+-                           IOEventHandler *fd_event,
+-                           void *opaque)
++                           const QemuChrHandlers *handlers, void *opaque)
+ {
+-    if (!opaque && !fd_can_read && !fd_read && !fd_event) {
++    if (!s) {
++        return;
++    }
++    if (!opaque && !handlers) {
+         /* chr driver being released. */
+         ++s->avail_connections;
+     }
+-    s->chr_can_read = fd_can_read;
+-    s->chr_read = fd_read;
+-    s->chr_event = fd_event;
++    if (!handlers) {
++        handlers = &null_handlers;
++    }
++    s->chr_can_read = handlers->fd_can_read;
++    s->chr_read = handlers->fd_read;
++    s->chr_event = handlers->fd_event;
+     s->handler_opaque = opaque;
+     if (s->chr_update_read_handler)
+         s->chr_update_read_handler(s);
+@@ -443,6 +450,12 @@ static void mux_chr_event(void *opaque, int event)
+         mux_chr_send_event(d, i, event);
+ }
+ 
++static const QemuChrHandlers mux_chr_handlers = {
++    .fd_can_read = mux_chr_can_read,
++    .fd_read = mux_chr_read,
++    .fd_event = mux_chr_event,
++};
++
+ static void mux_chr_update_read_handler(CharDriverState *chr)
+ {
+     MuxDriver *d = chr->opaque;
+@@ -457,8 +470,7 @@ static void mux_chr_update_read_handler(CharDriverState *chr)
+     d->chr_event[d->mux_cnt] = chr->chr_event;
+     /* Fix up the real driver with mux routines */
+     if (d->mux_cnt == 0) {
+-        qemu_chr_add_handlers(d->drv, mux_chr_can_read, mux_chr_read,
+-                              mux_chr_event, chr);
++        qemu_chr_add_handlers(d->drv, &mux_chr_handlers, chr);
+     }
+     if (d->focus != -1) {
+         mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_OUT);
+diff --git a/qemu-char.h b/qemu-char.h
+index a121e04..ff206cb 100644
+--- a/qemu-char.h
++++ b/qemu-char.h
+@@ -223,10 +223,15 @@ void qemu_chr_be_write(CharDriverState *s, uint8_t *buf, int len);
+  */
+ void qemu_chr_be_event(CharDriverState *s, int event);
+ 
+-void qemu_chr_add_handlers(CharDriverState *s,
+-                           IOCanReadHandler *fd_can_read,
+-                           IOReadHandler *fd_read,
+-                           IOEventHandler *fd_event,
++
++typedef struct QemuChrHandlers {
++    IOCanReadHandler *fd_can_read;
++    IOReadHandler *fd_read;
++    IOHandler *fd_write_unblocked;
++    IOEventHandler *fd_event;
++} QemuChrHandlers;
++
++void qemu_chr_add_handlers(CharDriverState *s, const QemuChrHandlers *handlers,
+                            void *opaque);
+ 
+ void qemu_chr_generic_open(CharDriverState *s);
+diff --git a/qtest.c b/qtest.c
+index fbfab4e..4ab5b69 100644
+--- a/qtest.c
++++ b/qtest.c
+@@ -416,6 +416,13 @@ static void qtest_event(void *opaque, int event)
+     }
+ }
+ 
++static const QemuChrHandlers test_handlers = {
++    .fd_can_read = qtest_can_read,
++    .fd_read = qtest_read,
++    .fd_event = qtest_event,
++};
++
++
+ int qtest_init(void)
+ {
+     CharDriverState *chr;
+@@ -425,7 +432,7 @@ int qtest_init(void)
+     configure_icount("0");
+     chr = qemu_chr_new("qtest", qtest_chrdev, NULL);
+ 
+-    qemu_chr_add_handlers(chr, qtest_can_read, qtest_read, qtest_event, chr);
++    qemu_chr_add_handlers(chr, &test_handlers, chr);
+     qemu_chr_fe_set_echo(chr, true);
+ 
+     inbuf = g_string_new("");
+-- 
+1.8.1
+
diff --git a/0102-iohandlers-Add-enable-disable_write_fd_handler-funct.patch b/0102-iohandlers-Add-enable-disable_write_fd_handler-funct.patch
deleted file mode 100644
index 95a6996..0000000
--- a/0102-iohandlers-Add-enable-disable_write_fd_handler-funct.patch
+++ /dev/null
@@ -1,80 +0,0 @@
-From 448ba28f493820e91b65986901165cb28ff5fd78 Mon Sep 17 00:00:00 2001
-Message-Id: <448ba28f493820e91b65986901165cb28ff5fd78.1354903384.git.crobinso@redhat.com>
-In-Reply-To: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com>
-References: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com>
-From: Amit Shah <amit.shah@redhat.com>
-Date: Mon, 21 Mar 2011 20:32:58 +0100
-Subject: [PATCH] iohandlers: Add enable/disable_write_fd_handler() functions
-
-These will be used to provide a cleaner API for the nonblocking case.
-
-Signed-off-by: Amit Shah <amit.shah@redhat.com>
-Signed-off-by: Cole Robinson <crobinso@redhat.com>
----
- iohandler.c | 35 +++++++++++++++++++++++++++++++++++
- main-loop.h |  3 +++
- 2 files changed, 38 insertions(+)
-
-diff --git a/iohandler.c b/iohandler.c
-index 60460a6..6cf2cdd 100644
---- a/iohandler.c
-+++ b/iohandler.c
-@@ -46,6 +46,41 @@ typedef struct IOHandlerRecord {
- static QLIST_HEAD(, IOHandlerRecord) io_handlers =
-     QLIST_HEAD_INITIALIZER(io_handlers);
- 
-+static IOHandlerRecord *find_iohandler(int fd)
-+{
-+    IOHandlerRecord *ioh;
-+
-+    QLIST_FOREACH(ioh, &io_handlers, next) {
-+        if (ioh->fd == fd) {
-+            return ioh;
-+        }
-+    }
-+    return NULL;
-+}
-+
-+void enable_write_fd_handler(int fd, IOHandler *fd_write)
-+{
-+    IOHandlerRecord *ioh;
-+
-+    ioh = find_iohandler(fd);
-+    if (!ioh) {
-+        return;
-+    }
-+
-+    ioh->fd_write = fd_write;
-+}
-+
-+void disable_write_fd_handler(int fd)
-+{
-+    IOHandlerRecord *ioh;
-+
-+    ioh = find_iohandler(fd);
-+    if (!ioh) {
-+        return;
-+    }
-+
-+    ioh->fd_write = NULL;
-+}
- 
- /* XXX: fd_read_poll should be suppressed, but an API change is
-    necessary in the character devices to suppress fd_can_read(). */
-diff --git a/main-loop.h b/main-loop.h
-index 326c742..883ad43 100644
---- a/main-loop.h
-+++ b/main-loop.h
-@@ -166,6 +166,9 @@ void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque);
- typedef void IOReadHandler(void *opaque, const uint8_t *buf, int size);
- typedef int IOCanReadHandler(void *opaque);
- 
-+void enable_write_fd_handler(int fd, IOHandler *fd_write);
-+void disable_write_fd_handler(int fd);
-+
- /**
-  * qemu_set_fd_handler2: Register a file descriptor with the main loop
-  *
--- 
-1.8.0
-
diff --git a/0103-char-Add-framework-for-a-write-unblocked-callback.patch b/0103-char-Add-framework-for-a-write-unblocked-callback.patch
deleted file mode 100644
index 9388d16..0000000
--- a/0103-char-Add-framework-for-a-write-unblocked-callback.patch
+++ /dev/null
@@ -1,65 +0,0 @@
-From ea5fefd1ca7fb951c534333a78618ec6d6d89581 Mon Sep 17 00:00:00 2001
-Message-Id: <ea5fefd1ca7fb951c534333a78618ec6d6d89581.1354903384.git.crobinso@redhat.com>
-In-Reply-To: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com>
-References: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com>
-From: Amit Shah <amit.shah@redhat.com>
-Date: Mon, 21 Mar 2011 21:41:42 +0100
-Subject: [PATCH] char: Add framework for a 'write unblocked' callback
-
-The char layer can let users know that the driver will block on further
-input.  For users interested in not blocking, they can assign a function
-pointer that will be called back when the driver becomes writable.  This
-patch just adds the function pointers to the CharDriverState structure,
-future patches will enable the nonblocking and callback functionality.
-
-Signed-off-by: Amit Shah <amit.shah@redhat.com>
-Signed-off-by: Cole Robinson <crobinso@redhat.com>
----
- qemu-char.c | 3 +++
- qemu-char.h | 4 ++++
- 2 files changed, 7 insertions(+)
-
-diff --git a/qemu-char.c b/qemu-char.c
-index 97247fb..c9e6e36 100644
---- a/qemu-char.c
-+++ b/qemu-char.c
-@@ -212,11 +212,14 @@ void qemu_chr_add_handlers(CharDriverState *s,
-     }
-     s->chr_can_read = handlers->fd_can_read;
-     s->chr_read = handlers->fd_read;
-+    s->chr_write_unblocked = handlers->fd_write_unblocked;
-     s->chr_event = handlers->fd_event;
-     s->handler_opaque = opaque;
-     if (s->chr_update_read_handler)
-         s->chr_update_read_handler(s);
- 
-+    s->write_blocked = false;
-+
-     /* We're connecting to an already opened device, so let's make sure we
-        also get the open event */
-     if (s->opened) {
-diff --git a/qemu-char.h b/qemu-char.h
-index ff206cb..9e1b0f1 100644
---- a/qemu-char.h
-+++ b/qemu-char.h
-@@ -63,6 +63,9 @@ struct CharDriverState {
-     IOEventHandler *chr_event;
-     IOCanReadHandler *chr_can_read;
-     IOReadHandler *chr_read;
-+    IOHandler *chr_write_unblocked;
-+    void (*chr_enable_write_fd_handler)(struct CharDriverState *chr);
-+    void (*chr_disable_write_fd_handler)(struct CharDriverState *chr);
-     void *handler_opaque;
-     void (*chr_close)(struct CharDriverState *chr);
-     void (*chr_accept_input)(struct CharDriverState *chr);
-@@ -75,6 +78,7 @@ struct CharDriverState {
-     char *filename;
-     int opened;
-     int avail_connections;
-+    bool write_blocked; /* Are we in a blocked state? */
-     QTAILQ_ENTRY(CharDriverState) next;
- };
- 
--- 
-1.8.0
-
diff --git a/0103-iohandlers-Add-enable-disable_write_fd_handler-funct.patch b/0103-iohandlers-Add-enable-disable_write_fd_handler-funct.patch
new file mode 100644
index 0000000..cbbf8f3
--- /dev/null
+++ b/0103-iohandlers-Add-enable-disable_write_fd_handler-funct.patch
@@ -0,0 +1,77 @@
+From ebe349109322787302da1f65709b77568055ce96 Mon Sep 17 00:00:00 2001
+From: Amit Shah <amit.shah@redhat.com>
+Date: Mon, 21 Mar 2011 20:32:58 +0100
+Subject: [PATCH] iohandlers: Add enable/disable_write_fd_handler() functions
+
+These will be used to provide a cleaner API for the nonblocking case.
+
+Signed-off-by: Amit Shah <amit.shah@redhat.com>
+Signed-off-by: Cole Robinson <crobinso@redhat.com>
+---
+ iohandler.c | 35 +++++++++++++++++++++++++++++++++++
+ main-loop.h |  3 +++
+ 2 files changed, 38 insertions(+)
+
+diff --git a/iohandler.c b/iohandler.c
+index 60460a6..6cf2cdd 100644
+--- a/iohandler.c
++++ b/iohandler.c
+@@ -46,6 +46,41 @@ typedef struct IOHandlerRecord {
+ static QLIST_HEAD(, IOHandlerRecord) io_handlers =
+     QLIST_HEAD_INITIALIZER(io_handlers);
+ 
++static IOHandlerRecord *find_iohandler(int fd)
++{
++    IOHandlerRecord *ioh;
++
++    QLIST_FOREACH(ioh, &io_handlers, next) {
++        if (ioh->fd == fd) {
++            return ioh;
++        }
++    }
++    return NULL;
++}
++
++void enable_write_fd_handler(int fd, IOHandler *fd_write)
++{
++    IOHandlerRecord *ioh;
++
++    ioh = find_iohandler(fd);
++    if (!ioh) {
++        return;
++    }
++
++    ioh->fd_write = fd_write;
++}
++
++void disable_write_fd_handler(int fd)
++{
++    IOHandlerRecord *ioh;
++
++    ioh = find_iohandler(fd);
++    if (!ioh) {
++        return;
++    }
++
++    ioh->fd_write = NULL;
++}
+ 
+ /* XXX: fd_read_poll should be suppressed, but an API change is
+    necessary in the character devices to suppress fd_can_read(). */
+diff --git a/main-loop.h b/main-loop.h
+index 326c742..883ad43 100644
+--- a/main-loop.h
++++ b/main-loop.h
+@@ -166,6 +166,9 @@ void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque);
+ typedef void IOReadHandler(void *opaque, const uint8_t *buf, int size);
+ typedef int IOCanReadHandler(void *opaque);
+ 
++void enable_write_fd_handler(int fd, IOHandler *fd_write);
++void disable_write_fd_handler(int fd);
++
+ /**
+  * qemu_set_fd_handler2: Register a file descriptor with the main loop
+  *
+-- 
+1.8.1
+
diff --git a/0104-char-Add-framework-for-a-write-unblocked-callback.patch b/0104-char-Add-framework-for-a-write-unblocked-callback.patch
new file mode 100644
index 0000000..7fc3be9
--- /dev/null
+++ b/0104-char-Add-framework-for-a-write-unblocked-callback.patch
@@ -0,0 +1,62 @@
+From 646046655c6aed23a9e39064242e0803704d74e8 Mon Sep 17 00:00:00 2001
+From: Amit Shah <amit.shah@redhat.com>
+Date: Mon, 21 Mar 2011 21:41:42 +0100
+Subject: [PATCH] char: Add framework for a 'write unblocked' callback
+
+The char layer can let users know that the driver will block on further
+input.  For users interested in not blocking, they can assign a function
+pointer that will be called back when the driver becomes writable.  This
+patch just adds the function pointers to the CharDriverState structure,
+future patches will enable the nonblocking and callback functionality.
+
+Signed-off-by: Amit Shah <amit.shah@redhat.com>
+Signed-off-by: Cole Robinson <crobinso@redhat.com>
+---
+ qemu-char.c | 3 +++
+ qemu-char.h | 4 ++++
+ 2 files changed, 7 insertions(+)
+
+diff --git a/qemu-char.c b/qemu-char.c
+index 97247fb..c9e6e36 100644
+--- a/qemu-char.c
++++ b/qemu-char.c
+@@ -212,11 +212,14 @@ void qemu_chr_add_handlers(CharDriverState *s,
+     }
+     s->chr_can_read = handlers->fd_can_read;
+     s->chr_read = handlers->fd_read;
++    s->chr_write_unblocked = handlers->fd_write_unblocked;
+     s->chr_event = handlers->fd_event;
+     s->handler_opaque = opaque;
+     if (s->chr_update_read_handler)
+         s->chr_update_read_handler(s);
+ 
++    s->write_blocked = false;
++
+     /* We're connecting to an already opened device, so let's make sure we
+        also get the open event */
+     if (s->opened) {
+diff --git a/qemu-char.h b/qemu-char.h
+index ff206cb..9e1b0f1 100644
+--- a/qemu-char.h
++++ b/qemu-char.h
+@@ -63,6 +63,9 @@ struct CharDriverState {
+     IOEventHandler *chr_event;
+     IOCanReadHandler *chr_can_read;
+     IOReadHandler *chr_read;
++    IOHandler *chr_write_unblocked;
++    void (*chr_enable_write_fd_handler)(struct CharDriverState *chr);
++    void (*chr_disable_write_fd_handler)(struct CharDriverState *chr);
+     void *handler_opaque;
+     void (*chr_close)(struct CharDriverState *chr);
+     void (*chr_accept_input)(struct CharDriverState *chr);
+@@ -75,6 +78,7 @@ struct CharDriverState {
+     char *filename;
+     int opened;
+     int avail_connections;
++    bool write_blocked; /* Are we in a blocked state? */
+     QTAILQ_ENTRY(CharDriverState) next;
+ };
+ 
+-- 
+1.8.1
+
diff --git a/0104-char-Update-send_all-to-handle-nonblocking-chardev-w.patch b/0104-char-Update-send_all-to-handle-nonblocking-chardev-w.patch
deleted file mode 100644
index 49f08ff..0000000
--- a/0104-char-Update-send_all-to-handle-nonblocking-chardev-w.patch
+++ /dev/null
@@ -1,176 +0,0 @@
-From dfbe8c51243ecd2ad33037cfbbb37440cc3d03ee Mon Sep 17 00:00:00 2001
-Message-Id: <dfbe8c51243ecd2ad33037cfbbb37440cc3d03ee.1354903384.git.crobinso@redhat.com>
-In-Reply-To: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com>
-References: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com>
-From: Amit Shah <amit.shah@redhat.com>
-Date: Mon, 21 Mar 2011 22:00:27 +0100
-Subject: [PATCH] char: Update send_all() to handle nonblocking chardev write
- requests
-
-The send_all function is modified to return to the caller in case the
-driver cannot handle any more data.  It returns -EAGAIN or
-WSAEWOULDBLOCK on non-Windows and Windows platforms respectively.  This
-is only done when the caller sets a callback function handler indicating
-it's not interested in blocking till the driver has written out all the
-data.
-
-Currently there's no driver or caller that supports this.  Future
-commits will add such capability.
-
-Signed-off-by: Amit Shah <amit.shah@redhat.com>
-Signed-off-by: Cole Robinson <crobinso@redhat.com>
----
- qemu-char.c   | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++------
- qemu_socket.h |  2 +-
- 2 files changed, 64 insertions(+), 7 deletions(-)
-
-diff --git a/qemu-char.c b/qemu-char.c
-index c9e6e36..53803a3 100644
---- a/qemu-char.c
-+++ b/qemu-char.c
-@@ -509,7 +509,7 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv)
- 
- 
- #ifdef _WIN32
--int send_all(int fd, const void *buf, int len1)
-+static int do_send(int fd, const void *buf, int len1, bool nonblock)
- {
-     int ret, len;
- 
-@@ -517,9 +517,14 @@ int send_all(int fd, const void *buf, int len1)
-     while (len > 0) {
-         ret = send(fd, buf, len, 0);
-         if (ret < 0) {
-+            if (nonblock && len1 - len) {
-+                return len1 - len;
-+            }
-             errno = WSAGetLastError();
-             if (errno != WSAEWOULDBLOCK) {
-                 return -1;
-+            } else if (errno == WSAEWOULDBLOCK && nonblock) {
-+                return WSAEWOULDBLOCK;
-             }
-         } else if (ret == 0) {
-             break;
-@@ -533,7 +538,7 @@ int send_all(int fd, const void *buf, int len1)
- 
- #else
- 
--int send_all(int fd, const void *_buf, int len1)
-+static int do_send(int fd, const void *_buf, int len1, bool nonblock)
- {
-     int ret, len;
-     const uint8_t *buf = _buf;
-@@ -542,8 +547,15 @@ int send_all(int fd, const void *_buf, int len1)
-     while (len > 0) {
-         ret = write(fd, buf, len);
-         if (ret < 0) {
--            if (errno != EINTR && errno != EAGAIN)
-+            if (nonblock && len1 - len) {
-+                return len1 - len;
-+            }
-+            if (errno == EAGAIN && nonblock) {
-+                return -EAGAIN;
-+            }
-+            if (errno != EINTR && errno != EAGAIN) {
-                 return -1;
-+            }
-         } else if (ret == 0) {
-             break;
-         } else {
-@@ -558,6 +570,44 @@ int send_all(int fd, const void *_buf, int len1)
- #define STDIO_MAX_CLIENTS 1
- static int stdio_nb_clients;
- 
-+int send_all(CharDriverState *chr, int fd, const void *_buf, int len1)
-+{
-+    int ret, eagain_errno;
-+    bool nonblock;
-+
-+    if (chr && chr->write_blocked) {
-+        /*
-+         * The caller should not send us data while we're blocked,
-+         * but this can happen when multiple writers are woken at once,
-+         * so simply return -EAGAIN.
-+         */
-+        return -EAGAIN;
-+    }
-+
-+    nonblock = false;
-+    /*
-+     * Ensure the char backend is able to receive and handle the
-+     * 'write unblocked' event before we turn on nonblock support.
-+     */
-+    if (chr && chr->chr_enable_write_fd_handler && chr->chr_write_unblocked) {
-+        nonblock = true;
-+    }
-+    ret = do_send(fd, _buf, len1, nonblock);
-+
-+#ifdef _WIN32
-+    eagain_errno = WSAEWOULDBLOCK;
-+#else
-+    eagain_errno = -EAGAIN;
-+#endif
-+
-+    if (nonblock && (ret == eagain_errno || (ret >= 0 && ret < len1))) {
-+        /* Update fd handler to wake up when chr becomes writable */
-+        chr->chr_enable_write_fd_handler(chr);
-+        chr->write_blocked = true;
-+    }
-+    return ret;
-+}
-+
- #ifndef _WIN32
- 
- typedef struct {
-@@ -569,7 +619,7 @@ typedef struct {
- static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
- {
-     FDCharDriver *s = chr->opaque;
--    return send_all(s->fd_out, buf, len);
-+    return send_all(chr, s->fd_out, buf, len);
- }
- 
- static int fd_chr_read_poll(void *opaque)
-@@ -888,7 +938,7 @@ static int pty_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
-         pty_chr_update_read_handler(chr);
-         return 0;
-     }
--    return send_all(s->fd, buf, len);
-+    return send_all(chr, s->fd, buf, len);
- }
- 
- static int pty_chr_read_poll(void *opaque)
-@@ -2179,8 +2229,15 @@ static void tcp_closed(void *opaque)
- static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
- {
-     TCPCharDriver *s = chr->opaque;
-+
-     if (s->connected) {
--        return send_all(s->fd, buf, len);
-+        int ret;
-+
-+        ret = send_all(chr, s->fd, buf, len);
-+        if (ret == -1 && errno == EPIPE) {
-+            tcp_closed(chr);
-+        }
-+        return ret;
-     } else {
-         /* XXX: indicate an error ? */
-         return len;
-diff --git a/qemu_socket.h b/qemu_socket.h
-index 02490ad..cceab98 100644
---- a/qemu_socket.h
-+++ b/qemu_socket.h
-@@ -36,7 +36,7 @@ int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
- int socket_set_cork(int fd, int v);
- void socket_set_block(int fd);
- void socket_set_nonblock(int fd);
--int send_all(int fd, const void *buf, int len1);
-+int send_all(CharDriverState *chr, int fd, const void *buf, int len1);
- 
- /* callback function for nonblocking connect
-  * valid fd on success, negative error code on failure
--- 
-1.8.0
-
diff --git a/0105-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch b/0105-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch
deleted file mode 100644
index 7ff4ab6..0000000
--- a/0105-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch
+++ /dev/null
@@ -1,85 +0,0 @@
-From 26139c9fd71229699c6d59c31631a539ac3830fd Mon Sep 17 00:00:00 2001
-Message-Id: <26139c9fd71229699c6d59c31631a539ac3830fd.1354903384.git.crobinso@redhat.com>
-In-Reply-To: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com>
-References: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com>
-From: Amit Shah <amit.shah@redhat.com>
-Date: Mon, 21 Mar 2011 22:02:47 +0100
-Subject: [PATCH] char: Equip the unix/tcp backend to handle nonblocking
- writes#
-
-Now that the infrastructure is in place to return -EAGAIN to callers,
-individual char drivers can set their update_fd_handlers() function to
-set or remove an fd's write handler.  This handler checks if the driver
-became writable.
-
-A generic callback routine is used for unblocking writes and letting
-users of chardevs know that a driver became writable again.
-
-Signed-off-by: Amit Shah <amit.shah@redhat.com>
-Signed-off-by: Cole Robinson <crobinso@redhat.com>
----
- qemu-char.c | 34 ++++++++++++++++++++++++++++++++++
- 1 file changed, 34 insertions(+)
-
-diff --git a/qemu-char.c b/qemu-char.c
-index 53803a3..e7cd42a 100644
---- a/qemu-char.c
-+++ b/qemu-char.c
-@@ -106,6 +106,19 @@
- static QTAILQ_HEAD(CharDriverStateHead, CharDriverState) chardevs =
-     QTAILQ_HEAD_INITIALIZER(chardevs);
- 
-+/*
-+ * Generic routine that gets called when chardev becomes writable.
-+ * Lets chardev user know it's OK to send more data.
-+ */
-+static void char_write_unblocked(void *opaque)
-+{
-+    CharDriverState *chr = opaque;
-+
-+    chr->write_blocked = false;
-+    chr->chr_disable_write_fd_handler(chr);
-+    chr->chr_write_unblocked(chr->handler_opaque);
-+}
-+
- void qemu_chr_be_event(CharDriverState *s, int event)
- {
-     /* Keep track if the char device is open */
-@@ -2508,6 +2521,25 @@ static void tcp_chr_close(CharDriverState *chr)
-     qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
- }
- 
-+static void tcp_enable_write_fd_handler(CharDriverState *chr)
-+{
-+    TCPCharDriver *s = chr->opaque;
-+
-+    /*
-+     * This function is called only after tcp_chr_connect() is called
-+     * (either in 'server' mode or client mode.  So we're sure of
-+     * s->fd being initialised.
-+     */
-+    enable_write_fd_handler(s->fd, char_write_unblocked);
-+}
-+
-+static void tcp_disable_write_fd_handler(CharDriverState *chr)
-+{
-+    TCPCharDriver *s = chr->opaque;
-+
-+    disable_write_fd_handler(s->fd);
-+}
-+
- static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
- {
-     CharDriverState *chr = NULL;
-@@ -2563,6 +2595,8 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
-     chr->chr_close = tcp_chr_close;
-     chr->get_msgfd = tcp_get_msgfd;
-     chr->chr_add_client = tcp_chr_add_client;
-+    chr->chr_enable_write_fd_handler = tcp_enable_write_fd_handler;
-+    chr->chr_disable_write_fd_handler = tcp_disable_write_fd_handler;
- 
-     if (is_listen) {
-         s->listen_fd = fd;
--- 
-1.8.0
-
diff --git a/0105-char-Update-send_all-to-handle-nonblocking-chardev-w.patch b/0105-char-Update-send_all-to-handle-nonblocking-chardev-w.patch
new file mode 100644
index 0000000..af5fba1
--- /dev/null
+++ b/0105-char-Update-send_all-to-handle-nonblocking-chardev-w.patch
@@ -0,0 +1,173 @@
+From 98984a6b82406c233819a7afa7f35d3df4c386b0 Mon Sep 17 00:00:00 2001
+From: Amit Shah <amit.shah@redhat.com>
+Date: Mon, 21 Mar 2011 22:00:27 +0100
+Subject: [PATCH] char: Update send_all() to handle nonblocking chardev write
+ requests
+
+The send_all function is modified to return to the caller in case the
+driver cannot handle any more data.  It returns -EAGAIN or
+WSAEWOULDBLOCK on non-Windows and Windows platforms respectively.  This
+is only done when the caller sets a callback function handler indicating
+it's not interested in blocking till the driver has written out all the
+data.
+
+Currently there's no driver or caller that supports this.  Future
+commits will add such capability.
+
+Signed-off-by: Amit Shah <amit.shah@redhat.com>
+Signed-off-by: Cole Robinson <crobinso@redhat.com>
+---
+ qemu-char.c   | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++------
+ qemu_socket.h |  2 +-
+ 2 files changed, 64 insertions(+), 7 deletions(-)
+
+diff --git a/qemu-char.c b/qemu-char.c
+index c9e6e36..53803a3 100644
+--- a/qemu-char.c
++++ b/qemu-char.c
+@@ -509,7 +509,7 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv)
+ 
+ 
+ #ifdef _WIN32
+-int send_all(int fd, const void *buf, int len1)
++static int do_send(int fd, const void *buf, int len1, bool nonblock)
+ {
+     int ret, len;
+ 
+@@ -517,9 +517,14 @@ int send_all(int fd, const void *buf, int len1)
+     while (len > 0) {
+         ret = send(fd, buf, len, 0);
+         if (ret < 0) {
++            if (nonblock && len1 - len) {
++                return len1 - len;
++            }
+             errno = WSAGetLastError();
+             if (errno != WSAEWOULDBLOCK) {
+                 return -1;
++            } else if (errno == WSAEWOULDBLOCK && nonblock) {
++                return WSAEWOULDBLOCK;
+             }
+         } else if (ret == 0) {
+             break;
+@@ -533,7 +538,7 @@ int send_all(int fd, const void *buf, int len1)
+ 
+ #else
+ 
+-int send_all(int fd, const void *_buf, int len1)
++static int do_send(int fd, const void *_buf, int len1, bool nonblock)
+ {
+     int ret, len;
+     const uint8_t *buf = _buf;
+@@ -542,8 +547,15 @@ int send_all(int fd, const void *_buf, int len1)
+     while (len > 0) {
+         ret = write(fd, buf, len);
+         if (ret < 0) {
+-            if (errno != EINTR && errno != EAGAIN)
++            if (nonblock && len1 - len) {
++                return len1 - len;
++            }
++            if (errno == EAGAIN && nonblock) {
++                return -EAGAIN;
++            }
++            if (errno != EINTR && errno != EAGAIN) {
+                 return -1;
++            }
+         } else if (ret == 0) {
+             break;
+         } else {
+@@ -558,6 +570,44 @@ int send_all(int fd, const void *_buf, int len1)
+ #define STDIO_MAX_CLIENTS 1
+ static int stdio_nb_clients;
+ 
++int send_all(CharDriverState *chr, int fd, const void *_buf, int len1)
++{
++    int ret, eagain_errno;
++    bool nonblock;
++
++    if (chr && chr->write_blocked) {
++        /*
++         * The caller should not send us data while we're blocked,
++         * but this can happen when multiple writers are woken at once,
++         * so simply return -EAGAIN.
++         */
++        return -EAGAIN;
++    }
++
++    nonblock = false;
++    /*
++     * Ensure the char backend is able to receive and handle the
++     * 'write unblocked' event before we turn on nonblock support.
++     */
++    if (chr && chr->chr_enable_write_fd_handler && chr->chr_write_unblocked) {
++        nonblock = true;
++    }
++    ret = do_send(fd, _buf, len1, nonblock);
++
++#ifdef _WIN32
++    eagain_errno = WSAEWOULDBLOCK;
++#else
++    eagain_errno = -EAGAIN;
++#endif
++
++    if (nonblock && (ret == eagain_errno || (ret >= 0 && ret < len1))) {
++        /* Update fd handler to wake up when chr becomes writable */
++        chr->chr_enable_write_fd_handler(chr);
++        chr->write_blocked = true;
++    }
++    return ret;
++}
++
+ #ifndef _WIN32
+ 
+ typedef struct {
+@@ -569,7 +619,7 @@ typedef struct {
+ static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+ {
+     FDCharDriver *s = chr->opaque;
+-    return send_all(s->fd_out, buf, len);
++    return send_all(chr, s->fd_out, buf, len);
+ }
+ 
+ static int fd_chr_read_poll(void *opaque)
+@@ -888,7 +938,7 @@ static int pty_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+         pty_chr_update_read_handler(chr);
+         return 0;
+     }
+-    return send_all(s->fd, buf, len);
++    return send_all(chr, s->fd, buf, len);
+ }
+ 
+ static int pty_chr_read_poll(void *opaque)
+@@ -2179,8 +2229,15 @@ static void tcp_closed(void *opaque)
+ static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+ {
+     TCPCharDriver *s = chr->opaque;
++
+     if (s->connected) {
+-        return send_all(s->fd, buf, len);
++        int ret;
++
++        ret = send_all(chr, s->fd, buf, len);
++        if (ret == -1 && errno == EPIPE) {
++            tcp_closed(chr);
++        }
++        return ret;
+     } else {
+         /* XXX: indicate an error ? */
+         return len;
+diff --git a/qemu_socket.h b/qemu_socket.h
+index 02490ad..cceab98 100644
+--- a/qemu_socket.h
++++ b/qemu_socket.h
+@@ -36,7 +36,7 @@ int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
+ int socket_set_cork(int fd, int v);
+ void socket_set_block(int fd);
+ void socket_set_nonblock(int fd);
+-int send_all(int fd, const void *buf, int len1);
++int send_all(CharDriverState *chr, int fd, const void *buf, int len1);
+ 
+ /* callback function for nonblocking connect
+  * valid fd on success, negative error code on failure
+-- 
+1.8.1
+
diff --git a/0106-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch b/0106-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch
new file mode 100644
index 0000000..0958e59
--- /dev/null
+++ b/0106-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch
@@ -0,0 +1,82 @@
+From e8a6c8da28eb73704099b4ae2172bca7fa4d0bd7 Mon Sep 17 00:00:00 2001
+From: Amit Shah <amit.shah@redhat.com>
+Date: Mon, 21 Mar 2011 22:02:47 +0100
+Subject: [PATCH] char: Equip the unix/tcp backend to handle nonblocking
+ writes#
+
+Now that the infrastructure is in place to return -EAGAIN to callers,
+individual char drivers can set their update_fd_handlers() function to
+set or remove an fd's write handler.  This handler checks if the driver
+became writable.
+
+A generic callback routine is used for unblocking writes and letting
+users of chardevs know that a driver became writable again.
+
+Signed-off-by: Amit Shah <amit.shah@redhat.com>
+Signed-off-by: Cole Robinson <crobinso@redhat.com>
+---
+ qemu-char.c | 34 ++++++++++++++++++++++++++++++++++
+ 1 file changed, 34 insertions(+)
+
+diff --git a/qemu-char.c b/qemu-char.c
+index 53803a3..e7cd42a 100644
+--- a/qemu-char.c
++++ b/qemu-char.c
+@@ -106,6 +106,19 @@
+ static QTAILQ_HEAD(CharDriverStateHead, CharDriverState) chardevs =
+     QTAILQ_HEAD_INITIALIZER(chardevs);
+ 
++/*
++ * Generic routine that gets called when chardev becomes writable.
++ * Lets chardev user know it's OK to send more data.
++ */
++static void char_write_unblocked(void *opaque)
++{
++    CharDriverState *chr = opaque;
++
++    chr->write_blocked = false;
++    chr->chr_disable_write_fd_handler(chr);
++    chr->chr_write_unblocked(chr->handler_opaque);
++}
++
+ void qemu_chr_be_event(CharDriverState *s, int event)
+ {
+     /* Keep track if the char device is open */
+@@ -2508,6 +2521,25 @@ static void tcp_chr_close(CharDriverState *chr)
+     qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
+ }
+ 
++static void tcp_enable_write_fd_handler(CharDriverState *chr)
++{
++    TCPCharDriver *s = chr->opaque;
++
++    /*
++     * This function is called only after tcp_chr_connect() is called
++     * (either in 'server' mode or client mode.  So we're sure of
++     * s->fd being initialised.
++     */
++    enable_write_fd_handler(s->fd, char_write_unblocked);
++}
++
++static void tcp_disable_write_fd_handler(CharDriverState *chr)
++{
++    TCPCharDriver *s = chr->opaque;
++
++    disable_write_fd_handler(s->fd);
++}
++
+ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
+ {
+     CharDriverState *chr = NULL;
+@@ -2563,6 +2595,8 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
+     chr->chr_close = tcp_chr_close;
+     chr->get_msgfd = tcp_get_msgfd;
+     chr->chr_add_client = tcp_chr_add_client;
++    chr->chr_enable_write_fd_handler = tcp_enable_write_fd_handler;
++    chr->chr_disable_write_fd_handler = tcp_disable_write_fd_handler;
+ 
+     if (is_listen) {
+         s->listen_fd = fd;
+-- 
+1.8.1
+
diff --git a/0106-char-Throttle-when-host-connection-is-down.patch b/0106-char-Throttle-when-host-connection-is-down.patch
deleted file mode 100644
index d373330..0000000
--- a/0106-char-Throttle-when-host-connection-is-down.patch
+++ /dev/null
@@ -1,60 +0,0 @@
-From c2ddb156db52808a89d91edf5bb1449f226d3ecd Mon Sep 17 00:00:00 2001
-Message-Id: <c2ddb156db52808a89d91edf5bb1449f226d3ecd.1354903384.git.crobinso@redhat.com>
-In-Reply-To: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com>
-References: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com>
-From: Amit Shah <amit.shah@redhat.com>
-Date: Mon, 21 Mar 2011 22:05:10 +0100
-Subject: [PATCH] char: Throttle when host connection is down#
-
-When the host-side connection goes down, throttle the virtio-serial bus
-and later unthrottle when a connection gets established.  This helps
-prevent any lost IO (guest->host) while the host connection was down.
-
-Bugzilla: 621484
-
-This commit actually helps the bug mentioned above as no writes will now
-get lost because of the throttling done here.  With just the patches
-sent earlier for that bug, one write will end up getting lost in the
-worst case (host d/c, guest write, host connect).
-
-Signed-off-by: Amit Shah <amit.shah@redhat.com>
-Signed-off-by: Cole Robinson <crobinso@redhat.com>
----
- qemu-char.c | 14 ++++++++++++++
- 1 file changed, 14 insertions(+)
-
-diff --git a/qemu-char.c b/qemu-char.c
-index e7cd42a..5c71f0c 100644
---- a/qemu-char.c
-+++ b/qemu-char.c
-@@ -140,6 +140,9 @@ static void qemu_chr_fire_open_event(void *opaque)
- {
-     CharDriverState *s = opaque;
-     qemu_chr_be_event(s, CHR_EVENT_OPENED);
-+    if (s->write_blocked) {
-+        char_write_unblocked(s);
-+    }
-     qemu_free_timer(s->open_timer);
-     s->open_timer = NULL;
- }
-@@ -2249,6 +2252,17 @@ static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
-         ret = send_all(chr, s->fd, buf, len);
-         if (ret == -1 && errno == EPIPE) {
-             tcp_closed(chr);
-+
-+            if (chr->chr_enable_write_fd_handler && chr->chr_write_unblocked) {
-+                /*
-+                 * Since we haven't written out anything, let's say
-+                 * we're throttled.  This will prevent any output from
-+                 * the guest getting lost if host-side chardev goes
-+                 * down.  Unthrottle when we re-connect.
-+                 */
-+                chr->write_blocked = true;
-+                return 0;
-+            }
-         }
-         return ret;
-     } else {
--- 
-1.8.0
-
diff --git a/0107-char-Throttle-when-host-connection-is-down.patch b/0107-char-Throttle-when-host-connection-is-down.patch
new file mode 100644
index 0000000..a62a123
--- /dev/null
+++ b/0107-char-Throttle-when-host-connection-is-down.patch
@@ -0,0 +1,57 @@
+From 7ce910503a5db38f23a13ae5f56e256d80caf1e4 Mon Sep 17 00:00:00 2001
+From: Amit Shah <amit.shah@redhat.com>
+Date: Mon, 21 Mar 2011 22:05:10 +0100
+Subject: [PATCH] char: Throttle when host connection is down#
+
+When the host-side connection goes down, throttle the virtio-serial bus
+and later unthrottle when a connection gets established.  This helps
+prevent any lost IO (guest->host) while the host connection was down.
+
+Bugzilla: 621484
+
+This commit actually helps the bug mentioned above as no writes will now
+get lost because of the throttling done here.  With just the patches
+sent earlier for that bug, one write will end up getting lost in the
+worst case (host d/c, guest write, host connect).
+
+Signed-off-by: Amit Shah <amit.shah@redhat.com>
+Signed-off-by: Cole Robinson <crobinso@redhat.com>
+---
+ qemu-char.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/qemu-char.c b/qemu-char.c
+index e7cd42a..5c71f0c 100644
+--- a/qemu-char.c
++++ b/qemu-char.c
+@@ -140,6 +140,9 @@ static void qemu_chr_fire_open_event(void *opaque)
+ {
+     CharDriverState *s = opaque;
+     qemu_chr_be_event(s, CHR_EVENT_OPENED);
++    if (s->write_blocked) {
++        char_write_unblocked(s);
++    }
+     qemu_free_timer(s->open_timer);
+     s->open_timer = NULL;
+ }
+@@ -2249,6 +2252,17 @@ static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+         ret = send_all(chr, s->fd, buf, len);
+         if (ret == -1 && errno == EPIPE) {
+             tcp_closed(chr);
++
++            if (chr->chr_enable_write_fd_handler && chr->chr_write_unblocked) {
++                /*
++                 * Since we haven't written out anything, let's say
++                 * we're throttled.  This will prevent any output from
++                 * the guest getting lost if host-side chardev goes
++                 * down.  Unthrottle when we re-connect.
++                 */
++                chr->write_blocked = true;
++                return 0;
++            }
+         }
+         return ret;
+     } else {
+-- 
+1.8.1
+
diff --git a/0107-virtio-console-Enable-port-throttling-when-chardev-i.patch b/0107-virtio-console-Enable-port-throttling-when-chardev-i.patch
deleted file mode 100644
index 7435322..0000000
--- a/0107-virtio-console-Enable-port-throttling-when-chardev-i.patch
+++ /dev/null
@@ -1,53 +0,0 @@
-From afae0976cf4e3ba7f2810c1afaecac96646a2a2b Mon Sep 17 00:00:00 2001
-Message-Id: <afae0976cf4e3ba7f2810c1afaecac96646a2a2b.1354903384.git.crobinso@redhat.com>
-In-Reply-To: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com>
-References: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com>
-From: Amit Shah <amit.shah@redhat.com>
-Date: Mon, 21 Mar 2011 22:06:41 +0100
-Subject: [PATCH] virtio-console: Enable port throttling when chardev is slow
- to consume data
-
-When a chardev indicates it can't accept more data, we tell the
-virtio-serial code to stop sending us any more data till we tell
-otherwise.  This helps in guests continuing to run normally while the vq
-keeps getting full and eventually the guest stops queueing more data.
-As soon as the chardev indicates it can accept more data, start pushing!
-
-Signed-off-by: Amit Shah <amit.shah@redhat.com>
-Signed-off-by: Cole Robinson <crobinso@redhat.com>
----
- hw/virtio-console.c | 11 +++++++++++
- 1 file changed, 11 insertions(+)
-
-diff --git a/hw/virtio-console.c b/hw/virtio-console.c
-index 066590c..2b5e515 100644
---- a/hw/virtio-console.c
-+++ b/hw/virtio-console.c
-@@ -20,6 +20,16 @@ typedef struct VirtConsole {
-     CharDriverState *chr;
- } VirtConsole;
- 
-+/*
-+ * Callback function that's called from chardevs when backend becomes
-+ * writable.
-+ */
-+static void chr_write_unblocked(void *opaque)
-+{
-+    VirtConsole *vcon = opaque;
-+
-+    virtio_serial_throttle_port(&vcon->port, false);
-+}
- 
- /* Callback function that's called when the guest sends us data */
- static ssize_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
-@@ -110,6 +120,7 @@ static const QemuChrHandlers chr_handlers = {
-     .fd_can_read = chr_can_read,
-     .fd_read = chr_read,
-     .fd_event = chr_event,
-+    .fd_write_unblocked = chr_write_unblocked,
- };
- 
- static int virtconsole_initfn(VirtIOSerialPort *port)
--- 
-1.8.0
-
diff --git a/0108-spice-qemu-char.c-add-throttling.patch b/0108-spice-qemu-char.c-add-throttling.patch
deleted file mode 100644
index 0e7b992..0000000
--- a/0108-spice-qemu-char.c-add-throttling.patch
+++ /dev/null
@@ -1,138 +0,0 @@
-From bffc95c205b473df9bba81dbf676504d0981d392 Mon Sep 17 00:00:00 2001
-Message-Id: <bffc95c205b473df9bba81dbf676504d0981d392.1354903384.git.crobinso@redhat.com>
-In-Reply-To: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com>
-References: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com>
-From: Alon Levy <alevy@redhat.com>
-Date: Tue, 22 Mar 2011 12:27:59 +0200
-Subject: [PATCH] spice-qemu-char.c: add throttling
-
-BZ: 672191
-
-upstream: not submitted (explained below)
-
-Adds throttling support to spicevmc chardev. Uses a timer to avoid recursing:
-1. spice-server: reds.c:            read_from_vdi_port
-2. qemu:         spice-qemu-char.c: vmc_read
-3.                                  chr_write_unblocked
-                                (calls virtio_serial_throttle_port(port, false))
-4. qemu:         virtio ...
-5. qemu:         spice-qemu-char.c: spice_chr_write
-6. qemu:         spice-qemu-char.c: wakeup (calls into spice-server)
-7. spice-server: ...
-8. qemu:         spice-qemu-char.c: vmc_read
-
-Instead, in vmc_read if we were throttled and we are just about to return
-all the bytes we will set a timer to be triggered immediately to call
-chr_write_unblocked. Then we return after 2 above, and 3 is called from the
-timer callback. This also means we can later remove some ugly recursion protection
-from spice-server.
-
-The other tricky point in this patch is not returning the leftover chunk twice.
-When we throttle, by definition we have data that spice server didn't consume.
-It is being kept by virtio-serial, and by us. The next vmc_read callback needs
-to not return it, but just do unthrottling. Then virtio will give us the remaining
-chunk as usual in spice_chr_write, and we will pass it to spice server in the
-next vmc_read.
-
-This patch relies on Amit's series to expose throttling to chardev's, which
-was not accepted upstream, and will not be accepted upstream until the mainloop
-is reworked to use glib.
-
-Signed-off-by: Cole Robinson <crobinso@redhat.com>
----
- spice-qemu-char.c | 39 +++++++++++++++++++++++++++++++++++----
- 1 file changed, 35 insertions(+), 4 deletions(-)
-
-diff --git a/spice-qemu-char.c b/spice-qemu-char.c
-index 09aa22d..fba2bfb 100644
---- a/spice-qemu-char.c
-+++ b/spice-qemu-char.c
-@@ -1,4 +1,6 @@
- #include "config-host.h"
-+#include "qemu-common.h"
-+#include "qemu-timer.h"
- #include "trace.h"
- #include "ui/qemu-spice.h"
- #include <spice.h>
-@@ -25,6 +27,7 @@ typedef struct SpiceCharDriver {
-     uint8_t               *datapos;
-     ssize_t               bufsize, datalen;
-     uint32_t              debug;
-+    QEMUTimer             *unblock_timer;
- } SpiceCharDriver;
- 
- static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
-@@ -50,6 +53,17 @@ static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
-     return out;
- }
- 
-+static void spice_chr_unblock(void *opaque)
-+{
-+    SpiceCharDriver *scd = opaque;
-+
-+    if (scd->chr->chr_write_unblocked == NULL) {
-+        dprintf(scd, 1, "%s: backend doesn't support unthrottling.\n", __func__);
-+        return;
-+    }
-+    scd->chr->chr_write_unblocked(scd->chr->handler_opaque);
-+}
-+
- static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
- {
-     SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
-@@ -61,9 +75,16 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
-         scd->datapos += bytes;
-         scd->datalen -= bytes;
-         assert(scd->datalen >= 0);
--        if (scd->datalen == 0) {
--            scd->datapos = 0;
--        }
-+    }
-+    if (scd->datalen == 0 && scd->chr->write_blocked) {
-+        dprintf(scd, 1, "%s: unthrottling (%d)\n", __func__, bytes);
-+        scd->chr->write_blocked = false;
-+        /*
-+         * set a timer instead of calling scd->chr->chr_write_unblocked directly,
-+         * because that will call back into spice_chr_write (see
-+         * virtio-console.c:chr_write_unblocked), which is unwanted.
-+         */
-+        qemu_mod_timer(scd->unblock_timer, 0);
-     }
-     trace_spice_vmc_read(bytes, len);
-     return bytes;
-@@ -135,6 +156,7 @@ static void vmc_unregister_interface(SpiceCharDriver *scd)
- static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
- {
-     SpiceCharDriver *s = chr->opaque;
-+    int read_bytes;
- 
-     dprintf(s, 2, "%s: %d\n", __func__, len);
-     vmc_register_interface(s);
-@@ -147,7 +169,15 @@ static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
-     s->datapos = s->buffer;
-     s->datalen = len;
-     spice_server_char_device_wakeup(&s->sin);
--    return len;
-+    read_bytes = len - s->datalen;
-+    if (read_bytes != len) {
-+        dprintf(s, 1, "%s: throttling: %d < %d (%zd)\n", __func__,
-+                read_bytes, len, s->bufsize);
-+        s->chr->write_blocked = true;
-+        /* We'll get passed in the unconsumed data with the next call */
-+        s->datalen = 0;
-+    }
-+    return read_bytes;
- }
- 
- static void spice_chr_close(struct CharDriverState *chr)
-@@ -225,6 +255,7 @@ CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
-     chr->chr_close = spice_chr_close;
-     chr->chr_guest_open = spice_chr_guest_open;
-     chr->chr_guest_close = spice_chr_guest_close;
-+    s->unblock_timer = qemu_new_timer_ms(vm_clock, spice_chr_unblock, s);
- 
- #if SPICE_SERVER_VERSION < 0x000901
-     /* See comment in vmc_state() */
--- 
-1.8.0
-
diff --git a/0108-virtio-console-Enable-port-throttling-when-chardev-i.patch b/0108-virtio-console-Enable-port-throttling-when-chardev-i.patch
new file mode 100644
index 0000000..5662289
--- /dev/null
+++ b/0108-virtio-console-Enable-port-throttling-when-chardev-i.patch
@@ -0,0 +1,50 @@
+From 8fd5d7cbbb8245185c800062fc6bc0ac9e749375 Mon Sep 17 00:00:00 2001
+From: Amit Shah <amit.shah@redhat.com>
+Date: Mon, 21 Mar 2011 22:06:41 +0100
+Subject: [PATCH] virtio-console: Enable port throttling when chardev is slow
+ to consume data
+
+When a chardev indicates it can't accept more data, we tell the
+virtio-serial code to stop sending us any more data till we tell
+otherwise.  This helps in guests continuing to run normally while the vq
+keeps getting full and eventually the guest stops queueing more data.
+As soon as the chardev indicates it can accept more data, start pushing!
+
+Signed-off-by: Amit Shah <amit.shah@redhat.com>
+Signed-off-by: Cole Robinson <crobinso@redhat.com>
+---
+ hw/virtio-console.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/hw/virtio-console.c b/hw/virtio-console.c
+index 066590c..2b5e515 100644
+--- a/hw/virtio-console.c
++++ b/hw/virtio-console.c
+@@ -20,6 +20,16 @@ typedef struct VirtConsole {
+     CharDriverState *chr;
+ } VirtConsole;
+ 
++/*
++ * Callback function that's called from chardevs when backend becomes
++ * writable.
++ */
++static void chr_write_unblocked(void *opaque)
++{
++    VirtConsole *vcon = opaque;
++
++    virtio_serial_throttle_port(&vcon->port, false);
++}
+ 
+ /* Callback function that's called when the guest sends us data */
+ static ssize_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
+@@ -110,6 +120,7 @@ static const QemuChrHandlers chr_handlers = {
+     .fd_can_read = chr_can_read,
+     .fd_read = chr_read,
+     .fd_event = chr_event,
++    .fd_write_unblocked = chr_write_unblocked,
+ };
+ 
+ static int virtconsole_initfn(VirtIOSerialPort *port)
+-- 
+1.8.1
+
diff --git a/0109-spice-qemu-char.c-add-throttling.patch b/0109-spice-qemu-char.c-add-throttling.patch
new file mode 100644
index 0000000..0b9ffb1
--- /dev/null
+++ b/0109-spice-qemu-char.c-add-throttling.patch
@@ -0,0 +1,135 @@
+From 283c20975f9fb16afbd1e8ce733f474f5a978939 Mon Sep 17 00:00:00 2001
+From: Alon Levy <alevy@redhat.com>
+Date: Tue, 22 Mar 2011 12:27:59 +0200
+Subject: [PATCH] spice-qemu-char.c: add throttling
+
+BZ: 672191
+
+upstream: not submitted (explained below)
+
+Adds throttling support to spicevmc chardev. Uses a timer to avoid recursing:
+1. spice-server: reds.c:            read_from_vdi_port
+2. qemu:         spice-qemu-char.c: vmc_read
+3.                                  chr_write_unblocked
+                                (calls virtio_serial_throttle_port(port, false))
+4. qemu:         virtio ...
+5. qemu:         spice-qemu-char.c: spice_chr_write
+6. qemu:         spice-qemu-char.c: wakeup (calls into spice-server)
+7. spice-server: ...
+8. qemu:         spice-qemu-char.c: vmc_read
+
+Instead, in vmc_read if we were throttled and we are just about to return
+all the bytes we will set a timer to be triggered immediately to call
+chr_write_unblocked. Then we return after 2 above, and 3 is called from the
+timer callback. This also means we can later remove some ugly recursion protection
+from spice-server.
+
+The other tricky point in this patch is not returning the leftover chunk twice.
+When we throttle, by definition we have data that spice server didn't consume.
+It is being kept by virtio-serial, and by us. The next vmc_read callback needs
+to not return it, but just do unthrottling. Then virtio will give us the remaining
+chunk as usual in spice_chr_write, and we will pass it to spice server in the
+next vmc_read.
+
+This patch relies on Amit's series to expose throttling to chardev's, which
+was not accepted upstream, and will not be accepted upstream until the mainloop
+is reworked to use glib.
+
+Signed-off-by: Cole Robinson <crobinso@redhat.com>
+---
+ spice-qemu-char.c | 39 +++++++++++++++++++++++++++++++++++----
+ 1 file changed, 35 insertions(+), 4 deletions(-)
+
+diff --git a/spice-qemu-char.c b/spice-qemu-char.c
+index 09aa22d..fba2bfb 100644
+--- a/spice-qemu-char.c
++++ b/spice-qemu-char.c
+@@ -1,4 +1,6 @@
+ #include "config-host.h"
++#include "qemu-common.h"
++#include "qemu-timer.h"
+ #include "trace.h"
+ #include "ui/qemu-spice.h"
+ #include <spice.h>
+@@ -25,6 +27,7 @@ typedef struct SpiceCharDriver {
+     uint8_t               *datapos;
+     ssize_t               bufsize, datalen;
+     uint32_t              debug;
++    QEMUTimer             *unblock_timer;
+ } SpiceCharDriver;
+ 
+ static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
+@@ -50,6 +53,17 @@ static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
+     return out;
+ }
+ 
++static void spice_chr_unblock(void *opaque)
++{
++    SpiceCharDriver *scd = opaque;
++
++    if (scd->chr->chr_write_unblocked == NULL) {
++        dprintf(scd, 1, "%s: backend doesn't support unthrottling.\n", __func__);
++        return;
++    }
++    scd->chr->chr_write_unblocked(scd->chr->handler_opaque);
++}
++
+ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
+ {
+     SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
+@@ -61,9 +75,16 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
+         scd->datapos += bytes;
+         scd->datalen -= bytes;
+         assert(scd->datalen >= 0);
+-        if (scd->datalen == 0) {
+-            scd->datapos = 0;
+-        }
++    }
++    if (scd->datalen == 0 && scd->chr->write_blocked) {
++        dprintf(scd, 1, "%s: unthrottling (%d)\n", __func__, bytes);
++        scd->chr->write_blocked = false;
++        /*
++         * set a timer instead of calling scd->chr->chr_write_unblocked directly,
++         * because that will call back into spice_chr_write (see
++         * virtio-console.c:chr_write_unblocked), which is unwanted.
++         */
++        qemu_mod_timer(scd->unblock_timer, 0);
+     }
+     trace_spice_vmc_read(bytes, len);
+     return bytes;
+@@ -135,6 +156,7 @@ static void vmc_unregister_interface(SpiceCharDriver *scd)
+ static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+ {
+     SpiceCharDriver *s = chr->opaque;
++    int read_bytes;
+ 
+     dprintf(s, 2, "%s: %d\n", __func__, len);
+     vmc_register_interface(s);
+@@ -147,7 +169,15 @@ static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+     s->datapos = s->buffer;
+     s->datalen = len;
+     spice_server_char_device_wakeup(&s->sin);
+-    return len;
++    read_bytes = len - s->datalen;
++    if (read_bytes != len) {
++        dprintf(s, 1, "%s: throttling: %d < %d (%zd)\n", __func__,
++                read_bytes, len, s->bufsize);
++        s->chr->write_blocked = true;
++        /* We'll get passed in the unconsumed data with the next call */
++        s->datalen = 0;
++    }
++    return read_bytes;
+ }
+ 
+ static void spice_chr_close(struct CharDriverState *chr)
+@@ -225,6 +255,7 @@ CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
+     chr->chr_close = spice_chr_close;
+     chr->chr_guest_open = spice_chr_guest_open;
+     chr->chr_guest_close = spice_chr_guest_close;
++    s->unblock_timer = qemu_new_timer_ms(vm_clock, spice_chr_unblock, s);
+ 
+ #if SPICE_SERVER_VERSION < 0x000901
+     /* See comment in vmc_state() */
+-- 
+1.8.1
+
diff --git a/0109-spice-qemu-char.c-remove-intermediate-buffer.patch b/0109-spice-qemu-char.c-remove-intermediate-buffer.patch
deleted file mode 100644
index cde302e..0000000
--- a/0109-spice-qemu-char.c-remove-intermediate-buffer.patch
+++ /dev/null
@@ -1,76 +0,0 @@
-From 52b76076caf6f3f92b83a6f34b70417ddcd3d9d7 Mon Sep 17 00:00:00 2001
-Message-Id: <52b76076caf6f3f92b83a6f34b70417ddcd3d9d7.1354903384.git.crobinso@redhat.com>
-In-Reply-To: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com>
-References: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com>
-From: Alon Levy <alevy@redhat.com>
-Date: Tue, 22 Mar 2011 12:28:00 +0200
-Subject: [PATCH] spice-qemu-char.c: remove intermediate buffer
-
-BZ: 672191
-upstream: not submitted (explained below)
-
-virtio-serial's buffer is valid when it calls us, and we don't
-access it otherwise: vmc_read is only called in response to wakeup,
-or else we set datalen=0 and throttle. Then vmc_read is called back,
-we return 0 (not accessing the buffer) and set the timer to unthrottle.
-
-Also make datalen int and not ssize_t (to fit spice_chr_write signature).
-
-This relied on the previous patch that introduces throttling, which
-can't go upstream right now as explained in that patch.
-
-Signed-off-by: Cole Robinson <crobinso@redhat.com>
----
- spice-qemu-char.c | 18 ++++++------------
- 1 file changed, 6 insertions(+), 12 deletions(-)
-
-diff --git a/spice-qemu-char.c b/spice-qemu-char.c
-index fba2bfb..ef44bc0 100644
---- a/spice-qemu-char.c
-+++ b/spice-qemu-char.c
-@@ -23,9 +23,8 @@ typedef struct SpiceCharDriver {
-     SpiceCharDeviceInstance     sin;
-     char                  *subtype;
-     bool                  active;
--    uint8_t               *buffer;
--    uint8_t               *datapos;
--    ssize_t               bufsize, datalen;
-+    const uint8_t         *datapos;
-+    int                   datalen;
-     uint32_t              debug;
-     QEMUTimer             *unblock_timer;
- } SpiceCharDriver;
-@@ -69,7 +68,7 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
-     SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
-     int bytes = MIN(len, scd->datalen);
- 
--    dprintf(scd, 2, "%s: %p %d/%d/%zd\n", __func__, scd->datapos, len, bytes, scd->datalen);
-+    dprintf(scd, 2, "%s: %p %d/%d/%d\n", __func__, scd->datapos, len, bytes, scd->datalen);
-     if (bytes > 0) {
-         memcpy(buf, scd->datapos, bytes);
-         scd->datapos += bytes;
-@@ -161,18 +160,13 @@ static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
-     dprintf(s, 2, "%s: %d\n", __func__, len);
-     vmc_register_interface(s);
-     assert(s->datalen == 0);
--    if (s->bufsize < len) {
--        s->bufsize = len;
--        s->buffer = g_realloc(s->buffer, s->bufsize);
--    }
--    memcpy(s->buffer, buf, len);
--    s->datapos = s->buffer;
-+    s->datapos = buf;
-     s->datalen = len;
-     spice_server_char_device_wakeup(&s->sin);
-     read_bytes = len - s->datalen;
-     if (read_bytes != len) {
--        dprintf(s, 1, "%s: throttling: %d < %d (%zd)\n", __func__,
--                read_bytes, len, s->bufsize);
-+        dprintf(s, 1, "%s: throttling: %d < %d\n", __func__,
-+                read_bytes, len);
-         s->chr->write_blocked = true;
-         /* We'll get passed in the unconsumed data with the next call */
-         s->datalen = 0;
--- 
-1.8.0
-
diff --git a/0110-spice-qemu-char.c-remove-intermediate-buffer.patch b/0110-spice-qemu-char.c-remove-intermediate-buffer.patch
new file mode 100644
index 0000000..87a38f7
--- /dev/null
+++ b/0110-spice-qemu-char.c-remove-intermediate-buffer.patch
@@ -0,0 +1,73 @@
+From 445c0874a4fdc2195f2a2f8a4843377c88323153 Mon Sep 17 00:00:00 2001
+From: Alon Levy <alevy@redhat.com>
+Date: Tue, 22 Mar 2011 12:28:00 +0200
+Subject: [PATCH] spice-qemu-char.c: remove intermediate buffer
+
+BZ: 672191
+upstream: not submitted (explained below)
+
+virtio-serial's buffer is valid when it calls us, and we don't
+access it otherwise: vmc_read is only called in response to wakeup,
+or else we set datalen=0 and throttle. Then vmc_read is called back,
+we return 0 (not accessing the buffer) and set the timer to unthrottle.
+
+Also make datalen int and not ssize_t (to fit spice_chr_write signature).
+
+This relied on the previous patch that introduces throttling, which
+can't go upstream right now as explained in that patch.
+
+Signed-off-by: Cole Robinson <crobinso@redhat.com>
+---
+ spice-qemu-char.c | 18 ++++++------------
+ 1 file changed, 6 insertions(+), 12 deletions(-)
+
+diff --git a/spice-qemu-char.c b/spice-qemu-char.c
+index fba2bfb..ef44bc0 100644
+--- a/spice-qemu-char.c
++++ b/spice-qemu-char.c
+@@ -23,9 +23,8 @@ typedef struct SpiceCharDriver {
+     SpiceCharDeviceInstance     sin;
+     char                  *subtype;
+     bool                  active;
+-    uint8_t               *buffer;
+-    uint8_t               *datapos;
+-    ssize_t               bufsize, datalen;
++    const uint8_t         *datapos;
++    int                   datalen;
+     uint32_t              debug;
+     QEMUTimer             *unblock_timer;
+ } SpiceCharDriver;
+@@ -69,7 +68,7 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
+     SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
+     int bytes = MIN(len, scd->datalen);
+ 
+-    dprintf(scd, 2, "%s: %p %d/%d/%zd\n", __func__, scd->datapos, len, bytes, scd->datalen);
++    dprintf(scd, 2, "%s: %p %d/%d/%d\n", __func__, scd->datapos, len, bytes, scd->datalen);
+     if (bytes > 0) {
+         memcpy(buf, scd->datapos, bytes);
+         scd->datapos += bytes;
+@@ -161,18 +160,13 @@ static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+     dprintf(s, 2, "%s: %d\n", __func__, len);
+     vmc_register_interface(s);
+     assert(s->datalen == 0);
+-    if (s->bufsize < len) {
+-        s->bufsize = len;
+-        s->buffer = g_realloc(s->buffer, s->bufsize);
+-    }
+-    memcpy(s->buffer, buf, len);
+-    s->datapos = s->buffer;
++    s->datapos = buf;
+     s->datalen = len;
+     spice_server_char_device_wakeup(&s->sin);
+     read_bytes = len - s->datalen;
+     if (read_bytes != len) {
+-        dprintf(s, 1, "%s: throttling: %d < %d (%zd)\n", __func__,
+-                read_bytes, len, s->bufsize);
++        dprintf(s, 1, "%s: throttling: %d < %d\n", __func__,
++                read_bytes, len);
+         s->chr->write_blocked = true;
+         /* We'll get passed in the unconsumed data with the next call */
+         s->datalen = 0;
+-- 
+1.8.1
+
diff --git a/0110-usb-redir-Add-flow-control-support.patch b/0110-usb-redir-Add-flow-control-support.patch
deleted file mode 100644
index 90a6522..0000000
--- a/0110-usb-redir-Add-flow-control-support.patch
+++ /dev/null
@@ -1,69 +0,0 @@
-From 4e6a76dd0e35b00e9592a53afc8cffac4cc35951 Mon Sep 17 00:00:00 2001
-Message-Id: <4e6a76dd0e35b00e9592a53afc8cffac4cc35951.1354903384.git.crobinso@redhat.com>
-In-Reply-To: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com>
-References: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com>
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Tue, 19 Jul 2011 10:56:19 +0200
-Subject: [PATCH] usb-redir: Add flow control support
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-Signed-off-by: Cole Robinson <crobinso@redhat.com>
----
- hw/usb/redirect.c | 22 ++++++++++++++++++++--
- 1 file changed, 20 insertions(+), 2 deletions(-)
-
-diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
-index c921d2d..dfb1773 100644
---- a/hw/usb/redirect.c
-+++ b/hw/usb/redirect.c
-@@ -239,8 +239,9 @@ static int usbredir_read(void *priv, uint8_t *data, int count)
- static int usbredir_write(void *priv, uint8_t *data, int count)
- {
-     USBRedirDevice *dev = priv;
-+    int r;
- 
--    if (!dev->cs->opened) {
-+    if (!dev->cs->opened || dev->cs->write_blocked) {
-         return 0;
-     }
- 
-@@ -249,7 +250,16 @@ static int usbredir_write(void *priv, uint8_t *data, int count)
-         return 0;
-     }
- 
--    return qemu_chr_fe_write(dev->cs, data, count);
-+    r = qemu_chr_fe_write(dev->cs, data, count);
-+
-+    if (r < 0) {
-+        if (dev->cs->write_blocked) {
-+           return 0;
-+        }
-+        return -1;
-+    }
-+
-+    return r;
- }
- 
- /*
-@@ -1037,10 +1047,18 @@ static void usbredir_chardev_event(void *opaque, int event)
-     }
- }
- 
-+static void usbredir_chardev_write_unblocked(void *opaque)
-+{
-+    USBRedirDevice *dev = opaque;
-+
-+    usbredirparser_do_write(dev->parser);
-+}
-+
- static const QemuChrHandlers usbredir_chr_handlers = {
-     .fd_can_read = usbredir_chardev_can_read,
-     .fd_read = usbredir_chardev_read,
-     .fd_event = usbredir_chardev_event,
-+    .fd_write_unblocked = usbredir_chardev_write_unblocked,
- };
- 
- /*
--- 
-1.8.0
-
diff --git a/0111-char-Disable-write-callback-if-throttled-chardev-is-.patch b/0111-char-Disable-write-callback-if-throttled-chardev-is-.patch
deleted file mode 100644
index cfa9567..0000000
--- a/0111-char-Disable-write-callback-if-throttled-chardev-is-.patch
+++ /dev/null
@@ -1,40 +0,0 @@
-From 736b3ad749e5c60de44d4c5836b59d2287b6b918 Mon Sep 17 00:00:00 2001
-Message-Id: <736b3ad749e5c60de44d4c5836b59d2287b6b918.1354903384.git.crobinso@redhat.com>
-In-Reply-To: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com>
-References: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com>
-From: Amit Shah <amit.shah@redhat.com>
-Date: Fri, 2 Dec 2011 15:42:55 +0530
-Subject: [PATCH] char: Disable write callback if throttled chardev is
- detached
-
-If a throttled chardev is detached from the frontend device, all future
-callbacks should be suppressed.  Not doing this results in a segfault.
-
-Bugzilla: 745758
-Upstream: Not applicable, since throttling is a RHEL6-only feature.
-
-Signed-off-by: Amit Shah <amit.shah@redhat.com>
-Signed-off-by: Cole Robinson <crobinso@redhat.com>
----
- qemu-char.c | 5 +++++
- 1 file changed, 5 insertions(+)
-
-diff --git a/qemu-char.c b/qemu-char.c
-index 5c71f0c..16ad6b6 100644
---- a/qemu-char.c
-+++ b/qemu-char.c
-@@ -224,6 +224,11 @@ void qemu_chr_add_handlers(CharDriverState *s,
-         ++s->avail_connections;
-     }
-     if (!handlers) {
-+        if (s->write_blocked) {
-+            /* Ensure we disable the callback if we were throttled */
-+            s->chr_disable_write_fd_handler(s);
-+            /* s->write_blocked is cleared below */
-+        }
-         handlers = &null_handlers;
-     }
-     s->chr_can_read = handlers->fd_can_read;
--- 
-1.8.0
-
diff --git a/0111-usb-redir-Add-flow-control-support.patch b/0111-usb-redir-Add-flow-control-support.patch
new file mode 100644
index 0000000..bbbdaec
--- /dev/null
+++ b/0111-usb-redir-Add-flow-control-support.patch
@@ -0,0 +1,65 @@
+From 8f9c374199cd82c5364d8f759cd23f2f17f2911f Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Tue, 19 Jul 2011 10:56:19 +0200
+Subject: [PATCH] usb-redir: Add flow control support
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ hw/usb/redirect.c | 22 ++++++++++++++++++++--
+ 1 file changed, 20 insertions(+), 2 deletions(-)
+
+diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
+index c921d2d..56c3c24 100644
+--- a/hw/usb/redirect.c
++++ b/hw/usb/redirect.c
+@@ -239,8 +239,9 @@ static int usbredir_read(void *priv, uint8_t *data, int count)
+ static int usbredir_write(void *priv, uint8_t *data, int count)
+ {
+     USBRedirDevice *dev = priv;
++    int r;
+ 
+-    if (!dev->cs->opened) {
++    if (!dev->cs->opened || dev->cs->write_blocked) {
+         return 0;
+     }
+ 
+@@ -249,7 +250,16 @@ static int usbredir_write(void *priv, uint8_t *data, int count)
+         return 0;
+     }
+ 
+-    return qemu_chr_fe_write(dev->cs, data, count);
++    r = qemu_chr_fe_write(dev->cs, data, count);
++
++    if (r < 0) {
++        if (dev->cs->write_blocked) {
++           return 0;
++        }
++        return -1;
++    }
++
++    return r;
+ }
+ 
+ /*
+@@ -1037,10 +1047,18 @@ static void usbredir_chardev_event(void *opaque, int event)
+     }
+ }
+ 
++static void usbredir_chardev_write_unblocked(void *opaque)
++{
++    USBRedirDevice *dev = opaque;
++
++    usbredirparser_do_write(dev->parser);
++}
++
+ static const QemuChrHandlers usbredir_chr_handlers = {
+     .fd_can_read = usbredir_chardev_can_read,
+     .fd_read = usbredir_chardev_read,
+     .fd_event = usbredir_chardev_event,
++    .fd_write_unblocked = usbredir_chardev_write_unblocked,
+ };
+ 
+ /*
+-- 
+1.8.1
+
diff --git a/0112-char-Disable-write-callback-if-throttled-chardev-is-.patch b/0112-char-Disable-write-callback-if-throttled-chardev-is-.patch
new file mode 100644
index 0000000..4722f36
--- /dev/null
+++ b/0112-char-Disable-write-callback-if-throttled-chardev-is-.patch
@@ -0,0 +1,36 @@
+From 824da34c4d46c0e7707198dc0c4714a5ab775251 Mon Sep 17 00:00:00 2001
+From: Amit Shah <amit.shah@redhat.com>
+Date: Fri, 2 Dec 2011 15:42:55 +0530
+Subject: [PATCH] char: Disable write callback if throttled chardev is detached
+
+If a throttled chardev is detached from the frontend device, all future
+callbacks should be suppressed.  Not doing this results in a segfault.
+
+Bugzilla: 745758
+Upstream: Not applicable, since throttling is a RHEL6-only feature.
+
+Signed-off-by: Amit Shah <amit.shah@redhat.com>
+Signed-off-by: Cole Robinson <crobinso@redhat.com>
+---
+ qemu-char.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/qemu-char.c b/qemu-char.c
+index 5c71f0c..16ad6b6 100644
+--- a/qemu-char.c
++++ b/qemu-char.c
+@@ -224,6 +224,11 @@ void qemu_chr_add_handlers(CharDriverState *s,
+         ++s->avail_connections;
+     }
+     if (!handlers) {
++        if (s->write_blocked) {
++            /* Ensure we disable the callback if we were throttled */
++            s->chr_disable_write_fd_handler(s);
++            /* s->write_blocked is cleared below */
++        }
+         handlers = &null_handlers;
+     }
+     s->chr_can_read = handlers->fd_can_read;
+-- 
+1.8.1
+
diff --git a/0112-hw-virtio-serial-bus-replay-guest-open-on-destinatio.patch b/0112-hw-virtio-serial-bus-replay-guest-open-on-destinatio.patch
deleted file mode 100644
index 0247ec7..0000000
--- a/0112-hw-virtio-serial-bus-replay-guest-open-on-destinatio.patch
+++ /dev/null
@@ -1,57 +0,0 @@
-From 1f54fab0e8f692986254b69c607f4151d9743260 Mon Sep 17 00:00:00 2001
-Message-Id: <1f54fab0e8f692986254b69c607f4151d9743260.1354903384.git.crobinso@redhat.com>
-In-Reply-To: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com>
-References: <9f0944a25bc1094fa7a74ac9df14e184e2c5c82d.1354903384.git.crobinso@redhat.com>
-From: Alon Levy <alevy@redhat.com>
-Date: Fri, 16 Nov 2012 16:24:47 +0200
-Subject: [PATCH] hw/virtio-serial-bus: replay guest open on destination
-
-This is rewrite of a patch carried in Fedora previously based
-on new code upstream, here is the original message, it still applies:
-(the original fedora patch was commit id
-a9bc20afc1f0604ee81c23b7c67d627e51d2e8d4, this is useful for grepping in
-logs, it isn't in upstream)
-
-When migrating a host with with a spice agent running the mouse becomes
-non operational after the migration. This is rhbz #725965.
-
-The problem is that after migration spice doesn't know the guest agent
-is open.  Spice is just a char dev here. And a chardev cannot query it's
-device, the device has to let the chardev know when it is open. Right
-now after migration the chardev which is recreated is in it's default
-state, which assumes the guest is disconnected.
-
-Char devices carry no information across migration, but the
-virtio-serial does already carry the guest_connected state. This patch
-passes that bit to the chardev.
----
- hw/virtio-serial-bus.c | 6 ++++++
- 1 file changed, 6 insertions(+)
-
-diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
-index 155da58..fd19984 100644
---- a/hw/virtio-serial-bus.c
-+++ b/hw/virtio-serial-bus.c
-@@ -641,6 +641,7 @@ static void virtio_serial_post_load_timer_cb(void *opaque)
-     VirtIOSerial *s = opaque;
-     VirtIOSerialPort *port;
-     uint8_t host_connected;
-+    VirtIOSerialPortClass *vsc;
- 
-     for (i = 0 ; i < s->post_load.nr_active_ports; ++i) {
-         port = s->post_load.connected[i].port;
-@@ -653,6 +654,11 @@ static void virtio_serial_post_load_timer_cb(void *opaque)
-             send_control_event(port, VIRTIO_CONSOLE_PORT_OPEN,
-                                port->host_connected);
-         }
-+        vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
-+        if (port->guest_connected && vsc->guest_open) {
-+            /* replay guest open */
-+            vsc->guest_open(port);
-+        }
-     }
-     g_free(s->post_load.connected);
-     s->post_load.connected = NULL;
--- 
-1.8.0
-
diff --git a/0113-hw-virtio-serial-bus-replay-guest-open-on-destinatio.patch b/0113-hw-virtio-serial-bus-replay-guest-open-on-destinatio.patch
new file mode 100644
index 0000000..42a73fd
--- /dev/null
+++ b/0113-hw-virtio-serial-bus-replay-guest-open-on-destinatio.patch
@@ -0,0 +1,54 @@
+From ab88ff277044974715aab3fd88b168c00605d193 Mon Sep 17 00:00:00 2001
+From: Alon Levy <alevy@redhat.com>
+Date: Fri, 16 Nov 2012 16:24:47 +0200
+Subject: [PATCH] hw/virtio-serial-bus: replay guest open on destination
+
+This is rewrite of a patch carried in Fedora previously based
+on new code upstream, here is the original message, it still applies:
+(the original fedora patch was commit id
+a9bc20afc1f0604ee81c23b7c67d627e51d2e8d4, this is useful for grepping in
+logs, it isn't in upstream)
+
+When migrating a host with with a spice agent running the mouse becomes
+non operational after the migration. This is rhbz #725965.
+
+The problem is that after migration spice doesn't know the guest agent
+is open.  Spice is just a char dev here. And a chardev cannot query it's
+device, the device has to let the chardev know when it is open. Right
+now after migration the chardev which is recreated is in it's default
+state, which assumes the guest is disconnected.
+
+Char devices carry no information across migration, but the
+virtio-serial does already carry the guest_connected state. This patch
+passes that bit to the chardev.
+---
+ hw/virtio-serial-bus.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
+index 155da58..fd19984 100644
+--- a/hw/virtio-serial-bus.c
++++ b/hw/virtio-serial-bus.c
+@@ -641,6 +641,7 @@ static void virtio_serial_post_load_timer_cb(void *opaque)
+     VirtIOSerial *s = opaque;
+     VirtIOSerialPort *port;
+     uint8_t host_connected;
++    VirtIOSerialPortClass *vsc;
+ 
+     for (i = 0 ; i < s->post_load.nr_active_ports; ++i) {
+         port = s->post_load.connected[i].port;
+@@ -653,6 +654,11 @@ static void virtio_serial_post_load_timer_cb(void *opaque)
+             send_control_event(port, VIRTIO_CONSOLE_PORT_OPEN,
+                                port->host_connected);
+         }
++        vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
++        if (port->guest_connected && vsc->guest_open) {
++            /* replay guest open */
++            vsc->guest_open(port);
++        }
+     }
+     g_free(s->post_load.connected);
+     s->post_load.connected = NULL;
+-- 
+1.8.1
+
diff --git a/qemu.spec b/qemu.spec
index 2302acd..4432977 100644
--- a/qemu.spec
+++ b/qemu.spec
@@ -120,7 +120,7 @@
 Summary: QEMU is a FAST! processor emulator
 Name: qemu
 Version: 1.3.0
-Release: 2%{?dist}
+Release: 3%{?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
@@ -137,25 +137,31 @@ ExclusiveArch: %{kvm_archs}
 %endif
 
 Source0: http://wiki.qemu-project.org/download/%{name}-%{version}.tar.bz2
-# libcacard build fixes (heading upstream)
-Patch1: 0000-libcacard-fix-missing-symbols-in-libcacard.so.patch
-Patch2: 0001-configure-move-vscclient-binary-under-libcacard.patch
-# Fix migration from qemu-kvm 1.2 to qemu 1.3
-Patch3: 0002-Fix-migration-from-qemu-kvm-1.2.patch
+# libcacard build fixes (upstream)
+Patch0001: 0001-libcacard-fix-missing-symbols-in-libcacard.so.patch
+Patch0002: 0002-configure-move-vscclient-binary-under-libcacard.patch
+
+# Fix test suite on i686 (patch heading upstream)
+Patch0003: 0003-rtc-test-skip-year-2038-overflow-check-in-case-time_.patch
+
+# Fix migration from qemu-kvm 1.2 to qemu 1.3 (non-upstream)
+Patch0004: 0004-Fix-migration-compat-with-qemu-kvm.patch
+
 # Flow control series
-Patch4: 0100-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch
-Patch5: 0101-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch
-Patch6: 0102-iohandlers-Add-enable-disable_write_fd_handler-funct.patch
-Patch7: 0103-char-Add-framework-for-a-write-unblocked-callback.patch
-Patch8: 0104-char-Update-send_all-to-handle-nonblocking-chardev-w.patch
-Patch9: 0105-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch
-Patch10: 0106-char-Throttle-when-host-connection-is-down.patch
-Patch11: 0107-virtio-console-Enable-port-throttling-when-chardev-i.patch
-Patch12: 0108-spice-qemu-char.c-add-throttling.patch
-Patch13: 0109-spice-qemu-char.c-remove-intermediate-buffer.patch
-Patch14: 0110-usb-redir-Add-flow-control-support.patch
-Patch15: 0111-char-Disable-write-callback-if-throttled-chardev-is-.patch
-Patch16: 0112-hw-virtio-serial-bus-replay-guest-open-on-destinatio.patch
+Patch0101: 0101-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch
+Patch0102: 0102-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch
+Patch0103: 0103-iohandlers-Add-enable-disable_write_fd_handler-funct.patch
+Patch0104: 0104-char-Add-framework-for-a-write-unblocked-callback.patch
+Patch0105: 0105-char-Update-send_all-to-handle-nonblocking-chardev-w.patch
+Patch0106: 0106-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch
+Patch0107: 0107-char-Throttle-when-host-connection-is-down.patch
+Patch0108: 0108-virtio-console-Enable-port-throttling-when-chardev-i.patch
+Patch0109: 0109-spice-qemu-char.c-add-throttling.patch
+Patch0110: 0110-spice-qemu-char.c-remove-intermediate-buffer.patch
+Patch0111: 0111-usb-redir-Add-flow-control-support.patch
+Patch0112: 0112-char-Disable-write-callback-if-throttled-chardev-is-.patch
+Patch0113: 0113-hw-virtio-serial-bus-replay-guest-open-on-destinatio.patch
+
 
 Source1: qemu.binfmt
 
@@ -362,24 +368,13 @@ with the host over a virtio-serial channel named "org.qemu.guest_agent.0"
 This package does not need to be installed on the host OS.
 
 %post guest-agent
-if [ $1 -eq 1 ] ; then
-    # Initial installation.
-    /bin/systemctl daemon-reload >/dev/null 2>&1 || :
-fi
+%systemd_post qemu-guest-agent.service
 
 %preun guest-agent
-if [ $1 -eq 0 ] ; then
-    # Package removal, not upgrade.
-    /bin/systemctl stop qemu-guest-agent.service > /dev/null 2>&1 || :
-fi
+%systemd_preun qemu-guest-agent.service
 
 %postun guest-agent
-/bin/systemctl daemon-reload >/dev/null 2>&1 || :
-if [ $1 -ge 1 ] ; then
-    # Package upgrade, not uninstall.
-    /bin/systemctl try-restart qemu-guest-agent.service >/dev/null 2>&1 || :
-fi
-
+%systemd_postun_with_restart qemu-guest-agent.service
 
 
 %if 0%{?user:1}
@@ -626,22 +621,31 @@ CAC emulation development files.
 
 %prep
 %setup -q
-%patch1 -p1
-%patch2 -p1
-%patch3 -p1
-%patch4 -p1
-%patch5 -p1
-%patch6 -p1
-%patch7 -p1
-%patch8 -p1
-%patch9 -p1
-%patch10 -p1
-%patch11 -p1
-%patch12 -p1
-%patch13 -p1
-%patch14 -p1
-%patch15 -p1
-%patch16 -p1
+# libcacard build fixes (upstream)
+%patch0001 -p1
+%patch0002 -p1
+
+# Fix test suite on i686 (patch heading upstream)
+%patch0003 -p1
+
+# Fix migration from qemu-kvm 1.2 to qemu 1.3 (non-upstream)
+%patch0004 -p1
+
+# Flow control series
+%patch0101 -p1
+%patch0102 -p1
+%patch0103 -p1
+%patch0104 -p1
+%patch0105 -p1
+%patch0106 -p1
+%patch0107 -p1
+%patch0108 -p1
+%patch0109 -p1
+%patch0110 -p1
+%patch0111 -p1
+%patch0112 -p1
+%patch0113 -p1
+
 
 
 %build
@@ -681,13 +685,19 @@ dobuild() {
         --sysconfdir=%{_sysconfdir} \
         --interp-prefix=%{_prefix}/qemu-%%M \
         --audio-drv-list=pa,sdl,alsa,oss \
+        --localstatedir=%{_localstatedir} \
+        --libexecdir=%{_libexecdir} \
         --disable-strip \
         --extra-ldflags="$extraldflags -pie -Wl,-z,relro -Wl,-z,now" \
         --extra-cflags="%{optflags} -fPIE -DPIE" \
+        --enable-mixemu \
+        --enable-trace-backend=dtrace \
+        --disable-werror \
+        --disable-xen \
+        --enable-kvm \
 %if 0%{?have_spice:1}
         --enable-spice \
 %endif
-        --enable-mixemu \
 %if 0%{?have_seccomp:1}
         --enable-seccomp \
 %endif
@@ -699,10 +709,6 @@ dobuild() {
 %else
         --disable-fdt \
 %endif
-        --enable-trace-backend=dtrace \
-        --disable-werror \
-        --disable-xen \
-        --enable-kvm \
         "$@"
 
     echo "config-host.mak contents:"
@@ -903,14 +909,9 @@ make %{?_smp_mflags} $buildldflags DESTDIR=$RPM_BUILD_ROOT install-libcacard
 find $RPM_BUILD_ROOT -name '*.la' -or -name '*.a' | xargs rm -f
 find $RPM_BUILD_ROOT -name "libcacard.so*" -exec chmod +x \{\} \;
 
-%check
-# qemu 1.3 tests fail on i686:
-# GTESTER check-qtest-i386
-# **
-# ERROR:tests/rtc-test.c:209:set_year_20xx: assertion failed (cmos_read(RTC_HOURS) == 0x02): (25 == 2)
-# GTester: last random seed: R02S3c33904d728a7716fb49ee76edbb6e40
 
-#make check
+%check
+make check
 
 %ifarch %{kvm_archs}
 %post %{kvm_package}
@@ -920,13 +921,11 @@ sh %{_sysconfdir}/sysconfig/modules/kvm.modules || :
 udevadm trigger --sysname-match=kvm || :
 %endif
 
+
 %if %{without separate_kvm}
 %post common
-if [ $1 -eq 1 ] ; then
-    # Initial installation
-    /bin/systemctl enable ksm.service >/dev/null 2>&1 || :
-    /bin/systemctl enable ksmtuned.service >/dev/null 2>&1 || :
-fi
+%systemd_post ksm.service
+%systemd_post ksmtuned.service
 
 getent group kvm >/dev/null || groupadd -g 36 -r kvm
 getent group qemu >/dev/null || groupadd -g 107 -r qemu
@@ -934,22 +933,15 @@ getent passwd qemu >/dev/null || \
   useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \
     -c "qemu user" qemu
 
+
 %preun common
-if [ $1 -eq 0 ] ; then
-    # Package removal, not upgrade
-    /bin/systemctl --no-reload disable ksmtuned.service > /dev/null 2>&1 || :
-    /bin/systemctl --no-reload disable ksm.service > /dev/null 2>&1 || :
-    /bin/systemctl stop ksmtuned.service > /dev/null 2>&1 || :
-    /bin/systemctl stop ksm.service > /dev/null 2>&1 || :
-fi
+%systemd_preun ksm.service
+%systemd_preun ksmtuned.service
+
 
 %postun common
-/bin/systemctl daemon-reload >/dev/null 2>&1 || :
-if [ $1 -ge 1 ] ; then
-    # Package upgrade, not uninstall
-    /bin/systemctl try-restart ksmtuned.service >/dev/null 2>&1 || :
-    /bin/systemctl try-restart ksm.service >/dev/null 2>&1 || :
-fi
+%systemd_postun_with_restart ksm.service
+%systemd_postun_with_restart ksmtuned.service
 %endif
 
 
@@ -1266,6 +1258,11 @@ fi
 %{_libdir}/pkgconfig/libcacard.pc
 
 %changelog
+* Tue Jan 15 2013 Cole Robinson <crobinso@redhat.com> - 2:1.3.0-3
+- Fix migration from qemu-kvm
+- Fix the test suite on i686
+- Use systemd macros in specfile (bz #850285)
+
 * Tue Jan 15 2013 Hans de Goede <hdegoede@redhat.com> - 2:1.3.0-2
 - Fix 0110-usb-redir-Add-flow-control-support.patch being mangled on rebase
   to 1.3.0, breaking usbredir support