diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/tg3.c | 86 |
1 files changed, 50 insertions, 36 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index ad0289ab26c..b571b20ce6e 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -1612,6 +1612,50 @@ static void tg3_link_report(struct tg3 *tp) } } +static u8 tg3_resolve_flowctrl_1000T(u16 lcladv, u16 rmtadv) +{ + u8 cap = 0; + + if (lcladv & ADVERTISE_PAUSE_CAP) { + if (lcladv & ADVERTISE_PAUSE_ASYM) { + if (rmtadv & LPA_PAUSE_CAP) + cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX; + else if (rmtadv & LPA_PAUSE_ASYM) + cap = TG3_FLOW_CTRL_RX; + } else { + if (rmtadv & LPA_PAUSE_CAP) + cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX; + } + } else if (lcladv & ADVERTISE_PAUSE_ASYM) { + if ((rmtadv & LPA_PAUSE_CAP) && (rmtadv & LPA_PAUSE_ASYM)) + cap = TG3_FLOW_CTRL_TX; + } + + return cap; +} + +static u8 tg3_resolve_flowctrl_1000X(u16 lcladv, u16 rmtadv) +{ + u8 cap = 0; + + if (lcladv & ADVERTISE_1000XPAUSE) { + if (lcladv & ADVERTISE_1000XPSE_ASYM) { + if (rmtadv & LPA_1000XPAUSE) + cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX; + else if (rmtadv & LPA_1000XPAUSE_ASYM) + cap = TG3_FLOW_CTRL_RX; + } else { + if (rmtadv & LPA_1000XPAUSE) + cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX; + } + } else if (lcladv & ADVERTISE_1000XPSE_ASYM) { + if ((rmtadv & LPA_1000XPAUSE) && (rmtadv & LPA_1000XPAUSE_ASYM)) + cap = TG3_FLOW_CTRL_TX; + } + + return cap; +} + static void tg3_setup_flow_control(struct tg3 *tp, u32 local_adv, u32 remote_adv) { u8 new_tg3_flags = 0; @@ -1619,42 +1663,12 @@ static void tg3_setup_flow_control(struct tg3 *tp, u32 local_adv, u32 remote_adv u32 old_tx_mode = tp->tx_mode; if (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) { - - /* Convert 1000BaseX flow control bits to 1000BaseT - * bits before resolving flow control. - */ - if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) { - local_adv &= ~(ADVERTISE_PAUSE_CAP | - ADVERTISE_PAUSE_ASYM); - remote_adv &= ~(LPA_PAUSE_CAP | LPA_PAUSE_ASYM); - - if (local_adv & ADVERTISE_1000XPAUSE) - local_adv |= ADVERTISE_PAUSE_CAP; - if (local_adv & ADVERTISE_1000XPSE_ASYM) - local_adv |= ADVERTISE_PAUSE_ASYM; - if (remote_adv & LPA_1000XPAUSE) - remote_adv |= LPA_PAUSE_CAP; - if (remote_adv & LPA_1000XPAUSE_ASYM) - remote_adv |= LPA_PAUSE_ASYM; - } - - if (local_adv & ADVERTISE_PAUSE_CAP) { - if (local_adv & ADVERTISE_PAUSE_ASYM) { - if (remote_adv & LPA_PAUSE_CAP) - new_tg3_flags = TG3_FLOW_CTRL_RX | - TG3_FLOW_CTRL_TX; - else if (remote_adv & LPA_PAUSE_ASYM) - new_tg3_flags = TG3_FLOW_CTRL_RX; - } else { - if (remote_adv & LPA_PAUSE_CAP) - new_tg3_flags = TG3_FLOW_CTRL_RX | - TG3_FLOW_CTRL_TX; - } - } else if (local_adv & ADVERTISE_PAUSE_ASYM) { - if ((remote_adv & LPA_PAUSE_CAP) && - (remote_adv & LPA_PAUSE_ASYM)) - new_tg3_flags = TG3_FLOW_CTRL_TX; - } + if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) + new_tg3_flags = tg3_resolve_flowctrl_1000X(local_adv, + remote_adv); + else + new_tg3_flags = tg3_resolve_flowctrl_1000T(local_adv, + remote_adv); } else { new_tg3_flags = tp->link_config.flowctrl; } |