Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 134312
b: refs/heads/master
c: 0ecc061
h: refs/heads/master
v: v3
  • Loading branch information
Peter P Waskiewicz Jr authored and David S. Miller committed Feb 7, 2009
1 parent c9e43aa commit 2126b19
Show file tree
Hide file tree
Showing 8 changed files with 328 additions and 123 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 394827913e371b058849349c6fc9d52c59c31a3d
refs/heads/master: 0ecc061d1967e9f2694502079e00d9d6e1e39072
177 changes: 113 additions & 64 deletions trunk/drivers/net/ixgbe/ixgbe_82598.c
Original file line number Diff line number Diff line change
Expand Up @@ -255,119 +255,169 @@ 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
* @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.
* Enable flow control according to the current settings.
**/
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 reg;

if (packetbuf_num < 0 || packetbuf_num > 7) {
hw_dbg(hw, "Invalid packet buffer number [%d], expected range is"
" 0-7\n", packetbuf_num);
}

frctl_reg = IXGBE_READ_REG(hw, IXGBE_FCTRL);
frctl_reg &= ~(IXGBE_FCTRL_RFCE | IXGBE_FCTRL_RPFCE);
fctrl_reg = IXGBE_READ_REG(hw, IXGBE_FCTRL);
fctrl_reg &= ~(IXGBE_FCTRL_RFCE | IXGBE_FCTRL_RPFCE);

rmcs_reg = IXGBE_READ_REG(hw, IXGBE_RMCS);
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
* 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:
* 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)
* 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.type) {
switch (hw->fc.current_mode) {
case ixgbe_fc_none:
/* Flow control completely disabled by software override. */
break;
case ixgbe_fc_rx_pause:
/*
* Rx Flow control is enabled,
* and Tx Flow control is disabled.
* 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.
*/
frctl_reg |= IXGBE_FCTRL_RFCE;
fctrl_reg |= IXGBE_FCTRL_RFCE;
break;
case ixgbe_fc_tx_pause:
/*
* Tx Flow control is enabled, and Rx Flow control is disabled,
* by a software over-ride.
* Tx Flow control is enabled, and Rx Flow control is
* disabled by software override.
*/
rmcs_reg |= IXGBE_RMCS_TFCE_802_3X;
break;
case ixgbe_fc_full:
/*
* Flow control (both Rx and Tx) is enabled by a software
* over-ride.
*/
frctl_reg |= IXGBE_FCTRL_RFCE;
/* Flow control (both Rx and Tx) is enabled by SW override. */
fctrl_reg |= IXGBE_FCTRL_RFCE;
rmcs_reg |= IXGBE_RMCS_TFCE_802_3X;
break;
default:
/* We should never get here. The value should be 0-3. */
hw_dbg(hw, "Flow control param set incorrectly\n");
ret_val = -IXGBE_ERR_CONFIG;
goto out;
break;
}

/* 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);

/*
* Check for invalid software configuration, zeros are completely
* 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) {
/* Set up and enable Rx high/low water mark thresholds, enable XON. */
if (hw->fc.current_mode & ixgbe_fc_tx_pause) {
if (hw->fc.send_xon) {
IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num),
(hw->fc.low_water | IXGBE_FCRTL_XONE));
} else {
IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num),
hw->fc.low_water);
}

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));

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;
}

/**
Expand Down Expand Up @@ -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
* or switch with different Flow Control capabilities.
*/
hw->fc.original_type = hw->fc.type;
ixgbe_setup_fc_82598(hw, 0);

/* Add delay to filter out noises during initial link setup */
Expand Down
138 changes: 138 additions & 0 deletions trunk/drivers/net/ixgbe/ixgbe_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -1486,6 +1486,144 @@ s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw)
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
* @hw: pointer to hardware structure
Expand Down
3 changes: 3 additions & 0 deletions trunk/drivers/net/ixgbe/ixgbe_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
s32 ixgbe_enable_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_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask);
Expand Down
Loading

0 comments on commit 2126b19

Please sign in to comment.