Skip to content

Commit

Permalink
ixgbe: cleanup race conditions in link setup
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Alexander Duyck authored and Jeff Kirsher committed Nov 17, 2010
1 parent 7d637bc commit 73c4b7c
Showing 1 changed file with 19 additions and 28 deletions.
47 changes: 19 additions & 28 deletions drivers/net/ixgbe/ixgbe_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1712,17 +1712,18 @@ static void ixgbe_check_sfp_event(struct ixgbe_adapter *adapter, u32 eicr)
{
struct ixgbe_hw *hw = &adapter->hw;

if (eicr & IXGBE_EICR_GPI_SDP2) {
/* Clear the interrupt */
IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP2);
if (!test_bit(__IXGBE_DOWN, &adapter->state))
schedule_work(&adapter->sfp_config_module_task);
}

if (eicr & IXGBE_EICR_GPI_SDP1) {
/* Clear the interrupt */
IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1);
schedule_work(&adapter->multispeed_fiber_task);
} else if (eicr & IXGBE_EICR_GPI_SDP2) {
/* Clear the interrupt */
IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP2);
schedule_work(&adapter->sfp_config_module_task);
} else {
/* Interrupt isn't for us... */
return;
if (!test_bit(__IXGBE_DOWN, &adapter->state))
schedule_work(&adapter->multispeed_fiber_task);
}
}

Expand Down Expand Up @@ -3587,6 +3588,14 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
clear_bit(__IXGBE_DOWN, &adapter->state);
ixgbe_napi_enable_all(adapter);

if (ixgbe_is_sfp(hw)) {
ixgbe_sfp_link_config(adapter);
} else {
err = ixgbe_non_sfp_link_config(hw);
if (err)
e_err(probe, "link_config FAILED %d\n", err);
}

/* clear any pending interrupts, may auto mask */
IXGBE_READ_REG(hw, IXGBE_EICR);
ixgbe_irq_enable(adapter, true, true);
Expand All @@ -3609,26 +3618,8 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
* If we're not hot-pluggable SFP+, we just need to configure link
* and bring it up.
*/
if (hw->phy.type == ixgbe_phy_unknown) {
err = hw->phy.ops.identify(hw);
if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
/*
* Take the device down and schedule the sfp tasklet
* which will unregister_netdev and log it.
*/
ixgbe_down(adapter);
schedule_work(&adapter->sfp_config_module_task);
return err;
}
}

if (ixgbe_is_sfp(hw)) {
ixgbe_sfp_link_config(adapter);
} else {
err = ixgbe_non_sfp_link_config(hw);
if (err)
e_err(probe, "link_config FAILED %d\n", err);
}
if (hw->phy.type == ixgbe_phy_unknown)
schedule_work(&adapter->sfp_config_module_task);

/* enable transmits */
netif_tx_start_all_queues(adapter->netdev);
Expand Down

0 comments on commit 73c4b7c

Please sign in to comment.