Commit 5be73b47 authored by Matt Carlson's avatar Matt Carlson Committed by David S. Miller

[TG3]: Correct sw autoneg flow control advertisements

This patch modifies the software autoneg code to use the administrator
specified flow control parameters.  Since the autonegotiation code uses
alternative flow control enumerations, the 1000-BaseX utility functions
are used and code was added to convert the definitions to and from the
alternate enumerations.
Signed-off-by: default avatarMatt Carlson <mcarlson@broadcom.com>
Signed-off-by: default avatarMichael Chan <mchan@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 82cd3d11
...@@ -1695,7 +1695,7 @@ static void tg3_setup_flow_control(struct tg3 *tp, u32 local_adv, u32 remote_adv ...@@ -1695,7 +1695,7 @@ static void tg3_setup_flow_control(struct tg3 *tp, u32 local_adv, u32 remote_adv
u32 old_tx_mode = tp->tx_mode; u32 old_tx_mode = tp->tx_mode;
if (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) { if (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) {
if (tp->tg3_flags2 & (TG3_FLG2_MII_SERDES|TG3_FLG2_HW_AUTONEG)) if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES)
new_tg3_flags = tg3_resolve_flowctrl_1000X(local_adv, new_tg3_flags = tg3_resolve_flowctrl_1000X(local_adv,
remote_adv); remote_adv);
else else
...@@ -2317,6 +2317,7 @@ struct tg3_fiber_aneginfo { ...@@ -2317,6 +2317,7 @@ struct tg3_fiber_aneginfo {
static int tg3_fiber_aneg_smachine(struct tg3 *tp, static int tg3_fiber_aneg_smachine(struct tg3 *tp,
struct tg3_fiber_aneginfo *ap) struct tg3_fiber_aneginfo *ap)
{ {
u16 flowctrl;
unsigned long delta; unsigned long delta;
u32 rx_cfg_reg; u32 rx_cfg_reg;
int ret; int ret;
...@@ -2416,7 +2417,12 @@ static int tg3_fiber_aneg_smachine(struct tg3 *tp, ...@@ -2416,7 +2417,12 @@ static int tg3_fiber_aneg_smachine(struct tg3 *tp,
case ANEG_STATE_ABILITY_DETECT_INIT: case ANEG_STATE_ABILITY_DETECT_INIT:
ap->flags &= ~(MR_TOGGLE_TX); ap->flags &= ~(MR_TOGGLE_TX);
ap->txconfig = (ANEG_CFG_FD | ANEG_CFG_PS1); ap->txconfig = ANEG_CFG_FD;
flowctrl = tg3_advert_flowctrl_1000X(tp->link_config.flowctrl);
if (flowctrl & ADVERTISE_1000XPAUSE)
ap->txconfig |= ANEG_CFG_PS1;
if (flowctrl & ADVERTISE_1000XPSE_ASYM)
ap->txconfig |= ANEG_CFG_PS2;
tw32(MAC_TX_AUTO_NEG, ap->txconfig); tw32(MAC_TX_AUTO_NEG, ap->txconfig);
tp->mac_mode |= MAC_MODE_SEND_CONFIGS; tp->mac_mode |= MAC_MODE_SEND_CONFIGS;
tw32_f(MAC_MODE, tp->mac_mode); tw32_f(MAC_MODE, tp->mac_mode);
...@@ -2562,7 +2568,7 @@ static int tg3_fiber_aneg_smachine(struct tg3 *tp, ...@@ -2562,7 +2568,7 @@ static int tg3_fiber_aneg_smachine(struct tg3 *tp,
return ret; return ret;
} }
static int fiber_autoneg(struct tg3 *tp, u32 *flags) static int fiber_autoneg(struct tg3 *tp, u32 *txflags, u32 *rxflags)
{ {
int res = 0; int res = 0;
struct tg3_fiber_aneginfo aninfo; struct tg3_fiber_aneginfo aninfo;
...@@ -2596,7 +2602,8 @@ static int fiber_autoneg(struct tg3 *tp, u32 *flags) ...@@ -2596,7 +2602,8 @@ static int fiber_autoneg(struct tg3 *tp, u32 *flags)
tw32_f(MAC_MODE, tp->mac_mode); tw32_f(MAC_MODE, tp->mac_mode);
udelay(40); udelay(40);
*flags = aninfo.flags; *txflags = aninfo.txconfig;
*rxflags = aninfo.flags;
if (status == ANEG_DONE && if (status == ANEG_DONE &&
(aninfo.flags & (MR_AN_COMPLETE | MR_LINK_OK | (aninfo.flags & (MR_AN_COMPLETE | MR_LINK_OK |
...@@ -2806,18 +2813,21 @@ static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status) ...@@ -2806,18 +2813,21 @@ static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status)
goto out; goto out;
if (tp->link_config.autoneg == AUTONEG_ENABLE) { if (tp->link_config.autoneg == AUTONEG_ENABLE) {
u32 flags; u32 txflags, rxflags;
int i; int i;
if (fiber_autoneg(tp, &flags)) { if (fiber_autoneg(tp, &txflags, &rxflags)) {
u32 local_adv, remote_adv; u32 local_adv = 0, remote_adv = 0;
local_adv = ADVERTISE_PAUSE_CAP; if (txflags & ANEG_CFG_PS1)
remote_adv = 0; local_adv |= ADVERTISE_1000XPAUSE;
if (flags & MR_LP_ADV_SYM_PAUSE) if (txflags & ANEG_CFG_PS2)
remote_adv |= LPA_PAUSE_CAP; local_adv |= ADVERTISE_1000XPSE_ASYM;
if (flags & MR_LP_ADV_ASYM_PAUSE)
remote_adv |= LPA_PAUSE_ASYM; if (rxflags & MR_LP_ADV_SYM_PAUSE)
remote_adv |= LPA_1000XPAUSE;
if (rxflags & MR_LP_ADV_ASYM_PAUSE)
remote_adv |= LPA_1000XPAUSE_ASYM;
tg3_setup_flow_control(tp, local_adv, remote_adv); tg3_setup_flow_control(tp, local_adv, remote_adv);
...@@ -2841,6 +2851,8 @@ static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status) ...@@ -2841,6 +2851,8 @@ static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status)
!(mac_status & MAC_STATUS_RCVD_CFG)) !(mac_status & MAC_STATUS_RCVD_CFG))
current_link_up = 1; current_link_up = 1;
} else { } else {
tg3_setup_flow_control(tp, 0, 0);
/* Forcing 1000FD link up. */ /* Forcing 1000FD link up. */
current_link_up = 1; current_link_up = 1;
......
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