diff options
author | Oliver Neukum <oneukum@suse.de> | 2011-01-06 15:55:13 -0500 |
---|---|---|
committer | Francois Romieu <romieu@fr.zoreil.com> | 2011-03-05 04:04:37 -0500 |
commit | 54405cde762408b00a445466a40da4f7f33a8479 (patch) | |
tree | 6cb4ed1c104a272232846c2000b71fe50fdba62a /drivers/net/r8169.c | |
parent | 5a5e4443150713347a7a7e4d0880b343348f5811 (diff) |
r8169: support control of advertising.
This allows "ethtool advertise" to control the speed and duplex
features the device offers the switch.
Signed-off-by: Oliver Neukum <oneukum@suse.de>
Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
Diffstat (limited to 'drivers/net/r8169.c')
-rw-r--r-- | drivers/net/r8169.c | 54 |
1 files changed, 37 insertions, 17 deletions
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 2543edd9a2cc..d842d00d7abd 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c | |||
@@ -551,7 +551,7 @@ struct rtl8169_private { | |||
551 | void (*up)(struct rtl8169_private *); | 551 | void (*up)(struct rtl8169_private *); |
552 | } pll_power_ops; | 552 | } pll_power_ops; |
553 | 553 | ||
554 | int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex); | 554 | int (*set_speed)(struct net_device *, u8 aneg, u16 sp, u8 dpx, u32 adv); |
555 | int (*get_settings)(struct net_device *, struct ethtool_cmd *); | 555 | int (*get_settings)(struct net_device *, struct ethtool_cmd *); |
556 | void (*phy_reset_enable)(struct rtl8169_private *tp); | 556 | void (*phy_reset_enable)(struct rtl8169_private *tp); |
557 | void (*hw_start)(struct net_device *); | 557 | void (*hw_start)(struct net_device *); |
@@ -1108,7 +1108,7 @@ static int rtl8169_get_regs_len(struct net_device *dev) | |||
1108 | } | 1108 | } |
1109 | 1109 | ||
1110 | static int rtl8169_set_speed_tbi(struct net_device *dev, | 1110 | static int rtl8169_set_speed_tbi(struct net_device *dev, |
1111 | u8 autoneg, u16 speed, u8 duplex) | 1111 | u8 autoneg, u16 speed, u8 duplex, u32 ignored) |
1112 | { | 1112 | { |
1113 | struct rtl8169_private *tp = netdev_priv(dev); | 1113 | struct rtl8169_private *tp = netdev_priv(dev); |
1114 | void __iomem *ioaddr = tp->mmio_addr; | 1114 | void __iomem *ioaddr = tp->mmio_addr; |
@@ -1131,10 +1131,11 @@ static int rtl8169_set_speed_tbi(struct net_device *dev, | |||
1131 | } | 1131 | } |
1132 | 1132 | ||
1133 | static int rtl8169_set_speed_xmii(struct net_device *dev, | 1133 | static int rtl8169_set_speed_xmii(struct net_device *dev, |
1134 | u8 autoneg, u16 speed, u8 duplex) | 1134 | u8 autoneg, u16 speed, u8 duplex, u32 adv) |
1135 | { | 1135 | { |
1136 | struct rtl8169_private *tp = netdev_priv(dev); | 1136 | struct rtl8169_private *tp = netdev_priv(dev); |
1137 | int giga_ctrl, bmcr; | 1137 | int giga_ctrl, bmcr; |
1138 | int rc = -EINVAL; | ||
1138 | 1139 | ||
1139 | rtl_writephy(tp, 0x1f, 0x0000); | 1140 | rtl_writephy(tp, 0x1f, 0x0000); |
1140 | 1141 | ||
@@ -1142,8 +1143,18 @@ static int rtl8169_set_speed_xmii(struct net_device *dev, | |||
1142 | int auto_nego; | 1143 | int auto_nego; |
1143 | 1144 | ||
1144 | auto_nego = rtl_readphy(tp, MII_ADVERTISE); | 1145 | auto_nego = rtl_readphy(tp, MII_ADVERTISE); |
1145 | auto_nego |= (ADVERTISE_10HALF | ADVERTISE_10FULL | | 1146 | auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL | |
1146 | ADVERTISE_100HALF | ADVERTISE_100FULL); | 1147 | ADVERTISE_100HALF | ADVERTISE_100FULL); |
1148 | |||
1149 | if (adv & ADVERTISED_10baseT_Half) | ||
1150 | auto_nego |= ADVERTISE_10HALF; | ||
1151 | if (adv & ADVERTISED_10baseT_Full) | ||
1152 | auto_nego |= ADVERTISE_10FULL; | ||
1153 | if (adv & ADVERTISED_100baseT_Half) | ||
1154 | auto_nego |= ADVERTISE_100HALF; | ||
1155 | if (adv & ADVERTISED_100baseT_Full) | ||
1156 | auto_nego |= ADVERTISE_100FULL; | ||
1157 | |||
1147 | auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; | 1158 | auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; |
1148 | 1159 | ||
1149 | giga_ctrl = rtl_readphy(tp, MII_CTRL1000); | 1160 | giga_ctrl = rtl_readphy(tp, MII_CTRL1000); |
@@ -1160,10 +1171,15 @@ static int rtl8169_set_speed_xmii(struct net_device *dev, | |||
1160 | (tp->mac_version != RTL_GIGA_MAC_VER_16) && | 1171 | (tp->mac_version != RTL_GIGA_MAC_VER_16) && |
1161 | (tp->mac_version != RTL_GIGA_MAC_VER_29) && | 1172 | (tp->mac_version != RTL_GIGA_MAC_VER_29) && |
1162 | (tp->mac_version != RTL_GIGA_MAC_VER_30)) { | 1173 | (tp->mac_version != RTL_GIGA_MAC_VER_30)) { |
1163 | giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; | 1174 | if (adv & ADVERTISED_1000baseT_Half) |
1164 | } else { | 1175 | giga_ctrl |= ADVERTISE_1000HALF; |
1176 | if (adv & ADVERTISED_1000baseT_Full) | ||
1177 | giga_ctrl |= ADVERTISE_1000FULL; | ||
1178 | } else if (adv & (ADVERTISED_1000baseT_Half | | ||
1179 | ADVERTISED_1000baseT_Full)) { | ||
1165 | netif_info(tp, link, dev, | 1180 | netif_info(tp, link, dev, |
1166 | "PHY does not support 1000Mbps\n"); | 1181 | "PHY does not support 1000Mbps\n"); |
1182 | goto out; | ||
1167 | } | 1183 | } |
1168 | 1184 | ||
1169 | bmcr = BMCR_ANENABLE | BMCR_ANRESTART; | 1185 | bmcr = BMCR_ANENABLE | BMCR_ANRESTART; |
@@ -1178,7 +1194,7 @@ static int rtl8169_set_speed_xmii(struct net_device *dev, | |||
1178 | else if (speed == SPEED_100) | 1194 | else if (speed == SPEED_100) |
1179 | bmcr = BMCR_SPEED100; | 1195 | bmcr = BMCR_SPEED100; |
1180 | else | 1196 | else |
1181 | return -EINVAL; | 1197 | goto out; |
1182 | 1198 | ||
1183 | if (duplex == DUPLEX_FULL) | 1199 | if (duplex == DUPLEX_FULL) |
1184 | bmcr |= BMCR_FULLDPLX; | 1200 | bmcr |= BMCR_FULLDPLX; |
@@ -1199,16 +1215,18 @@ static int rtl8169_set_speed_xmii(struct net_device *dev, | |||
1199 | } | 1215 | } |
1200 | } | 1216 | } |
1201 | 1217 | ||
1202 | return 0; | 1218 | rc = 0; |
1219 | out: | ||
1220 | return rc; | ||
1203 | } | 1221 | } |
1204 | 1222 | ||
1205 | static int rtl8169_set_speed(struct net_device *dev, | 1223 | static int rtl8169_set_speed(struct net_device *dev, |
1206 | u8 autoneg, u16 speed, u8 duplex) | 1224 | u8 autoneg, u16 speed, u8 duplex, u32 advertising) |
1207 | { | 1225 | { |
1208 | struct rtl8169_private *tp = netdev_priv(dev); | 1226 | struct rtl8169_private *tp = netdev_priv(dev); |
1209 | int ret; | 1227 | int ret; |
1210 | 1228 | ||
1211 | ret = tp->set_speed(dev, autoneg, speed, duplex); | 1229 | ret = tp->set_speed(dev, autoneg, speed, duplex, advertising); |
1212 | 1230 | ||
1213 | if (netif_running(dev) && (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) | 1231 | if (netif_running(dev) && (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) |
1214 | mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT); | 1232 | mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT); |
@@ -1223,7 +1241,8 @@ static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
1223 | int ret; | 1241 | int ret; |
1224 | 1242 | ||
1225 | spin_lock_irqsave(&tp->lock, flags); | 1243 | spin_lock_irqsave(&tp->lock, flags); |
1226 | ret = rtl8169_set_speed(dev, cmd->autoneg, cmd->speed, cmd->duplex); | 1244 | ret = rtl8169_set_speed(dev, |
1245 | cmd->autoneg, cmd->speed, cmd->duplex, cmd->advertising); | ||
1227 | spin_unlock_irqrestore(&tp->lock, flags); | 1246 | spin_unlock_irqrestore(&tp->lock, flags); |
1228 | 1247 | ||
1229 | return ret; | 1248 | return ret; |
@@ -2669,11 +2688,12 @@ static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp) | |||
2669 | 2688 | ||
2670 | rtl8169_phy_reset(dev, tp); | 2689 | rtl8169_phy_reset(dev, tp); |
2671 | 2690 | ||
2672 | /* | 2691 | rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL, |
2673 | * rtl8169_set_speed_xmii takes good care of the Fast Ethernet | 2692 | ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | |
2674 | * only 8101. Don't panic. | 2693 | ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | |
2675 | */ | 2694 | tp->mii.supports_gmii ? |
2676 | rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL); | 2695 | ADVERTISED_1000baseT_Half | |
2696 | ADVERTISED_1000baseT_Full : 0); | ||
2677 | 2697 | ||
2678 | if (RTL_R8(PHYstatus) & TBI_Enable) | 2698 | if (RTL_R8(PHYstatus) & TBI_Enable) |
2679 | netif_info(tp, link, dev, "TBI auto-negotiating\n"); | 2699 | netif_info(tp, link, dev, "TBI auto-negotiating\n"); |