Commit 3577aa1b authored by françois romieu's avatar françois romieu Committed by David S. Miller

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: default avatarFrancois Romieu <romieu@fr.zoreil.com>
Tested-by: default avatarJean Delvare <jdelvare@suse.de>
Cc: Edward Hsu <edward_hsu@realtek.com.tw>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 381f0517
...@@ -843,75 +843,81 @@ static int rtl8169_set_speed_xmii(struct net_device *dev, ...@@ -843,75 +843,81 @@ static int rtl8169_set_speed_xmii(struct net_device *dev,
{ {
struct rtl8169_private *tp = netdev_priv(dev); struct rtl8169_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr; void __iomem *ioaddr = tp->mmio_addr;
int auto_nego, giga_ctrl; int giga_ctrl, bmcr;
auto_nego = mdio_read(ioaddr, MII_ADVERTISE);
auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL |
ADVERTISE_100HALF | ADVERTISE_100FULL);
giga_ctrl = mdio_read(ioaddr, MII_CTRL1000);
giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
if (autoneg == AUTONEG_ENABLE) { if (autoneg == AUTONEG_ENABLE) {
int auto_nego;
auto_nego = mdio_read(ioaddr, MII_ADVERTISE);
auto_nego |= (ADVERTISE_10HALF | ADVERTISE_10FULL | auto_nego |= (ADVERTISE_10HALF | ADVERTISE_10FULL |
ADVERTISE_100HALF | ADVERTISE_100FULL); ADVERTISE_100HALF | ADVERTISE_100FULL);
giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
} else {
if (speed == SPEED_10)
auto_nego |= ADVERTISE_10HALF | ADVERTISE_10FULL;
else if (speed == SPEED_100)
auto_nego |= ADVERTISE_100HALF | ADVERTISE_100FULL;
else if (speed == SPEED_1000)
giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF;
if (duplex == DUPLEX_HALF)
auto_nego &= ~(ADVERTISE_10FULL | ADVERTISE_100FULL);
if (duplex == DUPLEX_FULL)
auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_100HALF);
/* This tweak comes straight from Realtek's driver. */ giga_ctrl = mdio_read(ioaddr, MII_CTRL1000);
if ((speed == SPEED_100) && (duplex == DUPLEX_HALF) && giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
((tp->mac_version == RTL_GIGA_MAC_VER_13) ||
(tp->mac_version == RTL_GIGA_MAC_VER_16))) {
auto_nego = ADVERTISE_100HALF | ADVERTISE_CSMA;
}
}
/* The 8100e/8101e/8102e do Fast Ethernet only. */ /* The 8100e/8101e/8102e do Fast Ethernet only. */
if ((tp->mac_version == RTL_GIGA_MAC_VER_07) || if ((tp->mac_version != RTL_GIGA_MAC_VER_07) &&
(tp->mac_version == RTL_GIGA_MAC_VER_08) || (tp->mac_version != RTL_GIGA_MAC_VER_08) &&
(tp->mac_version == RTL_GIGA_MAC_VER_09) || (tp->mac_version != RTL_GIGA_MAC_VER_09) &&
(tp->mac_version == RTL_GIGA_MAC_VER_10) || (tp->mac_version != RTL_GIGA_MAC_VER_10) &&
(tp->mac_version == RTL_GIGA_MAC_VER_13) || (tp->mac_version != RTL_GIGA_MAC_VER_13) &&
(tp->mac_version == RTL_GIGA_MAC_VER_14) || (tp->mac_version != RTL_GIGA_MAC_VER_14) &&
(tp->mac_version == RTL_GIGA_MAC_VER_15) || (tp->mac_version != RTL_GIGA_MAC_VER_15) &&
(tp->mac_version == RTL_GIGA_MAC_VER_16)) { (tp->mac_version != RTL_GIGA_MAC_VER_16)) {
if ((giga_ctrl & (ADVERTISE_1000FULL | ADVERTISE_1000HALF)) && giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF;
netif_msg_link(tp)) { } else if (netif_msg_link(tp)) {
printk(KERN_INFO "%s: PHY does not support 1000Mbps.\n", printk(KERN_INFO "%s: PHY does not support 1000Mbps.\n",
dev->name); dev->name);
} }
giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
}
auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; bmcr = BMCR_ANENABLE | BMCR_ANRESTART;
if ((tp->mac_version == RTL_GIGA_MAC_VER_11) || if ((tp->mac_version == RTL_GIGA_MAC_VER_11) ||
(tp->mac_version == RTL_GIGA_MAC_VER_12) || (tp->mac_version == RTL_GIGA_MAC_VER_12) ||
(tp->mac_version >= RTL_GIGA_MAC_VER_17)) { (tp->mac_version >= RTL_GIGA_MAC_VER_17)) {
/* /*
* Wake up the PHY. * Wake up the PHY.
* Vendor specific (0x1f) and reserved (0x0e) MII registers. * Vendor specific (0x1f) and reserved (0x0e) MII
* registers.
*/ */
mdio_write(ioaddr, 0x1f, 0x0000); mdio_write(ioaddr, 0x1f, 0x0000);
mdio_write(ioaddr, 0x0e, 0x0000); mdio_write(ioaddr, 0x0e, 0x0000);
} }
tp->phy_1000_ctrl_reg = giga_ctrl;
mdio_write(ioaddr, MII_ADVERTISE, auto_nego); mdio_write(ioaddr, MII_ADVERTISE, auto_nego);
mdio_write(ioaddr, MII_CTRL1000, giga_ctrl); mdio_write(ioaddr, MII_CTRL1000, giga_ctrl);
mdio_write(ioaddr, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART); } else {
giga_ctrl = 0;
if (speed == SPEED_10)
bmcr = 0;
else if (speed == SPEED_100)
bmcr = BMCR_SPEED100;
else
return -EINVAL;
if (duplex == DUPLEX_FULL)
bmcr |= BMCR_FULLDPLX;
mdio_write(ioaddr, 0x1f, 0x0000);
}
tp->phy_1000_ctrl_reg = giga_ctrl;
mdio_write(ioaddr, MII_BMCR, bmcr);
if ((tp->mac_version == RTL_GIGA_MAC_VER_02) ||
(tp->mac_version == RTL_GIGA_MAC_VER_03)) {
if ((speed == SPEED_100) && (autoneg != AUTONEG_ENABLE)) {
mdio_write(ioaddr, 0x17, 0x2138);
mdio_write(ioaddr, 0x0e, 0x0260);
} else {
mdio_write(ioaddr, 0x17, 0x2108);
mdio_write(ioaddr, 0x0e, 0x0000);
}
}
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment