diff options
author | Mark Rustad <mark.d.rustad@intel.com> | 2014-03-12 04:38:40 +0400 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2014-04-11 16:58:05 +0400 |
commit | 58cf663f0e962a51f051a84e38be281335bdf1fd (patch) | |
tree | a4a55234717f6135c645647f94afe01ca56c482d /drivers | |
parent | 6d39d589bb76ee8a1c6cde6822006ae0053decff (diff) | |
download | linux-58cf663f0e962a51f051a84e38be281335bdf1fd.tar.xz |
ixgbe: Add bit to mark service task initialization
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 15 |
2 files changed, 15 insertions, 1 deletions
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h index 55c53a1cbb62..1a12c1dd7a27 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h @@ -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, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 8436c651b735..00c9308455b8 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -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); |