aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/tg3.c
diff options
context:
space:
mode:
authorMatt Carlson <mcarlson@broadcom.com>2007-12-20 23:09:29 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 17:59:34 -0500
commit5be73b471bbed9ca61ddfd952a2cb7701f94f034 (patch)
treec5c611830287ecb9c8f372d93846db3cb94a42ea /drivers/net/tg3.c
parent82cd3d11f359763da445a7636ee683a922aaf025 (diff)
[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: Matt Carlson <mcarlson@broadcom.com> Signed-off-by: Michael Chan <mchan@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/tg3.c')
-rw-r--r--drivers/net/tg3.c38
1 files changed, 25 insertions, 13 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 3caead4c270..cdade05bdd0 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -1695,7 +1695,7 @@ static void tg3_setup_flow_control(struct tg3 *tp, u32 local_adv, u32 remote_adv
1695 u32 old_tx_mode = tp->tx_mode; 1695 u32 old_tx_mode = tp->tx_mode;
1696 1696
1697 if (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) { 1697 if (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) {
1698 if (tp->tg3_flags2 & (TG3_FLG2_MII_SERDES|TG3_FLG2_HW_AUTONEG)) 1698 if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES)
1699 new_tg3_flags = tg3_resolve_flowctrl_1000X(local_adv, 1699 new_tg3_flags = tg3_resolve_flowctrl_1000X(local_adv,
1700 remote_adv); 1700 remote_adv);
1701 else 1701 else
@@ -2317,6 +2317,7 @@ struct tg3_fiber_aneginfo {
2317static int tg3_fiber_aneg_smachine(struct tg3 *tp, 2317static int tg3_fiber_aneg_smachine(struct tg3 *tp,
2318 struct tg3_fiber_aneginfo *ap) 2318 struct tg3_fiber_aneginfo *ap)
2319{ 2319{
2320 u16 flowctrl;
2320 unsigned long delta; 2321 unsigned long delta;
2321 u32 rx_cfg_reg; 2322 u32 rx_cfg_reg;
2322 int ret; 2323 int ret;
@@ -2416,7 +2417,12 @@ static int tg3_fiber_aneg_smachine(struct tg3 *tp,
2416 2417
2417 case ANEG_STATE_ABILITY_DETECT_INIT: 2418 case ANEG_STATE_ABILITY_DETECT_INIT:
2418 ap->flags &= ~(MR_TOGGLE_TX); 2419 ap->flags &= ~(MR_TOGGLE_TX);
2419 ap->txconfig = (ANEG_CFG_FD | ANEG_CFG_PS1); 2420 ap->txconfig = ANEG_CFG_FD;
2421 flowctrl = tg3_advert_flowctrl_1000X(tp->link_config.flowctrl);
2422 if (flowctrl & ADVERTISE_1000XPAUSE)
2423 ap->txconfig |= ANEG_CFG_PS1;
2424 if (flowctrl & ADVERTISE_1000XPSE_ASYM)
2425 ap->txconfig |= ANEG_CFG_PS2;
2420 tw32(MAC_TX_AUTO_NEG, ap->txconfig); 2426 tw32(MAC_TX_AUTO_NEG, ap->txconfig);
2421 tp->mac_mode |= MAC_MODE_SEND_CONFIGS; 2427 tp->mac_mode |= MAC_MODE_SEND_CONFIGS;
2422 tw32_f(MAC_MODE, tp->mac_mode); 2428 tw32_f(MAC_MODE, tp->mac_mode);
@@ -2562,7 +2568,7 @@ static int tg3_fiber_aneg_smachine(struct tg3 *tp,
2562 return ret; 2568 return ret;
2563} 2569}
2564 2570
2565static int fiber_autoneg(struct tg3 *tp, u32 *flags) 2571static int fiber_autoneg(struct tg3 *tp, u32 *txflags, u32 *rxflags)
2566{ 2572{
2567 int res = 0; 2573 int res = 0;
2568 struct tg3_fiber_aneginfo aninfo; 2574 struct tg3_fiber_aneginfo aninfo;
@@ -2596,7 +2602,8 @@ static int fiber_autoneg(struct tg3 *tp, u32 *flags)
2596 tw32_f(MAC_MODE, tp->mac_mode); 2602 tw32_f(MAC_MODE, tp->mac_mode);
2597 udelay(40); 2603 udelay(40);
2598 2604
2599 *flags = aninfo.flags; 2605 *txflags = aninfo.txconfig;
2606 *rxflags = aninfo.flags;
2600 2607
2601 if (status == ANEG_DONE && 2608 if (status == ANEG_DONE &&
2602 (aninfo.flags & (MR_AN_COMPLETE | MR_LINK_OK | 2609 (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 goto out; 2813 goto out;
2807 2814
2808 if (tp->link_config.autoneg == AUTONEG_ENABLE) { 2815 if (tp->link_config.autoneg == AUTONEG_ENABLE) {
2809 u32 flags; 2816 u32 txflags, rxflags;
2810 int i; 2817 int i;
2811 2818
2812 if (fiber_autoneg(tp, &flags)) { 2819 if (fiber_autoneg(tp, &txflags, &rxflags)) {
2813 u32 local_adv, remote_adv; 2820 u32 local_adv = 0, remote_adv = 0;
2814 2821
2815 local_adv = ADVERTISE_PAUSE_CAP; 2822 if (txflags & ANEG_CFG_PS1)
2816 remote_adv = 0; 2823 local_adv |= ADVERTISE_1000XPAUSE;
2817 if (flags & MR_LP_ADV_SYM_PAUSE) 2824 if (txflags & ANEG_CFG_PS2)
2818 remote_adv |= LPA_PAUSE_CAP; 2825 local_adv |= ADVERTISE_1000XPSE_ASYM;
2819 if (flags & MR_LP_ADV_ASYM_PAUSE) 2826
2820 remote_adv |= LPA_PAUSE_ASYM; 2827 if (rxflags & MR_LP_ADV_SYM_PAUSE)
2828 remote_adv |= LPA_1000XPAUSE;
2829 if (rxflags & MR_LP_ADV_ASYM_PAUSE)
2830 remote_adv |= LPA_1000XPAUSE_ASYM;
2821 2831
2822 tg3_setup_flow_control(tp, local_adv, remote_adv); 2832 tg3_setup_flow_control(tp, local_adv, remote_adv);
2823 2833
@@ -2841,6 +2851,8 @@ static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status)
2841 !(mac_status & MAC_STATUS_RCVD_CFG)) 2851 !(mac_status & MAC_STATUS_RCVD_CFG))
2842 current_link_up = 1; 2852 current_link_up = 1;
2843 } else { 2853 } else {
2854 tg3_setup_flow_control(tp, 0, 0);
2855
2844 /* Forcing 1000FD link up. */ 2856 /* Forcing 1000FD link up. */
2845 current_link_up = 1; 2857 current_link_up = 1;
2846 2858