ixgbevf: Add bit to mark work queue initialization
authorMark Rustad <mark.d.rustad@intel.com>
Wed, 12 Mar 2014 00:38:51 +0000 (00:38 +0000)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Fri, 11 Apr 2014 12:58:06 +0000 (05:58 -0700)
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>
drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c

index e7e7d695816b2246ca1e2efcf74a184e65f803e2..a0a1de9ce2389fdcc15ebad8f19a26b456d12447 100644 (file)
@@ -421,6 +421,7 @@ enum ixbgevf_state_t {
        __IXGBEVF_DOWN,
        __IXGBEVF_DISABLED,
        __IXGBEVF_REMOVING,
+       __IXGBEVF_WORK_INIT,
 };
 
 struct ixgbevf_cb {
index 4ba139b2d25a42ff43d896eed13249f61930c60b..905c26cfa60049bf3e4f84eac7f181d8743bbc33 100644 (file)
@@ -107,7 +107,8 @@ static void ixgbevf_remove_adapter(struct ixgbe_hw *hw)
                return;
        hw->hw_addr = NULL;
        dev_err(&adapter->pdev->dev, "Adapter removed\n");
-       schedule_work(&adapter->watchdog_task);
+       if (test_bit(__IXGBEVF_WORK_INIT, &adapter->state))
+               schedule_work(&adapter->watchdog_task);
 }
 
 static 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)
        adapter->watchdog_timer.function = ixgbevf_watchdog;
        adapter->watchdog_timer.data = (unsigned long)adapter;
 
+       if (IXGBE_REMOVED(hw->hw_addr)) {
+               err = -EIO;
+               goto err_sw_init;
+       }
        INIT_WORK(&adapter->reset_task, ixgbevf_reset_task);
        INIT_WORK(&adapter->watchdog_task, ixgbevf_watchdog_task);
+       set_bit(__IXGBEVF_WORK_INIT, &adapter->state);
 
        err = ixgbevf_init_interrupt_scheme(adapter);
        if (err)
@@ -3667,6 +3673,9 @@ static pci_ers_result_t ixgbevf_io_error_detected(struct pci_dev *pdev,
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct ixgbevf_adapter *adapter = netdev_priv(netdev);
 
+       if (!test_bit(__IXGBEVF_WORK_INIT, &adapter->state))
+               return PCI_ERS_RESULT_DISCONNECT;
+
        rtnl_lock();
        netif_device_detach(netdev);