aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMatt Carlson <mcarlson@broadcom.com>2007-12-20 23:06:19 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 17:59:30 -0500
commit95937268b7c4c334a3d98f7177c7d5a00b74b2e7 (patch)
treeff2be09fd189aac2429c93420421115f427c6a7e /drivers
parent8d018621085b8d00511768c343d941676bd77ee9 (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.c86
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
1615static 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
1637static 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
1615static void tg3_setup_flow_control(struct tg3 *tp, u32 local_adv, u32 remote_adv) 1659static 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 }