diff options
Diffstat (limited to 'drivers/net/ethernet/intel/e1000/e1000_main.c')
| -rw-r--r-- | drivers/net/ethernet/intel/e1000/e1000_main.c | 60 | 
1 files changed, 23 insertions, 37 deletions
diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c index e38622825fa7..46e6544ed1b7 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_main.c +++ b/drivers/net/ethernet/intel/e1000/e1000_main.c @@ -494,13 +494,20 @@ static void e1000_down_and_stop(struct e1000_adapter *adapter)  {  	set_bit(__E1000_DOWN, &adapter->flags); -	/* Only kill reset task if adapter is not resetting */ -	if (!test_bit(__E1000_RESETTING, &adapter->flags)) -		cancel_work_sync(&adapter->reset_task); -  	cancel_delayed_work_sync(&adapter->watchdog_task); + +	/* +	 * Since the watchdog task can reschedule other tasks, we should cancel +	 * it first, otherwise we can run into the situation when a work is +	 * still running after the adapter has been turned down. +	 */ +  	cancel_delayed_work_sync(&adapter->phy_info_task);  	cancel_delayed_work_sync(&adapter->fifo_stall_task); + +	/* Only kill reset task if adapter is not resetting */ +	if (!test_bit(__E1000_RESETTING, &adapter->flags)) +		cancel_work_sync(&adapter->reset_task);  }  void e1000_down(struct e1000_adapter *adapter) @@ -544,21 +551,8 @@ void e1000_down(struct e1000_adapter *adapter)  	e1000_clean_all_rx_rings(adapter);  } -static void e1000_reinit_safe(struct e1000_adapter *adapter) -{ -	while (test_and_set_bit(__E1000_RESETTING, &adapter->flags)) -		msleep(1); -	mutex_lock(&adapter->mutex); -	e1000_down(adapter); -	e1000_up(adapter); -	mutex_unlock(&adapter->mutex); -	clear_bit(__E1000_RESETTING, &adapter->flags); -} -  void e1000_reinit_locked(struct e1000_adapter *adapter)  { -	/* if rtnl_lock is not held the call path is bogus */ -	ASSERT_RTNL();  	WARN_ON(in_interrupt());  	while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))  		msleep(1); @@ -1316,7 +1310,6 @@ static int e1000_sw_init(struct e1000_adapter *adapter)  	e1000_irq_disable(adapter);  	spin_lock_init(&adapter->stats_lock); -	mutex_init(&adapter->mutex);  	set_bit(__E1000_DOWN, &adapter->flags); @@ -1440,6 +1433,10 @@ static int e1000_close(struct net_device *netdev)  {  	struct e1000_adapter *adapter = netdev_priv(netdev);  	struct e1000_hw *hw = &adapter->hw; +	int count = E1000_CHECK_RESET_COUNT; + +	while (test_bit(__E1000_RESETTING, &adapter->flags) && count--) +		usleep_range(10000, 20000);  	WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags));  	e1000_down(adapter); @@ -2325,11 +2322,8 @@ static void e1000_update_phy_info_task(struct work_struct *work)  	struct e1000_adapter *adapter = container_of(work,  						     struct e1000_adapter,  						     phy_info_task.work); -	if (test_bit(__E1000_DOWN, &adapter->flags)) -		return; -	mutex_lock(&adapter->mutex); +  	e1000_phy_get_info(&adapter->hw, &adapter->phy_info); -	mutex_unlock(&adapter->mutex);  }  /** @@ -2345,9 +2339,6 @@ static void e1000_82547_tx_fifo_stall_task(struct work_struct *work)  	struct net_device *netdev = adapter->netdev;  	u32 tctl; -	if (test_bit(__E1000_DOWN, &adapter->flags)) -		return; -	mutex_lock(&adapter->mutex);  	if (atomic_read(&adapter->tx_fifo_stall)) {  		if ((er32(TDT) == er32(TDH)) &&  		   (er32(TDFT) == er32(TDFH)) && @@ -2368,7 +2359,6 @@ static void e1000_82547_tx_fifo_stall_task(struct work_struct *work)  			schedule_delayed_work(&adapter->fifo_stall_task, 1);  		}  	} -	mutex_unlock(&adapter->mutex);  }  bool e1000_has_link(struct e1000_adapter *adapter) @@ -2422,10 +2412,6 @@ static void e1000_watchdog(struct work_struct *work)  	struct e1000_tx_ring *txdr = adapter->tx_ring;  	u32 link, tctl; -	if (test_bit(__E1000_DOWN, &adapter->flags)) -		return; - -	mutex_lock(&adapter->mutex);  	link = e1000_has_link(adapter);  	if ((netif_carrier_ok(netdev)) && link)  		goto link_up; @@ -2516,7 +2502,7 @@ link_up:  			adapter->tx_timeout_count++;  			schedule_work(&adapter->reset_task);  			/* exit immediately since reset is imminent */ -			goto unlock; +			return;  		}  	} @@ -2544,9 +2530,6 @@ link_up:  	/* Reschedule the task */  	if (!test_bit(__E1000_DOWN, &adapter->flags))  		schedule_delayed_work(&adapter->watchdog_task, 2 * HZ); - -unlock: -	mutex_unlock(&adapter->mutex);  }  enum latency_range { @@ -3495,10 +3478,8 @@ static void e1000_reset_task(struct work_struct *work)  	struct e1000_adapter *adapter =  		container_of(work, struct e1000_adapter, reset_task); -	if (test_bit(__E1000_DOWN, &adapter->flags)) -		return;  	e_err(drv, "Reset adapter\n"); -	e1000_reinit_safe(adapter); +	e1000_reinit_locked(adapter);  }  /** @@ -4963,6 +4944,11 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake)  	netif_device_detach(netdev);  	if (netif_running(netdev)) { +		int count = E1000_CHECK_RESET_COUNT; + +		while (test_bit(__E1000_RESETTING, &adapter->flags) && count--) +			usleep_range(10000, 20000); +  		WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags));  		e1000_down(adapter);  	}  | 
