mirror of https://gitee.com/openkylin/linux.git
ixgbe: convert low_water into an array
Since fc.high_water is an array, we should treat low_water as an array also. This allows the algorithm to output different values for different TCs, and then we can distinguish between them. In addition, this patch changes one path that didn't honor the return value from ixgbe_setup_fc. Reported-by: Aaron Salter <aaron.k.salter@intel.com> Signed-off-by: Jacob Keller <jacob.e.keller@intel.com> Tested-by: Phil Schmitt <phillip.j.schmitt@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
This commit is contained in:
parent
fd0d192be6
commit
e5776620a7
|
@ -337,19 +337,25 @@ static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw)
|
||||||
int i;
|
int i;
|
||||||
bool link_up;
|
bool link_up;
|
||||||
|
|
||||||
/*
|
/* Validate the water mark configuration */
|
||||||
* Validate the water mark configuration for packet buffer 0. Zero
|
if (!hw->fc.pause_time) {
|
||||||
* water marks indicate that the packet buffer was not configured
|
|
||||||
* and the watermarks for packet buffer 0 should always be configured.
|
|
||||||
*/
|
|
||||||
if (!hw->fc.low_water ||
|
|
||||||
!hw->fc.high_water[0] ||
|
|
||||||
!hw->fc.pause_time) {
|
|
||||||
hw_dbg(hw, "Invalid water mark configuration\n");
|
|
||||||
ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
|
ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Low water mark of zero causes XOFF floods */
|
||||||
|
for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
|
||||||
|
if ((hw->fc.current_mode & ixgbe_fc_tx_pause) &&
|
||||||
|
hw->fc.high_water[i]) {
|
||||||
|
if (!hw->fc.low_water[i] ||
|
||||||
|
hw->fc.low_water[i] >= hw->fc.high_water[i]) {
|
||||||
|
hw_dbg(hw, "Invalid water mark configuration\n");
|
||||||
|
ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* On 82598 having Rx FC on causes resets while doing 1G
|
* On 82598 having Rx FC on causes resets while doing 1G
|
||||||
* so if it's on turn it off once we know link_speed. For
|
* so if it's on turn it off once we know link_speed. For
|
||||||
|
@ -432,12 +438,11 @@ static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw)
|
||||||
IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl_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);
|
||||||
|
|
||||||
fcrtl = (hw->fc.low_water << 10) | IXGBE_FCRTL_XONE;
|
|
||||||
|
|
||||||
/* Set up and enable Rx high/low water mark thresholds, enable XON. */
|
/* Set up and enable Rx high/low water mark thresholds, enable XON. */
|
||||||
for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
|
for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
|
||||||
if ((hw->fc.current_mode & ixgbe_fc_tx_pause) &&
|
if ((hw->fc.current_mode & ixgbe_fc_tx_pause) &&
|
||||||
hw->fc.high_water[i]) {
|
hw->fc.high_water[i]) {
|
||||||
|
fcrtl = (hw->fc.low_water[i] << 10) | IXGBE_FCRTL_XONE;
|
||||||
fcrth = (hw->fc.high_water[i] << 10) | IXGBE_FCRTH_FCEN;
|
fcrth = (hw->fc.high_water[i] << 10) | IXGBE_FCRTH_FCEN;
|
||||||
IXGBE_WRITE_REG(hw, IXGBE_FCRTL(i), fcrtl);
|
IXGBE_WRITE_REG(hw, IXGBE_FCRTL(i), fcrtl);
|
||||||
IXGBE_WRITE_REG(hw, IXGBE_FCRTH(i), fcrth);
|
IXGBE_WRITE_REG(hw, IXGBE_FCRTH(i), fcrth);
|
||||||
|
|
|
@ -271,6 +271,7 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw)
|
||||||
**/
|
**/
|
||||||
s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw)
|
s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw)
|
||||||
{
|
{
|
||||||
|
s32 ret_val;
|
||||||
u32 ctrl_ext;
|
u32 ctrl_ext;
|
||||||
|
|
||||||
/* Set the media type */
|
/* Set the media type */
|
||||||
|
@ -292,12 +293,15 @@ s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw)
|
||||||
IXGBE_WRITE_FLUSH(hw);
|
IXGBE_WRITE_FLUSH(hw);
|
||||||
|
|
||||||
/* Setup flow control */
|
/* Setup flow control */
|
||||||
ixgbe_setup_fc(hw);
|
ret_val = ixgbe_setup_fc(hw);
|
||||||
|
if (!ret_val)
|
||||||
|
goto out;
|
||||||
|
|
||||||
/* Clear adapter stopped flag */
|
/* Clear adapter stopped flag */
|
||||||
hw->adapter_stopped = false;
|
hw->adapter_stopped = false;
|
||||||
|
|
||||||
return 0;
|
out:
|
||||||
|
return ret_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2106,19 +2110,25 @@ s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw)
|
||||||
u32 fcrtl, fcrth;
|
u32 fcrtl, fcrth;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/*
|
/* Validate the water mark configuration. */
|
||||||
* Validate the water mark configuration for packet buffer 0. Zero
|
if (!hw->fc.pause_time) {
|
||||||
* water marks indicate that the packet buffer was not configured
|
|
||||||
* and the watermarks for packet buffer 0 should always be configured.
|
|
||||||
*/
|
|
||||||
if (!hw->fc.low_water ||
|
|
||||||
!hw->fc.high_water[0] ||
|
|
||||||
!hw->fc.pause_time) {
|
|
||||||
hw_dbg(hw, "Invalid water mark configuration\n");
|
|
||||||
ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
|
ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Low water mark of zero causes XOFF floods */
|
||||||
|
for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
|
||||||
|
if ((hw->fc.current_mode & ixgbe_fc_tx_pause) &&
|
||||||
|
hw->fc.high_water[i]) {
|
||||||
|
if (!hw->fc.low_water[i] ||
|
||||||
|
hw->fc.low_water[i] >= hw->fc.high_water[i]) {
|
||||||
|
hw_dbg(hw, "Invalid water mark configuration\n");
|
||||||
|
ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Negotiate the fc mode to use */
|
/* Negotiate the fc mode to use */
|
||||||
ixgbe_fc_autoneg(hw);
|
ixgbe_fc_autoneg(hw);
|
||||||
|
|
||||||
|
@ -2181,12 +2191,11 @@ s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw)
|
||||||
IXGBE_WRITE_REG(hw, IXGBE_MFLCN, mflcn_reg);
|
IXGBE_WRITE_REG(hw, IXGBE_MFLCN, mflcn_reg);
|
||||||
IXGBE_WRITE_REG(hw, IXGBE_FCCFG, fccfg_reg);
|
IXGBE_WRITE_REG(hw, IXGBE_FCCFG, fccfg_reg);
|
||||||
|
|
||||||
fcrtl = (hw->fc.low_water << 10) | IXGBE_FCRTL_XONE;
|
|
||||||
|
|
||||||
/* Set up and enable Rx high/low water mark thresholds, enable XON. */
|
/* Set up and enable Rx high/low water mark thresholds, enable XON. */
|
||||||
for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
|
for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
|
||||||
if ((hw->fc.current_mode & ixgbe_fc_tx_pause) &&
|
if ((hw->fc.current_mode & ixgbe_fc_tx_pause) &&
|
||||||
hw->fc.high_water[i]) {
|
hw->fc.high_water[i]) {
|
||||||
|
fcrtl = (hw->fc.low_water[i] << 10) | IXGBE_FCRTL_XONE;
|
||||||
IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), fcrtl);
|
IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), fcrtl);
|
||||||
fcrth = (hw->fc.high_water[i] << 10) | IXGBE_FCRTH_FCEN;
|
fcrth = (hw->fc.high_water[i] << 10) | IXGBE_FCRTH_FCEN;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -208,7 +208,6 @@ s32 ixgbe_dcb_config_pfc_82598(struct ixgbe_hw *hw, u8 pfc_en)
|
||||||
|
|
||||||
IXGBE_WRITE_REG(hw, IXGBE_FCTRL, reg);
|
IXGBE_WRITE_REG(hw, IXGBE_FCTRL, reg);
|
||||||
|
|
||||||
fcrtl = (hw->fc.low_water << 10) | IXGBE_FCRTL_XONE;
|
|
||||||
/* Configure PFC Tx thresholds per TC */
|
/* Configure PFC Tx thresholds per TC */
|
||||||
for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
|
for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
|
||||||
if (!(pfc_en & (1 << i))) {
|
if (!(pfc_en & (1 << i))) {
|
||||||
|
@ -217,6 +216,7 @@ s32 ixgbe_dcb_config_pfc_82598(struct ixgbe_hw *hw, u8 pfc_en)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fcrtl = (hw->fc.low_water[i] << 10) | IXGBE_FCRTL_XONE;
|
||||||
reg = (hw->fc.high_water[i] << 10) | IXGBE_FCRTH_FCEN;
|
reg = (hw->fc.high_water[i] << 10) | IXGBE_FCRTH_FCEN;
|
||||||
IXGBE_WRITE_REG(hw, IXGBE_FCRTL(i), fcrtl);
|
IXGBE_WRITE_REG(hw, IXGBE_FCRTL(i), fcrtl);
|
||||||
IXGBE_WRITE_REG(hw, IXGBE_FCRTH(i), reg);
|
IXGBE_WRITE_REG(hw, IXGBE_FCRTH(i), reg);
|
||||||
|
|
|
@ -242,7 +242,6 @@ s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, u8 pfc_en, u8 *prio_tc)
|
||||||
max_tc = prio_tc[i];
|
max_tc = prio_tc[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
fcrtl = (hw->fc.low_water << 10) | IXGBE_FCRTL_XONE;
|
|
||||||
|
|
||||||
/* Configure PFC Tx thresholds per TC */
|
/* Configure PFC Tx thresholds per TC */
|
||||||
for (i = 0; i <= max_tc; i++) {
|
for (i = 0; i <= max_tc; i++) {
|
||||||
|
@ -257,6 +256,7 @@ s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, u8 pfc_en, u8 *prio_tc)
|
||||||
|
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
reg = (hw->fc.high_water[i] << 10) | IXGBE_FCRTH_FCEN;
|
reg = (hw->fc.high_water[i] << 10) | IXGBE_FCRTH_FCEN;
|
||||||
|
fcrtl = (hw->fc.low_water[i] << 10) | IXGBE_FCRTL_XONE;
|
||||||
IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), fcrtl);
|
IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), fcrtl);
|
||||||
} else {
|
} else {
|
||||||
reg = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)) - 32;
|
reg = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)) - 32;
|
||||||
|
|
|
@ -81,9 +81,7 @@ struct ixgbe_fcoe {
|
||||||
void *extra_ddp_buffer;
|
void *extra_ddp_buffer;
|
||||||
dma_addr_t extra_ddp_buffer_dma;
|
dma_addr_t extra_ddp_buffer_dma;
|
||||||
unsigned long mode;
|
unsigned long mode;
|
||||||
#ifdef CONFIG_IXGBE_DCB
|
|
||||||
u8 up;
|
u8 up;
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _IXGBE_FCOE_H */
|
#endif /* _IXGBE_FCOE_H */
|
||||||
|
|
|
@ -4100,8 +4100,8 @@ static int ixgbe_hpbthresh(struct ixgbe_adapter *adapter, int pb)
|
||||||
(tc < IXGBE_FCOE_JUMBO_FRAME_SIZE) &&
|
(tc < IXGBE_FCOE_JUMBO_FRAME_SIZE) &&
|
||||||
(pb == ixgbe_fcoe_get_tc(adapter)))
|
(pb == ixgbe_fcoe_get_tc(adapter)))
|
||||||
tc = IXGBE_FCOE_JUMBO_FRAME_SIZE;
|
tc = IXGBE_FCOE_JUMBO_FRAME_SIZE;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Calculate delay value for device */
|
/* Calculate delay value for device */
|
||||||
switch (hw->mac.type) {
|
switch (hw->mac.type) {
|
||||||
case ixgbe_mac_X540:
|
case ixgbe_mac_X540:
|
||||||
|
@ -4142,7 +4142,7 @@ static int ixgbe_hpbthresh(struct ixgbe_adapter *adapter, int pb)
|
||||||
* @adapter: board private structure to calculate for
|
* @adapter: board private structure to calculate for
|
||||||
* @pb: packet buffer to calculate
|
* @pb: packet buffer to calculate
|
||||||
*/
|
*/
|
||||||
static int ixgbe_lpbthresh(struct ixgbe_adapter *adapter)
|
static int ixgbe_lpbthresh(struct ixgbe_adapter *adapter, int pb)
|
||||||
{
|
{
|
||||||
struct ixgbe_hw *hw = &adapter->hw;
|
struct ixgbe_hw *hw = &adapter->hw;
|
||||||
struct net_device *dev = adapter->netdev;
|
struct net_device *dev = adapter->netdev;
|
||||||
|
@ -4152,6 +4152,14 @@ static int ixgbe_lpbthresh(struct ixgbe_adapter *adapter)
|
||||||
/* Calculate max LAN frame size */
|
/* Calculate max LAN frame size */
|
||||||
tc = dev->mtu + ETH_HLEN + ETH_FCS_LEN;
|
tc = dev->mtu + ETH_HLEN + ETH_FCS_LEN;
|
||||||
|
|
||||||
|
#ifdef IXGBE_FCOE
|
||||||
|
/* FCoE traffic class uses FCOE jumbo frames */
|
||||||
|
if ((dev->features & NETIF_F_FCOE_MTU) &&
|
||||||
|
(tc < IXGBE_FCOE_JUMBO_FRAME_SIZE) &&
|
||||||
|
(pb == netdev_get_prio_tc_map(dev, adapter->fcoe.up)))
|
||||||
|
tc = IXGBE_FCOE_JUMBO_FRAME_SIZE;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Calculate delay value for device */
|
/* Calculate delay value for device */
|
||||||
switch (hw->mac.type) {
|
switch (hw->mac.type) {
|
||||||
case ixgbe_mac_X540:
|
case ixgbe_mac_X540:
|
||||||
|
@ -4178,15 +4186,17 @@ static void ixgbe_pbthresh_setup(struct ixgbe_adapter *adapter)
|
||||||
if (!num_tc)
|
if (!num_tc)
|
||||||
num_tc = 1;
|
num_tc = 1;
|
||||||
|
|
||||||
hw->fc.low_water = ixgbe_lpbthresh(adapter);
|
|
||||||
|
|
||||||
for (i = 0; i < num_tc; i++) {
|
for (i = 0; i < num_tc; i++) {
|
||||||
hw->fc.high_water[i] = ixgbe_hpbthresh(adapter, i);
|
hw->fc.high_water[i] = ixgbe_hpbthresh(adapter, i);
|
||||||
|
hw->fc.low_water[i] = ixgbe_lpbthresh(adapter, i);
|
||||||
|
|
||||||
/* Low water marks must not be larger than high water marks */
|
/* Low water marks must not be larger than high water marks */
|
||||||
if (hw->fc.low_water > hw->fc.high_water[i])
|
if (hw->fc.low_water[i] > hw->fc.high_water[i])
|
||||||
hw->fc.low_water = 0;
|
hw->fc.low_water[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (; i < MAX_TRAFFIC_CLASS; i++)
|
||||||
|
hw->fc.high_water[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ixgbe_configure_pb(struct ixgbe_adapter *adapter)
|
static void ixgbe_configure_pb(struct ixgbe_adapter *adapter)
|
||||||
|
|
|
@ -2746,7 +2746,7 @@ struct ixgbe_bus_info {
|
||||||
/* Flow control parameters */
|
/* Flow control parameters */
|
||||||
struct ixgbe_fc_info {
|
struct ixgbe_fc_info {
|
||||||
u32 high_water[MAX_TRAFFIC_CLASS]; /* Flow Control High-water */
|
u32 high_water[MAX_TRAFFIC_CLASS]; /* Flow Control High-water */
|
||||||
u32 low_water; /* Flow Control Low-water */
|
u32 low_water[MAX_TRAFFIC_CLASS]; /* Flow Control Low-water */
|
||||||
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 */
|
||||||
|
|
Loading…
Reference in New Issue