diff options
author | Yuval Mintz <Yuval.Mintz@qlogic.com> | 2015-06-25 08:19:21 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-06-25 09:30:33 -0400 |
commit | 1359d73c1d6fa737545d946f9bcb4b9a6b13a6ea (patch) | |
tree | fa29dc8742c83df1cde02c1bdf5f5881771cfe4f /drivers/net | |
parent | b175c3a44fab06e1eccc793e3dadccbf6afc54cf (diff) |
bnx2x: Correct asymmetric flow-control
This fixes several issues relating to asymmetric configuration:
1. When user requests to disable TX, the local-device needs to
advertise both PAUSE and ASM_DIR, but to avoid transmitting pause
frames. In the 578xx, it would ignore the TX disable.
2. When user advertises RX-only, ASM_DIR was advertised instead of
PAUSE/ASM_DIR.
3. When changing mode, the advertised PAUSE/ASM_DIR was not cleared
before setting new one, so disabling RX or TX had no impact on the
'advertised' as appeared in the 'ethtool -a' output.
Signed-off-by: Yaniv Rosner <Yaniv.Rosner@qlogic.com>
Signed-off-by: Yuval Mintz <Yuval.Mintz@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c | 33 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 10 |
2 files changed, 29 insertions, 14 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index 21a0d6afca4a..b287fc8d3c80 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c | |||
@@ -3392,9 +3392,9 @@ static void bnx2x_calc_ieee_aneg_adv(struct bnx2x_phy *phy, | |||
3392 | case BNX2X_FLOW_CTRL_AUTO: | 3392 | case BNX2X_FLOW_CTRL_AUTO: |
3393 | switch (params->req_fc_auto_adv) { | 3393 | switch (params->req_fc_auto_adv) { |
3394 | case BNX2X_FLOW_CTRL_BOTH: | 3394 | case BNX2X_FLOW_CTRL_BOTH: |
3395 | case BNX2X_FLOW_CTRL_RX: | ||
3395 | *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH; | 3396 | *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH; |
3396 | break; | 3397 | break; |
3397 | case BNX2X_FLOW_CTRL_RX: | ||
3398 | case BNX2X_FLOW_CTRL_TX: | 3398 | case BNX2X_FLOW_CTRL_TX: |
3399 | *ieee_fc |= | 3399 | *ieee_fc |= |
3400 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC; | 3400 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC; |
@@ -3488,14 +3488,21 @@ static void bnx2x_ext_phy_set_pause(struct link_params *params, | |||
3488 | bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV_PAUSE, val); | 3488 | bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV_PAUSE, val); |
3489 | } | 3489 | } |
3490 | 3490 | ||
3491 | static void bnx2x_pause_resolve(struct link_vars *vars, u32 pause_result) | 3491 | static void bnx2x_pause_resolve(struct bnx2x_phy *phy, |
3492 | { /* LD LP */ | 3492 | struct link_params *params, |
3493 | struct link_vars *vars, | ||
3494 | u32 pause_result) | ||
3495 | { | ||
3496 | struct bnx2x *bp = params->bp; | ||
3497 | /* LD LP */ | ||
3493 | switch (pause_result) { /* ASYM P ASYM P */ | 3498 | switch (pause_result) { /* ASYM P ASYM P */ |
3494 | case 0xb: /* 1 0 1 1 */ | 3499 | case 0xb: /* 1 0 1 1 */ |
3500 | DP(NETIF_MSG_LINK, "Flow Control: TX only\n"); | ||
3495 | vars->flow_ctrl = BNX2X_FLOW_CTRL_TX; | 3501 | vars->flow_ctrl = BNX2X_FLOW_CTRL_TX; |
3496 | break; | 3502 | break; |
3497 | 3503 | ||
3498 | case 0xe: /* 1 1 1 0 */ | 3504 | case 0xe: /* 1 1 1 0 */ |
3505 | DP(NETIF_MSG_LINK, "Flow Control: RX only\n"); | ||
3499 | vars->flow_ctrl = BNX2X_FLOW_CTRL_RX; | 3506 | vars->flow_ctrl = BNX2X_FLOW_CTRL_RX; |
3500 | break; | 3507 | break; |
3501 | 3508 | ||
@@ -3503,10 +3510,22 @@ static void bnx2x_pause_resolve(struct link_vars *vars, u32 pause_result) | |||
3503 | case 0x7: /* 0 1 1 1 */ | 3510 | case 0x7: /* 0 1 1 1 */ |
3504 | case 0xd: /* 1 1 0 1 */ | 3511 | case 0xd: /* 1 1 0 1 */ |
3505 | case 0xf: /* 1 1 1 1 */ | 3512 | case 0xf: /* 1 1 1 1 */ |
3506 | vars->flow_ctrl = BNX2X_FLOW_CTRL_BOTH; | 3513 | /* If the user selected to advertise RX ONLY, |
3514 | * although we advertised both, need to enable | ||
3515 | * RX only. | ||
3516 | */ | ||
3517 | if (params->req_fc_auto_adv == BNX2X_FLOW_CTRL_BOTH) { | ||
3518 | DP(NETIF_MSG_LINK, "Flow Control: RX & TX\n"); | ||
3519 | vars->flow_ctrl = BNX2X_FLOW_CTRL_BOTH; | ||
3520 | } else { | ||
3521 | DP(NETIF_MSG_LINK, "Flow Control: RX only\n"); | ||
3522 | vars->flow_ctrl = BNX2X_FLOW_CTRL_RX; | ||
3523 | } | ||
3507 | break; | 3524 | break; |
3508 | 3525 | ||
3509 | default: | 3526 | default: |
3527 | DP(NETIF_MSG_LINK, "Flow Control: None\n"); | ||
3528 | vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE; | ||
3510 | break; | 3529 | break; |
3511 | } | 3530 | } |
3512 | if (pause_result & (1<<0)) | 3531 | if (pause_result & (1<<0)) |
@@ -3567,7 +3586,7 @@ static void bnx2x_ext_phy_update_adv_fc(struct bnx2x_phy *phy, | |||
3567 | pause_result |= (lp_pause & | 3586 | pause_result |= (lp_pause & |
3568 | MDIO_AN_REG_ADV_PAUSE_MASK) >> 10; | 3587 | MDIO_AN_REG_ADV_PAUSE_MASK) >> 10; |
3569 | DP(NETIF_MSG_LINK, "Ext PHY pause result 0x%x\n", pause_result); | 3588 | DP(NETIF_MSG_LINK, "Ext PHY pause result 0x%x\n", pause_result); |
3570 | bnx2x_pause_resolve(vars, pause_result); | 3589 | bnx2x_pause_resolve(phy, params, vars, pause_result); |
3571 | 3590 | ||
3572 | } | 3591 | } |
3573 | 3592 | ||
@@ -5396,7 +5415,7 @@ static void bnx2x_update_adv_fc(struct bnx2x_phy *phy, | |||
5396 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>7; | 5415 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>7; |
5397 | DP(NETIF_MSG_LINK, "pause_result CL37 0x%x\n", pause_result); | 5416 | DP(NETIF_MSG_LINK, "pause_result CL37 0x%x\n", pause_result); |
5398 | } | 5417 | } |
5399 | bnx2x_pause_resolve(vars, pause_result); | 5418 | bnx2x_pause_resolve(phy, params, vars, pause_result); |
5400 | 5419 | ||
5401 | } | 5420 | } |
5402 | 5421 | ||
@@ -7129,7 +7148,7 @@ static void bnx2x_8073_resolve_fc(struct bnx2x_phy *phy, | |||
7129 | pause_result |= (lp_pause & | 7148 | pause_result |= (lp_pause & |
7130 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 7; | 7149 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 7; |
7131 | 7150 | ||
7132 | bnx2x_pause_resolve(vars, pause_result); | 7151 | bnx2x_pause_resolve(phy, params, vars, pause_result); |
7133 | DP(NETIF_MSG_LINK, "Ext PHY CL37 pause result 0x%x\n", | 7152 | DP(NETIF_MSG_LINK, "Ext PHY CL37 pause result 0x%x\n", |
7134 | pause_result); | 7153 | pause_result); |
7135 | } | 7154 | } |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 33501bcddc48..a03a9f25f8bb 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | |||
@@ -2287,13 +2287,11 @@ static int bnx2x_set_spio(struct bnx2x *bp, int spio, u32 mode) | |||
2287 | void bnx2x_calc_fc_adv(struct bnx2x *bp) | 2287 | void bnx2x_calc_fc_adv(struct bnx2x *bp) |
2288 | { | 2288 | { |
2289 | u8 cfg_idx = bnx2x_get_link_cfg_idx(bp); | 2289 | u8 cfg_idx = bnx2x_get_link_cfg_idx(bp); |
2290 | |||
2291 | bp->port.advertising[cfg_idx] &= ~(ADVERTISED_Asym_Pause | | ||
2292 | ADVERTISED_Pause); | ||
2290 | switch (bp->link_vars.ieee_fc & | 2293 | switch (bp->link_vars.ieee_fc & |
2291 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK) { | 2294 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK) { |
2292 | case MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE: | ||
2293 | bp->port.advertising[cfg_idx] &= ~(ADVERTISED_Asym_Pause | | ||
2294 | ADVERTISED_Pause); | ||
2295 | break; | ||
2296 | |||
2297 | case MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH: | 2295 | case MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH: |
2298 | bp->port.advertising[cfg_idx] |= (ADVERTISED_Asym_Pause | | 2296 | bp->port.advertising[cfg_idx] |= (ADVERTISED_Asym_Pause | |
2299 | ADVERTISED_Pause); | 2297 | ADVERTISED_Pause); |
@@ -2304,8 +2302,6 @@ void bnx2x_calc_fc_adv(struct bnx2x *bp) | |||
2304 | break; | 2302 | break; |
2305 | 2303 | ||
2306 | default: | 2304 | default: |
2307 | bp->port.advertising[cfg_idx] &= ~(ADVERTISED_Asym_Pause | | ||
2308 | ADVERTISED_Pause); | ||
2309 | break; | 2305 | break; |
2310 | } | 2306 | } |
2311 | } | 2307 | } |