Commit 0ecc061d authored by Peter P Waskiewicz Jr's avatar Peter P Waskiewicz Jr Committed by David S. Miller

ixgbe: Update flow control state machine in link setup

The flow control handling is overly complicated and difficult to maintain.
This patch cleans up the flow control handling and makes it much more
explicit.  It also adds 1G flow control autonegotiation, for 1G copper
links, 1G KX links, and 1G fiber links.
Signed-off-by: default avatarPeter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 39482791
...@@ -255,104 +255,75 @@ static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw) ...@@ -255,104 +255,75 @@ static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw)
} }
/** /**
* ixgbe_setup_fc_82598 - Configure flow control settings * ixgbe_fc_enable_82598 - Enable flow control
* @hw: pointer to hardware structure * @hw: pointer to hardware structure
* @packetbuf_num: packet buffer number (0-7) * @packetbuf_num: packet buffer number (0-7)
* *
* Configures the flow control settings based on SW configuration. This * Enable flow control according to the current settings.
* function is used for 802.3x flow control configuration only.
**/ **/
static s32 ixgbe_setup_fc_82598(struct ixgbe_hw *hw, s32 packetbuf_num) static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num)
{ {
u32 frctl_reg; s32 ret_val = 0;
u32 fctrl_reg;
u32 rmcs_reg; u32 rmcs_reg;
u32 reg;
if (packetbuf_num < 0 || packetbuf_num > 7) { fctrl_reg = IXGBE_READ_REG(hw, IXGBE_FCTRL);
hw_dbg(hw, "Invalid packet buffer number [%d], expected range is" fctrl_reg &= ~(IXGBE_FCTRL_RFCE | IXGBE_FCTRL_RPFCE);
" 0-7\n", packetbuf_num);
}
frctl_reg = IXGBE_READ_REG(hw, IXGBE_FCTRL);
frctl_reg &= ~(IXGBE_FCTRL_RFCE | IXGBE_FCTRL_RPFCE);
rmcs_reg = IXGBE_READ_REG(hw, IXGBE_RMCS); rmcs_reg = IXGBE_READ_REG(hw, IXGBE_RMCS);
rmcs_reg &= ~(IXGBE_RMCS_TFCE_PRIORITY | IXGBE_RMCS_TFCE_802_3X); rmcs_reg &= ~(IXGBE_RMCS_TFCE_PRIORITY | IXGBE_RMCS_TFCE_802_3X);
/* /*
* 10 gig parts do not have a word in the EEPROM to determine the * The possible values of fc.current_mode are:
* default flow control setting, so we explicitly set it to full.
*/
if (hw->fc.type == ixgbe_fc_default)
hw->fc.type = ixgbe_fc_full;
/*
* We want to save off the original Flow Control configuration just in
* case we get disconnected and then reconnected into a different hub
* or switch with different Flow Control capabilities.
*/
hw->fc.original_type = hw->fc.type;
/*
* The possible values of the "flow_control" parameter are:
* 0: Flow control is completely disabled * 0: Flow control is completely disabled
* 1: Rx flow control is enabled (we can receive pause frames but not * 1: Rx flow control is enabled (we can receive pause frames,
* send pause frames). * but not send pause frames).
* 2: Tx flow control is enabled (we can send pause frames but we do not * 2: Tx flow control is enabled (we can send pause frames but
* support receiving pause frames) * we do not support receiving pause frames).
* 3: Both Rx and Tx flow control (symmetric) are enabled. * 3: Both Rx and Tx flow control (symmetric) are enabled.
* other: Invalid. * other: Invalid.
*/ */
switch (hw->fc.type) { switch (hw->fc.current_mode) {
case ixgbe_fc_none: case ixgbe_fc_none:
/* Flow control completely disabled by software override. */
break; break;
case ixgbe_fc_rx_pause: case ixgbe_fc_rx_pause:
/* /*
* Rx Flow control is enabled, * Rx Flow control is enabled and Tx Flow control is
* and Tx Flow control is disabled. * disabled by software override. Since there really
* isn't a way to advertise that we are capable of RX
* Pause ONLY, we will advertise that we support both
* symmetric and asymmetric Rx PAUSE. Later, we will
* disable the adapter's ability to send PAUSE frames.
*/ */
frctl_reg |= IXGBE_FCTRL_RFCE; fctrl_reg |= IXGBE_FCTRL_RFCE;
break; break;
case ixgbe_fc_tx_pause: case ixgbe_fc_tx_pause:
/* /*
* Tx Flow control is enabled, and Rx Flow control is disabled, * Tx Flow control is enabled, and Rx Flow control is
* by a software over-ride. * disabled by software override.
*/ */
rmcs_reg |= IXGBE_RMCS_TFCE_802_3X; rmcs_reg |= IXGBE_RMCS_TFCE_802_3X;
break; break;
case ixgbe_fc_full: case ixgbe_fc_full:
/* /* Flow control (both Rx and Tx) is enabled by SW override. */
* Flow control (both Rx and Tx) is enabled by a software fctrl_reg |= IXGBE_FCTRL_RFCE;
* over-ride.
*/
frctl_reg |= IXGBE_FCTRL_RFCE;
rmcs_reg |= IXGBE_RMCS_TFCE_802_3X; rmcs_reg |= IXGBE_RMCS_TFCE_802_3X;
break; break;
default: default:
/* We should never get here. The value should be 0-3. */
hw_dbg(hw, "Flow control param set incorrectly\n"); hw_dbg(hw, "Flow control param set incorrectly\n");
ret_val = -IXGBE_ERR_CONFIG;
goto out;
break; break;
} }
/* Enable 802.3x based flow control settings. */ /* Enable 802.3x based flow control settings. */
IXGBE_WRITE_REG(hw, IXGBE_FCTRL, frctl_reg); IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl_reg);
IXGBE_WRITE_REG(hw, IXGBE_RMCS, rmcs_reg); IXGBE_WRITE_REG(hw, IXGBE_RMCS, rmcs_reg);
/* /* Set up and enable Rx high/low water mark thresholds, enable XON. */
* Check for invalid software configuration, zeros are completely if (hw->fc.current_mode & ixgbe_fc_tx_pause) {
* invalid for all parameters used past this point, and if we enable
* flow control with zero water marks, we blast flow control packets.
*/
if (!hw->fc.low_water || !hw->fc.high_water || !hw->fc.pause_time) {
hw_dbg(hw, "Flow control structure initialized incorrectly\n");
return IXGBE_ERR_INVALID_LINK_SETTINGS;
}
/*
* We need to set up the Receive Threshold high and low water
* marks as well as (optionally) enabling the transmission of
* XON frames.
*/
if (hw->fc.type & ixgbe_fc_tx_pause) {
if (hw->fc.send_xon) { if (hw->fc.send_xon) {
IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num), IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num),
(hw->fc.low_water | IXGBE_FCRTL_XONE)); (hw->fc.low_water | IXGBE_FCRTL_XONE));
...@@ -360,14 +331,93 @@ static s32 ixgbe_setup_fc_82598(struct ixgbe_hw *hw, s32 packetbuf_num) ...@@ -360,14 +331,93 @@ static s32 ixgbe_setup_fc_82598(struct ixgbe_hw *hw, s32 packetbuf_num)
IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num), IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num),
hw->fc.low_water); hw->fc.low_water);
} }
IXGBE_WRITE_REG(hw, IXGBE_FCRTH(packetbuf_num), IXGBE_WRITE_REG(hw, IXGBE_FCRTH(packetbuf_num),
(hw->fc.high_water)|IXGBE_FCRTH_FCEN); (hw->fc.high_water | IXGBE_FCRTH_FCEN));
} }
IXGBE_WRITE_REG(hw, IXGBE_FCTTV(0), hw->fc.pause_time); /* Configure pause time (2 TCs per register) */
reg = IXGBE_READ_REG(hw, IXGBE_FCTTV(packetbuf_num));
if ((packetbuf_num & 1) == 0)
reg = (reg & 0xFFFF0000) | hw->fc.pause_time;
else
reg = (reg & 0x0000FFFF) | (hw->fc.pause_time << 16);
IXGBE_WRITE_REG(hw, IXGBE_FCTTV(packetbuf_num / 2), reg);
IXGBE_WRITE_REG(hw, IXGBE_FCRTV, (hw->fc.pause_time >> 1)); IXGBE_WRITE_REG(hw, IXGBE_FCRTV, (hw->fc.pause_time >> 1));
return 0; out:
return ret_val;
}
/**
* ixgbe_setup_fc_82598 - Configure flow control settings
* @hw: pointer to hardware structure
* @packetbuf_num: packet buffer number (0-7)
*
* Configures the flow control settings based on SW configuration. This
* function is used for 802.3x flow control configuration only.
**/
static s32 ixgbe_setup_fc_82598(struct ixgbe_hw *hw, s32 packetbuf_num)
{
s32 ret_val = 0;
ixgbe_link_speed speed;
bool link_up;
/* Validate the packetbuf configuration */
if (packetbuf_num < 0 || packetbuf_num > 7) {
hw_dbg(hw, "Invalid packet buffer number [%d], expected range is"
" 0-7\n", packetbuf_num);
ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
goto out;
}
/*
* Validate the water mark configuration. Zero water marks are invalid
* because it causes the controller to just blast out fc packets.
*/
if (!hw->fc.low_water || !hw->fc.high_water || !hw->fc.pause_time) {
hw_dbg(hw, "Invalid water mark configuration\n");
ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
goto out;
}
/*
* Validate the requested mode. Strict IEEE mode does not allow
* ixgbe_fc_rx_pause because it will cause testing anomalies.
*/
if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
hw_dbg(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
goto out;
}
/*
* 10gig parts do not have a word in the EEPROM to determine the
* default flow control setting, so we explicitly set it to full.
*/
if (hw->fc.requested_mode == ixgbe_fc_default)
hw->fc.requested_mode = ixgbe_fc_full;
/*
* Save off the requested flow control mode for use later. Depending
* on the link partner's capabilities, we may or may not use this mode.
*/
hw->fc.current_mode = hw->fc.requested_mode;
/* Decide whether to use autoneg or not. */
hw->mac.ops.check_link(hw, &speed, &link_up, false);
if (hw->phy.multispeed_fiber && (speed == IXGBE_LINK_SPEED_1GB_FULL))
ret_val = ixgbe_fc_autoneg(hw);
if (ret_val)
goto out;
ret_val = ixgbe_fc_enable_82598(hw, packetbuf_num);
out:
return ret_val;
} }
/** /**
...@@ -414,7 +464,6 @@ static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw) ...@@ -414,7 +464,6 @@ static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw)
* case we get disconnected and then reconnected into a different hub * case we get disconnected and then reconnected into a different hub
* or switch with different Flow Control capabilities. * or switch with different Flow Control capabilities.
*/ */
hw->fc.original_type = hw->fc.type;
ixgbe_setup_fc_82598(hw, 0); ixgbe_setup_fc_82598(hw, 0);
/* Add delay to filter out noises during initial link setup */ /* Add delay to filter out noises during initial link setup */
......
...@@ -1486,6 +1486,144 @@ s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw) ...@@ -1486,6 +1486,144 @@ s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw)
return 0; return 0;
} }
/**
* ixgbe_fc_autoneg - Configure flow control
* @hw: pointer to hardware structure
*
* Negotiates flow control capabilities with link partner using autoneg and
* applies the results.
**/
s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw)
{
s32 ret_val = 0;
u32 i, reg, pcs_anadv_reg, pcs_lpab_reg;
reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
/*
* The possible values of fc.current_mode are:
* 0: Flow control is completely disabled
* 1: Rx flow control is enabled (we can receive pause frames,
* but not send pause frames).
* 2: Tx flow control is enabled (we can send pause frames but
* we do not support receiving pause frames).
* 3: Both Rx and Tx flow control (symmetric) are enabled.
* other: Invalid.
*/
switch (hw->fc.current_mode) {
case ixgbe_fc_none:
/* Flow control completely disabled by software override. */
reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
break;
case ixgbe_fc_rx_pause:
/*
* Rx Flow control is enabled and Tx Flow control is
* disabled by software override. Since there really
* isn't a way to advertise that we are capable of RX
* Pause ONLY, we will advertise that we support both
* symmetric and asymmetric Rx PAUSE. Later, we will
* disable the adapter's ability to send PAUSE frames.
*/
reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
break;
case ixgbe_fc_tx_pause:
/*
* Tx Flow control is enabled, and Rx Flow control is
* disabled by software override.
*/
reg |= (IXGBE_PCS1GANA_ASM_PAUSE);
reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE);
break;
case ixgbe_fc_full:
/* Flow control (both Rx and Tx) is enabled by SW override. */
reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
break;
default:
hw_dbg(hw, "Flow control param set incorrectly\n");
ret_val = -IXGBE_ERR_CONFIG;
goto out;
break;
}
IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg);
reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL);
/* Set PCS register for autoneg */
/* Enable and restart autoneg */
reg |= IXGBE_PCS1GLCTL_AN_ENABLE | IXGBE_PCS1GLCTL_AN_RESTART;
/* Disable AN timeout */
if (hw->fc.strict_ieee)
reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN;
hw_dbg(hw, "Configuring Autoneg; PCS_LCTL = 0x%08X\n", reg);
IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg);
/* See if autonegotiation has succeeded */
hw->mac.autoneg_succeeded = 0;
for (i = 0; i < FIBER_LINK_UP_LIMIT; i++) {
msleep(10);
reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA);
if ((reg & (IXGBE_PCS1GLSTA_LINK_OK |
IXGBE_PCS1GLSTA_AN_COMPLETE)) ==
(IXGBE_PCS1GLSTA_LINK_OK |
IXGBE_PCS1GLSTA_AN_COMPLETE)) {
if (!(reg & IXGBE_PCS1GLSTA_AN_TIMED_OUT))
hw->mac.autoneg_succeeded = 1;
break;
}
}
if (!hw->mac.autoneg_succeeded) {
/* Autoneg failed to achieve a link, so we turn fc off */
hw->fc.current_mode = ixgbe_fc_none;
hw_dbg(hw, "Flow Control = NONE.\n");
goto out;
}
/*
* Read the AN advertisement and LP ability registers and resolve
* local flow control settings accordingly
*/
pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP);
if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
(pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE)) {
/*
* Now we need to check if the user selected Rx ONLY
* of pause frames. In this case, we had to advertise
* FULL flow control because we could not advertise RX
* ONLY. Hence, we must now check to see if we need to
* turn OFF the TRANSMISSION of PAUSE frames.
*/
if (hw->fc.requested_mode == ixgbe_fc_full) {
hw->fc.current_mode = ixgbe_fc_full;
hw_dbg(hw, "Flow Control = FULL.\n");
} else {
hw->fc.current_mode = ixgbe_fc_rx_pause;
hw_dbg(hw, "Flow Control = RX PAUSE frames only.\n");
}
} else if (!(pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
(pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) &&
(pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
(pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) {
hw->fc.current_mode = ixgbe_fc_tx_pause;
hw_dbg(hw, "Flow Control = TX PAUSE frames only.\n");
} else if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
(pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) &&
!(pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
(pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) {
hw->fc.current_mode = ixgbe_fc_rx_pause;
hw_dbg(hw, "Flow Control = RX PAUSE frames only.\n");
} else {
hw->fc.current_mode = ixgbe_fc_none;
hw_dbg(hw, "Flow Control = NONE.\n");
}
out:
return ret_val;
}
/** /**
* ixgbe_disable_pcie_master - Disable PCI-express master access * ixgbe_disable_pcie_master - Disable PCI-express master access
* @hw: pointer to hardware structure * @hw: pointer to hardware structure
......
...@@ -61,6 +61,9 @@ s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list, ...@@ -61,6 +61,9 @@ s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list,
u32 addr_count, ixgbe_mc_addr_itr func); u32 addr_count, ixgbe_mc_addr_itr func);
s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw); s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw);
s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw); s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw);
s32 ixgbe_setup_fc_generic(struct ixgbe_hw *hw, s32 packetbuf_num);
s32 ixgbe_fc_enable(struct ixgbe_hw *hw, s32 packtetbuf_num);
s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw);
s32 ixgbe_validate_mac_addr(u8 *mac_addr); s32 ixgbe_validate_mac_addr(u8 *mac_addr);
s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask); s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask);
......
...@@ -298,7 +298,7 @@ s32 ixgbe_dcb_config_pfc_82598(struct ixgbe_hw *hw, ...@@ -298,7 +298,7 @@ s32 ixgbe_dcb_config_pfc_82598(struct ixgbe_hw *hw,
reg = IXGBE_READ_REG(hw, IXGBE_RMCS); reg = IXGBE_READ_REG(hw, IXGBE_RMCS);
reg &= ~IXGBE_RMCS_TFCE_802_3X; reg &= ~IXGBE_RMCS_TFCE_802_3X;
/* correct the reporting of our flow control status */ /* correct the reporting of our flow control status */
hw->fc.type = ixgbe_fc_none; hw->fc.current_mode = ixgbe_fc_none;
reg |= IXGBE_RMCS_TFCE_PRIORITY; reg |= IXGBE_RMCS_TFCE_PRIORITY;
IXGBE_WRITE_REG(hw, IXGBE_RMCS, reg); IXGBE_WRITE_REG(hw, IXGBE_RMCS, reg);
......
...@@ -224,13 +224,13 @@ static void ixgbe_get_pauseparam(struct net_device *netdev, ...@@ -224,13 +224,13 @@ static void ixgbe_get_pauseparam(struct net_device *netdev,
struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_hw *hw = &adapter->hw; struct ixgbe_hw *hw = &adapter->hw;
pause->autoneg = (hw->fc.type == ixgbe_fc_full ? 1 : 0); pause->autoneg = (hw->fc.current_mode == ixgbe_fc_full ? 1 : 0);
if (hw->fc.type == ixgbe_fc_rx_pause) { if (hw->fc.current_mode == ixgbe_fc_rx_pause) {
pause->rx_pause = 1; pause->rx_pause = 1;
} else if (hw->fc.type == ixgbe_fc_tx_pause) { } else if (hw->fc.current_mode == ixgbe_fc_tx_pause) {
pause->tx_pause = 1; pause->tx_pause = 1;
} else if (hw->fc.type == ixgbe_fc_full) { } else if (hw->fc.current_mode == ixgbe_fc_full) {
pause->rx_pause = 1; pause->rx_pause = 1;
pause->tx_pause = 1; pause->tx_pause = 1;
} }
...@@ -244,22 +244,17 @@ static int ixgbe_set_pauseparam(struct net_device *netdev, ...@@ -244,22 +244,17 @@ static int ixgbe_set_pauseparam(struct net_device *netdev,
if ((pause->autoneg == AUTONEG_ENABLE) || if ((pause->autoneg == AUTONEG_ENABLE) ||
(pause->rx_pause && pause->tx_pause)) (pause->rx_pause && pause->tx_pause))
hw->fc.type = ixgbe_fc_full; hw->fc.requested_mode = ixgbe_fc_full;
else if (pause->rx_pause && !pause->tx_pause) else if (pause->rx_pause && !pause->tx_pause)
hw->fc.type = ixgbe_fc_rx_pause; hw->fc.requested_mode = ixgbe_fc_rx_pause;
else if (!pause->rx_pause && pause->tx_pause) else if (!pause->rx_pause && pause->tx_pause)
hw->fc.type = ixgbe_fc_tx_pause; hw->fc.requested_mode = ixgbe_fc_tx_pause;
else if (!pause->rx_pause && !pause->tx_pause) else if (!pause->rx_pause && !pause->tx_pause)
hw->fc.type = ixgbe_fc_none; hw->fc.requested_mode = ixgbe_fc_none;
else else
return -EINVAL; return -EINVAL;
hw->fc.original_type = hw->fc.type; hw->mac.ops.setup_fc(hw, 0);
if (netif_running(netdev))
ixgbe_reinit_locked(adapter);
else
ixgbe_reset(adapter);
return 0; return 0;
} }
......
...@@ -1954,11 +1954,43 @@ static void ixgbe_configure(struct ixgbe_adapter *adapter) ...@@ -1954,11 +1954,43 @@ static void ixgbe_configure(struct ixgbe_adapter *adapter)
(adapter->rx_ring[i].count - 1)); (adapter->rx_ring[i].count - 1));
} }
/**
* ixgbe_link_config - set up initial link with default speed and duplex
* @hw: pointer to private hardware struct
*
* Returns 0 on success, negative on failure
**/
static int ixgbe_link_config(struct ixgbe_hw *hw)
{
u32 autoneg;
bool link_up = false;
u32 ret = IXGBE_ERR_LINK_SETUP;
if (hw->mac.ops.check_link)
ret = hw->mac.ops.check_link(hw, &autoneg, &link_up, false);
if (ret)
goto link_cfg_out;
if (hw->mac.ops.get_link_capabilities)
ret = hw->mac.ops.get_link_capabilities(hw, &autoneg,
&hw->mac.autoneg);
if (ret)
goto link_cfg_out;
if (hw->mac.ops.setup_link_speed)
ret = hw->mac.ops.setup_link_speed(hw, autoneg, true, link_up);
link_cfg_out:
return ret;
}
static int ixgbe_up_complete(struct ixgbe_adapter *adapter) static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
{ {
struct net_device *netdev = adapter->netdev; struct net_device *netdev = adapter->netdev;
struct ixgbe_hw *hw = &adapter->hw; struct ixgbe_hw *hw = &adapter->hw;
int i, j = 0; int i, j = 0;
int err;
int max_frame = netdev->mtu + ETH_HLEN + ETH_FCS_LEN; int max_frame = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
u32 txdctl, rxdctl, mhadd; u32 txdctl, rxdctl, mhadd;
u32 gpie; u32 gpie;
...@@ -2039,6 +2071,10 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) ...@@ -2039,6 +2071,10 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
ixgbe_irq_enable(adapter); ixgbe_irq_enable(adapter);
err = ixgbe_link_config(hw);
if (err)
dev_err(&adapter->pdev->dev, "link_config FAILED %d\n", err);
/* enable transmits */ /* enable transmits */
netif_tx_start_all_queues(netdev); netif_tx_start_all_queues(netdev);
...@@ -2792,8 +2828,7 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) ...@@ -2792,8 +2828,7 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
adapter->flags |= IXGBE_FLAG_FAN_FAIL_CAPABLE; adapter->flags |= IXGBE_FLAG_FAN_FAIL_CAPABLE;
/* default flow control settings */ /* default flow control settings */
hw->fc.original_type = ixgbe_fc_none; hw->fc.requested_mode = ixgbe_fc_none;
hw->fc.type = ixgbe_fc_none;
hw->fc.high_water = IXGBE_DEFAULT_FCRTH; hw->fc.high_water = IXGBE_DEFAULT_FCRTH;
hw->fc.low_water = IXGBE_DEFAULT_FCRTL; hw->fc.low_water = IXGBE_DEFAULT_FCRTL;
hw->fc.pause_time = IXGBE_DEFAULT_FCPAUSE; hw->fc.pause_time = IXGBE_DEFAULT_FCPAUSE;
...@@ -3916,37 +3951,6 @@ static void ixgbe_netpoll(struct net_device *netdev) ...@@ -3916,37 +3951,6 @@ static void ixgbe_netpoll(struct net_device *netdev)
} }
#endif #endif
/**
* ixgbe_link_config - set up initial link with default speed and duplex
* @hw: pointer to private hardware struct
*
* Returns 0 on success, negative on failure
**/
static int ixgbe_link_config(struct ixgbe_hw *hw)
{
u32 autoneg;
bool link_up = false;
u32 ret = IXGBE_ERR_LINK_SETUP;
if (hw->mac.ops.check_link)
ret = hw->mac.ops.check_link(hw, &autoneg, &link_up, false);
if (ret || !link_up)
goto link_cfg_out;
if (hw->mac.ops.get_link_capabilities)
ret = hw->mac.ops.get_link_capabilities(hw, &autoneg,
&hw->mac.autoneg);
if (ret)
goto link_cfg_out;
if (hw->mac.ops.setup_link_speed)
ret = hw->mac.ops.setup_link_speed(hw, autoneg, true, true);
link_cfg_out:
return ret;
}
static const struct net_device_ops ixgbe_netdev_ops = { static const struct net_device_ops ixgbe_netdev_ops = {
.ndo_open = ixgbe_open, .ndo_open = ixgbe_open,
.ndo_stop = ixgbe_close, .ndo_stop = ixgbe_close,
...@@ -4197,13 +4201,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, ...@@ -4197,13 +4201,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
/* reset the hardware with the new settings */ /* reset the hardware with the new settings */
hw->mac.ops.start_hw(hw); hw->mac.ops.start_hw(hw);
/* link_config depends on start_hw being called at least once */
err = ixgbe_link_config(hw);
if (err) {
dev_err(&pdev->dev, "setup_link_speed FAILED %d\n", err);
goto err_register;
}
netif_carrier_off(netdev); netif_carrier_off(netdev);
strcpy(netdev->name, "eth%d"); strcpy(netdev->name, "eth%d");
......
...@@ -771,6 +771,28 @@ ...@@ -771,6 +771,28 @@
#define IXGBE_LINK_UP_TIME 90 /* 9.0 Seconds */ #define IXGBE_LINK_UP_TIME 90 /* 9.0 Seconds */
#define IXGBE_AUTO_NEG_TIME 45 /* 4.5 Seconds */ #define IXGBE_AUTO_NEG_TIME 45 /* 4.5 Seconds */
#define FIBER_LINK_UP_LIMIT 50
/* PCS1GLSTA Bit Masks */
#define IXGBE_PCS1GLSTA_LINK_OK 1
#define IXGBE_PCS1GLSTA_SYNK_OK 0x10
#define IXGBE_PCS1GLSTA_AN_COMPLETE 0x10000
#define IXGBE_PCS1GLSTA_AN_PAGE_RX 0x20000
#define IXGBE_PCS1GLSTA_AN_TIMED_OUT 0x40000
#define IXGBE_PCS1GLSTA_AN_REMOTE_FAULT 0x80000
#define IXGBE_PCS1GLSTA_AN_ERROR_RWS 0x100000
#define IXGBE_PCS1GANA_SYM_PAUSE 0x80
#define IXGBE_PCS1GANA_ASM_PAUSE 0x100
/* PCS1GLCTL Bit Masks */
#define IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN 0x00040000 /* PCS 1G autoneg to en */
#define IXGBE_PCS1GLCTL_FLV_LINK_UP 1
#define IXGBE_PCS1GLCTL_FORCE_LINK 0x20
#define IXGBE_PCS1GLCTL_LOW_LINK_LATCH 0x40
#define IXGBE_PCS1GLCTL_AN_ENABLE 0x10000
#define IXGBE_PCS1GLCTL_AN_RESTART 0x20000
/* SW Semaphore Register bitmasks */ /* SW Semaphore Register bitmasks */
#define IXGBE_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */ #define IXGBE_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */
#define IXGBE_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */ #define IXGBE_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */
...@@ -1270,7 +1292,7 @@ enum ixgbe_media_type { ...@@ -1270,7 +1292,7 @@ enum ixgbe_media_type {
}; };
/* Flow Control Settings */ /* Flow Control Settings */
enum ixgbe_fc_type { enum ixgbe_fc_mode {
ixgbe_fc_none = 0, ixgbe_fc_none = 0,
ixgbe_fc_rx_pause, ixgbe_fc_rx_pause,
ixgbe_fc_tx_pause, ixgbe_fc_tx_pause,
...@@ -1294,8 +1316,8 @@ struct ixgbe_fc_info { ...@@ -1294,8 +1316,8 @@ struct ixgbe_fc_info {
u16 pause_time; /* Flow Control Pause timer */ u16 pause_time; /* Flow Control Pause timer */
bool send_xon; /* Flow control send XON */ bool send_xon; /* Flow control send XON */
bool strict_ieee; /* Strict IEEE mode */ bool strict_ieee; /* Strict IEEE mode */
enum ixgbe_fc_type type; /* Type of flow control */ enum ixgbe_fc_mode current_mode; /* FC mode in effect */
enum ixgbe_fc_type original_type; enum ixgbe_fc_mode requested_mode; /* FC mode requested by caller */
}; };
/* Statistics counters collected by the MAC */ /* Statistics counters collected by the MAC */
...@@ -1475,6 +1497,7 @@ struct ixgbe_phy_info { ...@@ -1475,6 +1497,7 @@ struct ixgbe_phy_info {
bool reset_disable; bool reset_disable;
ixgbe_autoneg_advertised autoneg_advertised; ixgbe_autoneg_advertised autoneg_advertised;
bool autoneg_wait_to_complete; bool autoneg_wait_to_complete;
bool multispeed_fiber;
}; };
struct ixgbe_hw { struct ixgbe_hw {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment