diff options
Diffstat (limited to 'drivers/net/ethernet/intel/e1000/e1000_main.c')
-rw-r--r-- | drivers/net/ethernet/intel/e1000/e1000_main.c | 72 |
1 files changed, 46 insertions, 26 deletions
diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c index 46e6544..59ad007 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_main.c +++ b/drivers/net/ethernet/intel/e1000/e1000_main.c @@ -494,20 +494,13 @@ static void e1000_down_and_stop(struct e1000_adapter *adapter) { set_bit(__E1000_DOWN, &adapter->flags); - 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); + + cancel_delayed_work_sync(&adapter->watchdog_task); + cancel_delayed_work_sync(&adapter->phy_info_task); + cancel_delayed_work_sync(&adapter->fifo_stall_task); } void e1000_down(struct e1000_adapter *adapter) @@ -551,8 +544,21 @@ 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); @@ -1012,14 +1018,19 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent) */ pci_using_dac = 0; if ((hw->bus_type == e1000_bus_type_pcix) && - !dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64))) { + !dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) { + /* according to DMA-API-HOWTO, coherent calls will always + * succeed if the set call did + */ + dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64)); pci_using_dac = 1; } else { - err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); + err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); if (err) { pr_err("No usable DMA config, aborting\n"); goto err_dma; } + dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); } netdev->netdev_ops = &e1000_netdev_ops; @@ -1310,6 +1321,7 @@ 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); @@ -1433,10 +1445,6 @@ 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); @@ -2322,8 +2330,11 @@ 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); } /** @@ -2339,6 +2350,9 @@ 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)) && @@ -2359,6 +2373,7 @@ 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) @@ -2412,6 +2427,10 @@ 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; @@ -2502,7 +2521,7 @@ link_up: adapter->tx_timeout_count++; schedule_work(&adapter->reset_task); /* exit immediately since reset is imminent */ - return; + goto unlock; } } @@ -2530,6 +2549,9 @@ 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 { @@ -3478,8 +3500,10 @@ 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_locked(adapter); + e1000_reinit_safe(adapter); } /** @@ -3893,7 +3917,8 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter, " next_to_watch <%x>\n" " jiffies <%lx>\n" " next_to_watch.status <%x>\n", - (unsigned long)(tx_ring - adapter->tx_ring), + (unsigned long)((tx_ring - adapter->tx_ring) / + sizeof(struct e1000_tx_ring)), readl(hw->hw_addr + tx_ring->tdh), readl(hw->hw_addr + tx_ring->tdt), tx_ring->next_to_use, @@ -4944,11 +4969,6 @@ 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); } |