ixgbe: Add bit to mark service task initialization
authorMark Rustad <mark.d.rustad@intel.com>
Wed, 12 Mar 2014 00:38:40 +0000 (00:38 +0000)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Fri, 11 Apr 2014 12:58:05 +0000 (05:58 -0700)
There needs to be an indication when the service task has been
initialized. This is because register access prior to that time
can detect a removal and attempt to schedule the service task.
Adding the __IXGBE_SERVICE_INITED bit allows this to be checked
and if not set prevent the service task scheduling. By checking
for a removal right after initialization, the probe can be failed
at that point without getting the service 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/ixgbe/ixgbe.h
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c

index 55c53a1..1a12c1d 100644 (file)
@@ -811,6 +811,7 @@ enum ixgbe_state_t {
        __IXGBE_DISABLED,
        __IXGBE_REMOVING,
        __IXGBE_SERVICE_SCHED,
+       __IXGBE_SERVICE_INITED,
        __IXGBE_IN_SFP_INIT,
        __IXGBE_PTP_RUNNING,
        __IXGBE_PTP_TX_IN_PROGRESS,
index 8436c65..00c9308 100644 (file)
@@ -297,7 +297,8 @@ static void ixgbe_remove_adapter(struct ixgbe_hw *hw)
                return;
        hw->hw_addr = NULL;
        e_dev_err("Adapter removed\n");
-       ixgbe_service_event_schedule(adapter);
+       if (test_bit(__IXGBE_SERVICE_INITED, &adapter->state))
+               ixgbe_service_event_schedule(adapter);
 }
 
 void ixgbe_check_remove(struct ixgbe_hw *hw, u32 reg)
@@ -8023,6 +8024,10 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        /* EEPROM */
        memcpy(&hw->eeprom.ops, ii->eeprom_ops, sizeof(hw->eeprom.ops));
        eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+       if (ixgbe_removed(hw->hw_addr)) {
+               err = -EIO;
+               goto err_ioremap;
+       }
        /* If EEPROM is valid (bit 8 = 1), use default otherwise use bit bang */
        if (!(eec & (1 << 8)))
                hw->eeprom.ops.read = &ixgbe_read_eeprom_bit_bang_generic;
@@ -8185,7 +8190,12 @@ skip_sriov:
        setup_timer(&adapter->service_timer, &ixgbe_service_timer,
                    (unsigned long) adapter);
 
+       if (ixgbe_removed(hw->hw_addr)) {
+               err = -EIO;
+               goto err_sw_init;
+       }
        INIT_WORK(&adapter->service_task, ixgbe_service_task);
+       set_bit(__IXGBE_SERVICE_INITED, &adapter->state);
        clear_bit(__IXGBE_SERVICE_SCHED, &adapter->state);
 
        err = ixgbe_init_interrupt_scheme(adapter);
@@ -8494,6 +8504,9 @@ static pci_ers_result_t ixgbe_io_error_detected(struct pci_dev *pdev,
 
 skip_bad_vf_detection:
 #endif /* CONFIG_PCI_IOV */
+       if (!test_bit(__IXGBE_SERVICE_INITED, &adapter->state))
+               return PCI_ERS_RESULT_DISCONNECT;
+
        rtnl_lock();
        netif_device_detach(netdev);