r8169: fix data corruption issue on RTL8402
authorHeiner Kallweit <hkallweit1@gmail.com>
Thu, 1 Oct 2020 07:23:02 +0000 (09:23 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 29 Oct 2020 08:06:59 +0000 (09:06 +0100)
[ Upstream commit ef9da46ddef071e1bbb943afbbe9b38771855554 ]

Petr reported that after resume from suspend RTL8402 partially
truncates incoming packets, and re-initializing register RxConfig
before the actual chip re-initialization sequence is needed to avoid
the issue.

Reported-by: Petr Tesarik <ptesarik@suse.cz>
Proposed-by: Petr Tesarik <ptesarik@suse.cz>
Tested-by: Petr Tesarik <ptesarik@suse.cz>
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/net/ethernet/realtek/r8169.c

index c7364d9496e39f5aa4c869511d73fea60701f0d7..72961082e398365db1521d4d2cda137b5ac3508c 100644 (file)
@@ -4501,6 +4501,58 @@ static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr)
        rtl_unlock_work(tp);
 }
 
+static void rtl_init_rxcfg(struct rtl8169_private *tp)
+{
+       void __iomem *ioaddr = tp->mmio_addr;
+
+       switch (tp->mac_version) {
+       case RTL_GIGA_MAC_VER_01:
+       case RTL_GIGA_MAC_VER_02:
+       case RTL_GIGA_MAC_VER_03:
+       case RTL_GIGA_MAC_VER_04:
+       case RTL_GIGA_MAC_VER_05:
+       case RTL_GIGA_MAC_VER_06:
+       case RTL_GIGA_MAC_VER_10:
+       case RTL_GIGA_MAC_VER_11:
+       case RTL_GIGA_MAC_VER_12:
+       case RTL_GIGA_MAC_VER_13:
+       case RTL_GIGA_MAC_VER_14:
+       case RTL_GIGA_MAC_VER_15:
+       case RTL_GIGA_MAC_VER_16:
+       case RTL_GIGA_MAC_VER_17:
+               RTL_W32(RxConfig, RX_FIFO_THRESH | RX_DMA_BURST);
+               break;
+       case RTL_GIGA_MAC_VER_18:
+       case RTL_GIGA_MAC_VER_19:
+       case RTL_GIGA_MAC_VER_20:
+       case RTL_GIGA_MAC_VER_21:
+       case RTL_GIGA_MAC_VER_22:
+       case RTL_GIGA_MAC_VER_23:
+       case RTL_GIGA_MAC_VER_24:
+       case RTL_GIGA_MAC_VER_34:
+       case RTL_GIGA_MAC_VER_35:
+               RTL_W32(RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST);
+               break;
+       case RTL_GIGA_MAC_VER_40:
+       case RTL_GIGA_MAC_VER_41:
+       case RTL_GIGA_MAC_VER_42:
+       case RTL_GIGA_MAC_VER_43:
+       case RTL_GIGA_MAC_VER_44:
+       case RTL_GIGA_MAC_VER_45:
+       case RTL_GIGA_MAC_VER_46:
+       case RTL_GIGA_MAC_VER_47:
+       case RTL_GIGA_MAC_VER_48:
+       case RTL_GIGA_MAC_VER_49:
+       case RTL_GIGA_MAC_VER_50:
+       case RTL_GIGA_MAC_VER_51:
+               RTL_W32(RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST | RX_EARLY_OFF);
+               break;
+       default:
+               RTL_W32(RxConfig, RX128_INT_EN | RX_DMA_BURST);
+               break;
+       }
+}
+
 static int rtl_set_mac_address(struct net_device *dev, void *p)
 {
        struct rtl8169_private *tp = netdev_priv(dev);
@@ -4519,6 +4571,10 @@ static int rtl_set_mac_address(struct net_device *dev, void *p)
 
        pm_runtime_put_noidle(d);
 
+       /* Reportedly at least Asus X453MA truncates packets otherwise */
+       if (tp->mac_version == RTL_GIGA_MAC_VER_37)
+               rtl_init_rxcfg(tp);
+
        return 0;
 }
 
@@ -4956,58 +5012,6 @@ static void rtl_init_pll_power_ops(struct rtl8169_private *tp)
        }
 }
 
-static void rtl_init_rxcfg(struct rtl8169_private *tp)
-{
-       void __iomem *ioaddr = tp->mmio_addr;
-
-       switch (tp->mac_version) {
-       case RTL_GIGA_MAC_VER_01:
-       case RTL_GIGA_MAC_VER_02:
-       case RTL_GIGA_MAC_VER_03:
-       case RTL_GIGA_MAC_VER_04:
-       case RTL_GIGA_MAC_VER_05:
-       case RTL_GIGA_MAC_VER_06:
-       case RTL_GIGA_MAC_VER_10:
-       case RTL_GIGA_MAC_VER_11:
-       case RTL_GIGA_MAC_VER_12:
-       case RTL_GIGA_MAC_VER_13:
-       case RTL_GIGA_MAC_VER_14:
-       case RTL_GIGA_MAC_VER_15:
-       case RTL_GIGA_MAC_VER_16:
-       case RTL_GIGA_MAC_VER_17:
-               RTL_W32(RxConfig, RX_FIFO_THRESH | RX_DMA_BURST);
-               break;
-       case RTL_GIGA_MAC_VER_18:
-       case RTL_GIGA_MAC_VER_19:
-       case RTL_GIGA_MAC_VER_20:
-       case RTL_GIGA_MAC_VER_21:
-       case RTL_GIGA_MAC_VER_22:
-       case RTL_GIGA_MAC_VER_23:
-       case RTL_GIGA_MAC_VER_24:
-       case RTL_GIGA_MAC_VER_34:
-       case RTL_GIGA_MAC_VER_35:
-               RTL_W32(RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST);
-               break;
-       case RTL_GIGA_MAC_VER_40:
-       case RTL_GIGA_MAC_VER_41:
-       case RTL_GIGA_MAC_VER_42:
-       case RTL_GIGA_MAC_VER_43:
-       case RTL_GIGA_MAC_VER_44:
-       case RTL_GIGA_MAC_VER_45:
-       case RTL_GIGA_MAC_VER_46:
-       case RTL_GIGA_MAC_VER_47:
-       case RTL_GIGA_MAC_VER_48:
-       case RTL_GIGA_MAC_VER_49:
-       case RTL_GIGA_MAC_VER_50:
-       case RTL_GIGA_MAC_VER_51:
-               RTL_W32(RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST | RX_EARLY_OFF);
-               break;
-       default:
-               RTL_W32(RxConfig, RX128_INT_EN | RX_DMA_BURST);
-               break;
-       }
-}
-
 static void rtl8169_init_ring_indexes(struct rtl8169_private *tp)
 {
        tp->dirty_tx = tp->cur_tx = tp->cur_rx = 0;