From c5f051522192af7eae5f380882dd240a1aab9456 Mon Sep 17 00:00:00 2001 From: Mark McLoughlin <markmc@redhat.com> Date: Fri, 15 May 2009 13:00:45 +0100 Subject: [PATCH 15/16] Fix live migratation failure after pcnet NIC hot-unplug https://bugzilla.redhat.com/500981 pcnet registers a savevm handler which is not removed when the NIC is hot-unplugged. This patch just cherry-picks pci_pcnet_cleanup() from: http://git.kernel.org/?p=virt/kvm/qemu-kvm.git;a=commitdiff;h=a34b6eb776 Signed-off-by: Mark McLoughlin <markmc@redhat.com> Message-Id: <1242388845.25932.11.camel@blaa> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com> Bugzilla: 501729 RH-Upstream-status: applied(qemu-kvm/master) Depends: <1242387172.25932.5.camel@blaa> Depends: <1242387177.25932.6.camel@blaa> Acked-by: Eduardo Habkost <ehabkost@redhat.com> Acked-by: Kevin Wolf <kwolf@redhat.com> Acked-by: Juan Quintela <quintela@redhat.com> --- qemu/hw/pcnet.c | 33 ++++++++++++++++++++++++++++++--- 1 files changed, 30 insertions(+), 3 deletions(-) diff --git a/qemu/hw/pcnet.c b/qemu/hw/pcnet.c index f5bf15d..9dfc922 100644 --- a/qemu/hw/pcnet.c +++ b/qemu/hw/pcnet.c @@ -1929,7 +1929,15 @@ static int pcnet_load(QEMUFile *f, void *opaque, int version_id) return 0; } -static void pcnet_common_init(PCNetState *d, NICInfo *nd, const char *info_str) +static void pcnet_common_cleanup(PCNetState *d) +{ + unregister_savevm("pcnet", d); + + qemu_del_timer(d->poll_timer); + qemu_free_timer(d->poll_timer); +} + +static void pcnet_common_init(PCNetState *d, NICInfo *nd, const char *info_str, NetCleanup *cleanup) { d->poll_timer = qemu_new_timer(vm_clock, pcnet_poll_timer, d); @@ -1938,6 +1946,7 @@ static void pcnet_common_init(PCNetState *d, NICInfo *nd, const char *info_str) if (nd && nd->vlan) { d->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, pcnet_receive, pcnet_can_receive, d); + d->vc->cleanup = cleanup; qemu_format_nic_info_str(d->vc, d->nd->macaddr); } else { @@ -1985,6 +1994,22 @@ static void pci_physical_memory_read(void *dma_opaque, target_phys_addr_t addr, cpu_physical_memory_read(addr, buf, len); } +static void pci_pcnet_cleanup(VLANClientState *vc) +{ + PCNetState *d = vc->opaque; + + pcnet_common_cleanup(d); +} + +static int pci_pcnet_uninit(PCIDevice *dev) +{ + PCNetState *d = (PCNetState *)dev; + + cpu_unregister_io_memory(d->mmio_index); + + return 0; +} + PCIDevice *pci_pcnet_init(PCIBus *bus, NICInfo *nd, int devfn) { PCNetState *d; @@ -2000,6 +2025,8 @@ PCIDevice *pci_pcnet_init(PCIBus *bus, NICInfo *nd, int devfn) if (!d) return NULL; + d->dev.unregister = pci_pcnet_uninit; + pci_conf = d->dev.config; *(uint16_t *)&pci_conf[0x00] = cpu_to_le16(0x1022); @@ -2034,7 +2061,7 @@ PCIDevice *pci_pcnet_init(PCIBus *bus, NICInfo *nd, int devfn) d->phys_mem_write = pci_physical_memory_write; d->pci_dev = &d->dev; - pcnet_common_init(d, nd, "pcnet"); + pcnet_common_init(d, nd, "pcnet", pci_pcnet_cleanup); return (PCIDevice *)d; } @@ -2109,6 +2136,6 @@ void lance_init(NICInfo *nd, target_phys_addr_t leaddr, void *dma_opaque, d->phys_mem_read = ledma_memory_read; d->phys_mem_write = ledma_memory_write; - pcnet_common_init(d, nd, "lance"); + pcnet_common_init(d, nd, "lance", NULL); } #endif /* TARGET_SPARC */ -- 1.6.3.rc4.29.g8146