diff options
author | Matt Carlson <mcarlson@broadcom.com> | 2007-12-20 23:06:19 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 17:59:30 -0500 |
commit | 95937268b7c4c334a3d98f7177c7d5a00b74b2e7 (patch) | |
tree | ff2be09fd189aac2429c93420421115f427c6a7e /drivers | |
parent | 8d018621085b8d00511768c343d941676bd77ee9 (diff) |
[TG3]: Add 1000T & 1000X flowctrl resolvers
This patch adds two new utility functions to resolve flow control. One
function resolves flow control based on 1000-BaseT register definitions.
The other resolves flow control based on 1000-Base X register
definitions.
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')
-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 ad0289ab26c9..b571b20ce6ec 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -1612,6 +1612,50 @@ static void tg3_link_report(struct tg3 *tp) | |||
1612 | } | 1612 | } |
1613 | } | 1613 | } |
1614 | 1614 | ||
1615 | static u8 tg3_resolve_flowctrl_1000T(u16 lcladv, u16 rmtadv) | ||
1616 | { | ||
1617 | u8 cap = 0; | ||
1618 | |||
1619 | if (lcladv & ADVERTISE_PAUSE_CAP) { | ||
1620 | if (lcladv & ADVERTISE_PAUSE_ASYM) { | ||
1621 | if (rmtadv & LPA_PAUSE_CAP) | ||
1622 | cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX; | ||
1623 | else if (rmtadv & LPA_PAUSE_ASYM) | ||
1624 | cap = TG3_FLOW_CTRL_RX; | ||
1625 | } else { | ||
1626 | if (rmtadv & LPA_PAUSE_CAP) | ||
1627 | cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX; | ||
1628 | } | ||
1629 | } else if (lcladv & ADVERTISE_PAUSE_ASYM) { | ||
1630 | if ((rmtadv & LPA_PAUSE_CAP) && (rmtadv & LPA_PAUSE_ASYM)) | ||
1631 | cap = TG3_FLOW_CTRL_TX; | ||
1632 | } | ||
1633 | |||
1634 | return cap; | ||
1635 | } | ||
1636 | |||
1637 | static u8 tg3_resolve_flowctrl_1000X(u16 lcladv, u16 rmtadv) | ||
1638 | { | ||
1639 | u8 cap = 0; | ||
1640 | |||
1641 | if (lcladv & ADVERTISE_1000XPAUSE) { | ||
1642 | if (lcladv & ADVERTISE_1000XPSE_ASYM) { | ||
1643 | if (rmtadv & LPA_1000XPAUSE) | ||
1644 | cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX; | ||
1645 | else if (rmtadv & LPA_1000XPAUSE_ASYM) | ||
1646 | cap = TG3_FLOW_CTRL_RX; | ||
1647 | } else { | ||
1648 | if (rmtadv & LPA_1000XPAUSE) | ||
1649 | cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX; | ||
1650 | } | ||
1651 | } else if (lcladv & ADVERTISE_1000XPSE_ASYM) { | ||
1652 | if ((rmtadv & LPA_1000XPAUSE) && (rmtadv & LPA_1000XPAUSE_ASYM)) | ||
1653 | cap = TG3_FLOW_CTRL_TX; | ||
1654 | } | ||
1655 | |||
1656 | return cap; | ||
1657 | } | ||
1658 | |||
1615 | static void tg3_setup_flow_control(struct tg3 *tp, u32 local_adv, u32 remote_adv) | 1659 | static void tg3_setup_flow_control(struct tg3 *tp, u32 local_adv, u32 remote_adv) |
1616 | { | 1660 | { |
1617 | u8 new_tg3_flags = 0; | 1661 | u8 new_tg3_flags = 0; |
@@ -1619,42 +1663,12 @@ static void tg3_setup_flow_control(struct tg3 *tp, u32 local_adv, u32 remote_adv | |||
1619 | u32 old_tx_mode = tp->tx_mode; | 1663 | u32 old_tx_mode = tp->tx_mode; |
1620 | 1664 | ||
1621 | if (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) { | 1665 | if (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) { |
1622 | 1666 | if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) | |
1623 | /* Convert 1000BaseX flow control bits to 1000BaseT | 1667 | new_tg3_flags = tg3_resolve_flowctrl_1000X(local_adv, |
1624 | * bits before resolving flow control. | 1668 | remote_adv); |
1625 | */ | 1669 | else |
1626 | if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) { | 1670 | new_tg3_flags = tg3_resolve_flowctrl_1000T(local_adv, |
1627 | local_adv &= ~(ADVERTISE_PAUSE_CAP | | 1671 | remote_adv); |
1628 | ADVERTISE_PAUSE_ASYM); | ||
1629 | remote_adv &= ~(LPA_PAUSE_CAP | LPA_PAUSE_ASYM); | ||
1630 | |||
1631 | if (local_adv & ADVERTISE_1000XPAUSE) | ||
1632 | local_adv |= ADVERTISE_PAUSE_CAP; | ||
1633 | if (local_adv & ADVERTISE_1000XPSE_ASYM) | ||
1634 | local_adv |= ADVERTISE_PAUSE_ASYM; | ||
1635 | if (remote_adv & LPA_1000XPAUSE) | ||
1636 | remote_adv |= LPA_PAUSE_CAP; | ||
1637 | if (remote_adv & LPA_1000XPAUSE_ASYM) | ||
1638 | remote_adv |= LPA_PAUSE_ASYM; | ||
1639 | } | ||
1640 | |||
1641 | if (local_adv & ADVERTISE_PAUSE_CAP) { | ||
1642 | if (local_adv & ADVERTISE_PAUSE_ASYM) { | ||
1643 | if (remote_adv & LPA_PAUSE_CAP) | ||
1644 | new_tg3_flags = TG3_FLOW_CTRL_RX | | ||
1645 | TG3_FLOW_CTRL_TX; | ||
1646 | else if (remote_adv & LPA_PAUSE_ASYM) | ||
1647 | new_tg3_flags = TG3_FLOW_CTRL_RX; | ||
1648 | } else { | ||
1649 | if (remote_adv & LPA_PAUSE_CAP) | ||
1650 | new_tg3_flags = TG3_FLOW_CTRL_RX | | ||
1651 | TG3_FLOW_CTRL_TX; | ||
1652 | } | ||
1653 | } else if (local_adv & ADVERTISE_PAUSE_ASYM) { | ||
1654 | if ((remote_adv & LPA_PAUSE_CAP) && | ||
1655 | (remote_adv & LPA_PAUSE_ASYM)) | ||
1656 | new_tg3_flags = TG3_FLOW_CTRL_TX; | ||
1657 | } | ||
1658 | } else { | 1672 | } else { |
1659 | new_tg3_flags = tp->link_config.flowctrl; | 1673 | new_tg3_flags = tp->link_config.flowctrl; |
1660 | } | 1674 | } |