diff options
author | Mark Rustad <mark.d.rustad@intel.com> | 2014-03-11 20:38:35 -0400 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2014-03-31 18:48:03 -0400 |
commit | 41c62843eb6a0ea3e2f1e06ca3ec7b2f64452f7b (patch) | |
tree | de994b24163c5e42a9e75fd8d750eb090856e5e5 | |
parent | 75009b3a88cd8f56315eb4ced296ee2f060cf946 (diff) |
ixgbe: Fix rcu warnings induced by LER
Resolve some rcu warnings produced when LER actions take place.
This appears to be due to not holding the rtnl lock when calling
ixgbe_down, so hold the lock. Also avoid disabling the device
when it is already disabled. This check is necessary because the
callback can be called more than once in some cases.
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/ixgbe/ixgbe.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 23 |
2 files changed, 19 insertions, 5 deletions
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h index 26d27aae9793..55c53a1cbb62 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h | |||
@@ -808,6 +808,7 @@ enum ixgbe_state_t { | |||
808 | __IXGBE_TESTING, | 808 | __IXGBE_TESTING, |
809 | __IXGBE_RESETTING, | 809 | __IXGBE_RESETTING, |
810 | __IXGBE_DOWN, | 810 | __IXGBE_DOWN, |
811 | __IXGBE_DISABLED, | ||
811 | __IXGBE_REMOVING, | 812 | __IXGBE_REMOVING, |
812 | __IXGBE_SERVICE_SCHED, | 813 | __IXGBE_SERVICE_SCHED, |
813 | __IXGBE_IN_SFP_INIT, | 814 | __IXGBE_IN_SFP_INIT, |
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index c4b930c0ce7f..8436c651b735 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | |||
@@ -5566,6 +5566,8 @@ static int ixgbe_resume(struct pci_dev *pdev) | |||
5566 | e_dev_err("Cannot enable PCI device from suspend\n"); | 5566 | e_dev_err("Cannot enable PCI device from suspend\n"); |
5567 | return err; | 5567 | return err; |
5568 | } | 5568 | } |
5569 | smp_mb__before_clear_bit(); | ||
5570 | clear_bit(__IXGBE_DISABLED, &adapter->state); | ||
5569 | pci_set_master(pdev); | 5571 | pci_set_master(pdev); |
5570 | 5572 | ||
5571 | pci_wake_from_d3(pdev, false); | 5573 | pci_wake_from_d3(pdev, false); |
@@ -5663,7 +5665,8 @@ static int __ixgbe_shutdown(struct pci_dev *pdev, bool *enable_wake) | |||
5663 | 5665 | ||
5664 | ixgbe_release_hw_control(adapter); | 5666 | ixgbe_release_hw_control(adapter); |
5665 | 5667 | ||
5666 | pci_disable_device(pdev); | 5668 | if (!test_and_set_bit(__IXGBE_DISABLED, &adapter->state)) |
5669 | pci_disable_device(pdev); | ||
5667 | 5670 | ||
5668 | return 0; | 5671 | return 0; |
5669 | } | 5672 | } |
@@ -8313,7 +8316,8 @@ err_alloc_etherdev: | |||
8313 | pci_select_bars(pdev, IORESOURCE_MEM)); | 8316 | pci_select_bars(pdev, IORESOURCE_MEM)); |
8314 | err_pci_reg: | 8317 | err_pci_reg: |
8315 | err_dma: | 8318 | err_dma: |
8316 | pci_disable_device(pdev); | 8319 | if (!test_and_set_bit(__IXGBE_DISABLED, &adapter->state)) |
8320 | pci_disable_device(pdev); | ||
8317 | return err; | 8321 | return err; |
8318 | } | 8322 | } |
8319 | 8323 | ||
@@ -8382,7 +8386,8 @@ static void ixgbe_remove(struct pci_dev *pdev) | |||
8382 | 8386 | ||
8383 | pci_disable_pcie_error_reporting(pdev); | 8387 | pci_disable_pcie_error_reporting(pdev); |
8384 | 8388 | ||
8385 | pci_disable_device(pdev); | 8389 | if (!test_and_set_bit(__IXGBE_DISABLED, &adapter->state)) |
8390 | pci_disable_device(pdev); | ||
8386 | } | 8391 | } |
8387 | 8392 | ||
8388 | /** | 8393 | /** |
@@ -8489,14 +8494,20 @@ static pci_ers_result_t ixgbe_io_error_detected(struct pci_dev *pdev, | |||
8489 | 8494 | ||
8490 | skip_bad_vf_detection: | 8495 | skip_bad_vf_detection: |
8491 | #endif /* CONFIG_PCI_IOV */ | 8496 | #endif /* CONFIG_PCI_IOV */ |
8497 | rtnl_lock(); | ||
8492 | netif_device_detach(netdev); | 8498 | netif_device_detach(netdev); |
8493 | 8499 | ||
8494 | if (state == pci_channel_io_perm_failure) | 8500 | if (state == pci_channel_io_perm_failure) { |
8501 | rtnl_unlock(); | ||
8495 | return PCI_ERS_RESULT_DISCONNECT; | 8502 | return PCI_ERS_RESULT_DISCONNECT; |
8503 | } | ||
8496 | 8504 | ||
8497 | if (netif_running(netdev)) | 8505 | if (netif_running(netdev)) |
8498 | ixgbe_down(adapter); | 8506 | ixgbe_down(adapter); |
8499 | pci_disable_device(pdev); | 8507 | |
8508 | if (!test_and_set_bit(__IXGBE_DISABLED, &adapter->state)) | ||
8509 | pci_disable_device(pdev); | ||
8510 | rtnl_unlock(); | ||
8500 | 8511 | ||
8501 | /* Request a slot reset. */ | 8512 | /* Request a slot reset. */ |
8502 | return PCI_ERS_RESULT_NEED_RESET; | 8513 | return PCI_ERS_RESULT_NEED_RESET; |
@@ -8518,6 +8529,8 @@ static pci_ers_result_t ixgbe_io_slot_reset(struct pci_dev *pdev) | |||
8518 | e_err(probe, "Cannot re-enable PCI device after reset.\n"); | 8529 | e_err(probe, "Cannot re-enable PCI device after reset.\n"); |
8519 | result = PCI_ERS_RESULT_DISCONNECT; | 8530 | result = PCI_ERS_RESULT_DISCONNECT; |
8520 | } else { | 8531 | } else { |
8532 | smp_mb__before_clear_bit(); | ||
8533 | clear_bit(__IXGBE_DISABLED, &adapter->state); | ||
8521 | adapter->hw.hw_addr = adapter->io_addr; | 8534 | adapter->hw.hw_addr = adapter->io_addr; |
8522 | pci_set_master(pdev); | 8535 | pci_set_master(pdev); |
8523 | pci_restore_state(pdev); | 8536 | pci_restore_state(pdev); |