Commit ("r8169: enable ALDPS for power saving") caused a regression on
RTL8168evl/8111evl [1], so it got reverted.

Instead of reverting the whole commit, let's reinstate ALDPS for all
models other than RTL8168evl/8111evl.

[1] https://lkml.org/lkml/2013/1/5/36

Cc: Francois Romieu <rom...@fr.zoreil.com>
Cc: Hayes Wang <hayesw...@realtek.com>
Cc: Jörg Otte <jrg.o...@gmail.com>
Signed-off-by: Kai-Heng Feng <kai.heng.f...@canonical.com>
---
 drivers/net/ethernet/realtek/r8169.c | 58 +++++++++++++++++++++++++++++-------
 1 file changed, 48 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/realtek/r8169.c 
b/drivers/net/ethernet/realtek/r8169.c
index e03fcf914690..54bb9b15d541 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -733,6 +733,7 @@ enum features {
        RTL_FEATURE_WOL         = (1 << 0),
        RTL_FEATURE_MSI         = (1 << 1),
        RTL_FEATURE_GMII        = (1 << 2),
+       RTL_FEATURE_FW_LOADED   = (1 << 3),
 };
 
 struct rtl8169_counters {
@@ -2785,8 +2786,10 @@ static void rtl_apply_firmware(struct rtl8169_private 
*tp)
        struct rtl_fw *rtl_fw = tp->rtl_fw;
 
        /* TODO: release firmware once rtl_phy_write_fw signals failures. */
-       if (!IS_ERR_OR_NULL(rtl_fw))
+       if (!IS_ERR_OR_NULL(rtl_fw)) {
                rtl_phy_write_fw(tp, rtl_fw);
+               tp->features |= RTL_FEATURE_FW_LOADED;
+       }
 }
 
 static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 
val)
@@ -2797,6 +2800,31 @@ static void rtl_apply_firmware_cond(struct 
rtl8169_private *tp, u8 reg, u16 val)
                rtl_apply_firmware(tp);
 }
 
+static void r810x_aldps_disable(struct rtl8169_private *tp)
+{
+       rtl_writephy(tp, 0x1f, 0x0000);
+       rtl_writephy(tp, 0x18, 0x0310);
+       msleep(100);
+}
+
+static void r810x_aldps_enable(struct rtl8169_private *tp)
+{
+       if (!(tp->features & RTL_FEATURE_FW_LOADED))
+               return;
+
+       rtl_writephy(tp, 0x1f, 0x0000);
+       rtl_writephy(tp, 0x18, 0x8310);
+}
+
+static void r8168_aldps_enable_1(struct rtl8169_private *tp)
+{
+       if (!(tp->features & RTL_FEATURE_FW_LOADED))
+               return;
+
+       rtl_writephy(tp, 0x1f, 0x0000);
+       rtl_w0w1_phy(tp, 0x15, 0x1000, 0x0000);
+}
+
 static void rtl8169s_hw_phy_config(struct rtl8169_private *tp)
 {
        static const struct phy_reg phy_reg_init[] = {
@@ -3587,6 +3615,10 @@ static void rtl8168e_2_hw_phy_config(struct 
rtl8169_private *tp)
        rtl_w0w1_phy(tp, 0x10, 0x0000, 0x0400);
        rtl_writephy(tp, 0x1f, 0x0000);
 
+       /* Don't enable ALDPS for RTL8168evl/8111evl.
+        * https://lkml.org/lkml/2013/1/5/36
+        */
+
        /* Broken BIOS workaround: feed GigaMAC registers with MAC address. */
        rtl_rar_exgmac_set(tp, tp->dev->dev_addr);
 }
@@ -3661,6 +3693,8 @@ static void rtl8168f_1_hw_phy_config(struct 
rtl8169_private *tp)
        rtl_writephy(tp, 0x05, 0x8b85);
        rtl_w0w1_phy(tp, 0x06, 0x4000, 0x0000);
        rtl_writephy(tp, 0x1f, 0x0000);
+
+       r8168_aldps_enable_1(tp);
 }
 
 static void rtl8168f_2_hw_phy_config(struct rtl8169_private *tp)
@@ -3668,6 +3702,8 @@ static void rtl8168f_2_hw_phy_config(struct 
rtl8169_private *tp)
        rtl_apply_firmware(tp);
 
        rtl8168f_hw_phy_config(tp);
+
+       r8168_aldps_enable_1(tp);
 }
 
 static void rtl8411_hw_phy_config(struct rtl8169_private *tp)
@@ -4019,6 +4055,8 @@ static void rtl8168h_2_hw_phy_config(struct 
rtl8169_private *tp)
                rtl_w0w1_phy(tp, 0x10, 0x0000, 0x0004);
 
        rtl_writephy(tp, 0x1f, 0x0000);
+
+       r8168_aldps_enable_1(tp);
 }
 
 static void rtl8168ep_1_hw_phy_config(struct rtl8169_private *tp)
@@ -4188,21 +4226,19 @@ static void rtl8105e_hw_phy_config(struct 
rtl8169_private *tp)
        };
 
        /* Disable ALDPS before ram code */
-       rtl_writephy(tp, 0x1f, 0x0000);
-       rtl_writephy(tp, 0x18, 0x0310);
-       msleep(100);
+       r810x_aldps_disable(tp);
 
        rtl_apply_firmware(tp);
 
        rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+
+       r810x_aldps_enable(tp);
 }
 
 static void rtl8402_hw_phy_config(struct rtl8169_private *tp)
 {
        /* Disable ALDPS before setting firmware */
-       rtl_writephy(tp, 0x1f, 0x0000);
-       rtl_writephy(tp, 0x18, 0x0310);
-       msleep(20);
+       r810x_aldps_disable(tp);
 
        rtl_apply_firmware(tp);
 
@@ -4212,6 +4248,8 @@ static void rtl8402_hw_phy_config(struct rtl8169_private 
*tp)
        rtl_writephy(tp, 0x10, 0x401f);
        rtl_writephy(tp, 0x19, 0x7030);
        rtl_writephy(tp, 0x1f, 0x0000);
+
+       r810x_aldps_enable(tp);
 }
 
 static void rtl8106e_hw_phy_config(struct rtl8169_private *tp)
@@ -4224,9 +4262,7 @@ static void rtl8106e_hw_phy_config(struct rtl8169_private 
*tp)
        };
 
        /* Disable ALDPS before ram code */
-       rtl_writephy(tp, 0x1f, 0x0000);
-       rtl_writephy(tp, 0x18, 0x0310);
-       msleep(100);
+       r810x_aldps_disable(tp);
 
        rtl_apply_firmware(tp);
 
@@ -4234,6 +4270,8 @@ static void rtl8106e_hw_phy_config(struct rtl8169_private 
*tp)
        rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
 
        rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
+
+       r810x_aldps_enable(tp);
 }
 
 static void rtl_hw_phy_config(struct net_device *dev)
-- 
2.14.1

Reply via email to