diff options
author | Jack F Vogel <jfv@FreeBSD.org> | 2007-11-26 19:47:03 +0000 |
---|---|---|
committer | Jack F Vogel <jfv@FreeBSD.org> | 2007-11-26 19:47:03 +0000 |
commit | abcc80c87a6723358ffc3320ee6283832bc0eba9 (patch) | |
tree | 7ec7c69e1c426977e178213e231c2c482918d0aa /sys/dev/em/if_em.c | |
parent | 91b4ff52c76a257a994f72cc45a8b669ca04ec75 (diff) | |
download | src-abcc80c87a6723358ffc3320ee6283832bc0eba9.tar.gz src-abcc80c87a6723358ffc3320ee6283832bc0eba9.zip |
Fix for a reported panic in certain circumstances. When
calling em_stop() now make sure the TX lock is held as
well as CORE.
Notes
Notes:
svn path=/head/; revision=173952
Diffstat (limited to 'sys/dev/em/if_em.c')
-rw-r--r-- | sys/dev/em/if_em.c | 19 |
1 files changed, 17 insertions, 2 deletions
diff --git a/sys/dev/em/if_em.c b/sys/dev/em/if_em.c index 88cf57a537b1..2dedfdb55e14 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"); |