aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Carlson <mcarlson@broadcom.com>2007-12-20 23:08:00 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 17:59:31 -0500
commitba4d07a8483e6ec0de3194960f8aca862711454c (patch)
tree9f69fc77c1d3768cfd88575a42a38715a2e48011
parent95937268b7c4c334a3d98f7177c7d5a00b74b2e7 (diff)
[TG3]: Add 1000T & 1000X flowctl adv helpers
This patch adds two functions designed to convert abstract TX & RX flow control parameters to 1000-BaseT and 1000-BaseX autonegotiation advertisements. Code that uses standard definitions which statically advertises TX & RX flow control has been replaced with code that configures the advertisements based on administrator dictated preferences. 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>
-rw-r--r--drivers/net/tg3.c62
1 files changed, 48 insertions, 14 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index b571b20ce6e..5b83a542660 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -1612,6 +1612,38 @@ static void tg3_link_report(struct tg3 *tp)
1612 } 1612 }
1613} 1613}
1614 1614
1615static u16 tg3_advert_flowctrl_1000T(u8 flow_ctrl)
1616{
1617 u16 miireg;
1618
1619 if ((flow_ctrl & TG3_FLOW_CTRL_TX) && (flow_ctrl & TG3_FLOW_CTRL_RX))
1620 miireg = ADVERTISE_PAUSE_CAP;
1621 else if (flow_ctrl & TG3_FLOW_CTRL_TX)
1622 miireg = ADVERTISE_PAUSE_ASYM;
1623 else if (flow_ctrl & TG3_FLOW_CTRL_RX)
1624 miireg = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
1625 else
1626 miireg = 0;
1627
1628 return miireg;
1629}
1630
1631static u16 tg3_advert_flowctrl_1000X(u8 flow_ctrl)
1632{
1633 u16 miireg;
1634
1635 if ((flow_ctrl & TG3_FLOW_CTRL_TX) && (flow_ctrl & TG3_FLOW_CTRL_RX))
1636 miireg = ADVERTISE_1000XPAUSE;
1637 else if (flow_ctrl & TG3_FLOW_CTRL_TX)
1638 miireg = ADVERTISE_1000XPSE_ASYM;
1639 else if (flow_ctrl & TG3_FLOW_CTRL_RX)
1640 miireg = ADVERTISE_1000XPAUSE | ADVERTISE_1000XPSE_ASYM;
1641 else
1642 miireg = 0;
1643
1644 return miireg;
1645}
1646
1615static u8 tg3_resolve_flowctrl_1000T(u16 lcladv, u16 rmtadv) 1647static u8 tg3_resolve_flowctrl_1000T(u16 lcladv, u16 rmtadv)
1616{ 1648{
1617 u8 cap = 0; 1649 u8 cap = 0;
@@ -1764,7 +1796,7 @@ static void tg3_phy_copper_begin(struct tg3 *tp)
1764 ~(ADVERTISED_1000baseT_Half | 1796 ~(ADVERTISED_1000baseT_Half |
1765 ADVERTISED_1000baseT_Full); 1797 ADVERTISED_1000baseT_Full);
1766 1798
1767 new_adv = (ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP); 1799 new_adv = ADVERTISE_CSMA;
1768 if (tp->link_config.advertising & ADVERTISED_10baseT_Half) 1800 if (tp->link_config.advertising & ADVERTISED_10baseT_Half)
1769 new_adv |= ADVERTISE_10HALF; 1801 new_adv |= ADVERTISE_10HALF;
1770 if (tp->link_config.advertising & ADVERTISED_10baseT_Full) 1802 if (tp->link_config.advertising & ADVERTISED_10baseT_Full)
@@ -1773,6 +1805,9 @@ static void tg3_phy_copper_begin(struct tg3 *tp)
1773 new_adv |= ADVERTISE_100HALF; 1805 new_adv |= ADVERTISE_100HALF;
1774 if (tp->link_config.advertising & ADVERTISED_100baseT_Full) 1806 if (tp->link_config.advertising & ADVERTISED_100baseT_Full)
1775 new_adv |= ADVERTISE_100FULL; 1807 new_adv |= ADVERTISE_100FULL;
1808
1809 new_adv |= tg3_advert_flowctrl_1000T(tp->link_config.flowctrl);
1810
1776 tg3_writephy(tp, MII_ADVERTISE, new_adv); 1811 tg3_writephy(tp, MII_ADVERTISE, new_adv);
1777 1812
1778 if (tp->link_config.advertising & 1813 if (tp->link_config.advertising &
@@ -1792,9 +1827,11 @@ static void tg3_phy_copper_begin(struct tg3 *tp)
1792 tg3_writephy(tp, MII_TG3_CTRL, 0); 1827 tg3_writephy(tp, MII_TG3_CTRL, 0);
1793 } 1828 }
1794 } else { 1829 } else {
1830 new_adv = tg3_advert_flowctrl_1000T(tp->link_config.flowctrl);
1831 new_adv |= ADVERTISE_CSMA;
1832
1795 /* Asking for a specific link mode. */ 1833 /* Asking for a specific link mode. */
1796 if (tp->link_config.speed == SPEED_1000) { 1834 if (tp->link_config.speed == SPEED_1000) {
1797 new_adv = ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP;
1798 tg3_writephy(tp, MII_ADVERTISE, new_adv); 1835 tg3_writephy(tp, MII_ADVERTISE, new_adv);
1799 1836
1800 if (tp->link_config.duplex == DUPLEX_FULL) 1837 if (tp->link_config.duplex == DUPLEX_FULL)
@@ -1805,11 +1842,7 @@ static void tg3_phy_copper_begin(struct tg3 *tp)
1805 tp->pci_chip_rev_id == CHIPREV_ID_5701_B0) 1842 tp->pci_chip_rev_id == CHIPREV_ID_5701_B0)
1806 new_adv |= (MII_TG3_CTRL_AS_MASTER | 1843 new_adv |= (MII_TG3_CTRL_AS_MASTER |
1807 MII_TG3_CTRL_ENABLE_AS_MASTER); 1844 MII_TG3_CTRL_ENABLE_AS_MASTER);
1808 tg3_writephy(tp, MII_TG3_CTRL, new_adv);
1809 } else { 1845 } else {
1810 tg3_writephy(tp, MII_TG3_CTRL, 0);
1811
1812 new_adv = ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP;
1813 if (tp->link_config.speed == SPEED_100) { 1846 if (tp->link_config.speed == SPEED_100) {
1814 if (tp->link_config.duplex == DUPLEX_FULL) 1847 if (tp->link_config.duplex == DUPLEX_FULL)
1815 new_adv |= ADVERTISE_100FULL; 1848 new_adv |= ADVERTISE_100FULL;
@@ -1822,7 +1855,11 @@ static void tg3_phy_copper_begin(struct tg3 *tp)
1822 new_adv |= ADVERTISE_10HALF; 1855 new_adv |= ADVERTISE_10HALF;
1823 } 1856 }
1824 tg3_writephy(tp, MII_ADVERTISE, new_adv); 1857 tg3_writephy(tp, MII_ADVERTISE, new_adv);
1858
1859 new_adv = 0;
1825 } 1860 }
1861
1862 tg3_writephy(tp, MII_TG3_CTRL, new_adv);
1826 } 1863 }
1827 1864
1828 if (tp->link_config.autoneg == AUTONEG_DISABLE && 1865 if (tp->link_config.autoneg == AUTONEG_DISABLE &&
@@ -2118,17 +2155,15 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
2118 2155
2119 if (tg3_readphy(tp, MII_ADVERTISE, &local_adv)) 2156 if (tg3_readphy(tp, MII_ADVERTISE, &local_adv))
2120 local_adv = 0; 2157 local_adv = 0;
2121 local_adv &= (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
2122 2158
2123 if (tg3_readphy(tp, MII_LPA, &remote_adv)) 2159 if (tg3_readphy(tp, MII_LPA, &remote_adv))
2124 remote_adv = 0; 2160 remote_adv = 0;
2125 2161
2126 remote_adv &= (LPA_PAUSE_CAP | LPA_PAUSE_ASYM); 2162 /* If we are not advertising what has been requested,
2127 2163 * bring the link down and reconfigure.
2128 /* If we are not advertising full pause capability,
2129 * something is wrong. Bring the link down and reconfigure.
2130 */ 2164 */
2131 if (local_adv != ADVERTISE_PAUSE_CAP) { 2165 if (local_adv !=
2166 tg3_advert_flowctrl_1000T(tp->link_config.flowctrl)) {
2132 current_link_up = 0; 2167 current_link_up = 0;
2133 } else { 2168 } else {
2134 tg3_setup_flow_control(tp, local_adv, remote_adv); 2169 tg3_setup_flow_control(tp, local_adv, remote_adv);
@@ -2973,8 +3008,7 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset)
2973 ADVERTISE_1000XPSE_ASYM | 3008 ADVERTISE_1000XPSE_ASYM |
2974 ADVERTISE_SLCT); 3009 ADVERTISE_SLCT);
2975 3010
2976 /* Always advertise symmetric PAUSE just like copper */ 3011 new_adv |= tg3_advert_flowctrl_1000X(tp->link_config.flowctrl);
2977 new_adv |= ADVERTISE_1000XPAUSE;
2978 3012
2979 if (tp->link_config.advertising & ADVERTISED_1000baseT_Half) 3013 if (tp->link_config.advertising & ADVERTISED_1000baseT_Half)
2980 new_adv |= ADVERTISE_1000XHALF; 3014 new_adv |= ADVERTISE_1000XHALF;