summaryrefslogtreecommitdiffstats
path: root/sys/dev/em/if_em.c
diff options
context:
space:
mode:
authorjfv <jfv@FreeBSD.org>2007-11-26 19:47:03 +0000
committerjfv <jfv@FreeBSD.org>2007-11-26 19:47:03 +0000
commitd397b858ba2633d10671f53553115361695b9c5f (patch)
tree7ec7c69e1c426977e178213e231c2c482918d0aa /sys/dev/em/if_em.c
parent17271746893e233ce3e2f4f489a4195a524f1eae (diff)
downloadFreeBSD-src-d397b858ba2633d10671f53553115361695b9c5f.zip
FreeBSD-src-d397b858ba2633d10671f53553115361695b9c5f.tar.gz
Fix for a reported panic in certain circumstances. When
calling em_stop() now make sure the TX lock is held as well as CORE.
Diffstat (limited to 'sys/dev/em/if_em.c')
-rw-r--r--sys/dev/em/if_em.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/sys/dev/em/if_em.c b/sys/dev/em/if_em.c
index 88cf57a..2dedfdb 100644
--- a/sys/dev/em/if_em.c
+++ b/sys/dev/em/if_em.c
@@ -803,6 +803,7 @@ em_detach(device_t dev)
em_disable_intr(adapter);
em_free_intr(adapter);
EM_CORE_LOCK(adapter);
+ EM_TX_LOCK(adapter);
adapter->in_detach = 1;
em_stop(adapter);
e1000_phy_hw_reset(&adapter->hw);
@@ -821,7 +822,6 @@ em_detach(device_t dev)
em_enable_wakeup(dev);
}
- EM_CORE_UNLOCK(adapter);
ether_ifdetach(adapter->ifp);
callout_drain(&adapter->timer);
@@ -834,6 +834,8 @@ em_detach(device_t dev)
e1000_remove_device(&adapter->hw);
em_free_transmit_structures(adapter);
em_free_receive_structures(adapter);
+ EM_TX_UNLOCK(adapter);
+ EM_CORE_UNLOCK(adapter);
/* Free Transmit Descriptor ring */
if (adapter->tx_desc_base) {
@@ -874,7 +876,10 @@ em_suspend(device_t dev)
struct adapter *adapter = device_get_softc(dev);
EM_CORE_LOCK(adapter);
+
+ EM_TX_LOCK(adapter);
em_stop(adapter);
+ EM_TX_UNLOCK(adapter);
em_release_manageability(adapter);
@@ -1082,8 +1087,11 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
} else
em_init_locked(adapter);
} else
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ EM_TX_LOCK(adapter);
em_stop(adapter);
+ EM_TX_UNLOCK(adapter);
+ }
adapter->if_flags = ifp->if_flags;
EM_CORE_UNLOCK(adapter);
break;
@@ -1241,7 +1249,9 @@ em_init_locked(struct adapter *adapter)
EM_CORE_LOCK_ASSERT(adapter);
+ EM_TX_LOCK(adapter);
em_stop(adapter);
+ EM_TX_UNLOCK(adapter);
/*
* Packet Buffer Allocation (PBA)
@@ -1349,7 +1359,9 @@ em_init_locked(struct adapter *adapter)
/* Prepare receive descriptors and buffers */
if (em_setup_receive_structures(adapter)) {
device_printf(dev, "Could not setup receive structures\n");
+ EM_TX_LOCK(adapter);
em_stop(adapter);
+ EM_TX_UNLOCK(adapter);
return;
}
em_initialize_receive_unit(adapter);
@@ -2527,6 +2539,8 @@ em_update_link_status(struct adapter *adapter)
* This routine disables all traffic on the adapter by issuing a
* global reset on the MAC and deallocates TX/RX buffers.
*
+ * This routine should always be called with BOTH the CORE
+ * and TX locks.
**********************************************************************/
static void
@@ -2536,6 +2550,7 @@ em_stop(void *arg)
struct ifnet *ifp = adapter->ifp;
EM_CORE_LOCK_ASSERT(adapter);
+ EM_TX_LOCK_ASSERT(adapter);
INIT_DEBUGOUT("em_stop: begin");
OpenPOWER on IntegriCloud