aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Rustad <mark.d.rustad@intel.com>2014-03-11 20:38:51 -0400
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2014-04-11 08:58:06 -0400
commitea699569b150daa5d5f6c23040da997b83e4cfa3 (patch)
tree90b1bedd5325581712071cad614a48aa7ab976e0
parent2049e1f6f5e6720b182c42695dbdef071804226e (diff)
ixgbevf: Add bit to mark work queue initialization
An indication of work queue initialization is needed. This is because register accesses prior to that time can detect a removal and attempt to schedule the watchdog task. Adding the __IXGBEVF_WORK_INIT bit allows this to be checked and if not set prevent the watchdog task scheduling. By checking for a removal right after initialization, the probe can be failed at that point without getting the watchdog task involved. Signed-off-by: Mark Rustad <mark.d.rustad@intel.com> Tested-by: Phil Schmitt <phillip.j.schmitt@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/ixgbevf.h1
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c11
2 files changed, 11 insertions, 1 deletions
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
index e7e7d695816b..a0a1de9ce238 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
@@ -421,6 +421,7 @@ enum ixbgevf_state_t {
421 __IXGBEVF_DOWN, 421 __IXGBEVF_DOWN,
422 __IXGBEVF_DISABLED, 422 __IXGBEVF_DISABLED,
423 __IXGBEVF_REMOVING, 423 __IXGBEVF_REMOVING,
424 __IXGBEVF_WORK_INIT,
424}; 425};
425 426
426struct ixgbevf_cb { 427struct ixgbevf_cb {
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index 4ba139b2d25a..905c26cfa600 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -107,7 +107,8 @@ static void ixgbevf_remove_adapter(struct ixgbe_hw *hw)
107 return; 107 return;
108 hw->hw_addr = NULL; 108 hw->hw_addr = NULL;
109 dev_err(&adapter->pdev->dev, "Adapter removed\n"); 109 dev_err(&adapter->pdev->dev, "Adapter removed\n");
110 schedule_work(&adapter->watchdog_task); 110 if (test_bit(__IXGBEVF_WORK_INIT, &adapter->state))
111 schedule_work(&adapter->watchdog_task);
111} 112}
112 113
113static void ixgbevf_check_remove(struct ixgbe_hw *hw, u32 reg) 114static void ixgbevf_check_remove(struct ixgbe_hw *hw, u32 reg)
@@ -3573,8 +3574,13 @@ static int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
3573 adapter->watchdog_timer.function = ixgbevf_watchdog; 3574 adapter->watchdog_timer.function = ixgbevf_watchdog;
3574 adapter->watchdog_timer.data = (unsigned long)adapter; 3575 adapter->watchdog_timer.data = (unsigned long)adapter;
3575 3576
3577 if (IXGBE_REMOVED(hw->hw_addr)) {
3578 err = -EIO;
3579 goto err_sw_init;
3580 }
3576 INIT_WORK(&adapter->reset_task, ixgbevf_reset_task); 3581 INIT_WORK(&adapter->reset_task, ixgbevf_reset_task);
3577 INIT_WORK(&adapter->watchdog_task, ixgbevf_watchdog_task); 3582 INIT_WORK(&adapter->watchdog_task, ixgbevf_watchdog_task);
3583 set_bit(__IXGBEVF_WORK_INIT, &adapter->state);
3578 3584
3579 err = ixgbevf_init_interrupt_scheme(adapter); 3585 err = ixgbevf_init_interrupt_scheme(adapter);
3580 if (err) 3586 if (err)
@@ -3667,6 +3673,9 @@ static pci_ers_result_t ixgbevf_io_error_detected(struct pci_dev *pdev,
3667 struct net_device *netdev = pci_get_drvdata(pdev); 3673 struct net_device *netdev = pci_get_drvdata(pdev);
3668 struct ixgbevf_adapter *adapter = netdev_priv(netdev); 3674 struct ixgbevf_adapter *adapter = netdev_priv(netdev);
3669 3675
3676 if (!test_bit(__IXGBEVF_WORK_INIT, &adapter->state))
3677 return PCI_ERS_RESULT_DISCONNECT;
3678
3670 rtnl_lock(); 3679 rtnl_lock();
3671 netif_device_detach(netdev); 3680 netif_device_detach(netdev);
3672 3681