r8169: fix auto speed down issue
authorHayes Wang <hayeswang@realtek.com>
Sat, 13 Apr 2013 10:26:55 +0000 (12:26 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 17 Apr 2013 04:02:31 +0000 (21:02 -0700)
commit e2409d83434d77874b461b78af6a19cd6e6a1280 upstream.

It would cause no link after suspending or shutdowning when the
nic changes the speed to 10M and connects to a link partner which
forces the speed to 100M.

Check the link partner ability to determine which speed to set.

The link speed down code path is not factored in this kernel version.

Signed-off-by: Hayes Wang <hayeswang@realtek.com>
Acked-by: Francois Romieu <romieu@fr.zoreil.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/net/r8169.c

index 80b230e6f20737f430d51cb2e3cea4f67b8791ce..8350f8d21f09fedfc77a872988dd3a3e4b375589 100644 (file)
@@ -3105,11 +3105,34 @@ static void r810x_phy_power_up(struct rtl8169_private *tp)
        rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE);
 }
 
+static void rtl_speed_down(struct rtl8169_private *tp)
+{
+       u32 adv;
+       int lpa;
+
+       rtl_writephy(tp, 0x1f, 0x0000);
+       lpa = rtl_readphy(tp, MII_LPA);
+
+       if (lpa & (LPA_10HALF | LPA_10FULL))
+               adv = ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full;
+       else if (lpa & (LPA_100HALF | LPA_100FULL))
+               adv = ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
+                     ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full;
+       else
+               adv = ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
+                     ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
+                     (tp->mii.supports_gmii ?
+                      ADVERTISED_1000baseT_Half |
+                      ADVERTISED_1000baseT_Full : 0);
+
+       rtl8169_set_speed(tp->dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL,
+                         adv);
+}
+
 static void r810x_pll_power_down(struct rtl8169_private *tp)
 {
        if (__rtl8169_get_wol(tp) & WAKE_ANY) {
-               rtl_writephy(tp, 0x1f, 0x0000);
-               rtl_writephy(tp, MII_BMCR, 0x0000);
+               rtl_speed_down(tp);
                return;
        }
 
@@ -3201,8 +3224,7 @@ static void r8168_pll_power_down(struct rtl8169_private *tp)
                rtl_ephy_write(ioaddr, 0x19, 0xff64);
 
        if (__rtl8169_get_wol(tp) & WAKE_ANY) {
-               rtl_writephy(tp, 0x1f, 0x0000);
-               rtl_writephy(tp, MII_BMCR, 0x0000);
+               rtl_speed_down(tp);
 
                if (tp->mac_version == RTL_GIGA_MAC_VER_32 ||
                    tp->mac_version == RTL_GIGA_MAC_VER_33)