aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorfrançois romieu <romieu@fr.zoreil.com>2009-05-19 06:46:48 -0400
committerDavid S. Miller <davem@davemloft.net>2009-05-19 17:31:28 -0400
commit3577aa1bd7efc9c474f59738d2fb89c168168d55 (patch)
treeb5ba4f04582ce0493f905d08a7d386d75c3bbe7a /drivers/net
parent381f05172bdca076390abd84813b09ea423ae8a9 (diff)
r8169: allow true forced mode setting
Due to mostly historic reasons, including a lack of reliability of the link handling (especially with the older 8169), the current r8169 driver emulates forced mode setting by limiting the advertised modes. With this change the driver allows real 10/100 forced mode settings on the 8169 and 8101/8102. Original idea by Vincent Steenhoute. The RTL_GIGA_MAC_VER_03 tweak was extracted from Realtek's r8169 v6.010.00 driver. Signed-off-by: Francois Romieu <romieu@fr.zoreil.com> Tested-by: Jean Delvare <jdelvare@suse.de> Cc: Edward Hsu <edward_hsu@realtek.com.tw> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/r8169.c112
1 files changed, 59 insertions, 53 deletions
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index b0573146934b..fb2e50da0e9c 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -843,75 +843,81 @@ static int rtl8169_set_speed_xmii(struct net_device *dev,
843{ 843{
844 struct rtl8169_private *tp = netdev_priv(dev); 844 struct rtl8169_private *tp = netdev_priv(dev);
845 void __iomem *ioaddr = tp->mmio_addr; 845 void __iomem *ioaddr = tp->mmio_addr;
846 int auto_nego, giga_ctrl; 846 int giga_ctrl, bmcr;
847
848 auto_nego = mdio_read(ioaddr, MII_ADVERTISE);
849 auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL |
850 ADVERTISE_100HALF | ADVERTISE_100FULL);
851 giga_ctrl = mdio_read(ioaddr, MII_CTRL1000);
852 giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
853 847
854 if (autoneg == AUTONEG_ENABLE) { 848 if (autoneg == AUTONEG_ENABLE) {
849 int auto_nego;
850
851 auto_nego = mdio_read(ioaddr, MII_ADVERTISE);
855 auto_nego |= (ADVERTISE_10HALF | ADVERTISE_10FULL | 852 auto_nego |= (ADVERTISE_10HALF | ADVERTISE_10FULL |
856 ADVERTISE_100HALF | ADVERTISE_100FULL); 853 ADVERTISE_100HALF | ADVERTISE_100FULL);
857 giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; 854 auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
858 } else {
859 if (speed == SPEED_10)
860 auto_nego |= ADVERTISE_10HALF | ADVERTISE_10FULL;
861 else if (speed == SPEED_100)
862 auto_nego |= ADVERTISE_100HALF | ADVERTISE_100FULL;
863 else if (speed == SPEED_1000)
864 giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF;
865
866 if (duplex == DUPLEX_HALF)
867 auto_nego &= ~(ADVERTISE_10FULL | ADVERTISE_100FULL);
868
869 if (duplex == DUPLEX_FULL)
870 auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_100HALF);
871 855
872 /* This tweak comes straight from Realtek's driver. */ 856 giga_ctrl = mdio_read(ioaddr, MII_CTRL1000);
873 if ((speed == SPEED_100) && (duplex == DUPLEX_HALF) && 857 giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
874 ((tp->mac_version == RTL_GIGA_MAC_VER_13) ||
875 (tp->mac_version == RTL_GIGA_MAC_VER_16))) {
876 auto_nego = ADVERTISE_100HALF | ADVERTISE_CSMA;
877 }
878 }
879 858
880 /* The 8100e/8101e/8102e do Fast Ethernet only. */ 859 /* The 8100e/8101e/8102e do Fast Ethernet only. */
881 if ((tp->mac_version == RTL_GIGA_MAC_VER_07) || 860 if ((tp->mac_version != RTL_GIGA_MAC_VER_07) &&
882 (tp->mac_version == RTL_GIGA_MAC_VER_08) || 861 (tp->mac_version != RTL_GIGA_MAC_VER_08) &&
883 (tp->mac_version == RTL_GIGA_MAC_VER_09) || 862 (tp->mac_version != RTL_GIGA_MAC_VER_09) &&
884 (tp->mac_version == RTL_GIGA_MAC_VER_10) || 863 (tp->mac_version != RTL_GIGA_MAC_VER_10) &&
885 (tp->mac_version == RTL_GIGA_MAC_VER_13) || 864 (tp->mac_version != RTL_GIGA_MAC_VER_13) &&
886 (tp->mac_version == RTL_GIGA_MAC_VER_14) || 865 (tp->mac_version != RTL_GIGA_MAC_VER_14) &&
887 (tp->mac_version == RTL_GIGA_MAC_VER_15) || 866 (tp->mac_version != RTL_GIGA_MAC_VER_15) &&
888 (tp->mac_version == RTL_GIGA_MAC_VER_16)) { 867 (tp->mac_version != RTL_GIGA_MAC_VER_16)) {
889 if ((giga_ctrl & (ADVERTISE_1000FULL | ADVERTISE_1000HALF)) && 868 giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF;
890 netif_msg_link(tp)) { 869 } else if (netif_msg_link(tp)) {
891 printk(KERN_INFO "%s: PHY does not support 1000Mbps.\n", 870 printk(KERN_INFO "%s: PHY does not support 1000Mbps.\n",
892 dev->name); 871 dev->name);
893 } 872 }
894 giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
895 }
896 873
897 auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; 874 bmcr = BMCR_ANENABLE | BMCR_ANRESTART;
875
876 if ((tp->mac_version == RTL_GIGA_MAC_VER_11) ||
877 (tp->mac_version == RTL_GIGA_MAC_VER_12) ||
878 (tp->mac_version >= RTL_GIGA_MAC_VER_17)) {
879 /*
880 * Wake up the PHY.
881 * Vendor specific (0x1f) and reserved (0x0e) MII
882 * registers.
883 */
884 mdio_write(ioaddr, 0x1f, 0x0000);
885 mdio_write(ioaddr, 0x0e, 0x0000);
886 }
887
888 mdio_write(ioaddr, MII_ADVERTISE, auto_nego);
889 mdio_write(ioaddr, MII_CTRL1000, giga_ctrl);
890 } else {
891 giga_ctrl = 0;
892
893 if (speed == SPEED_10)
894 bmcr = 0;
895 else if (speed == SPEED_100)
896 bmcr = BMCR_SPEED100;
897 else
898 return -EINVAL;
899
900 if (duplex == DUPLEX_FULL)
901 bmcr |= BMCR_FULLDPLX;
898 902
899 if ((tp->mac_version == RTL_GIGA_MAC_VER_11) ||
900 (tp->mac_version == RTL_GIGA_MAC_VER_12) ||
901 (tp->mac_version >= RTL_GIGA_MAC_VER_17)) {
902 /*
903 * Wake up the PHY.
904 * Vendor specific (0x1f) and reserved (0x0e) MII registers.
905 */
906 mdio_write(ioaddr, 0x1f, 0x0000); 903 mdio_write(ioaddr, 0x1f, 0x0000);
907 mdio_write(ioaddr, 0x0e, 0x0000);
908 } 904 }
909 905
910 tp->phy_1000_ctrl_reg = giga_ctrl; 906 tp->phy_1000_ctrl_reg = giga_ctrl;
911 907
912 mdio_write(ioaddr, MII_ADVERTISE, auto_nego); 908 mdio_write(ioaddr, MII_BMCR, bmcr);
913 mdio_write(ioaddr, MII_CTRL1000, giga_ctrl); 909
914 mdio_write(ioaddr, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART); 910 if ((tp->mac_version == RTL_GIGA_MAC_VER_02) ||
911 (tp->mac_version == RTL_GIGA_MAC_VER_03)) {
912 if ((speed == SPEED_100) && (autoneg != AUTONEG_ENABLE)) {
913 mdio_write(ioaddr, 0x17, 0x2138);
914 mdio_write(ioaddr, 0x0e, 0x0260);
915 } else {
916 mdio_write(ioaddr, 0x17, 0x2108);
917 mdio_write(ioaddr, 0x0e, 0x0000);
918 }
919 }
920
915 return 0; 921 return 0;
916} 922}
917 923