When device uninit(), we should ensure that it is not used by any subsystem. We can acheive this by two solution: 1.sync on big lock in uninit() function This is more easy, but it require that big lock can be recusive, because uninit() can be called by iothread or mmio-dispatch. 2.introduce unmap() as a sync point for all subsystem.
This patch adpots solotion 2. Signed-off-by: Liu Ping Fan <pingf...@linux.vnet.ibm.com> --- hw/e1000.c | 26 ++++++++++++++++++++++---- 1 files changed, 22 insertions(+), 4 deletions(-) diff --git a/hw/e1000.c b/hw/e1000.c index 0b4fce5..72c2324 100644 --- a/hw/e1000.c +++ b/hw/e1000.c @@ -168,7 +168,14 @@ set_phy_ctrl(E1000State *s, int index, uint16_t val) e1000_link_down(s); s->phy_reg[PHY_STATUS] &= ~MII_SR_AUTONEG_COMPLETE; DBGOUT(PHY, "Start link auto negotiation\n"); - qemu_mod_timer(s->autoneg_timer, qemu_get_clock_ms(vm_clock) + 500); + + qemu_mutex_unlock(&s->e1000_lock); + qemu_mutex_lock_iothread(); + if (DEVICE(s)->state < DEV_STATE_STOPPING) { + qemu_mod_timer(s->autoneg_timer, qemu_get_clock_ms(vm_clock) + 500); + } + qemu_mutex_unlock_iothread(); + qemu_mutex_lock(&s->e1000_lock); } } @@ -467,7 +474,9 @@ e1000_send_packet(E1000State *s, const uint8_t *buf, int size) } else { qemu_mutex_unlock(&s->e1000_lock); qemu_mutex_lock_iothread(); - qemu_send_packet(&s->nic->nc, buf, size); + if (DEVICE(s)->state < DEV_STATE_STOPPING) { + qemu_send_packet(&s->nic->nc, buf, size); + } qemu_mutex_unlock_iothread(); qemu_mutex_lock(&s->e1000_lock); } @@ -1221,6 +1230,16 @@ e1000_mmio_setup(E1000State *d) } static void +pci_e1000_unmap(PCIDevice *p) +{ + E1000State *d = DO_UPCAST(E1000State, dev, p); + + DEVICE(d)->state = DEV_STATE_STOPPING; + qemu_del_timer(d->autoneg_timer); + qemu_del_net_client(&d->nic->nc); +} + +static void e1000_cleanup(NetClientState *nc) { E1000State *s = DO_UPCAST(NICState, nc, nc)->opaque; @@ -1233,11 +1252,9 @@ pci_e1000_uninit(PCIDevice *dev) { E1000State *d = DO_UPCAST(E1000State, dev, dev); - qemu_del_timer(d->autoneg_timer); qemu_free_timer(d->autoneg_timer); memory_region_destroy(&d->mmio); memory_region_destroy(&d->io); - qemu_del_net_client(&d->nic->nc); } static NetClientInfo net_e1000_info = { @@ -1314,6 +1331,7 @@ static void e1000_class_init(ObjectClass *klass, void *data) k->init = pci_e1000_init; k->exit = pci_e1000_uninit; + k->unmap = pci_e1000_unmap; k->romfile = "pxe-e1000.rom"; k->vendor_id = PCI_VENDOR_ID_INTEL; k->device_id = E1000_DEVID; -- 1.7.4.4