diff options
author | Jesse Brandeburg <jesse.brandeburg@intel.com> | 2010-09-22 14:22:42 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-09-23 17:33:38 -0400 |
commit | 338c15e470d818f215d651505dc169d4e92f36a4 (patch) | |
tree | 90153c4c54f0b43ed48700a396db695d232f1878 /drivers/net/e1000 | |
parent | 5cf42fcda0fdddfe7f5ea8629cb7b820bf7e91ab (diff) |
e1000: fix occasional panic on unload
Net drivers in general have an issue where timers fired
by mod_timer or work threads with schedule_work are running
outside of the rtnl_lock.
With no other lock protection these routines are vulnerable
to races with driver unload or reset paths.
The longer term solution to this might be a redesign with
safer locks being taken in the driver to guarantee no
reentrance, but for now a safe and effective fix is
to take the rtnl_lock in these routines.
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Tested-by: Jeff Pieper <jeffrey.e.pieper@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/e1000')
-rw-r--r-- | drivers/net/e1000/e1000_main.c | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 5b4c6c061414..c88439deb7d8 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c | |||
@@ -521,8 +521,21 @@ void e1000_down(struct e1000_adapter *adapter) | |||
521 | e1000_clean_all_rx_rings(adapter); | 521 | e1000_clean_all_rx_rings(adapter); |
522 | } | 522 | } |
523 | 523 | ||
524 | void e1000_reinit_safe(struct e1000_adapter *adapter) | ||
525 | { | ||
526 | while (test_and_set_bit(__E1000_RESETTING, &adapter->flags)) | ||
527 | msleep(1); | ||
528 | rtnl_lock(); | ||
529 | e1000_down(adapter); | ||
530 | e1000_up(adapter); | ||
531 | rtnl_unlock(); | ||
532 | clear_bit(__E1000_RESETTING, &adapter->flags); | ||
533 | } | ||
534 | |||
524 | void e1000_reinit_locked(struct e1000_adapter *adapter) | 535 | void e1000_reinit_locked(struct e1000_adapter *adapter) |
525 | { | 536 | { |
537 | /* if rtnl_lock is not held the call path is bogus */ | ||
538 | ASSERT_RTNL(); | ||
526 | WARN_ON(in_interrupt()); | 539 | WARN_ON(in_interrupt()); |
527 | while (test_and_set_bit(__E1000_RESETTING, &adapter->flags)) | 540 | while (test_and_set_bit(__E1000_RESETTING, &adapter->flags)) |
528 | msleep(1); | 541 | msleep(1); |
@@ -2247,7 +2260,10 @@ static void e1000_update_phy_info_task(struct work_struct *work) | |||
2247 | struct e1000_adapter, | 2260 | struct e1000_adapter, |
2248 | phy_info_task); | 2261 | phy_info_task); |
2249 | struct e1000_hw *hw = &adapter->hw; | 2262 | struct e1000_hw *hw = &adapter->hw; |
2263 | |||
2264 | rtnl_lock(); | ||
2250 | e1000_phy_get_info(hw, &adapter->phy_info); | 2265 | e1000_phy_get_info(hw, &adapter->phy_info); |
2266 | rtnl_unlock(); | ||
2251 | } | 2267 | } |
2252 | 2268 | ||
2253 | /** | 2269 | /** |
@@ -2273,6 +2289,7 @@ static void e1000_82547_tx_fifo_stall_task(struct work_struct *work) | |||
2273 | struct net_device *netdev = adapter->netdev; | 2289 | struct net_device *netdev = adapter->netdev; |
2274 | u32 tctl; | 2290 | u32 tctl; |
2275 | 2291 | ||
2292 | rtnl_lock(); | ||
2276 | if (atomic_read(&adapter->tx_fifo_stall)) { | 2293 | if (atomic_read(&adapter->tx_fifo_stall)) { |
2277 | if ((er32(TDT) == er32(TDH)) && | 2294 | if ((er32(TDT) == er32(TDH)) && |
2278 | (er32(TDFT) == er32(TDFH)) && | 2295 | (er32(TDFT) == er32(TDFH)) && |
@@ -2293,6 +2310,7 @@ static void e1000_82547_tx_fifo_stall_task(struct work_struct *work) | |||
2293 | mod_timer(&adapter->tx_fifo_stall_timer, jiffies + 1); | 2310 | mod_timer(&adapter->tx_fifo_stall_timer, jiffies + 1); |
2294 | } | 2311 | } |
2295 | } | 2312 | } |
2313 | rtnl_unlock(); | ||
2296 | } | 2314 | } |
2297 | 2315 | ||
2298 | bool e1000_has_link(struct e1000_adapter *adapter) | 2316 | bool e1000_has_link(struct e1000_adapter *adapter) |
@@ -3160,7 +3178,7 @@ static void e1000_reset_task(struct work_struct *work) | |||
3160 | struct e1000_adapter *adapter = | 3178 | struct e1000_adapter *adapter = |
3161 | container_of(work, struct e1000_adapter, reset_task); | 3179 | container_of(work, struct e1000_adapter, reset_task); |
3162 | 3180 | ||
3163 | e1000_reinit_locked(adapter); | 3181 | e1000_reinit_safe(adapter); |
3164 | } | 3182 | } |
3165 | 3183 | ||
3166 | /** | 3184 | /** |