diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 2a229b8..e0008fd 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -13,6 +13,27 @@ config PHYLIB help Enable Ethernet PHY (physical media interface) support. +config RTL8211X_PHY_FORCE_MASTER + bool "Ethernet PHY RTL8211x: force 1000BASE-T master mode" + depends on PHYLIB + help + Force master mode for 1000BASE-T on RTl8211x PHYs (except for RTL8211F). + This can work around link stability and data corruption issues on gigabit + links which can occur in slave mode on certain PHYs, e.g. on the + RTL8211C(L). + + Please note that two directly connected devices (i.e. via crossover cable) + will not be able to establish a link between each other if they both force + master mode. Multiple devices forcing master mode when connected by a + network switch do not pose a problem as the switch configures its affected + ports into slave mode. + + This option only affects gigabit links. If you must establish a direct + connection between two devices which both force master mode, try forcing + the link speed to 100MBit/s. + + If unsure, say N. + menuconfig NETDEVICES bool "Network device support" depends on NET diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c index 259a87f..359ec50 100644 --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c @@ -12,6 +12,10 @@ #define PHY_AUTONEGOTIATE_TIMEOUT 5000 +/* RTL8211x 1000BASE-T Control Register */ +#define MIIM_RTL8211x_CTRL1000T_MSCE (1 << 12); +#define MIIM_RTL8211X_CTRL1000T_MASTER (1 << 11); + /* RTL8211x PHY Status Register */ #define MIIM_RTL8211x_PHY_STATUS 0x11 #define MIIM_RTL8211x_PHYSTAT_SPEED 0xc000 @@ -53,7 +57,14 @@ static int rtl8211x_config(struct phy_device *phydev) */ phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211x_PHY_INER, MIIM_RTL8211x_PHY_INTR_DIS); - +#ifdef CONFIG_RTL8211X_PHY_FORCE_MASTER + unsigned int reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_CTRL1000); + /* force manual master/slave configuration */ + reg |= MIIM_RTL8211x_CTRL1000T_MSCE; + /* force master mode */ + reg |= MIIM_RTL8211X_CTRL1000T_MASTER; + phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, reg); +#endif /* read interrupt status just to clear it */ phy_read(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211x_PHY_INER);