From b290f1c10550dba848417b7ba7d3f8631c06bf7a Mon Sep 17 00:00:00 2001
From: Amit Shah <amit.shah@redhat.com>
Date: Mon, 20 Sep 2010 08:12:58 -0300
Subject: [RHEL6 qemu-kvm PATCH 11/16] virtio-serial: Cleanup on device hot-unplug

RH-Author: Amit Shah <amit.shah@redhat.com>
Message-id: <0812c72ec3e5b474585eb1278b1afd97a870dd29.1284967504.git.amit.shah@redhat.com>
Patchwork-id: 12178
O-Subject: [RHEL 6.1 PATCH 4/4] virtio-serial: Cleanup on device hot-unplug
Bugzilla: 624396
RH-Acked-by: Markus Armbruster <armbru@redhat.com>
RH-Acked-by: Alex Williamson <alex.williamson@redhat.com>
RH-Acked-by: Jes Sorensen <Jes.Sorensen@redhat.com>

Free malloc'ed memory, unregister from savevm and clean up virtio-common
bits on device hot-unplug.

This was found performing a migration after device hot-unplug.

Bugzilla: 624396

Reported-by: <lihuang@redhat.com>
Signed-off-by: Amit Shah <amit.shah@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 8b53a865772789a3402a44aa80169f8dd728eba2)

Signed-off-by: Amit Shah <amit.shah@redhat.com>
---
 hw/virtio-pci.c        |   10 +++++++++-
 hw/virtio-serial-bus.c |   17 +++++++++++++++++
 hw/virtio.h            |    1 +
 3 files changed, 27 insertions(+), 1 deletions(-)

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 hw/virtio-pci.c        |   10 +++++++++-
 hw/virtio-serial-bus.c |   17 +++++++++++++++++
 hw/virtio.h            |    1 +
 3 files changed, 27 insertions(+), 1 deletions(-)

diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 5101541..35768d3 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -630,6 +630,14 @@ static int virtio_serial_init_pci(PCIDevice *pci_dev)
     return 0;
 }
 
+static int virtio_serial_exit_pci(PCIDevice *pci_dev)
+{
+    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
+
+    virtio_serial_exit(proxy->vdev);
+    return virtio_exit_pci(pci_dev);
+}
+
 static int virtio_net_init_pci(PCIDevice *pci_dev)
 {
     VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
@@ -708,7 +716,7 @@ static PCIDeviceInfo virtio_info[] = {
         .qdev.alias = "virtio-serial",
         .qdev.size = sizeof(VirtIOPCIProxy),
         .init      = virtio_serial_init_pci,
-        .exit      = virtio_exit_pci,
+        .exit      = virtio_serial_exit_pci,
         .qdev.props = (Property[]) {
             DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors,
                                DEV_NVECTORS_UNSPECIFIED),
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index cb6191d..7d10415 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -41,6 +41,8 @@ struct VirtIOSerial {
 
     VirtIOSerialBus *bus;
 
+    DeviceState *qdev;
+
     QTAILQ_HEAD(, VirtIOSerialPort) ports;
 
     /* bitmap for identifying active ports */
@@ -799,6 +801,8 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, uint32_t max_nr_ports)
     vser->vdev.get_config = get_config;
     vser->vdev.set_config = set_config;
 
+    vser->qdev = dev;
+
     /*
      * Register for the savevm section with the virtio-console name
      * to preserve backward compat
@@ -808,3 +812,16 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, uint32_t max_nr_ports)
 
     return vdev;
 }
+
+void virtio_serial_exit(VirtIODevice *vdev)
+{
+    VirtIOSerial *vser = DO_UPCAST(VirtIOSerial, vdev, vdev);
+
+    unregister_savevm(vser->qdev, "virtio-console", vser);
+
+    qemu_free(vser->ivqs);
+    qemu_free(vser->ovqs);
+    qemu_free(vser->ports_map);
+
+    virtio_cleanup(vdev);
+}
diff --git a/hw/virtio.h b/hw/virtio.h
index c358b27..5532dcf 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -193,6 +193,7 @@ VirtIODevice *virtio_balloon_init(DeviceState *dev);
 
 void virtio_net_exit(VirtIODevice *vdev);
 void virtio_blk_exit(VirtIODevice *vdev);
+void virtio_serial_exit(VirtIODevice *vdev);
 
 #define DEFINE_VIRTIO_COMMON_FEATURES(_state, _field) \
 	DEFINE_PROP_BIT("indirect_desc", _state, _field, \
-- 
1.6.5.5

