aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Duyck <alexander.h.duyck@intel.com>2010-11-16 22:26:57 -0500
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2010-11-16 22:26:57 -0500
commit73c4b7cdd25a8a769baf6dae5bc498400a9ddd93 (patch)
tree87782c2fc0f465456d09a4e40fda7a20f489e61f
parent7d637bcc8f461f19e1d018078792ec0cd9b07b1d (diff)
ixgbe: cleanup race conditions in link setup
This change makes it so that we perform link setup with interrupts disabled. If the SFP has not been detected previously we will schedule the SFP detection task to run in order to detect link. By doing this we avoid the possibility of interrupts firing in the middle of our link setup during ixgbe_up_complete. In addition this change makes it so that the multi-speed fiber setup and SFP setup are not mutually exclusive. The addresses issues seen in which a link would only come up at 1G on some multi-speed fiber modules. Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com> Tested-by: Ross Brattain <ross.b.brattain@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
-rw-r--r--drivers/net/ixgbe/ixgbe_main.c47
1 files changed, 19 insertions, 28 deletions
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index b798501500e6..0128fe666f0b 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -1712,17 +1712,18 @@ static void ixgbe_check_sfp_event(struct ixgbe_adapter *adapter, u32 eicr)
1712{ 1712{
1713 struct ixgbe_hw *hw = &adapter->hw; 1713 struct ixgbe_hw *hw = &adapter->hw;
1714 1714
1715 if (eicr & IXGBE_EICR_GPI_SDP2) {
1716 /* Clear the interrupt */
1717 IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP2);
1718 if (!test_bit(__IXGBE_DOWN, &adapter->state))
1719 schedule_work(&adapter->sfp_config_module_task);
1720 }
1721
1715 if (eicr & IXGBE_EICR_GPI_SDP1) { 1722 if (eicr & IXGBE_EICR_GPI_SDP1) {
1716 /* Clear the interrupt */ 1723 /* Clear the interrupt */
1717 IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1); 1724 IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1);
1718 schedule_work(&adapter->multispeed_fiber_task); 1725 if (!test_bit(__IXGBE_DOWN, &adapter->state))
1719 } else if (eicr & IXGBE_EICR_GPI_SDP2) { 1726 schedule_work(&adapter->multispeed_fiber_task);
1720 /* Clear the interrupt */
1721 IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP2);
1722 schedule_work(&adapter->sfp_config_module_task);
1723 } else {
1724 /* Interrupt isn't for us... */
1725 return;
1726 } 1727 }
1727} 1728}
1728 1729
@@ -3587,6 +3588,14 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
3587 clear_bit(__IXGBE_DOWN, &adapter->state); 3588 clear_bit(__IXGBE_DOWN, &adapter->state);
3588 ixgbe_napi_enable_all(adapter); 3589 ixgbe_napi_enable_all(adapter);
3589 3590
3591 if (ixgbe_is_sfp(hw)) {
3592 ixgbe_sfp_link_config(adapter);
3593 } else {
3594 err = ixgbe_non_sfp_link_config(hw);
3595 if (err)
3596 e_err(probe, "link_config FAILED %d\n", err);
3597 }
3598
3590 /* clear any pending interrupts, may auto mask */ 3599 /* clear any pending interrupts, may auto mask */
3591 IXGBE_READ_REG(hw, IXGBE_EICR); 3600 IXGBE_READ_REG(hw, IXGBE_EICR);
3592 ixgbe_irq_enable(adapter, true, true); 3601 ixgbe_irq_enable(adapter, true, true);
@@ -3609,26 +3618,8 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
3609 * If we're not hot-pluggable SFP+, we just need to configure link 3618 * If we're not hot-pluggable SFP+, we just need to configure link
3610 * and bring it up. 3619 * and bring it up.
3611 */ 3620 */
3612 if (hw->phy.type == ixgbe_phy_unknown) { 3621 if (hw->phy.type == ixgbe_phy_unknown)
3613 err = hw->phy.ops.identify(hw); 3622 schedule_work(&adapter->sfp_config_module_task);
3614 if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
3615 /*
3616 * Take the device down and schedule the sfp tasklet
3617 * which will unregister_netdev and log it.
3618 */
3619 ixgbe_down(adapter);
3620 schedule_work(&adapter->sfp_config_module_task);
3621 return err;
3622 }
3623 }
3624
3625 if (ixgbe_is_sfp(hw)) {
3626 ixgbe_sfp_link_config(adapter);
3627 } else {
3628 err = ixgbe_non_sfp_link_config(hw);
3629 if (err)
3630 e_err(probe, "link_config FAILED %d\n", err);
3631 }
3632 3623
3633 /* enable transmits */ 3624 /* enable transmits */
3634 netif_tx_start_all_queues(adapter->netdev); 3625 netif_tx_start_all_queues(adapter->netdev);