qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [patch v4 12/16] e1000: apply fine lock on e1000


From: Liu Ping Fan
Subject: [Qemu-devel] [patch v4 12/16] e1000: apply fine lock on e1000
Date: Mon, 22 Oct 2012 17:23:55 +0800

Use local lock to protect e1000. When calling the system function,
dropping the fine lock before acquiring the big lock. This will
introduce broken device state, which need extra effort to fix.

Signed-off-by: Liu Ping Fan <address@hidden>
---
 hw/e1000.c |   24 +++++++++++++++++++++++-
 1 files changed, 23 insertions(+), 1 deletions(-)

diff --git a/hw/e1000.c b/hw/e1000.c
index ae8a6c5..5eddab5 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -85,6 +85,7 @@ typedef struct E1000State_st {
     NICConf conf;
     MemoryRegion mmio;
     MemoryRegion io;
+    QemuMutex e1000_lock;
 
     uint32_t mac_reg[0x8000];
     uint16_t phy_reg[0x20];
@@ -223,13 +224,27 @@ static const uint32_t mac_reg_init[] = {
 static void
 set_interrupt_cause(E1000State *s, int index, uint32_t val)
 {
+    QemuThread *t;
+
     if (val && (E1000_DEVID >= E1000_DEV_ID_82547EI_MOBILE)) {
         /* Only for 8257x */
         val |= E1000_ICR_INT_ASSERTED;
     }
     s->mac_reg[ICR] = val;
     s->mac_reg[ICS] = val;
-    qemu_set_irq(s->dev.irq[0], (s->mac_reg[IMS] & s->mac_reg[ICR]) != 0);
+
+    t = pthread_getspecific(qemu_thread_key);
+    if (t->context_type == 1) {
+        qemu_mutex_unlock(&s->e1000_lock);
+        qemu_mutex_lock_iothread();
+    }
+    if (DEVICE(s)->state < DEV_STATE_STOPPING) {
+        qemu_set_irq(s->dev.irq[0], (s->mac_reg[IMS] & s->mac_reg[ICR]) != 0);
+    }
+    if (t->context_type == 1) {
+        qemu_mutex_unlock_iothread();
+        qemu_mutex_lock(&s->e1000_lock);
+    }
 }
 
 static void
@@ -268,6 +283,7 @@ static void e1000_reset(void *opaque)
     E1000State *d = opaque;
 
     qemu_del_timer(d->autoneg_timer);
+
     memset(d->phy_reg, 0, sizeof d->phy_reg);
     memmove(d->phy_reg, phy_reg_init, sizeof phy_reg_init);
     memset(d->mac_reg, 0, sizeof d->mac_reg);
@@ -448,7 +464,11 @@ e1000_send_packet(E1000State *s, const uint8_t *buf, int 
size)
     if (s->phy_reg[PHY_CTRL] & MII_CR_LOOPBACK) {
         s->nic->nc.info->receive(&s->nic->nc, buf, size);
     } else {
+        qemu_mutex_unlock(&s->e1000_lock);
+        qemu_mutex_lock_iothread();
         qemu_send_packet(&s->nic->nc, buf, size);
+        qemu_mutex_unlock_iothread();
+        qemu_mutex_lock(&s->e1000_lock);
     }
 }
 
@@ -1221,6 +1241,8 @@ static int pci_e1000_init(PCIDevice *pci_dev)
     int i;
     uint8_t *macaddr;
 
+    qemu_mutex_init(&d->e1000_lock);
+
     pci_conf = d->dev.config;
 
     /* TODO: RST# value should be 0, PCI spec 6.2.4 */
-- 
1.7.4.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]