Patchwork [v4,15/16] e1000: introduce unmap() to fix unplug issue

login
register
mail settings
Submitter pingfank@linux.vnet.ibm.com
Date Oct. 22, 2012, 9:23 a.m.
Message ID <1350897839-29593-16-git-send-email-pingfank@linux.vnet.ibm.com>
Download mbox | patch
Permalink /patch/193193/
State New
Headers show

Comments

pingfank@linux.vnet.ibm.com - Oct. 22, 2012, 9:23 a.m.
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 <pingfank@linux.vnet.ibm.com>
---
 hw/e1000.c |   26 ++++++++++++++++++++++----
 1 files changed, 22 insertions(+), 4 deletions(-)

Patch

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;