AI Trajectory


Trajectory: (Expand/Collapse All)
Seq Timestamp Type Name Duration
0/0 2026/10/08 11:04 flow patch-triage
5m Args:
null

Results:
{
  "EnableConfigs": [
    "USB_RTL8152",
    "USB_NET_DRIVERS"
  ],
  "FocusSymbols": [
    "r8159_hw_phy_cfg",
    "r8157_hw_phy_cfg",
    "r8159_init",
    "r8157_init",
    "r8156b_init",
    "rtl8157_enable",
    "rtl8156b_enable",
    "rtl8157_up",
    "rtl8157_down",
    "rtl8157_change_mtu",
    "rtl_fc_pause_pkt_en",
    "rtl_tgphy_access",
    "r8157_ups_en",
    "__rtl_get_pkg_det"
  ],
  "KMSANReasoning": "The patch refactors the r8152 USB Ethernet driver to support new hardware revisions (RTL8157 and RTL8159 variants) and updates register access helpers (ocp_reg_read, sram_read, etc.) to pass output data by pointer and return integer status codes for proper error handling.\n\nA careful examination of all modified and newly introduced code paths shows:\n1. No uninitialized kernel memory or structure padding is leaked to user space: ioctl and ethtool handlers (rtl8152_get_link_ksettings, r8153_get_eee, rtl8152_get_pauseparam, rtl8152_ioctl) now check return codes from register reads and abort or return appropriate errors instead of operating on or leaking uninitialized data.\n2. All out-parameters passed to register read functions are either guarded by return code checks or initialized prior to use.\n3. Heap allocations (such as in __rtl_get_pkg_det) only read the allocated buffer if usb_control_msg() returns the full expected size, and properly clean up afterwards.\n4. No network skb parsing or length manipulation is introduced that could lead to reading uninitialized bytes.\n\nConsequently, there are no uninitialized memory access or info-leak risks that would necessitate a dedicated KMSAN fuzzing session. Any potential issues (hardware timeouts, locking, logic bugs) are adequately addressed by standard testing and KASAN.",
  "NeedsKMSAN": false,
  "Reasoning": "The patch adds support for newer Realtek RTL8157 and RTL8159 USB Ethernet controllers (splitting RTL_VER_17 into QFN68 and QFN100 variants), refactors PHY/SRAM read and write helpers to propagate errors, refactors polling loops, implements flow control pause packet limiting, and introduces new device initialization and PHY configuration logic. In addition, it adds a new assertion (WARN_ON_ONCE) in r8159_hw_phy_cfg(). The driver is fully reachable and fuzzable via USB emulation (such as Raw Gadget or dummy_hcd) and subsequent network device interface configuration and ethtool/ioctl operations.",
  "WorthFuzzing": true
}

1/1 2026/10/08 11:04 action read-patch-diff
0m Args:
null

Results:
{
  "PatchDiff": "commit 7c46fb3d692dd4fe361e4ece17399e3895e2c8a6\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate:   Thu Oct 8 11:04:01 2026 +0000\n\n    syz-cluster: applied patch under review\n\ndiff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c\nindex af3d7dcb2f141..fc75e263b0e4c 100644\n--- a/drivers/net/usb/r8152.c\n+++ b/drivers/net/usb/r8152.c\n@@ -64,6 +64,7 @@\n #define PLA_MACDBG_POST\t\t0xd38e\t/* RTL_VER_04 only */\n #define PLA_EXTRA_STATUS\t0xd398\n #define PLA_GPHY_CTRL\t\t0xd3ae\n+#define PLA_PKG_DET\t\t0xdc48\n #define PLA_POL_GPIO_CTRL\t0xdc6a\n #define PLA_EFUSE_DATA\t\t0xdd00\n #define PLA_EFUSE_CMD\t\t0xdd02\n@@ -78,6 +79,7 @@\n #define PLA_EEE_TXTWSYS_2P5G\t0xe058\n #define PLA_EEEP_CR\t\t0xe080\n #define PLA_MAC_PWR_CTRL\t0xe0c0\n+#define PLA_RMT_WAKE\t\t0xe0c8\n #define PLA_MAC_PWR_CTRL2\t0xe0ca\n #define PLA_MAC_PWR_CTRL3\t0xe0cc\n #define PLA_MAC_PWR_CTRL4\t0xe0ce\n@@ -87,6 +89,7 @@\n #define PLA_MTPS\t\t0xe615\n #define PLA_TXFIFO_CTRL\t\t0xe618\n #define PLA_TXFIFO_FULL\t\t0xe61a\n+#define PLA_PAUSE_LIMIT         0xe61e\n #define PLA_RSTTALLY\t\t0xe800\n #define PLA_CR\t\t\t0xe813\n #define PLA_CRWECR\t\t0xe81c\n@@ -129,6 +132,7 @@\n #define USB_BURST_SIZE\t\t0xcfc0\n #define USB_FW_FIX_EN0\t\t0xcfca\n #define USB_FW_FIX_EN1\t\t0xcfcc\n+#define USB_FW_USB_VER          0xcfd7\n #define USB_LPM_CONFIG\t\t0xcfd8\n #define USB_ECM_OPTION\t\t0xcfee\n #define USB_CSTMR\t\t0xcfef\t/* RTL8153A */\n@@ -160,6 +164,9 @@\n #define USB_ADV_ADDR\t\t0xd5d6\n #define USB_ADV_DATA\t\t0xd5d8\n #define USB_ADV_CMD\t\t0xd5dc\n+#define USB_TGPHY_ADDR\t\t0xd630\n+#define USB_TGPHY_DATA\t\t0xd632\n+#define USB_TGPHY_CMD\t\t0xd634\n #define USB_UPS_CTRL\t\t0xd800\n #define USB_POWER_CUT\t\t0xd80a\n #define USB_MISC_0\t\t0xd81a\n@@ -289,10 +296,17 @@\n #define IFG_144NS\t\tBIT(9)\n #define IFG_96NS\t\t(BIT(9) | BIT(8))\n \n+/* PLA_PKG_DET */\n+#define PKG_MASK\t\t0x1e\n+\n /* PLA_MTPS */\n #define MTPS_JUMBO\t\t(12 * 1024 / 64)\n #define MTPS_DEFAULT\t\t(6 * 1024 / 64)\n \n+/* PLA_PAUSE_LIMIT */\n+#define PAUSE_LIMIT_EN\t\tBIT(3)\n+#define PAUSE_LIMIT_MASK\t0xf0\n+\n /* PLA_RSTTALLY */\n #define TALLY_RESET\t\t0x0001\n \n@@ -371,6 +385,9 @@\n #define MCU_CLK_RATIO_MASK\t0x0f0f0f0f\n #define ALDPS_SPDWN_RATIO\t0x0f87\n \n+/* PLA_RMT_WAKE */\n+#define RMT_WAKE_EN\t\tBIT(0)\n+\n /* PLA_MAC_PWR_CTRL2 */\n #define EEE_SPDWN_RATIO\t\t0x8007\n #define MAC_CLK_SPDWN_EN\tBIT(15)\n@@ -417,6 +434,7 @@\n \n /* PLA_INDICATE_FALG */\n #define UPCOMING_RUNTIME_D3\tBIT(0)\n+#define PREBOOT_OPTION\t\tBIT(1)\n \n /* PLA_MACDBG_PRE and PLA_MACDBG_POST */\n #define DEBUG_OE\t\tBIT(0)\n@@ -502,6 +520,10 @@\n #define ADV_CMD_WR\t\tBIT(1)\n #define ADV_CMD_IP\t\tBIT(2)\n \n+/* USB_TGPHY_CMD */\n+#define TGPHY_CMD_BUSY\t\tBIT(0)\n+#define TGPHY_CMD_WR\t\tBIT(1)\n+\n /* USB_UPS_CTRL */\n #define POWER_CUT\t\t0x0100\n \n@@ -542,6 +564,7 @@\n #define RX_AGG_DISABLE\t\t0x0010\n #define RX_ZERO_EN\t\t0x0080\n #define RX_DESC_16B\t\t0x0400\n+#define RX_END_TRANSFER_EN\tBIT(11)\n \n /* USB_U2P3_CTRL */\n #define U2P3_ENABLE\t\t0x0001\n@@ -597,6 +620,11 @@\n #define UPS_FLAGS_250M_CKDIV\t\tBIT(2)\n #define UPS_FLAGS_EN_ALDPS\t\tBIT(3)\n #define UPS_FLAGS_CTAP_SHORT_DIS\tBIT(4)\n+#define UPS_FLAGS_EN_100M_EEE\t\tBIT(9)\n+#define UPS_FLAGS_EN_1000M_EEE\t\tBIT(10)\n+#define UPS_FLAGS_EN_2500M_EEE\t\tBIT(11)\n+#define UPS_FLAGS_EN_5000M_EEE\t\tBIT(12)\n+#define UPS_FLAGS_EN_10G_EEE\t\tBIT(13)\n #define UPS_FLAGS_SPEED_MASK\t\t(0xf \u003c\u003c 16)\n #define ups_flags_speed(x)\t\t((x) \u003c\u003c 16)\n #define UPS_FLAGS_EN_EEE\t\tBIT(20)\n@@ -645,6 +673,7 @@ enum spd_duplex {\n /* OCP_POWER_CFG */\n #define EEE_CLKDIV_EN\t\t0x8000\n #define EN_ALDPS\t\t0x0004\n+#define EN_ALDPS_PLLOFF         0x0002\n #define EN_10M_PLLOFF\t\t0x0001\n \n /* OCP_EEE_CONFIG1 */\n@@ -948,6 +977,8 @@ struct r8152 {\n \t\tvoid (*hw_phy_cfg)(struct r8152 *tp);\n \t\tvoid (*autosuspend_en)(struct r8152 *tp, bool enable);\n \t\tvoid (*change_mtu)(struct r8152 *tp);\n+\t\tint (*phy_read)(struct r8152 *tp, u16 addr, u16 *data);\n+\t\tint (*phy_write)(struct r8152 *tp, u16 addr, u16 data);\n \t} rtl_ops;\n \n \tstruct ups_info {\n@@ -1247,7 +1278,8 @@ enum rtl_version {\n \tRTL_VER_14,\n \tRTL_VER_15,\n \tRTL_VER_16,\n-\tRTL_VER_17,\n+\tRTL_VER_17_QFN68,\n+\tRTL_VER_17_QFN100,\n \n \tRTL_VER_MAX\n };\n@@ -1626,7 +1658,7 @@ static void ocp_write_byte(struct r8152 *tp, u16 type, u16 index, u32 data)\n \tgeneric_ocp_write(tp, index, byen, sizeof(tmp), \u0026tmp, type);\n }\n \n-static u16 ocp_reg_read(struct r8152 *tp, u16 addr)\n+static int r8152_phy_read(struct r8152 *tp, u16 addr, u16 *data)\n {\n \tu16 ocp_base, ocp_index;\n \n@@ -1637,10 +1669,12 @@ static u16 ocp_reg_read(struct r8152 *tp, u16 addr)\n \t}\n \n \tocp_index = (addr \u0026 0x0fff) | 0xb000;\n-\treturn ocp_read_word(tp, MCU_TYPE_PLA, ocp_index);\n+\t*data = ocp_read_word(tp, MCU_TYPE_PLA, ocp_index);\n+\n+\treturn 0;\n }\n \n-static void ocp_reg_write(struct r8152 *tp, u16 addr, u16 data)\n+static int r8152_phy_write(struct r8152 *tp, u16 addr, u16 data)\n {\n \tu16 ocp_base, ocp_index;\n \n@@ -1652,16 +1686,33 @@ static void ocp_reg_write(struct r8152 *tp, u16 addr, u16 data)\n \n \tocp_index = (addr \u0026 0x0fff) | 0xb000;\n \tocp_write_word(tp, MCU_TYPE_PLA, ocp_index, data);\n+\n+\treturn 0;\n }\n \n-static inline void r8152_mdio_write(struct r8152 *tp, u32 reg_addr, u32 value)\n+static int ocp_reg_read(struct r8152 *tp, u16 addr, u16 *data)\n {\n-\tocp_reg_write(tp, OCP_BASE_MII + reg_addr * 2, value);\n+\treturn tp-\u003ertl_ops.phy_read(tp, addr, data);\n }\n \n-static inline int r8152_mdio_read(struct r8152 *tp, u32 reg_addr)\n+static int ocp_reg_write(struct r8152 *tp, u16 addr, u16 data)\n {\n-\treturn ocp_reg_read(tp, OCP_BASE_MII + reg_addr * 2);\n+\treturn tp-\u003ertl_ops.phy_write(tp, addr, data);\n+}\n+\n+static inline int r8152_mdio_write(struct r8152 *tp, u32 reg_addr, u32 value)\n+{\n+\treturn ocp_reg_write(tp, OCP_BASE_MII + reg_addr * 2, value);\n+}\n+\n+static int r8152_mdio_read(struct r8152 *tp, u32 reg_addr)\n+{\n+\tu16 data;\n+\tint ret;\n+\n+\tret = ocp_reg_read(tp, OCP_BASE_MII + reg_addr * 2, \u0026data);\n+\n+\treturn ret \u003c 0 ? ret : data;\n }\n \n static int wait_cmd_ready(struct r8152 *tp, u16 cmd)\n@@ -1780,16 +1831,32 @@ static int rtl_ip_set_bits(struct r8152 *tp, u16 addr, u32 set)\n \treturn rtl_ip_w0w1(tp, addr, 0, set);\n }\n \n-static void sram_write(struct r8152 *tp, u16 addr, u16 data)\n+static int sram_write(struct r8152 *tp, u16 addr, u16 data)\n {\n-\tocp_reg_write(tp, OCP_SRAM_ADDR, addr);\n-\tocp_reg_write(tp, OCP_SRAM_DATA, data);\n+\tint ret;\n+\n+\tret = ocp_reg_write(tp, OCP_SRAM_ADDR, addr);\n+\tif (ret \u003c 0)\n+\t\tgoto out;\n+\n+\tret = ocp_reg_write(tp, OCP_SRAM_DATA, data);\n+\n+out:\n+\treturn ret;\n }\n \n-static u16 sram_read(struct r8152 *tp, u16 addr)\n+static int sram_read(struct r8152 *tp, u16 addr, u16 *data)\n {\n-\tocp_reg_write(tp, OCP_SRAM_ADDR, addr);\n-\treturn ocp_reg_read(tp, OCP_SRAM_DATA);\n+\tint ret;\n+\n+\tret = ocp_reg_write(tp, OCP_SRAM_ADDR, addr);\n+\tif (ret \u003c 0)\n+\t\tgoto out;\n+\n+\tret = ocp_reg_read(tp, OCP_SRAM_DATA, data);\n+\n+out:\n+\treturn ret;\n }\n \n static int read_mii_word(struct net_device *netdev, int phy_id, int reg)\n@@ -1894,90 +1961,217 @@ static void ocp_byte_set_bits(struct r8152 *tp, u16 type, u16 index, u8 set)\n \tocp_byte_w0w1(tp, type, index, 0, set);\n }\n \n-static void ocp_reg_w0w1(struct r8152 *tp, u16 addr, u16 clear, u16 set)\n+static int ocp_reg_w0w1(struct r8152 *tp, u16 addr, u16 clear, u16 set)\n {\n \tu16 data;\n+\tint ret;\n+\n+\tret = ocp_reg_read(tp, addr, \u0026data);\n+\tif (ret \u003c 0)\n+\t\tgoto out;\n \n-\tdata = ocp_reg_read(tp, addr);\n \tdata = (data \u0026 ~clear) | set;\n-\tocp_reg_write(tp, addr, data);\n+\tret = ocp_reg_write(tp, addr, data);\n+\n+out:\n+\treturn ret;\n }\n \n-static void ocp_reg_clr_bits(struct r8152 *tp, u16 addr, u16 clear)\n+static int ocp_reg_clr_bits(struct r8152 *tp, u16 addr, u16 clear)\n {\n-\tocp_reg_w0w1(tp, addr, clear, 0);\n+\treturn ocp_reg_w0w1(tp, addr, clear, 0);\n }\n \n-static void ocp_reg_set_bits(struct r8152 *tp, u16 addr, u16 set)\n+static int ocp_reg_set_bits(struct r8152 *tp, u16 addr, u16 set)\n {\n-\tocp_reg_w0w1(tp, addr, 0, set);\n+\treturn ocp_reg_w0w1(tp, addr, 0, set);\n }\n \n-static void sram_write_w0w1(struct r8152 *tp, u16 addr, u16 clear, u16 set)\n+static int sram_write_w0w1(struct r8152 *tp, u16 addr, u16 clear, u16 set)\n {\n \tu16 data;\n+\tint ret;\n+\n+\tret = sram_read(tp, addr, \u0026data);\n+\tif (ret \u003c 0)\n+\t\tgoto out;\n \n-\tdata = sram_read(tp, addr);\n \tdata = (data \u0026 ~clear) | set;\n-\tocp_reg_write(tp, OCP_SRAM_DATA, data);\n+\tret = ocp_reg_write(tp, OCP_SRAM_DATA, data);\n+\n+out:\n+\treturn ret;\n }\n \n-static void sram_clr_bits(struct r8152 *tp, u16 addr, u16 clear)\n+static int sram_clr_bits(struct r8152 *tp, u16 addr, u16 clear)\n {\n-\tsram_write_w0w1(tp, addr, clear, 0);\n+\treturn sram_write_w0w1(tp, addr, clear, 0);\n }\n \n-static void sram_set_bits(struct r8152 *tp, u16 addr, u16 set)\n+static int sram_set_bits(struct r8152 *tp, u16 addr, u16 set)\n {\n-\tsram_write_w0w1(tp, addr, 0, set);\n+\treturn sram_write_w0w1(tp, addr, 0, set);\n }\n \n-static void sram2_write(struct r8152 *tp, u16 addr, u16 data)\n+static int sram2_write(struct r8152 *tp, u16 addr, u16 data)\n {\n-\tocp_reg_write(tp, OCP_SRAM2_ADDR, addr);\n-\tocp_reg_write(tp, OCP_SRAM2_DATA, data);\n+\tint ret;\n+\n+\tret = ocp_reg_write(tp, OCP_SRAM2_ADDR, addr);\n+\tif (ret \u003c 0)\n+\t\tgoto out;\n+\n+\tret = ocp_reg_write(tp, OCP_SRAM2_DATA, data);\n+\n+out:\n+\treturn ret;\n }\n \n-static u16 sram2_read(struct r8152 *tp, u16 addr)\n+static int sram2_read(struct r8152 *tp, u16 addr, u16 *data)\n {\n-\tocp_reg_write(tp, OCP_SRAM2_ADDR, addr);\n-\treturn ocp_reg_read(tp, OCP_SRAM2_DATA);\n+\tint ret;\n+\n+\tret = ocp_reg_write(tp, OCP_SRAM2_ADDR, addr);\n+\tif (ret \u003c 0)\n+\t\tgoto out;\n+\n+\tret = ocp_reg_read(tp, OCP_SRAM2_DATA, data);\n+\n+out:\n+\treturn ret;\n }\n \n-static void sram2_write_w0w1(struct r8152 *tp, u16 addr, u16 clear, u16 set)\n+static int sram2_write_w0w1(struct r8152 *tp, u16 addr, u16 clear, u16 set)\n {\n \tu16 data;\n+\tint ret;\n+\n+\tret = sram2_read(tp, addr, \u0026data);\n+\tif (ret \u003c 0)\n+\t\tgoto out;\n \n-\tdata = sram2_read(tp, addr);\n \tdata = (data \u0026 ~clear) | set;\n-\tocp_reg_write(tp, OCP_SRAM2_DATA, data);\n+\tret = ocp_reg_write(tp, OCP_SRAM2_DATA, data);\n+\n+out:\n+\treturn ret;\n }\n \n-static void r8152_mdio_clr_bit(struct r8152 *tp, u16 addr, u16 clear)\n+static int sram2_set_bits(struct r8152 *tp, u16 addr, u16 set)\n+{\n+\treturn sram2_write_w0w1(tp, addr, 0, set);\n+}\n+\n+static int sram2_clr_bits(struct r8152 *tp, u16 addr, u16 clear)\n+{\n+\treturn sram2_write_w0w1(tp, addr, clear, 0);\n+}\n+\n+static int r8152_mdio_clr_bit(struct r8152 *tp, u16 addr, u16 clear)\n {\n \tint data;\n \n \tdata = r8152_mdio_read(tp, addr);\n-\tr8152_mdio_write(tp, addr, data \u0026 ~clear);\n+\tif (data \u003c 0)\n+\t\tgoto out;\n+\n+\tdata = r8152_mdio_write(tp, addr, data \u0026 ~clear);\n+\n+out:\n+\treturn data;\n }\n \n-static void r8152_mdio_set_bit(struct r8152 *tp, u16 addr, u16 set)\n+static int r8152_mdio_set_bit(struct r8152 *tp, u16 addr, u16 set)\n {\n \tint data;\n \n \tdata = r8152_mdio_read(tp, addr);\n-\tr8152_mdio_write(tp, addr, data | set);\n+\tif (data \u003c 0)\n+\t\tgoto out;\n+\n+\tdata = r8152_mdio_write(tp, addr, data | set);\n+\n+out:\n+\treturn data;\n }\n \n static int r8152_mdio_test_and_clr_bit(struct r8152 *tp, u16 addr, u16 clear)\n {\n-\tint data;\n+\tint data, ret;\n \n-\tdata = r8152_mdio_read(tp, addr);\n-\tif (data \u0026 clear)\n-\t\tr8152_mdio_write(tp, addr, data \u0026 ~clear);\n+\tret = r8152_mdio_read(tp, addr);\n+\tif (ret \u003c 0)\n+\t\tgoto out;\n+\n+\tdata = ret;\n+\tif (data \u0026 clear) {\n+\t\tret = r8152_mdio_write(tp, addr, data \u0026 ~clear);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto out;\n+\t}\n+\n+\tret = !!(data \u0026 clear);\n+\n+out:\n+\treturn ret;\n+}\n+\n+static int wait_tgphy_cmd_ready(struct r8152 *tp)\n+{\n+\tu16 ocp_data;\n+\tint ret;\n+\n+\tret = read_poll_timeout(ocp_read_word, ocp_data,\n+\t\t\t\ttest_bit(RTL8152_INACCESSIBLE, \u0026tp-\u003eflags) ||\n+\t\t\t\t!(ocp_data \u0026 TGPHY_CMD_BUSY),\n+\t\t\t\t2000, 20000, false, tp,\n+\t\t\t\tMCU_TYPE_USB, USB_TGPHY_CMD);\n+\n+\tif (ret)\n+\t\tdev_err(\u0026tp-\u003eintf-\u003edev, \"TGPHY cmd busy timeout\\n\");\n+\n+\treturn test_bit(RTL8152_INACCESSIBLE, \u0026tp-\u003eflags) ? -ENODEV : ret;\n+}\n+\n+static int rtl_tgphy_access(struct r8152 *tp, u16 addr, u16 *data, bool write)\n+{\n+\tu16 cmd = 0;\n+\tint ret;\n+\n+\tret = wait_tgphy_cmd_ready(tp);\n+\tif (ret \u003c 0)\n+\t\tgoto out;\n+\n+\tif (write) {\n+\t\tcmd |= TGPHY_CMD_WR;\n+\t\tocp_write_word(tp, MCU_TYPE_USB, USB_TGPHY_DATA, *data);\n+\t}\n+\n+\tocp_write_word(tp, MCU_TYPE_USB, USB_TGPHY_ADDR, addr);\n+\n+\tcmd |= TGPHY_CMD_BUSY;\n+\tocp_write_word(tp, MCU_TYPE_USB, USB_TGPHY_CMD, cmd);\n+\n+\tif (!write) {\n+\t\tret = wait_tgphy_cmd_ready(tp);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto out;\n+\n+\t\t*data = ocp_read_word(tp, MCU_TYPE_USB, USB_TGPHY_DATA);\n+\t}\n+\n+out:\n+\treturn ret;\n+}\n+\n+static int r8157_phy_read(struct r8152 *tp, u16 addr, u16 *data)\n+{\n+\treturn rtl_tgphy_access(tp, addr, data, false);\n+}\n \n-\treturn data \u0026 clear;\n+static int r8157_phy_write(struct r8152 *tp, u16 addr, u16 data)\n+{\n+\treturn rtl_tgphy_access(tp, addr, \u0026data, true);\n }\n \n static int\n@@ -3412,7 +3606,8 @@ static void rtl8152_nic_reset(struct r8152 *tp)\n \t\tbreak;\n \n \tcase RTL_VER_16:\n-\tcase RTL_VER_17:\n+\tcase RTL_VER_17_QFN68:\n+\tcase RTL_VER_17_QFN100:\n \t\tocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_CR, CR_RE | CR_TE);\n \t\tbreak;\n \n@@ -3452,7 +3647,7 @@ static void rtl_eee_plus_en(struct r8152 *tp, bool enable)\n \n static void rtl_set_eee_plus(struct r8152 *tp)\n {\n-\tif (tp-\u003eversion == RTL_VER_17)\n+\tif (tp-\u003eversion == RTL_VER_17_QFN68 || tp-\u003eversion == RTL_VER_17_QFN100)\n \t\treturn rtl_eee_plus_en(tp, false);\n \n \tif (rtl8152_get_speed(tp) \u0026 _10bps)\n@@ -3640,7 +3835,8 @@ static void r8153_set_rx_early_timeout(struct r8152 *tp)\n \tcase RTL_VER_13:\n \tcase RTL_VER_15:\n \tcase RTL_VER_16:\n-\tcase RTL_VER_17:\n+\tcase RTL_VER_17_QFN68:\n+\tcase RTL_VER_17_QFN100:\n \t\tocp_write_word(tp, MCU_TYPE_USB, USB_RX_EARLY_TIMEOUT,\n \t\t\t       640 / 8);\n \t\tocp_write_word(tp, MCU_TYPE_USB, USB_RX_EXTRA_AGGR_TMR,\n@@ -3685,7 +3881,8 @@ static void r8153_set_rx_early_size(struct r8152 *tp)\n \t\t\t       ocp_data / 8);\n \t\tbreak;\n \tcase RTL_VER_16:\n-\tcase RTL_VER_17:\n+\tcase RTL_VER_17_QFN68:\n+\tcase RTL_VER_17_QFN100:\n \t\tocp_write_word(tp, MCU_TYPE_USB, USB_RX_EARLY_SIZE,\n \t\t\t       ocp_data / 16);\n \t\tbreak;\n@@ -3801,6 +3998,8 @@ static void rtl_rx_vlan_en(struct r8152 *tp, bool enable)\n \tcase RTL_VER_13:\n \tcase RTL_VER_15:\n \tcase RTL_VER_16:\n+\tcase RTL_VER_17_QFN68:\n+\tcase RTL_VER_17_QFN100:\n \tdefault:\n \t\tif (enable)\n \t\t\tocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_RCR1,\n@@ -4051,8 +4250,27 @@ static void r8156_ups_flags(struct r8152 *tp)\n \tif (tp-\u003eups_info.aldps)\n \t\tups_flags |= UPS_FLAGS_EN_ALDPS;\n \n-\tif (tp-\u003eups_info.eee)\n-\t\tups_flags |= UPS_FLAGS_EN_EEE;\n+\tif (tp-\u003eups_info.eee) {\n+\t\tswitch (tp-\u003eversion) {\n+\t\tcase RTL_VER_17_QFN68:\n+\t\t\tif (tp-\u003eeee_adv \u0026 MDIO_EEE_10GT)\n+\t\t\t\tups_flags |= UPS_FLAGS_EN_10G_EEE;\n+\t\t\tfallthrough;\n+\t\tcase RTL_VER_16:\n+\t\t\tif (tp-\u003eeee_adv \u0026 MDIO_EEE_100TX)\n+\t\t\t\tups_flags |= UPS_FLAGS_EN_100M_EEE;\n+\t\t\tif (tp-\u003eeee_adv \u0026 MDIO_EEE_1000T)\n+\t\t\t\tups_flags |= UPS_FLAGS_EN_1000M_EEE;\n+\t\t\tif (tp-\u003eeee_adv2 \u0026 MDIO_EEE_2_5GT)\n+\t\t\t\tups_flags |= UPS_FLAGS_EN_2500M_EEE;\n+\t\t\tif (tp-\u003eeee_adv2 \u0026 MDIO_EEE_5GT)\n+\t\t\t\tups_flags |= UPS_FLAGS_EN_5000M_EEE;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tups_flags |= UPS_FLAGS_EN_EEE;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n \n \tif (tp-\u003eups_info.flow_control)\n \t\tups_flags |= UPS_FLAGS_EN_FLOW_CTR;\n@@ -4103,20 +4321,33 @@ static void r8156_ups_flags(struct r8152 *tp)\n \tcase NWAY_2500M_FULL:\n \t\tups_flags |= ups_flags_speed(9);\n \t\tbreak;\n+\tcase NWAY_5000M_FULL:\n+\t\tups_flags |= ups_flags_speed(10);\n+\t\tbreak;\n+\tcase NWAY_10000M_FULL:\n+\t\tups_flags |= ups_flags_speed(11);\n+\t\tbreak;\n \tdefault:\n \t\tbreak;\n \t}\n \n-\tswitch (tp-\u003eups_info.lite_mode) {\n-\tcase 1:\n-\t\tups_flags |= 0 \u003c\u003c 5;\n-\t\tbreak;\n-\tcase 2:\n-\t\tups_flags |= 2 \u003c\u003c 5;\n+\tswitch (tp-\u003eversion) {\n+\tcase RTL_VER_16:\n+\tcase RTL_VER_17_QFN68:\n \t\tbreak;\n-\tcase 0:\n \tdefault:\n-\t\tups_flags |= 1 \u003c\u003c 5;\n+\t\tswitch (tp-\u003eups_info.lite_mode) {\n+\t\tcase 1:\n+\t\t\tups_flags |= 0 \u003c\u003c 5;\n+\t\t\tbreak;\n+\t\tcase 2:\n+\t\t\tups_flags |= 2 \u003c\u003c 5;\n+\t\t\tbreak;\n+\t\tcase 0:\n+\t\tdefault:\n+\t\t\tups_flags |= 1 \u003c\u003c 5;\n+\t\t\tbreak;\n+\t\t}\n \t\tbreak;\n \t}\n \n@@ -4150,11 +4381,13 @@ static void r8153b_green_en(struct r8152 *tp, bool enable)\n \n static u16 r8153_phy_status(struct r8152 *tp, u16 desired)\n {\n-\tu16 data;\n+\tu16 data = 0;\n \tint i;\n \n \tfor (i = 0; i \u003c 500; i++) {\n-\t\tdata = ocp_reg_read(tp, OCP_PHY_STATUS);\n+\t\tif (ocp_reg_read(tp, OCP_PHY_STATUS, \u0026data) \u003c 0)\n+\t\t\tbreak;\n+\n \t\tdata \u0026= PHY_STAT_MASK;\n \t\tif (desired) {\n \t\t\tif (data == desired)\n@@ -4172,6 +4405,23 @@ static u16 r8153_phy_status(struct r8152 *tp, u16 desired)\n \treturn data;\n }\n \n+static int wait_autoload_done(struct r8152 *tp)\n+{\n+\tu16 ocp_data;\n+\tint ret;\n+\n+\tret = read_poll_timeout(ocp_read_word, ocp_data,\n+\t\t\t\ttest_bit(RTL8152_INACCESSIBLE, \u0026tp-\u003eflags) ||\n+\t\t\t\t(ocp_data \u0026 AUTOLOAD_DONE),\n+\t\t\t\t20000, 10 * USEC_PER_SEC, false, tp,\n+\t\t\t\tMCU_TYPE_PLA, PLA_BOOT_CTRL);\n+\n+\tif (ret)\n+\t\tdev_err(\u0026tp-\u003eintf-\u003edev, \"autoload done timeout\\n\");\n+\n+\treturn test_bit(RTL8152_INACCESSIBLE, \u0026tp-\u003eflags) ? -ENODEV : 0;\n+}\n+\n static void r8153b_ups_en(struct r8152 *tp, bool enable)\n {\n \tif (enable) {\n@@ -4190,16 +4440,8 @@ static void r8153b_ups_en(struct r8152 *tp, bool enable)\n \t\t\t\t  UPS_FORCE_PWR_DOWN);\n \n \t\tif (ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0) \u0026 PCUT_STATUS) {\n-\t\t\tint i;\n-\n-\t\t\tfor (i = 0; i \u003c 500; i++) {\n-\t\t\t\tif (test_bit(RTL8152_INACCESSIBLE, \u0026tp-\u003eflags))\n-\t\t\t\t\treturn;\n-\t\t\t\tif (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) \u0026\n-\t\t\t\t    AUTOLOAD_DONE)\n-\t\t\t\t\tbreak;\n-\t\t\t\tmsleep(20);\n-\t\t\t}\n+\t\t\tif (wait_autoload_done(tp))\n+\t\t\t\treturn;\n \n \t\t\ttp-\u003ertl_ops.hw_phy_cfg(tp);\n \n@@ -4227,16 +4469,8 @@ static void r8153c_ups_en(struct r8152 *tp, bool enable)\n \t\t\t\t  UPS_FORCE_PWR_DOWN);\n \n \t\tif (ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0) \u0026 PCUT_STATUS) {\n-\t\t\tint i;\n-\n-\t\t\tfor (i = 0; i \u003c 500; i++) {\n-\t\t\t\tif (test_bit(RTL8152_INACCESSIBLE, \u0026tp-\u003eflags))\n-\t\t\t\t\treturn;\n-\t\t\t\tif (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) \u0026\n-\t\t\t\t    AUTOLOAD_DONE)\n-\t\t\t\t\tbreak;\n-\t\t\t\tmsleep(20);\n-\t\t\t}\n+\t\t\tif (wait_autoload_done(tp))\n+\t\t\t\treturn;\n \n \t\t\ttp-\u003ertl_ops.hw_phy_cfg(tp);\n \n@@ -4288,6 +4522,49 @@ static void r8156_ups_en(struct r8152 *tp, bool enable)\n \t}\n }\n \n+static void r8157_ups_en(struct r8152 *tp, bool enable)\n+{\n+\tif (enable) {\n+\t\tr8156_ups_flags(tp);\n+\n+\t\tocp_byte_set_bits(tp, MCU_TYPE_USB, USB_POWER_CUT,\n+\t\t\t\t  UPS_EN | USP_PREWAKE | PHASE2_EN);\n+\n+\t\tocp_byte_set_bits(tp, MCU_TYPE_USB, USB_MISC_2,\n+\t\t\t\t  UPS_FORCE_PWR_DOWN);\n+\t} else {\n+\t\tocp_byte_clr_bits(tp, MCU_TYPE_USB, USB_POWER_CUT,\n+\t\t\t\t  UPS_EN | USP_PREWAKE);\n+\n+\t\tocp_byte_clr_bits(tp, MCU_TYPE_USB, USB_MISC_2,\n+\t\t\t\t  UPS_FORCE_PWR_DOWN);\n+\n+\t\tif (ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0) \u0026 PCUT_STATUS) {\n+\t\t\tu32 ocp_data;\n+\t\t\tint ret;\n+\n+\t\t\tret = read_poll_timeout(ocp_read_word, ocp_data,\n+\t\t\t\t\t\tocp_data \u0026 BACKUP_RESTRORE, 200,\n+\t\t\t\t\t\t20000, false, tp, MCU_TYPE_USB,\n+\t\t\t\t\t\tUSB_GPHY_CTRL);\n+\t\t\tif (ret) {\n+\t\t\t\trtl_set_inaccessible(tp);\n+\t\t\t\tdev_err(\u0026tp-\u003eintf-\u003edev,\n+\t\t\t\t\t\"backup-restore timed out\\n\");\n+\t\t\t\treturn;\n+\t\t\t}\n+\n+\t\t\t/* clear USB fw_ver_reg */\n+\t\t\tocp_write_byte(tp, MCU_TYPE_USB, USB_FW_USB_VER, 0);\n+\n+\t\t\ttp-\u003ertl_ops.hw_phy_cfg(tp);\n+\n+\t\t\trtl8152_set_speed(tp, tp-\u003eautoneg, tp-\u003espeed,\n+\t\t\t\t\t  tp-\u003eduplex, tp-\u003eadvertising);\n+\t\t}\n+\t}\n+}\n+\n static void r8153_power_cut_en(struct r8152 *tp, bool enable)\n {\n \tif (enable)\n@@ -4446,9 +4723,28 @@ static void rtl8157_runtime_enable(struct r8152 *tp, bool enable)\n \t\tr8153b_u1u2en(tp, false);\n \t\tr8157_u2p3en(tp, false);\n \t\trtl_runtime_suspend_enable(tp, true);\n+\n+\t\tswitch (tp-\u003eversion) {\n+\t\tcase RTL_VER_16:\n+\t\tcase RTL_VER_17_QFN68:\n+\t\t\tr8157_ups_en(tp, true);\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tbreak;\n+\t\t}\n \t} else {\n \t\tr8153_queue_wake(tp, false);\n \t\trtl_runtime_suspend_enable(tp, false);\n+\n+\t\tswitch (tp-\u003eversion) {\n+\t\tcase RTL_VER_16:\n+\t\tcase RTL_VER_17_QFN68:\n+\t\t\tr8157_ups_en(tp, false);\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tbreak;\n+\t\t}\n+\n \t\tr8157_u2p3en(tp, true);\n \t\tif (tp-\u003eudev-\u003espeed \u003e= USB_SPEED_SUPER)\n \t\t\tr8153b_u1u2en(tp, true);\n@@ -4480,6 +4776,8 @@ static void r8153_teredo_off(struct r8152 *tp)\n \tcase RTL_VER_14:\n \tcase RTL_VER_15:\n \tcase RTL_VER_16:\n+\tcase RTL_VER_17_QFN68:\n+\tcase RTL_VER_17_QFN100:\n \tdefault:\n \t\t/* The bit 0 ~ 7 are relative with teredo settings. They are\n \t\t * W1C (write 1 to clear), so set all 1 to disable it.\n@@ -4534,7 +4832,8 @@ static void rtl_clear_bp(struct r8152 *tp, u16 type)\n \t\tbreak;\n \tcase RTL_VER_14:\n \tcase RTL_VER_16:\n-\tcase RTL_VER_17:\n+\tcase RTL_VER_17_QFN68:\n+\tcase RTL_VER_17_QFN100:\n \tdefault:\n \t\tocp_write_word(tp, type, USB_BP2_EN, 0);\n \t\tbp_num = 16;\n@@ -4556,7 +4855,8 @@ static inline void rtl_reset_ocp_base(struct r8152 *tp)\n static int rtl_phy_patch_request(struct r8152 *tp, bool request, bool wait)\n {\n \tu16 check;\n-\tint i;\n+\tu16 ocp_data;\n+\tint i, ret;\n \n \tif (request) {\n \t\tocp_reg_set_bits(tp, OCP_PHY_PATCH_CMD, PATCH_REQUEST);\n@@ -4567,25 +4867,29 @@ static int rtl_phy_patch_request(struct r8152 *tp, bool request, bool wait)\n \t}\n \n \tfor (i = 0; wait \u0026\u0026 i \u003c 5000; i++) {\n-\t\tu32 ocp_data;\n-\n \t\tif (test_bit(RTL8152_INACCESSIBLE, \u0026tp-\u003eflags))\n \t\t\treturn -ENODEV;\n \n \t\tusleep_range(1000, 2000);\n-\t\tocp_data = ocp_reg_read(tp, OCP_PHY_PATCH_STAT);\n-\t\tif ((ocp_data \u0026 PATCH_READY) ^ check)\n+\t\tret = ocp_reg_read(tp, OCP_PHY_PATCH_STAT, \u0026ocp_data);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\t\telse if ((ocp_data \u0026 PATCH_READY) ^ check)\n \t\t\tbreak;\n \t}\n \n-\tif (request \u0026\u0026 wait \u0026\u0026\n-\t    !(ocp_reg_read(tp, OCP_PHY_PATCH_STAT) \u0026 PATCH_READY)) {\n-\t\tdev_err(\u0026tp-\u003eintf-\u003edev, \"PHY patch request fail\\n\");\n-\t\trtl_phy_patch_request(tp, false, false);\n-\t\treturn -ETIME;\n-\t} else {\n-\t\treturn 0;\n+\tif (request \u0026\u0026 wait) {\n+\t\tret = ocp_reg_read(tp, OCP_PHY_PATCH_STAT, \u0026ocp_data);\n+\t\tif (ret \u003c 0) {\n+\t\t\treturn ret;\n+\t\t} else if (!(ocp_data \u0026 PATCH_READY)) {\n+\t\t\tdev_err(\u0026tp-\u003eintf-\u003edev, \"PHY patch request fail\\n\");\n+\t\t\trtl_phy_patch_request(tp, false, false);\n+\t\t\treturn -ETIME;\n+\t\t}\n \t}\n+\n+\treturn 0;\n }\n \n static void rtl_patch_key_set(struct r8152 *tp, u16 key_addr, u16 patch_key)\n@@ -4646,7 +4950,8 @@ static bool rtl8152_is_fw_phy_speed_up_ok(struct r8152 *tp, struct fw_phy_speed_\n \tcase RTL_VER_13:\n \tcase RTL_VER_15:\n \tcase RTL_VER_16:\n-\tcase RTL_VER_17:\n+\tcase RTL_VER_17_QFN68:\n+\tcase RTL_VER_17_QFN100:\n \tdefault:\n \t\tbreak;\n \t}\n@@ -5299,10 +5604,14 @@ static void rtl_ram_code_speed_up(struct r8152 *tp, struct fw_phy_speed_up *phy,\n {\n \tu32 len;\n \tu8 *data;\n+\tu16 ver;\n \n \trtl_reset_ocp_base(tp);\n \n-\tif (sram_read(tp, SRAM_GPHY_FW_VER) \u003e= __le16_to_cpu(phy-\u003eversion)) {\n+\tif (sram_read(tp, SRAM_GPHY_FW_VER, \u0026ver) \u003c 0)\n+\t\treturn;\n+\n+\tif (ver \u003e= __le16_to_cpu(phy-\u003eversion)) {\n \t\tdev_dbg(\u0026tp-\u003eintf-\u003edev, \"PHY firmware has been the newest\\n\");\n \t\treturn;\n \t}\n@@ -5349,7 +5658,8 @@ static void rtl_ram_code_speed_up(struct r8152 *tp, struct fw_phy_speed_up *phy,\n \n \trtl_phy_patch_request(tp, false, wait);\n \n-\tif (sram_read(tp, SRAM_GPHY_FW_VER) == __le16_to_cpu(phy-\u003eversion))\n+\tif (sram_read(tp, SRAM_GPHY_FW_VER, \u0026ver) \u003e= 0 \u0026\u0026\n+\t    ver == __le16_to_cpu(phy-\u003eversion))\n \t\tdev_dbg(\u0026tp-\u003eintf-\u003edev, \"successfully applied %s\\n\", phy-\u003einfo);\n \telse\n \t\tdev_err(\u0026tp-\u003eintf-\u003edev, \"ram code speedup mode fail\\n\");\n@@ -5357,14 +5667,17 @@ static void rtl_ram_code_speed_up(struct r8152 *tp, struct fw_phy_speed_up *phy,\n \n static int rtl8152_fw_phy_ver(struct r8152 *tp, struct fw_phy_ver *phy_ver)\n {\n-\tu16 ver_addr, ver;\n+\tu16 ver_addr, ver, cur_ver;\n \n \tver_addr = __le16_to_cpu(phy_ver-\u003ever.addr);\n \tver = __le16_to_cpu(phy_ver-\u003ever.data);\n \n \trtl_reset_ocp_base(tp);\n \n-\tif (sram_read(tp, ver_addr) \u003e= ver) {\n+\tif (sram_read(tp, ver_addr, \u0026cur_ver) \u003c 0)\n+\t\treturn 0;\n+\n+\tif (cur_ver \u003e= ver) {\n \t\tdev_dbg(\u0026tp-\u003eintf-\u003edev, \"PHY firmware has been the newest\\n\");\n \t\treturn 0;\n \t}\n@@ -5383,7 +5696,8 @@ static void rtl8152_fw_phy_fixup(struct r8152 *tp, struct fw_phy_fixup *fix)\n \trtl_reset_ocp_base(tp);\n \n \taddr = __le16_to_cpu(fix-\u003esetting.addr);\n-\tdata = ocp_reg_read(tp, addr);\n+\tif (ocp_reg_read(tp, addr, \u0026data) \u003c 0)\n+\t\treturn;\n \n \tswitch (__le16_to_cpu(fix-\u003ebit_cmd)) {\n \tcase FW_FIXUP_AND:\n@@ -5687,10 +6001,10 @@ static inline void r8152_mmd_indirect(struct r8152 *tp, u16 dev, u16 reg)\n \n static u16 r8152_mmd_read(struct r8152 *tp, u16 dev, u16 reg)\n {\n-\tu16 data;\n+\tu16 data = 0;\n \n \tr8152_mmd_indirect(tp, dev, reg);\n-\tdata = ocp_reg_read(tp, OCP_EEE_DATA);\n+\tocp_reg_read(tp, OCP_EEE_DATA, \u0026data);\n \tocp_reg_write(tp, OCP_EEE_AR, 0x0000);\n \n \treturn data;\n@@ -5755,7 +6069,8 @@ static void r8156_eee_en(struct r8152 *tp, bool enable)\n \n \tr8153_eee_en(tp, enable);\n \n-\tconfig = ocp_reg_read(tp, OCP_EEE_ADV2);\n+\tif (ocp_reg_read(tp, OCP_EEE_ADV2, \u0026config) \u003c 0)\n+\t\treturn;\n \n \tif (enable \u0026\u0026 (tp-\u003eeee_adv2 \u0026 MDIO_EEE_2_5GT))\n \t\tconfig |= MDIO_EEE_2_5GT;\n@@ -5806,7 +6121,8 @@ static void rtl_eee_enable(struct r8152 *tp, bool enable)\n \tcase RTL_VER_13:\n \tcase RTL_VER_15:\n \tcase RTL_VER_16:\n-\tcase RTL_VER_17:\n+\tcase RTL_VER_17_QFN68:\n+\tcase RTL_VER_17_QFN100:\n \t\tif (enable) {\n \t\t\tr8156_eee_en(tp, true);\n \t\t\tocp_reg_write(tp, OCP_EEE_ADV, tp-\u003eeee_adv);\n@@ -5961,27 +6277,125 @@ static void r8152b_enter_oob(struct r8152 *tp)\n \t\t\t   RCR_APM | RCR_AM | RCR_AB);\n }\n \n-static int r8153_pre_firmware_1(struct r8152 *tp)\n+static void rtl_fc_pause_pkt_en(struct r8152 *tp, u16 speed)\n {\n-\tint i;\n+\tint log2_ratio, ratio;\n+\tu16 num_pause_pkts;\n+\tu32 ocp_data;\n \n-\t/* Wait till the WTD timer is ready. It would take at most 104 ms. */\n-\tfor (i = 0; i \u003c 104; i++) {\n-\t\tu32 ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_WDT1_CTRL);\n+\tswitch (tp-\u003eversion) {\n+\tcase RTL_VER_10:\n+\tcase RTL_VER_11:\n+\t\tocp_write_word(tp, MCU_TYPE_USB, USB_FC_TIMER,\n+\t\t\t       CTRL_TIMER_EN | (1000 / 8));\n \n-\t\tif (test_bit(RTL8152_INACCESSIBLE, \u0026tp-\u003eflags))\n-\t\t\treturn -ENODEV;\n-\t\tif (!(ocp_data \u0026 WTD1_EN))\n-\t\t\tbreak;\n-\t\tusleep_range(1000, 2000);\n-\t}\n+\t\tocp_word_set_bits(tp, MCU_TYPE_USB, USB_FW_CTRL,\n+\t\t\t\t  FLOW_CTRL_PATCH_OPT);\n \n-\treturn 0;\n-}\n+\t\tocp_word_set_bits(tp, MCU_TYPE_USB, USB_FW_TASK, FC_PATCH_TASK);\n+\t\tbreak;\n+\tcase RTL_VER_12:\n+\tcase RTL_VER_13:\n+\tcase RTL_VER_15:\n+\t\tocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_RCR, SLOT_EN);\n \n-static int r8153_post_firmware_1(struct r8152 *tp)\n-{\n-\t/* set USB_BP_4 to support USB_SPEED_SUPER only */\n+\t\tocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_CPCR, FLOW_CTRL_EN);\n+\n+\t\t/* enable fc timer and set timer to 600 ms. */\n+\t\tocp_write_word(tp, MCU_TYPE_USB, USB_FC_TIMER,\n+\t\t\t       CTRL_TIMER_EN | (600 / 8));\n+\n+\t\tocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_POL_GPIO_CTRL);\n+\t\tif (!(ocp_data \u0026 DACK_DET_EN))\n+\t\t\tocp_word_set_bits(tp, MCU_TYPE_USB, USB_FW_CTRL,\n+\t\t\t\t\t  FLOW_CTRL_PATCH_2);\n+\n+\t\tocp_word_set_bits(tp, MCU_TYPE_USB, USB_FW_TASK, FC_PATCH_TASK);\n+\t\tbreak;\n+\tcase RTL_VER_16:\n+\tcase RTL_VER_17_QFN68:\n+\tcase RTL_VER_17_QFN100:\n+\t\tocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_RCR, SLOT_EN);\n+\n+\t\tnum_pause_pkts = 0xa;\n+\t\tratio = 10000;\n+\n+\t\tif (speed \u0026 _10bps) {\n+\t\t\tratio /= 10;\n+\t\t} else if (speed \u0026 _100bps) {\n+\t\t\tratio /= 100;\n+\t\t} else if (speed \u0026 _1000bps) {\n+\t\t\tratio /= 1000;\n+\t\t} else if (speed \u0026 _2500bps) {\n+\t\t\tratio /= 2500;\n+\t\t} else if (speed \u0026 _5000bps) {\n+\t\t\tratio /= 5000;\n+\t\t} else if (speed \u0026 _10000bps) {\n+\t\t\tratio /= 10000;\n+\t\t} else {\n+\t\t\t/* No rate bit is set, e.g. a 500 or 1250 Mbit/s\n+\t\t\t * sub-rate, which the driver does not advertise.\n+\t\t\t * Disarm the limit.\n+\t\t\t */\n+\t\t\tdev_err(\u0026tp-\u003eintf-\u003edev, \"Unknown link speed\\n\");\n+\t\t\tocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_PAUSE_LIMIT,\n+\t\t\t\t\t  PAUSE_LIMIT_EN);\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tlog2_ratio = ilog2(ratio);\n+\t\tnum_pause_pkts -= log2_ratio;\n+\n+\t\t/* Round ratio up to the next power of two if it is\n+\t\t * more than halfway there. Floating-point is avoided\n+\t\t * by rewriting ratio \u003e 1.5 * 2^log2_ratio as\n+\t\t * 2 * ratio \u003e 3 * 2^log2_ratio.\n+\t\t */\n+\t\tif (2 * ratio \u003e 3 * (1 \u003c\u003c log2_ratio))\n+\t\t\tnum_pause_pkts--;\n+\n+\t\t/* At most 2^num_pause_pkts pause packets would be sent.\n+\t\t *\n+\t\t *  10 Mbit/s -\u003e 2^0\n+\t\t * 100 Mbit/s -\u003e 2^3\n+\t\t *   1 Gbit/s -\u003e 2^7\n+\t\t * 2.5 Gbit/s -\u003e 2^8\n+\t\t *   5 Gbit/s -\u003e 2^9\n+\t\t *  10 Gbit/s -\u003e 2^10\n+\t\t */\n+\t\tocp_word_w0w1(tp, MCU_TYPE_PLA, PLA_PAUSE_LIMIT,\n+\t\t\t      PAUSE_LIMIT_MASK | PAUSE_LIMIT_EN,\n+\t\t\t      num_pause_pkts \u003c\u003c 4);\n+\n+\t\tocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_PAUSE_LIMIT,\n+\t\t\t\t  PAUSE_LIMIT_EN);\n+\t\tbreak;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+}\n+\n+static int r8153_pre_firmware_1(struct r8152 *tp)\n+{\n+\tint i;\n+\n+\t/* Wait till the WTD timer is ready. It would take at most 104 ms. */\n+\tfor (i = 0; i \u003c 104; i++) {\n+\t\tu32 ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_WDT1_CTRL);\n+\n+\t\tif (test_bit(RTL8152_INACCESSIBLE, \u0026tp-\u003eflags))\n+\t\t\treturn -ENODEV;\n+\t\tif (!(ocp_data \u0026 WTD1_EN))\n+\t\t\tbreak;\n+\t\tusleep_range(1000, 2000);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int r8153_post_firmware_1(struct r8152 *tp)\n+{\n+\t/* set USB_BP_4 to support USB_SPEED_SUPER only */\n \tif (ocp_read_byte(tp, MCU_TYPE_USB, USB_CSTMR) \u0026 FORCE_SUPER)\n \t\tocp_write_word(tp, MCU_TYPE_USB, USB_BP_4, BP4_SUPER_ONLY);\n \n@@ -6210,8 +6624,8 @@ static void r8153b_hw_phy_cfg(struct r8152 *tp)\n \t * rg_saw_cnt = OCP reg 0xC426 Bit[13:0]\n \t * swr_cnt_1ms_ini = 16000000 / rg_saw_cnt\n \t */\n-\tocp_data = ocp_reg_read(tp, 0xc426);\n-\tocp_data \u0026= 0x3fff;\n+\tocp_reg_read(tp, 0xc426, \u0026data);\n+\tocp_data = data \u0026 0x3fff;\n \tif (ocp_data) {\n \t\tu32 swr_cnt_1ms_ini;\n \n@@ -6391,24 +6805,16 @@ static int rtl8156_enable(struct r8152 *tp)\n \tif (test_bit(RTL8152_INACCESSIBLE, \u0026tp-\u003eflags))\n \t\treturn -ENODEV;\n \n-\tif (tp-\u003eversion \u003c RTL_VER_12)\n-\t\tr8156_fc_parameter(tp);\n-\n+\tr8156_fc_parameter(tp);\n \tset_tx_qlen(tp);\n \trtl_set_eee_plus(tp);\n \n-\tif (tp-\u003eversion \u003e= RTL_VER_12 \u0026\u0026 tp-\u003eversion \u003c= RTL_VER_17)\n-\t\tocp_word_clr_bits(tp, MCU_TYPE_USB, USB_RX_AGGR_NUM, RX_AGGR_NUM_MASK);\n-\n \tr8153_set_rx_early_timeout(tp);\n \tr8153_set_rx_early_size(tp);\n \n \tspeed = rtl8152_get_speed(tp);\n \trtl_set_ifg(tp, speed);\n \n-\tif (tp-\u003eversion \u003e= RTL_VER_16)\n-\t\treturn rtl_enable(tp);\n-\n \tif (speed \u0026 _2500bps)\n \t\tocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4,\n \t\t\t\t  IDLE_SPDWN_EN);\n@@ -6416,12 +6822,10 @@ static int rtl8156_enable(struct r8152 *tp)\n \t\tocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4,\n \t\t\t\t  IDLE_SPDWN_EN);\n \n-\tif (tp-\u003eversion \u003c RTL_VER_12) {\n-\t\tif (speed \u0026 _1000bps)\n-\t\t\tocp_write_word(tp, MCU_TYPE_PLA, PLA_EEE_TXTWSYS, 0x11);\n-\t\telse if (speed \u0026 _500bps)\n-\t\t\tocp_write_word(tp, MCU_TYPE_PLA, PLA_EEE_TXTWSYS, 0x3d);\n-\t}\n+\tif (speed \u0026 _1000bps)\n+\t\tocp_write_word(tp, MCU_TYPE_PLA, PLA_EEE_TXTWSYS, 0x11);\n+\telse if (speed \u0026 _500bps)\n+\t\tocp_write_word(tp, MCU_TYPE_PLA, PLA_EEE_TXTWSYS, 0x3d);\n \n \tif (tp-\u003eudev-\u003espeed == USB_SPEED_HIGH) {\n \t\t/* USB 0xb45e[3:0] l1_nyet_hird */\n@@ -6446,6 +6850,69 @@ static void rtl8156_disable(struct r8152 *tp)\n \trtl8153_disable(tp);\n }\n \n+static int rtl8156b_enable(struct r8152 *tp)\n+{\n+\tu16 speed;\n+\n+\tif (test_bit(RTL8152_INACCESSIBLE, \u0026tp-\u003eflags))\n+\t\treturn -ENODEV;\n+\n+\tset_tx_qlen(tp);\n+\trtl_set_eee_plus(tp);\n+\n+\tocp_word_clr_bits(tp, MCU_TYPE_USB, USB_RX_AGGR_NUM, RX_AGGR_NUM_MASK);\n+\n+\tr8153_set_rx_early_timeout(tp);\n+\tr8153_set_rx_early_size(tp);\n+\n+\tspeed = rtl8152_get_speed(tp);\n+\trtl_set_ifg(tp, speed);\n+\n+\tif (speed \u0026 _2500bps)\n+\t\tocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4,\n+\t\t\t\t  IDLE_SPDWN_EN);\n+\telse\n+\t\tocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4,\n+\t\t\t\t  IDLE_SPDWN_EN);\n+\n+\tif (tp-\u003eudev-\u003espeed == USB_SPEED_HIGH) {\n+\t\t/* USB 0xb45e[3:0] l1_nyet_hird */\n+\t\tif (is_flow_control(speed))\n+\t\t\tocp_word_w0w1(tp, MCU_TYPE_USB, USB_L1_CTRL, 0xf, 0xf);\n+\t\telse\n+\t\t\tocp_word_w0w1(tp, MCU_TYPE_USB, USB_L1_CTRL, 0xf, 0x1);\n+\t}\n+\n+\tocp_word_clr_bits(tp, MCU_TYPE_USB, USB_FW_TASK, FC_PATCH_TASK);\n+\tusleep_range(1000, 2000);\n+\tocp_word_set_bits(tp, MCU_TYPE_USB, USB_FW_TASK, FC_PATCH_TASK);\n+\n+\treturn rtl_enable(tp);\n+}\n+\n+static int rtl8157_enable(struct r8152 *tp)\n+{\n+\tu16 speed;\n+\n+\tif (test_bit(RTL8152_INACCESSIBLE, \u0026tp-\u003eflags))\n+\t\treturn -ENODEV;\n+\n+\tset_tx_qlen(tp);\n+\trtl_set_eee_plus(tp);\n+\n+\tocp_word_clr_bits(tp, MCU_TYPE_USB, USB_RX_AGGR_NUM, RX_AGGR_NUM_MASK);\n+\n+\tr8153_set_rx_early_timeout(tp);\n+\tr8153_set_rx_early_size(tp);\n+\n+\tspeed = rtl8152_get_speed(tp);\n+\trtl_fc_pause_pkt_en(tp, speed);\n+\n+\trtl_set_ifg(tp, speed);\n+\n+\treturn rtl_enable(tp);\n+}\n+\n static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex,\n \t\t\t     u32 advertising)\n {\n@@ -6517,7 +6984,11 @@ static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex,\n \t\tif (!advertising)\n \t\t\treturn -EINVAL;\n \n-\t\torig = r8152_mdio_read(tp, MII_ADVERTISE);\n+\t\tret = r8152_mdio_read(tp, MII_ADVERTISE);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto out;\n+\n+\t\torig = ret;\n \t\tnew1 = orig \u0026 ~(ADVERTISE_10HALF | ADVERTISE_10FULL |\n \t\t\t\tADVERTISE_100HALF | ADVERTISE_100FULL);\n \t\tif (advertising \u0026 RTL_ADVERTISED_10_HALF) {\n@@ -6544,7 +7015,11 @@ static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex,\n \t\t}\n \n \t\tif (tp-\u003emii.supports_gmii) {\n-\t\t\torig = r8152_mdio_read(tp, MII_CTRL1000);\n+\t\t\tret = r8152_mdio_read(tp, MII_CTRL1000);\n+\t\t\tif (ret \u003c 0)\n+\t\t\t\tgoto out;\n+\n+\t\t\torig = ret;\n \t\t\tnew1 = orig \u0026 ~(ADVERTISE_1000FULL |\n \t\t\t\t\tADVERTISE_1000HALF);\n \n@@ -6558,7 +7033,10 @@ static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex,\n \t\t}\n \n \t\tif (tp-\u003esupport_2500full || tp-\u003esupport_5000full || tp-\u003esupport_10000full) {\n-\t\t\torig = ocp_reg_read(tp, OCP_10GBT_CTRL);\n+\t\t\tret = ocp_reg_read(tp, OCP_10GBT_CTRL, \u0026orig);\n+\t\t\tif (ret \u003c 0)\n+\t\t\t\tgoto out;\n+\n \t\t\tnew1 = orig \u0026 ~(MDIO_AN_10GBT_CTRL_ADV2_5G | MDIO_AN_10GBT_CTRL_ADV5G\n \t\t\t\t\t| MDIO_AN_10GBT_CTRL_ADV10G);\n \n@@ -6589,20 +7067,23 @@ static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex,\n \tif (test_and_clear_bit(PHY_RESET, \u0026tp-\u003eflags))\n \t\tbmcr |= BMCR_RESET;\n \n-\tr8152_mdio_write(tp, MII_BMCR, bmcr);\n+\tret = r8152_mdio_write(tp, MII_BMCR, bmcr);\n+\tif (ret \u003c 0)\n+\t\tgoto out;\n \n \tif (bmcr \u0026 BMCR_RESET) {\n \t\tint i;\n \n \t\tfor (i = 0; i \u003c 50; i++) {\n \t\t\tmsleep(20);\n-\t\t\tif ((r8152_mdio_read(tp, MII_BMCR) \u0026 BMCR_RESET) == 0)\n+\t\t\tret = r8152_mdio_read(tp, MII_BMCR);\n+\t\t\tif (ret \u003c 0 || !(ret \u0026 BMCR_RESET))\n \t\t\t\tbreak;\n \t\t}\n \t}\n \n out:\n-\treturn ret;\n+\treturn ret \u003c 0 ? ret : 0;\n }\n \n static void rtl8152_up(struct r8152 *tp)\n@@ -6806,8 +7287,7 @@ static void rtl8156_up(struct r8152 *tp)\n \t\treturn;\n \n \tr8153b_u1u2en(tp, false);\n-\tif (tp-\u003eversion \u003c RTL_VER_16)\n-\t\tr8153_u2p3en(tp, false);\n+\tr8153_u2p3en(tp, false);\n \tr8153_aldps_en(tp, false);\n \n \trxdy_gated_en(tp, true);\n@@ -6820,8 +7300,7 @@ static void rtl8156_up(struct r8152 *tp)\n \n \tocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, NOW_IS_OOB);\n \n-\tif (tp-\u003eversion \u003e= RTL_VER_16)\n-\t\tocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_RCR1, BIT(3));\n+\tocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_RCR1, BIT(3));\n \n \tocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, MCU_BORW_EN);\n \n@@ -6845,9 +7324,8 @@ static void rtl8156_up(struct r8152 *tp)\n \n \tocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, PLA_MCU_SPDWN_EN);\n \n-\tif (tp-\u003eversion \u003c RTL_VER_16)\n-\t\tocp_word_clr_bits(tp, MCU_TYPE_USB, USB_SPEED_OPTION,\n-\t\t\t\t  RG_PWRDN_EN | ALL_SPEED_OFF);\n+\tocp_word_clr_bits(tp, MCU_TYPE_USB, USB_SPEED_OPTION,\n+\t\t\t  RG_PWRDN_EN | ALL_SPEED_OFF);\n \n \tocp_write_dword(tp, MCU_TYPE_USB, USB_RX_BUF_TH, 0x00600400);\n \n@@ -6857,10 +7335,19 @@ static void rtl8156_up(struct r8152 *tp)\n \t}\n \n \tr8153_aldps_en(tp, true);\n-\tif (tp-\u003eversion \u003c RTL_VER_16)\n-\t\tr8153_u2p3en(tp, true);\n+\tr8153_u2p3en(tp, true);\n+\n+\tswitch (tp-\u003eversion) {\n+\tcase RTL_VER_13:\n+\tcase RTL_VER_15:\n+\t\t/* Enable Clear_SDR */\n+\t\tocp_word_set_bits(tp, MCU_TYPE_USB, 0xd3ca, BIT(15));\n+\t\tbreak;\n+\tdefault:\n+\t\tbreak;\n+\t}\n \n-\tif (tp-\u003eversion \u003c RTL_VER_16 \u0026\u0026 tp-\u003eudev-\u003espeed \u003e= USB_SPEED_SUPER)\n+\tif (tp-\u003eudev-\u003espeed \u003e= USB_SPEED_SUPER)\n \t\tr8153b_u1u2en(tp, true);\n }\n \n@@ -6873,12 +7360,9 @@ static void rtl8156_down(struct r8152 *tp)\n \n \tocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3,\n \t\t\t  PLA_MCU_SPDWN_EN);\n-\n \tr8153b_u1u2en(tp, false);\n-\tif (tp-\u003eversion \u003c RTL_VER_16) {\n-\t\tr8153_u2p3en(tp, false);\n-\t\tr8153b_power_cut_en(tp, false);\n-\t}\n+\tr8153_u2p3en(tp, false);\n+\tr8153b_power_cut_en(tp, false);\n \tr8153_aldps_en(tp, false);\n \n \tocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, NOW_IS_OOB);\n@@ -6900,7 +7384,125 @@ static void rtl8156_down(struct r8152 *tp)\n \t */\n \tocp_write_word(tp, MCU_TYPE_PLA, PLA_TEREDO_WAKE_BASE, 0x00ff);\n \n-\tocp_byte_set_bits(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, NOW_IS_OOB);\n+\tocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_BDC_CR, ALDPS_PROXY_MODE);\n+\n+\tocp_byte_set_bits(tp, MCU_TYPE_PLA, PLA_OOB_CTRL,\n+\t\t\t  NOW_IS_OOB | DIS_MCU_CLROOB);\n+\n+\tocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, MCU_BORW_EN);\n+\n+\trtl_rx_vlan_en(tp, true);\n+\trxdy_gated_en(tp, false);\n+\n+\tocp_dword_set_bits(tp, MCU_TYPE_PLA, PLA_RCR,\n+\t\t\t   RCR_APM | RCR_AM | RCR_AB);\n+\n+\tr8153_aldps_en(tp, true);\n+}\n+\n+static void rtl8157_change_mtu(struct r8152 *tp)\n+{\n+\tu32 max_pkt_size = mtu_to_size(tp-\u003enetdev-\u003emtu);\n+\tu32 ocp_data;\n+\n+\tocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, max_pkt_size);\n+\n+\t/* Use at least 10K for MTPS */\n+\tocp_data = max_t(u32, max_pkt_size, 10 * 1024) / 64;\n+\n+\t/* 16 * 1024 / 64 = 0x100, so the max is 0xff for 8 bits data */\n+\tocp_data = min_t(u32, ocp_data, 0xff);\n+\n+\tocp_write_byte(tp, MCU_TYPE_PLA, PLA_MTPS, ocp_data);\n+\tr8156_fc_parameter(tp);\n+\n+\t/* TX share fifo free credit full threshold */\n+\tocp_write_word(tp, MCU_TYPE_PLA, PLA_TXFIFO_CTRL, 512 / 64);\n+\tocp_write_word(tp, MCU_TYPE_PLA, PLA_TXFIFO_FULL,\n+\t\t       ALIGN(max_pkt_size + tp-\u003etx_desc.size, 1024) / 16);\n+}\n+\n+static void rtl8157_up(struct r8152 *tp)\n+{\n+\tif (test_bit(RTL8152_INACCESSIBLE, \u0026tp-\u003eflags))\n+\t\treturn;\n+\n+\tr8153b_u1u2en(tp, false);\n+\tr8153_aldps_en(tp, false);\n+\n+\trxdy_gated_en(tp, true);\n+\tr8153_teredo_off(tp);\n+\n+\tocp_dword_clr_bits(tp, MCU_TYPE_PLA, PLA_RCR, RCR_ACPT_ALL);\n+\n+\trtl8152_nic_reset(tp);\n+\trtl_reset_bmu(tp);\n+\n+\tocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, NOW_IS_OOB);\n+\n+\tocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_RCR1, BIT(3));\n+\n+\tocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, MCU_BORW_EN);\n+\n+\trtl_rx_vlan_en(tp, tp-\u003enetdev-\u003efeatures \u0026 NETIF_F_HW_VLAN_CTAG_RX);\n+\n+\trtl8157_change_mtu(tp);\n+\n+\t/* share FIFO settings */\n+\tocp_word_w0w1(tp, MCU_TYPE_PLA, PLA_RXFIFO_FULL, RXFIFO_FULL_MASK,\n+\t\t      0x08);\n+\n+\tocp_word_clr_bits(tp, MCU_TYPE_USB, USB_SPEED_OPTION,\n+\t\t\t  RG_PWRDN_EN | ALL_SPEED_OFF);\n+\n+\tocp_write_dword(tp, MCU_TYPE_USB, USB_RX_BUF_TH, 0x00600400);\n+\n+\tif (tp-\u003esaved_wolopts != __rtl_get_wol(tp)) {\n+\t\tnetif_warn(tp, ifup, tp-\u003enetdev, \"wol setting is changed\\n\");\n+\t\t__rtl_set_wol(tp, tp-\u003esaved_wolopts);\n+\t}\n+\n+\tr8153_aldps_en(tp, true);\n+\n+\t/* Enable Clear_SDR */\n+\tocp_byte_set_bits(tp, MCU_TYPE_USB, 0xd378, BIT(7));\n+\t/* Clear SDR bit */\n+\tocp_word_clr_bits(tp, MCU_TYPE_USB, 0xcd06, BIT(15));\n+}\n+\n+static void rtl8157_down(struct r8152 *tp)\n+{\n+\tif (test_bit(RTL8152_INACCESSIBLE, \u0026tp-\u003eflags)) {\n+\t\trtl_drop_queued_tx(tp);\n+\t\treturn;\n+\t}\n+\n+\tr8153b_u1u2en(tp, false);\n+\tr8153_aldps_en(tp, false);\n+\n+\tocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, NOW_IS_OOB);\n+\n+\t/* RX FIFO settings for OOB */\n+\tocp_write_word(tp, MCU_TYPE_PLA, PLA_RXFIFO_FULL, 64 / 16);\n+\tocp_write_word(tp, MCU_TYPE_PLA, PLA_RX_FIFO_FULL, 1024 / 16);\n+\tocp_write_word(tp, MCU_TYPE_PLA, PLA_RX_FIFO_EMPTY, 4096 / 16);\n+\n+\trtl_disable(tp);\n+\trtl_reset_bmu(tp);\n+\n+\tocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, 1526);\n+\tocp_write_byte(tp, MCU_TYPE_PLA, PLA_MTPS, 10 * 1024 / 64);\n+\n+\t/* Clear teredo wake event. bit[15:8] is the teredo wakeup\n+\t * type. Set it to zero. bits[7:0] are the W1C bits about\n+\t * the events. Set them to all 1 to clear them.\n+\t */\n+\tocp_write_word(tp, MCU_TYPE_PLA, PLA_TEREDO_WAKE_BASE, 0x00ff);\n+\n+\tocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_BDC_CR, ALDPS_PROXY_MODE);\n+\n+\tocp_byte_set_bits(tp, MCU_TYPE_PLA, PLA_OOB_CTRL,\n+\t\t\t  NOW_IS_OOB | DIS_MCU_CLROOB);\n \n \tocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, MCU_BORW_EN);\n \n@@ -6931,7 +7533,12 @@ static bool rtl8152_in_nway(struct r8152 *tp)\n \n static bool rtl8153_in_nway(struct r8152 *tp)\n {\n-\tu16 phy_state = ocp_reg_read(tp, OCP_PHY_STATE) \u0026 0xff;\n+\tu16 phy_state;\n+\n+\tif (ocp_reg_read(tp, OCP_PHY_STATE, \u0026phy_state) \u003c 0)\n+\t\treturn false;\n+\n+\tphy_state \u0026= 0xff;\n \n \tif (phy_state == TXDIS_STATE || phy_state == ABD_STATE)\n \t\treturn false;\n@@ -6947,7 +7554,9 @@ static void r8156_mdio_force_mode(struct r8152 *tp)\n \t * 0: MDIO force mode\n \t * 1: MMD force mode\n \t */\n-\tdata = ocp_reg_read(tp, 0xa5b4);\n+\tif (ocp_reg_read(tp, 0xa5b4, \u0026data) \u003c 0)\n+\t\treturn;\n+\n \tif (data \u0026 BIT(15)) {\n \t\tdata \u0026= ~BIT(15);\n \t\tocp_reg_write(tp, 0xa5b4, data);\n@@ -7225,22 +7834,14 @@ static void r8152b_init(struct r8152 *tp)\n static void r8153_init(struct r8152 *tp)\n {\n \tu32 ocp_data;\n-\tint i;\n \n \tif (test_bit(RTL8152_INACCESSIBLE, \u0026tp-\u003eflags))\n \t\treturn;\n \n \tr8153_u1u2en(tp, false);\n \n-\tfor (i = 0; i \u003c 500; i++) {\n-\t\tif (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) \u0026\n-\t\t    AUTOLOAD_DONE)\n-\t\t\tbreak;\n-\n-\t\tmsleep(20);\n-\t\tif (test_bit(RTL8152_INACCESSIBLE, \u0026tp-\u003eflags))\n-\t\t\tbreak;\n-\t}\n+\tif (wait_autoload_done(tp))\n+\t\treturn;\n \n \tr8153_phy_status(tp, 0);\n \n@@ -7341,22 +7942,13 @@ static void r8153_init(struct r8152 *tp)\n \n static void r8153b_init(struct r8152 *tp)\n {\n-\tint i;\n-\n \tif (test_bit(RTL8152_INACCESSIBLE, \u0026tp-\u003eflags))\n \t\treturn;\n \n \tr8153b_u1u2en(tp, false);\n \n-\tfor (i = 0; i \u003c 500; i++) {\n-\t\tif (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) \u0026\n-\t\t    AUTOLOAD_DONE)\n-\t\t\tbreak;\n-\n-\t\tmsleep(20);\n-\t\tif (test_bit(RTL8152_INACCESSIBLE, \u0026tp-\u003eflags))\n-\t\t\tbreak;\n-\t}\n+\tif (wait_autoload_done(tp))\n+\t\treturn;\n \n \tr8153_phy_status(tp, 0);\n \n@@ -7411,8 +8003,6 @@ static void r8153b_init(struct r8152 *tp)\n \n static void r8153c_init(struct r8152 *tp)\n {\n-\tint i;\n-\n \tif (test_bit(RTL8152_INACCESSIBLE, \u0026tp-\u003eflags))\n \t\treturn;\n \n@@ -7425,15 +8015,8 @@ static void r8153c_init(struct r8152 *tp)\n \n \tocp_word_set_bits(tp, MCU_TYPE_USB, 0xcbf0, BIT(1));\n \n-\tfor (i = 0; i \u003c 500; i++) {\n-\t\tif (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) \u0026\n-\t\t    AUTOLOAD_DONE)\n-\t\t\tbreak;\n-\n-\t\tmsleep(20);\n-\t\tif (test_bit(RTL8152_INACCESSIBLE, \u0026tp-\u003eflags))\n-\t\t\treturn;\n-\t}\n+\tif (wait_autoload_done(tp))\n+\t\treturn;\n \n \tr8153_phy_status(tp, 0);\n \n@@ -7612,19 +8195,20 @@ static void r8156_hw_phy_cfg(struct r8152 *tp)\n \t\tocp_reg_clr_bits(tp, 0xa86a, BIT(0));\n \n \t\t/* MDI SWAP */\n+\t\tocp_reg_read(tp, 0xd068, \u0026data);\n \t\tif ((ocp_read_word(tp, MCU_TYPE_USB, USB_UPS_CFG) \u0026 MID_REVERSE) \u0026\u0026\n-\t\t    (ocp_reg_read(tp, 0xd068) \u0026 BIT(1))) {\n+\t\t    (data \u0026 BIT(1))) {\n \t\t\tu16 swap_a, swap_b;\n \n-\t\t\tdata = ocp_reg_read(tp, 0xd068);\n+\t\t\tocp_reg_read(tp, 0xd068, \u0026data);\n \t\t\tdata \u0026= ~0x1f;\n \t\t\tdata |= 0x1; /* p0 */\n \t\t\tocp_reg_write(tp, 0xd068, data);\n-\t\t\tswap_a = ocp_reg_read(tp, 0xd06a);\n+\t\t\tocp_reg_read(tp, 0xd06a, \u0026swap_a);\n \t\t\tdata \u0026= ~0x18;\n \t\t\tdata |= 0x18; /* p3 */\n \t\t\tocp_reg_write(tp, 0xd068, data);\n-\t\t\tswap_b = ocp_reg_read(tp, 0xd06a);\n+\t\t\tocp_reg_read(tp, 0xd06a, \u0026swap_b);\n \t\t\tdata \u0026= ~0x18; /* p0 */\n \t\t\tocp_reg_write(tp, 0xd068, data);\n \t\t\tocp_reg_write(tp, 0xd06a,\n@@ -7636,11 +8220,11 @@ static void r8156_hw_phy_cfg(struct r8152 *tp)\n \t\t\tdata \u0026= ~0x18;\n \t\t\tdata |= 0x08; /* p1 */\n \t\t\tocp_reg_write(tp, 0xd068, data);\n-\t\t\tswap_a = ocp_reg_read(tp, 0xd06a);\n+\t\t\tocp_reg_read(tp, 0xd06a, \u0026swap_a);\n \t\t\tdata \u0026= ~0x18;\n \t\t\tdata |= 0x10; /* p2 */\n \t\t\tocp_reg_write(tp, 0xd068, data);\n-\t\t\tswap_b = ocp_reg_read(tp, 0xd06a);\n+\t\t\tocp_reg_read(tp, 0xd06a, \u0026swap_b);\n \t\t\tdata \u0026= ~0x18;\n \t\t\tdata |= 0x08; /* p1 */\n \t\t\tocp_reg_write(tp, 0xd068, data);\n@@ -7651,16 +8235,16 @@ static void r8156_hw_phy_cfg(struct r8152 *tp)\n \t\t\tocp_reg_write(tp, 0xd068, data);\n \t\t\tocp_reg_write(tp, 0xd06a,\n \t\t\t\t      (swap_b \u0026 ~0x7ff) | (swap_a \u0026 0x7ff));\n-\t\t\tswap_a = ocp_reg_read(tp, 0xbd5a);\n-\t\t\tswap_b = ocp_reg_read(tp, 0xbd5c);\n+\t\t\tocp_reg_read(tp, 0xbd5a, \u0026swap_a);\n+\t\t\tocp_reg_read(tp, 0xbd5c, \u0026swap_b);\n \t\t\tocp_reg_write(tp, 0xbd5a, (swap_a \u0026 ~0x1f1f) |\n \t\t\t\t      ((swap_b \u0026 0x1f) \u003c\u003c 8) |\n \t\t\t\t      ((swap_b \u003e\u003e 8) \u0026 0x1f));\n \t\t\tocp_reg_write(tp, 0xbd5c, (swap_b \u0026 ~0x1f1f) |\n \t\t\t\t      ((swap_a \u0026 0x1f) \u003c\u003c 8) |\n \t\t\t\t      ((swap_a \u003e\u003e 8) \u0026 0x1f));\n-\t\t\tswap_a = ocp_reg_read(tp, 0xbc18);\n-\t\t\tswap_b = ocp_reg_read(tp, 0xbc1a);\n+\t\t\tocp_reg_read(tp, 0xbc18, \u0026swap_a);\n+\t\t\tocp_reg_read(tp, 0xbc1a, \u0026swap_b);\n \t\t\tocp_reg_write(tp, 0xbc18, (swap_a \u0026 ~0x1f1f) |\n \t\t\t\t      ((swap_b \u0026 0x1f) \u003c\u003c 8) |\n \t\t\t\t      ((swap_b \u003e\u003e 8) \u0026 0x1f));\n@@ -7985,11 +8569,14 @@ static void r8157_hw_phy_cfg(struct r8152 *tp)\n \tocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_PHY_PWR, PFM_PWM_SWITCH);\n \n \t/* Advanced Power Saving parameter */\n-\tocp_reg_set_bits(tp, 0xa430, BIT(0) | BIT(1));\n+\tocp_reg_set_bits(tp, OCP_POWER_CFG, EN_10M_PLLOFF | EN_ALDPS_PLLOFF);\n \n \t/* Disable ALDPS force mode */\n \tocp_reg_clr_bits(tp, 0xa44a, BIT(2));\n \n+\t/* Disable bypass_turn_off_clk_in_aldps */\n+\tocp_byte_clr_bits(tp, MCU_TYPE_PLA, 0xd3c8, BIT(0));\n+\n \tswitch (tp-\u003eversion) {\n \tcase RTL_VER_16:\n \t\t/* XG_INRX parameter */\n@@ -8005,7 +8592,7 @@ static void r8157_hw_phy_cfg(struct r8152 *tp)\n \t\tsram2_write_w0w1(tp, 0x8078, 0xff00, 0x3000);\n \n \t\t/* green mode */\n-\t\tsram2_write_w0w1(tp, 0x89e9, 0xff00, 0);\n+\t\tsram2_clr_bits(tp, 0x89e9, 0xff00);\n \t\tsram2_write_w0w1(tp, 0x8ffd, 0xff00, 0x0100);\n \t\tsram2_write_w0w1(tp, 0x8ffe, 0xff00, 0x0200);\n \t\tsram2_write_w0w1(tp, 0x8fff, 0xff00, 0x0400);\n@@ -8111,11 +8698,85 @@ static void r8157_hw_phy_cfg(struct r8152 *tp)\n \t\tsram2_write_w0w1(tp, 0x807c, 0xff00, 0x5000);\n \t\tsram2_write_w0w1(tp, 0x809d, 0xff00, 0x5000);\n \t\tbreak;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+\n+\tif (rtl_phy_patch_request(tp, true, true))\n+\t\treturn;\n+\n+\tocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, EEE_SPDWN_EN);\n+\n+\tocp_reg_w0w1(tp, OCP_DOWN_SPEED, EN_EEE_100 | EN_EEE_1000, EN_10M_CLKDIV);\n+\n+\ttp-\u003eups_info._10m_ckdiv = true;\n+\ttp-\u003eups_info.eee_plloff_100 = false;\n+\ttp-\u003eups_info.eee_plloff_giga = false;\n+\n+\tocp_reg_set_bits(tp, OCP_POWER_CFG, EEE_CLKDIV_EN);\n+\ttp-\u003eups_info.eee_ckdiv = true;\n \n-\tcase RTL_VER_17:\n-\t\t/* Disable bypass turn off clk in ALDPS */\n-\t\tocp_byte_clr_bits(tp, MCU_TYPE_PLA, 0xd3c8, BIT(0));\n+\trtl_phy_patch_request(tp, false, true);\n+\n+\trtl_green_en(tp, test_bit(GREEN_ETHERNET, \u0026tp-\u003eflags));\n \n+\tocp_reg_clr_bits(tp, 0xa428, BIT(9));\n+\tocp_reg_clr_bits(tp, 0xa5ea, BIT(0) | BIT(1));\n+\ttp-\u003eups_info.lite_mode = 0;\n+\n+\tif (tp-\u003eeee_en)\n+\t\trtl_eee_enable(tp, true);\n+\n+\tr8153_aldps_en(tp, true);\n+\tr8152b_enable_fc(tp);\n+\n+\tset_bit(PHY_RESET, \u0026tp-\u003eflags);\n+}\n+\n+static void r8159_hw_phy_cfg(struct r8152 *tp)\n+{\n+\tu16 data;\n+\n+\tr8156b_wait_loading_flash(tp);\n+\n+\tocp_word_test_and_clr_bits(tp, MCU_TYPE_USB, USB_MISC_0, PCUT_STATUS);\n+\n+\tdata = r8153_phy_status(tp, 0);\n+\tswitch (data) {\n+\tcase PHY_STAT_EXT_INIT:\n+\t\trtl8152_apply_firmware(tp, true);\n+\t\tocp_reg_clr_bits(tp, 0xa466, BIT(0));\n+\t\tocp_reg_clr_bits(tp, 0xa468, BIT(3) | BIT(1));\n+\t\tbreak;\n+\tcase PHY_STAT_LAN_ON:\n+\tcase PHY_STAT_PWRDN:\n+\tdefault:\n+\t\trtl8152_apply_firmware(tp, false);\n+\t\tbreak;\n+\t}\n+\n+\tr8152_mdio_test_and_clr_bit(tp, MII_BMCR, BMCR_PDOWN);\n+\n+\tr8153_aldps_en(tp, false);\n+\n+\tdata = r8153_phy_status(tp, PHY_STAT_LAN_ON);\n+\tWARN_ON_ONCE(data != PHY_STAT_LAN_ON);\n+\n+\t/* PFM mode */\n+\tocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_PHY_PWR, PFM_PWM_SWITCH);\n+\n+\t/* Advanced Power Saving parameter */\n+\tocp_reg_set_bits(tp, OCP_POWER_CFG, EN_10M_PLLOFF | EN_ALDPS_PLLOFF);\n+\n+\t/* Disable ALDPS force mode */\n+\tocp_reg_clr_bits(tp, 0xa44a, BIT(2));\n+\n+\t/* Disable bypass_turn_off_clk_in_aldps */\n+\tocp_byte_clr_bits(tp, MCU_TYPE_PLA, 0xd3c8, BIT(0));\n+\n+\tswitch (tp-\u003eversion) {\n+\tcase RTL_VER_17_QFN68:\n+\tcase RTL_VER_17_QFN100:\n \t\t/* Power level tuning\n \t\t * test mode power level\n \t\t */\n@@ -8125,22 +8786,35 @@ static void r8157_hw_phy_cfg(struct r8152 *tp)\n \t\tsram_write_w0w1(tp, 0x81ae, 0xff00, 0x0f00);\n \t\tsram_write_w0w1(tp, 0x81b9, 0xff00, 0xb900);\n \t\t/* normal link TX filter */\n-\t\tsram2_write_w0w1(tp, 0x83b0, 0x0e00, 0);\n-\t\tsram2_write_w0w1(tp, 0x83c5, 0x0e00, 0);\n-\t\tsram2_write_w0w1(tp, 0x83da, 0x0e00, 0);\n-\t\tsram2_write_w0w1(tp, 0x83ef, 0x0e00, 0);\n+\t\tsram2_clr_bits(tp, 0x83b0, 0x0e00);\n+\t\tsram2_clr_bits(tp, 0x83c5, 0x0e00);\n+\t\tsram2_clr_bits(tp, 0x83da, 0x0e00);\n+\t\tsram2_clr_bits(tp, 0x83ef, 0x0e00);\n+\n+\t\tocp_reg_w0w1(tp, 0xbf38, 0x01f0, 0x0160);\n+\t\tocp_reg_w0w1(tp, 0xbf3a, 0x001f, 0x0014);\n+\t\t/* shorten CLKS latency */\n+\t\tocp_reg_clr_bits(tp, 0xbf28, BIT(14) | BIT(13));\n+\t\tocp_reg_clr_bits(tp, 0xbf2c, BIT(15) | BIT(14));\n+\t\t/* CMP_Timer on MP_Timer=333\n+\t\t * GPHY OCP 0xbf28 bit[0] = 0x1\n+\t\t * GPHY OCP 0xbf28 bit[6:1] = 0x3\n+\t\t * GPHY OCP 0xbf28 bit[12:7] = 0x3\n+\t\t */\n+\t\tocp_reg_w0w1(tp, 0xbf28, 0x1fff, 0x0187);\n+\t\tocp_reg_w0w1(tp, 0xbf2a, 0x3f, 0x03);\n \n \t\t/* AFE power saving for 2.5G \u0026 5G */\n \t\tsram_write(tp, 0x8173, 0x8620);\n \t\tsram_write(tp, 0x8175, 0x8671);\n \n-\t\tsram_write_w0w1(tp, 0x817c, 0, BIT(13));\n-\t\tsram_write_w0w1(tp, 0x8187, 0, BIT(13));\n-\t\tsram_write_w0w1(tp, 0x8192, 0, BIT(13));\n-\t\tsram_write_w0w1(tp, 0x819d, 0, BIT(13));\n-\t\tsram_write_w0w1(tp, 0x81a8, BIT(13), 0);\n-\t\tsram_write_w0w1(tp, 0x81b3, BIT(13), 0);\n-\t\tsram_write_w0w1(tp, 0x81be, 0, BIT(13));\n+\t\tsram_set_bits(tp, 0x817c, BIT(13));\n+\t\tsram_set_bits(tp, 0x8187, BIT(13));\n+\t\tsram_set_bits(tp, 0x8192, BIT(13));\n+\t\tsram_set_bits(tp, 0x819d, BIT(13));\n+\t\tsram_clr_bits(tp, 0x81a8, BIT(13));\n+\t\tsram_clr_bits(tp, 0x81b3, BIT(13));\n+\t\tsram_set_bits(tp, 0x81be, BIT(13));\n \n \t\tsram_write_w0w1(tp, 0x817d, 0xff00, 0xa600);\n \t\tsram_write_w0w1(tp, 0x8188, 0xff00, 0xa600);\n@@ -8204,10 +8878,10 @@ static void r8157_hw_phy_cfg(struct r8152 *tp)\n \t\tsram2_write_w0w1(tp, 0x84b2, 0xff00, 0x6000);\n \t\t/* Training AAGC PAR (with uc2 patch) */\n \t\tsram2_write(tp, 0x8ffc, 0x6008);\n-\t\tsram2_write(tp, 0x8ffe, 0xf450);\n+\t\tsram2_write(tp, 0x8ffe, 0xf4ff);\n \t\t/* DAC BGK */\n-\t\tsram2_write_w0w1(tp, 0x8015, 0, BIT(9));\n-\t\tsram2_write_w0w1(tp, 0x8016, 0, BIT(11));\n+\t\tsram2_set_bits(tp, 0x8015, BIT(9));\n+\t\tsram2_set_bits(tp, 0x8016, BIT(11));\n \t\tsram2_write_w0w1(tp, 0x8fe6, 0xff00, 0x0800);\n \t\tsram2_write(tp, 0x8fe4, 0x2114);\n \t\t/* 10G PBO table */\n@@ -8216,14 +8890,14 @@ static void r8157_hw_phy_cfg(struct r8152 *tp)\n \t\tsram2_write_w0w1(tp, 0x864b, 0xff00, 0xdc00);\n \t\t/* 2.5G ado power window size */\n \t\tsram2_write_w0w1(tp, 0x8154, 0xc000, 0x4000);\n-\t\tsram2_write_w0w1(tp, 0x8158, 0xc000, 0);\n+\t\tsram2_clr_bits(tp, 0x8158, 0xc000);\n \t\t/* 10G lock far */\n \t\tsram2_write(tp, 0x826c, 0xffff);\n \t\tsram2_write(tp, 0x826e, 0xffff);\n \t\t/* XG INRX parameter */\n \t\tsram2_write_w0w1(tp, 0x8872, 0xff00, 0x0e00);\n-\t\tsram_write_w0w1(tp, 0x8012, 0, BIT(11));\n-\t\tsram_write_w0w1(tp, 0x8012, 0, BIT(14));\n+\t\tsram_set_bits(tp, 0x8012, BIT(11));\n+\t\tsram_set_bits(tp, 0x8012, BIT(14));\n \t\tocp_reg_set_bits(tp, 0xb576, BIT(0));\n \t\tsram_write_w0w1(tp, 0x834a, 0xff00, 0x0700);\n \t\tsram2_write_w0w1(tp, 0x8217, 0x3f00, 0x2a00);\n@@ -8234,100 +8908,372 @@ static void r8157_hw_phy_cfg(struct r8152 *tp)\n \t\t/* improve UBE */\n \t\tocp_reg_set_bits(tp, 0xbf0c, 0x7 \u003c\u003c 11);\n \t\t/* close Sparse NEC, improve connect 5EUU cable performance */\n-\t\tsram2_write_w0w1(tp, 0x88de, 0xff00, 0);\n+\t\tsram2_clr_bits(tp, 0x88de, 0xff00);\n \t\t/* 5G slave compatibility issue */\n \t\tsram2_write(tp, 0x80b4, 0x5195);\n \n-\t\t/* XG Test Mode\n-\t\t * xgtstm_map_tbl for mdi_cap_sel\n-\t\t */\n-\t\tsram_write(tp, 0x8370, 0x8671);\n-\t\tsram_write(tp, 0x8372, 0x86c8);\n-\t\t/* xgtstm_amp_map_tbl for  REG_IBX_UP_SHIFT_L */\n-\t\tsram_write(tp, 0x8401, 0x86c8);\n-\t\tsram_write(tp, 0x8403, 0x86da);\n-\t\tsram_write_w0w1(tp, 0x8406, 0x1800, 0x1000);\n-\t\tsram_write_w0w1(tp, 0x8408, 0x1800, 0x1000);\n-\t\tsram_write_w0w1(tp, 0x840a, 0x1800, 0x1000);\n-\t\tsram_write_w0w1(tp, 0x840c, 0x1800, 0x1000);\n-\t\tsram_write_w0w1(tp, 0x840e, 0x1800, 0x1000);\n-\t\tsram_write_w0w1(tp, 0x8410, 0x1800, 0x1000);\n-\t\tsram_write_w0w1(tp, 0x8412, 0x1800, 0x1000);\n-\t\tsram_write_w0w1(tp, 0x8414, 0x1800, 0x1000);\n-\t\tsram_write_w0w1(tp, 0x8416, 0x1800, 0x1000);\n+\t\t/* XG Test Mode\n+\t\t * xgtstm_map_tbl for mdi_cap_sel\n+\t\t */\n+\t\tsram_write(tp, 0x8370, 0x8671);\n+\t\tsram_write(tp, 0x8372, 0x86c8);\n+\t\t/* xgtstm_amp_map_tbl for  REG_IBX_UP_SHIFT_L */\n+\t\tsram_write(tp, 0x8401, 0x86c8);\n+\t\tsram_write(tp, 0x8403, 0x86da);\n+\t\tsram_write_w0w1(tp, 0x8406, 0x1800, 0x1000);\n+\t\tsram_write_w0w1(tp, 0x8408, 0x1800, 0x1000);\n+\t\tsram_write_w0w1(tp, 0x840a, 0x1800, 0x1000);\n+\t\tsram_write_w0w1(tp, 0x840c, 0x1800, 0x1000);\n+\t\tsram_write_w0w1(tp, 0x840e, 0x1800, 0x1000);\n+\t\tsram_write_w0w1(tp, 0x8410, 0x1800, 0x1000);\n+\t\tsram_write_w0w1(tp, 0x8412, 0x1800, 0x1000);\n+\t\tsram_write_w0w1(tp, 0x8414, 0x1800, 0x1000);\n+\t\tsram_write_w0w1(tp, 0x8416, 0x1800, 0x1000);\n+\n+\t\t/* Cable Test Patch */\n+\t\tsram_write(tp, 0x82bd, 0x1f40);\n+\n+\t\t/* Thermal sensor parameters */\n+\t\tocp_reg_w0w1(tp, 0xbfb4, 0x07ff, 0x0328);\n+\t\tocp_reg_write(tp, 0xbfb6, 0x3e14);\n+\n+\t\t/* spdchg_gtx_shape_100M */\n+\t\tocp_reg_write(tp, OCP_SRAM_ADDR, 0x81c4);\n+\t\tocp_reg_write(tp, OCP_SRAM_DATA, 0x003b);\n+\t\tocp_reg_write(tp, OCP_SRAM_DATA, 0x0086);\n+\t\tocp_reg_write(tp, OCP_SRAM_DATA, 0x00b7);\n+\t\tocp_reg_write(tp, OCP_SRAM_DATA, 0x00db);\n+\t\tocp_reg_write(tp, OCP_SRAM_DATA, 0x00fe);\n+\t\tocp_reg_write(tp, OCP_SRAM_DATA, 0x00fe);\n+\t\tocp_reg_write(tp, OCP_SRAM_DATA, 0x00fe);\n+\t\tocp_reg_write(tp, OCP_SRAM_DATA, 0x00fe);\n+\t\tocp_reg_write(tp, OCP_SRAM_DATA, 0x00c3);\n+\t\tocp_reg_write(tp, OCP_SRAM_DATA, 0x0078);\n+\t\tocp_reg_write(tp, OCP_SRAM_DATA, 0x0047);\n+\t\tocp_reg_write(tp, OCP_SRAM_DATA, 0x0023);\n+\n+\t\t/* lsbmsk_parameters\n+\t\t * RL6961_lsbmsk_parameter_250207\n+\t\t */\n+\t\tsram2_write(tp, 0x88d7, 0x01a0);\n+\t\tsram2_write(tp, 0x88d9, 0x01a0);\n+\t\tsram2_write(tp, 0x8ffa, 0x002a);\n+\n+\t\tsram2_write(tp, 0x8fee, 0xffdf);\n+\t\tsram2_write(tp, 0x8ff0, 0xffff);\n+\t\tsram2_write(tp, 0x8ff2, 0x0a4a);\n+\t\tsram2_write(tp, 0x8ff4, 0xaa5a);\n+\t\tsram2_write(tp, 0x8ff6, 0x0a4a);\n+\t\tsram2_write(tp, 0x8ff8, 0xaa5a);\n+\n+\t\tsram2_write_w0w1(tp, 0x88d5, 0xff00, 0x0200);\n+\n+\t\t/* spdchg_pga1_lpf_cap */\n+\t\tsram_write_w0w1(tp, 0x84bb, 0xff00, 0x0a00);\n+\t\tsram_write_w0w1(tp, 0x84c0, 0xff00, 0x1600);\n+\n+\t\t/* ENET PLL jitter improvement */\n+\t\tocp_reg_w0w1(tp, 0xbf8a, 0xfc00, 0x2000);\n+\t\tocp_reg_set_bits(tp, 0xbf88, BIT(2));\n+\t\tbreak;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+\n+\tif (rtl_phy_patch_request(tp, true, true))\n+\t\treturn;\n+\n+\tocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, EEE_SPDWN_EN);\n+\n+\tocp_reg_clr_bits(tp, OCP_DOWN_SPEED,\n+\t\t\t EN_EEE_100 | EN_EEE_1000 | EN_10M_CLKDIV);\n+\ttp-\u003eups_info._10m_ckdiv = false;\n+\ttp-\u003eups_info.eee_plloff_100 = false;\n+\ttp-\u003eups_info.eee_plloff_giga = false;\n+\n+\tocp_reg_set_bits(tp, OCP_POWER_CFG, EEE_CLKDIV_EN);\n+\ttp-\u003eups_info.eee_ckdiv = true;\n+\n+\trtl_phy_patch_request(tp, false, true);\n+\n+\trtl_green_en(tp, test_bit(GREEN_ETHERNET, \u0026tp-\u003eflags));\n+\n+\tocp_reg_clr_bits(tp, 0xa428, BIT(9));\n+\tocp_reg_clr_bits(tp, 0xa5ea, BIT(0) | BIT(1) | BIT(2));\n+\ttp-\u003eups_info.lite_mode = 0;\n+\n+\trtl_eee_enable(tp, tp-\u003eeee_en);\n+\n+\tr8153_aldps_en(tp, true);\n+\tr8152b_enable_fc(tp);\n+\n+\tset_bit(PHY_RESET, \u0026tp-\u003eflags);\n+}\n+\n+static void r8156_init(struct r8152 *tp)\n+{\n+\tu16 data;\n+\n+\tif (test_bit(RTL8152_INACCESSIBLE, \u0026tp-\u003eflags))\n+\t\treturn;\n+\n+\tocp_byte_clr_bits(tp, MCU_TYPE_USB, USB_ECM_OP, EN_ALL_SPEED);\n+\n+\tocp_write_word(tp, MCU_TYPE_USB, USB_SPEED_OPTION, 0);\n+\n+\tocp_word_set_bits(tp, MCU_TYPE_USB, USB_ECM_OPTION, BYPASS_MAC_RESET);\n+\n+\tr8153b_u1u2en(tp, false);\n+\n+\tif (wait_autoload_done(tp))\n+\t\treturn;\n+\n+\tdata = r8153_phy_status(tp, 0);\n+\tif (data == PHY_STAT_EXT_INIT)\n+\t\tocp_reg_clr_bits(tp, 0xa468, BIT(3) | BIT(1));\n+\n+\tr8152_mdio_test_and_clr_bit(tp, MII_BMCR, BMCR_PDOWN);\n+\n+\tdata = r8153_phy_status(tp, PHY_STAT_LAN_ON);\n+\n+\tr8153_u2p3en(tp, false);\n+\n+\t/* MSC timer = 0xfff * 8ms = 32760 ms */\n+\tocp_write_word(tp, MCU_TYPE_USB, USB_MSC_TIMER, 0x0fff);\n+\n+\t/* U1/U2/L1 idle timer. 500 us */\n+\tocp_write_word(tp, MCU_TYPE_USB, USB_U1U2_TIMER, 500);\n+\n+\tr8153b_power_cut_en(tp, false);\n+\tr8156_ups_en(tp, false);\n+\tr8153_queue_wake(tp, false);\n+\trtl_runtime_suspend_enable(tp, false);\n+\n+\tocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_INDICATE_FALG, PREBOOT_OPTION);\n+\n+\tocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_RMT_WAKE, RMT_WAKE_EN);\n+\n+\tif (tp-\u003eudev-\u003espeed \u003e= USB_SPEED_SUPER)\n+\t\tr8153b_u1u2en(tp, true);\n+\n+\tusb_enable_lpm(tp-\u003eudev);\n+\n+\trtl_fc_pause_pkt_en(tp, 0);\n+\n+\tr8156_mac_clk_spd(tp, true);\n+\n+\tocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3,\n+\t\t\t  PLA_MCU_SPDWN_EN);\n+\n+\tif (rtl8152_get_speed(tp) \u0026 LINK_STATUS)\n+\t\tocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS,\n+\t\t\t\t  CUR_LINK_OK | POLL_LINK_CHG);\n+\telse\n+\t\tocp_word_w0w1(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS, CUR_LINK_OK,\n+\t\t\t      POLL_LINK_CHG);\n+\n+\tset_bit(GREEN_ETHERNET, \u0026tp-\u003eflags);\n+\n+\tocp_word_clr_bits(tp, MCU_TYPE_USB, USB_USB_CTRL,\n+\t\t\t  RX_AGG_DISABLE | RX_ZERO_EN);\n+\n+\tocp_byte_set_bits(tp, MCU_TYPE_USB, USB_BMU_CONFIG, ACT_ODMA);\n+\n+\tr8156_mdio_force_mode(tp);\n+\trtl_tally_reset(tp);\n+\n+\ttp-\u003ecoalesce = 15000; /* 15 us */\n+}\n+\n+static void r8156b_u2phy_backup(struct r8152 *tp)\n+{\n+\tocp_write_word(tp, MCU_TYPE_USB, 0xd3ce, 0x181b);\n+\tocp_write_dword(tp, MCU_TYPE_USB, 0xd3d0, 0x616ccd99);\n+\tocp_write_dword(tp, MCU_TYPE_USB, 0xd3d4, 0x08fc8101);\n+\tocp_write_dword(tp, MCU_TYPE_USB, 0xd3d8, 0x159b1100);\n+\tocp_write_word(tp, MCU_TYPE_USB, 0xd3dc, 0x0a00);\n+}\n+\n+static void r8156b_init(struct r8152 *tp)\n+{\n+\tu16 data;\n+\n+\tif (test_bit(RTL8152_INACCESSIBLE, \u0026tp-\u003eflags))\n+\t\treturn;\n+\n+\tocp_byte_clr_bits(tp, MCU_TYPE_USB, USB_ECM_OP, EN_ALL_SPEED);\n+\n+\tocp_write_word(tp, MCU_TYPE_USB, USB_SPEED_OPTION, 0);\n+\n+\tocp_word_set_bits(tp, MCU_TYPE_USB, USB_ECM_OPTION, BYPASS_MAC_RESET);\n+\n+\tocp_word_set_bits(tp, MCU_TYPE_USB, USB_U2P3_CTRL, RX_DETECT8);\n+\n+\tr8153b_u1u2en(tp, false);\n+\n+\tswitch (tp-\u003eversion) {\n+\tcase RTL_VER_13:\n+\tcase RTL_VER_15:\n+\t\tr8156b_wait_loading_flash(tp);\n+\t\tbreak;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+\n+\tif (wait_autoload_done(tp))\n+\t\treturn;\n+\n+\tdata = r8153_phy_status(tp, 0);\n+\tif (data == PHY_STAT_EXT_INIT) {\n+\t\tocp_reg_clr_bits(tp, 0xa468, BIT(3) | BIT(1));\n+\t\tocp_reg_clr_bits(tp, 0xa466, BIT(0));\n+\t}\n+\n+\tr8152_mdio_test_and_clr_bit(tp, MII_BMCR, BMCR_PDOWN);\n+\n+\tdata = r8153_phy_status(tp, PHY_STAT_LAN_ON);\n+\n+\tr8153_u2p3en(tp, false);\n+\n+\t/* MSC timer = 0xfff * 8ms = 32760 ms */\n+\tocp_write_word(tp, MCU_TYPE_USB, USB_MSC_TIMER, 0x0fff);\n+\n+\t/* U1/U2/L1 idle timer. 500 us */\n+\tocp_write_word(tp, MCU_TYPE_USB, USB_U1U2_TIMER, 500);\n+\n+\tr8156b_u2phy_backup(tp);\n+\n+\tr8153b_power_cut_en(tp, false);\n+\tr8156_ups_en(tp, false);\n+\tr8153_queue_wake(tp, false);\n+\trtl_runtime_suspend_enable(tp, false);\n+\n+\tocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_INDICATE_FALG, PREBOOT_OPTION);\n+\n+\tocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_RMT_WAKE, RMT_WAKE_EN);\n+\n+\tif (tp-\u003eudev-\u003espeed \u003e= USB_SPEED_SUPER)\n+\t\tr8153b_u1u2en(tp, true);\n+\n+\tusb_enable_lpm(tp-\u003eudev);\n+\n+\trtl_fc_pause_pkt_en(tp, 0);\n+\n+\t/* Disable Auto Speed up */\n+\tocp_word_clr_bits(tp, MCU_TYPE_USB, USB_FW_CTRL, AUTO_SPEEDUP);\n+\n+\tr8156_mac_clk_spd(tp, true);\n+\n+\tocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3,\n+\t\t\t  PLA_MCU_SPDWN_EN);\n+\n+\tif (rtl8152_get_speed(tp) \u0026 LINK_STATUS)\n+\t\tocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS,\n+\t\t\t\t  CUR_LINK_OK | POLL_LINK_CHG);\n+\telse\n+\t\tocp_word_w0w1(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS,\n+\t\t\t      CUR_LINK_OK, POLL_LINK_CHG);\n+\n+\tset_bit(GREEN_ETHERNET, \u0026tp-\u003eflags);\n+\n+\tocp_word_clr_bits(tp, MCU_TYPE_USB, USB_USB_CTRL,\n+\t\t\t  RX_AGG_DISABLE | RX_ZERO_EN);\n+\n+\tr8156_mdio_force_mode(tp);\n+\trtl_tally_reset(tp);\n \n-\t\t/* Cable Test Patch */\n-\t\tsram_write(tp, 0x82bd, 0x1f40);\n+\ttp-\u003ecoalesce = 15000;\t/* 15 us */\n+}\n \n-\t\t/* Thermal sensor parameters */\n-\t\tocp_reg_w0w1(tp, 0xbfb4, 0x07ff, 0x0328);\n-\t\tocp_reg_write(tp, 0xbfb6, 0x3e14);\n+static void r8157_init(struct r8152 *tp)\n+{\n+\tu16 data;\n \n-\t\t/* spdchg_gtx_shape_100M */\n-\t\tocp_reg_write(tp, OCP_SRAM_ADDR, 0x81c4);\n-\t\tocp_reg_write(tp, OCP_SRAM_DATA, 0x003b);\n-\t\tocp_reg_write(tp, OCP_SRAM_DATA, 0x0086);\n-\t\tocp_reg_write(tp, OCP_SRAM_DATA, 0x00b7);\n-\t\tocp_reg_write(tp, OCP_SRAM_DATA, 0x00db);\n-\t\tocp_reg_write(tp, OCP_SRAM_DATA, 0x00fe);\n-\t\tocp_reg_write(tp, OCP_SRAM_DATA, 0x00fe);\n-\t\tocp_reg_write(tp, OCP_SRAM_DATA, 0x00fe);\n-\t\tocp_reg_write(tp, OCP_SRAM_DATA, 0x00fe);\n-\t\tocp_reg_write(tp, OCP_SRAM_DATA, 0x00c3);\n-\t\tocp_reg_write(tp, OCP_SRAM_DATA, 0x0078);\n-\t\tocp_reg_write(tp, OCP_SRAM_DATA, 0x0047);\n-\t\tocp_reg_write(tp, OCP_SRAM_DATA, 0x0023);\n+\tif (test_bit(RTL8152_INACCESSIBLE, \u0026tp-\u003eflags))\n+\t\treturn;\n \n-\t\t/* lsbmsk_parameters\n-\t\t * RL6961_lsbmsk_parameter_250207\n-\t\t */\n-\t\tsram2_write(tp, 0x88d7, 0x01a0);\n-\t\tsram2_write(tp, 0x88d9, 0x01a0);\n-\t\tsram2_write(tp, 0x8ffa, 0x002a);\n+\t/* Enable SW reset */\n+\tocp_byte_set_bits(tp, MCU_TYPE_USB, 0xcffe, BIT(3));\n+\tocp_byte_clr_bits(tp, MCU_TYPE_USB, 0xd3ca, BIT(0));\n \n-\t\tsram2_write(tp, 0x8fee, 0xffdf);\n-\t\tsram2_write(tp, 0x8ff0, 0xffff);\n-\t\tsram2_write(tp, 0x8ff2, 0x0a4a);\n-\t\tsram2_write(tp, 0x8ff4, 0xaa5a);\n-\t\tsram2_write(tp, 0x8ff6, 0x0a4a);\n-\t\tsram2_write(tp, 0x8ff8, 0xaa5a);\n+\tocp_byte_clr_bits(tp, MCU_TYPE_USB, USB_ECM_OP, EN_ALL_SPEED);\n \n-\t\tsram2_write_w0w1(tp, 0x88d5, 0xff00, 0x0200);\n-\t\tbreak;\n+\tocp_word_set_bits(tp, MCU_TYPE_USB, USB_ECM_OPTION, BYPASS_MAC_RESET);\n \n-\tdefault:\n-\t\tbreak;\n-\t}\n+\tr8153b_u1u2en(tp, false);\n \n-\tif (rtl_phy_patch_request(tp, true, true))\n+\tr8156b_wait_loading_flash(tp);\n+\n+\tif (wait_autoload_done(tp))\n \t\treturn;\n \n-\tocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, EEE_SPDWN_EN);\n+\tdata = r8153_phy_status(tp, 0);\n+\tif (data == PHY_STAT_EXT_INIT) {\n+\t\tocp_reg_clr_bits(tp, 0xa468, BIT(3) | BIT(1));\n+\t\tocp_reg_clr_bits(tp, 0xa466, BIT(0));\n+\t}\n \n-\tocp_reg_w0w1(tp, OCP_DOWN_SPEED, EN_EEE_100 | EN_EEE_1000, EN_10M_CLKDIV);\n+\tr8152_mdio_test_and_clr_bit(tp, MII_BMCR, BMCR_PDOWN);\n \n-\ttp-\u003eups_info._10m_ckdiv = true;\n-\ttp-\u003eups_info.eee_plloff_100 = false;\n-\ttp-\u003eups_info.eee_plloff_giga = false;\n+\tdata = r8153_phy_status(tp, PHY_STAT_LAN_ON);\n \n-\tocp_reg_set_bits(tp, OCP_POWER_CFG, EEE_CLKDIV_EN);\n-\ttp-\u003eups_info.eee_ckdiv = true;\n+\tr8157_u2p3en(tp, false);\n \n-\trtl_phy_patch_request(tp, false, true);\n+\t/* Disable Interrupt Mitigation */\n+\tocp_byte_clr_bits(tp, MCU_TYPE_USB, 0xcf04,\n+\t\t\t  BIT(0) | BIT(1) | BIT(2) | BIT(7));\n \n-\trtl_green_en(tp, test_bit(GREEN_ETHERNET, \u0026tp-\u003eflags));\n+\t/* MSC timer = 0xfff * 8ms = 32760 ms */\n+\tocp_write_word(tp, MCU_TYPE_USB, USB_MSC_TIMER, 0x0fff);\n \n-\tocp_reg_clr_bits(tp, 0xa428, BIT(9));\n-\tocp_reg_clr_bits(tp, 0xa5ea, BIT(0) | BIT(1));\n-\ttp-\u003eups_info.lite_mode = 0;\n+\t/* U1/U2/L1 idle timer. 500 us */\n+\tocp_write_word(tp, MCU_TYPE_USB, USB_U1U2_TIMER, 500);\n \n-\tif (tp-\u003eeee_en)\n-\t\trtl_eee_enable(tp, true);\n+\tr8157_power_cut_en(tp, false);\n+\tr8157_ups_en(tp, false);\n+\tr8153_queue_wake(tp, false);\n+\trtl_runtime_suspend_enable(tp, false);\n \n-\tr8153_aldps_en(tp, true);\n-\tr8152b_enable_fc(tp);\n+\tocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_INDICATE_FALG, PREBOOT_OPTION);\n \n-\tset_bit(PHY_RESET, \u0026tp-\u003eflags);\n+\tocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_RMT_WAKE, RMT_WAKE_EN);\n+\n+\t/* Clear Warm RST / Bus RST event flag */\n+\tocp_word_clr_bits(tp, MCU_TYPE_USB, 0xcd06, BIT(11));\n+\n+\tif (tp-\u003eudev-\u003espeed \u003e= USB_SPEED_SUPER)\n+\t\tr8153b_u1u2en(tp, true);\n+\n+\tusb_enable_lpm(tp-\u003eudev);\n+\n+\t/* Disable Auto Speed up */\n+\tocp_word_clr_bits(tp, MCU_TYPE_USB, USB_FW_CTRL, AUTO_SPEEDUP);\n+\n+\tr8156_mac_clk_spd(tp, true);\n+\n+\tif (rtl8152_get_speed(tp) \u0026 LINK_STATUS)\n+\t\tocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS,\n+\t\t\t\t  CUR_LINK_OK | POLL_LINK_CHG);\n+\telse\n+\t\tocp_word_w0w1(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS,\n+\t\t\t      CUR_LINK_OK, POLL_LINK_CHG);\n+\n+\tset_bit(GREEN_ETHERNET, \u0026tp-\u003eflags);\n+\n+\t/* RX aggregation / 16 bytes RX descriptor / Bulk In End transfer */\n+\tocp_word_clr_bits(tp, MCU_TYPE_USB, USB_USB_CTRL,\n+\t\t\t  RX_AGG_DISABLE | RX_DESC_16B | RX_END_TRANSFER_EN);\n+\n+\t/* Disable Rx Zero Len */\n+\trtl_bmu_clr_bits(tp, 0x2300, BIT(3));\n+\n+\t/* TX descriptor Signature */\n+\tocp_byte_clr_bits(tp, MCU_TYPE_USB, 0xd4ae, BIT(1));\n+\n+\tr8156_mdio_force_mode(tp);\n+\trtl_tally_reset(tp);\n+\n+\ttp-\u003ecoalesce = 15000;\t/* 15 us */\n }\n \n static int r8159_wait_backup_restore(struct r8152 *tp)\n@@ -8342,78 +9288,50 @@ static int r8159_wait_backup_restore(struct r8152 *tp)\n \t\t\t       ocp_data \u0026 BACKUP_RESTRORE, 200, 20000, false);\n }\n \n-static void r8156_init(struct r8152 *tp)\n+static void r8159_init(struct r8152 *tp)\n {\n-\tu32 ocp_data;\n \tu16 data;\n-\tint i;\n \n \tif (test_bit(RTL8152_INACCESSIBLE, \u0026tp-\u003eflags))\n \t\treturn;\n \n-\tif (tp-\u003eversion == RTL_VER_16 || tp-\u003eversion == RTL_VER_17) {\n-\t\tocp_byte_set_bits(tp, MCU_TYPE_USB, 0xcffe, BIT(3));\n-\t\tocp_byte_clr_bits(tp, MCU_TYPE_USB, 0xd3ca, BIT(0));\n-\t}\n+\t/* Enable SW reset */\n+\tocp_byte_set_bits(tp, MCU_TYPE_USB, 0xcffe, BIT(3));\n+\tocp_byte_clr_bits(tp, MCU_TYPE_USB, 0xd3ca, BIT(0));\n \n \tocp_byte_clr_bits(tp, MCU_TYPE_USB, USB_ECM_OP, EN_ALL_SPEED);\n \n-\tif (tp-\u003eversion \u003c RTL_VER_16)\n-\t\tocp_write_word(tp, MCU_TYPE_USB, USB_SPEED_OPTION, 0);\n-\n \tocp_word_set_bits(tp, MCU_TYPE_USB, USB_ECM_OPTION, BYPASS_MAC_RESET);\n \n-\tif (tp-\u003eversion \u003e= RTL_VER_12 \u0026\u0026 tp-\u003eversion \u003c= RTL_VER_15)\n-\t\tocp_word_set_bits(tp, MCU_TYPE_USB, USB_U2P3_CTRL, RX_DETECT8);\n-\n \tr8153b_u1u2en(tp, false);\n \n-\tswitch (tp-\u003eversion) {\n-\tcase RTL_VER_13:\n-\tcase RTL_VER_15:\n-\tcase RTL_VER_16:\n-\tcase RTL_VER_17:\n-\t\tr8156b_wait_loading_flash(tp);\n-\t\tbreak;\n-\tdefault:\n-\t\tbreak;\n-\t}\n-\n-\tfor (i = 0; i \u003c 500; i++) {\n-\t\tif (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) \u0026\n-\t\t    AUTOLOAD_DONE)\n-\t\t\tbreak;\n+\tr8156b_wait_loading_flash(tp);\n \n-\t\tmsleep(20);\n-\t\tif (test_bit(RTL8152_INACCESSIBLE, \u0026tp-\u003eflags))\n-\t\t\treturn;\n-\t}\n+\tif (wait_autoload_done(tp))\n+\t\treturn;\n \n-\tif (tp-\u003eversion == RTL_VER_17 \u0026\u0026 r8159_wait_backup_restore(tp)) {\n+\tif (r8159_wait_backup_restore(tp)) {\n \t\trtl_set_inaccessible(tp);\n-\t\tdev_err(\u0026tp-\u003eintf-\u003edev, \"init failed, backup-restore timed out\\n\");\n+\t\tdev_err(\u0026tp-\u003eintf-\u003edev,\n+\t\t\t\"init failed, backup-restore timed out\\n\");\n \t\treturn;\n \t}\n \n \tdata = r8153_phy_status(tp, 0);\n \tif (data == PHY_STAT_EXT_INIT) {\n \t\tocp_reg_clr_bits(tp, 0xa468, BIT(3) | BIT(1));\n-\t\tif (tp-\u003eversion \u003e= RTL_VER_12)\n-\t\t\tocp_reg_clr_bits(tp, 0xa466, BIT(0));\n+\t\tocp_reg_clr_bits(tp, 0xa466, BIT(0));\n \t}\n \n-\tdata = r8152_mdio_read(tp, MII_BMCR);\n-\tif (data \u0026 BMCR_PDOWN) {\n-\t\tdata \u0026= ~BMCR_PDOWN;\n-\t\tr8152_mdio_write(tp, MII_BMCR, data);\n-\t}\n+\tr8152_mdio_test_and_clr_bit(tp, MII_BMCR, BMCR_PDOWN);\n \n \tdata = r8153_phy_status(tp, PHY_STAT_LAN_ON);\n \n-\tif (tp-\u003eversion \u003e= RTL_VER_16)\n-\t\tr8157_u2p3en(tp, false);\n-\telse\n-\t\tr8153_u2p3en(tp, false);\n+\tr8157_u2p3en(tp, false);\n+\n+\t/* Disable Interrupt Mitigation */\n+\tocp_byte_clr_bits(tp, MCU_TYPE_USB, 0xcf04,\n+\t\t\t  BIT(0) | BIT(1) | BIT(2) | BIT(7));\n \n \t/* MSC timer = 0xfff * 8ms = 32760 ms */\n \tocp_write_word(tp, MCU_TYPE_USB, USB_MSC_TIMER, 0x0fff);\n@@ -8421,72 +9339,56 @@ static void r8156_init(struct r8152 *tp)\n \t/* U1/U2/L1 idle timer. 500 us */\n \tocp_write_word(tp, MCU_TYPE_USB, USB_U1U2_TIMER, 500);\n \n-\tif (tp-\u003eversion \u003e= RTL_VER_16)\n-\t\tr8157_power_cut_en(tp, false);\n-\telse\n-\t\tr8153b_power_cut_en(tp, false);\n-\n-\tr8156_ups_en(tp, false);\n+\tr8157_power_cut_en(tp, false);\n+\tr8157_ups_en(tp, false);\n \tr8153_queue_wake(tp, false);\n \trtl_runtime_suspend_enable(tp, false);\n \n-\tif (tp-\u003eudev-\u003espeed \u003e= USB_SPEED_SUPER)\n-\t\tr8153b_u1u2en(tp, true);\n+\tocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_INDICATE_FALG, PREBOOT_OPTION);\n \n-\tusb_enable_lpm(tp-\u003eudev);\n+\tocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_RMT_WAKE, RMT_WAKE_EN);\n \n-\tif (tp-\u003eversion \u003e= RTL_VER_12 \u0026\u0026 tp-\u003eversion \u003c= RTL_VER_15) {\n-\t\tocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_RCR, SLOT_EN);\n+\t/* Clear Warm RST / Bus RST event flag */\n+\tocp_word_clr_bits(tp, MCU_TYPE_USB, 0xcd06, BIT(11));\n \n-\t\tocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_CPCR, FLOW_CTRL_EN);\n+\t/* Disable FW u1u2 patch option */\n+\tocp_byte_clr_bits(tp, MCU_TYPE_USB, 0xb9a6, BIT(0));\n \n-\t\t/* enable fc timer and set timer to 600 ms. */\n-\t\tocp_write_word(tp, MCU_TYPE_USB, USB_FC_TIMER, CTRL_TIMER_EN | (600 / 8));\n+\tif (tp-\u003eudev-\u003espeed \u003e= USB_SPEED_SUPER)\n+\t\tr8153b_u1u2en(tp, true);\n \n-\t\tocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_FW_CTRL);\n-\t\tif (!(ocp_read_word(tp, MCU_TYPE_PLA, PLA_POL_GPIO_CTRL) \u0026 DACK_DET_EN))\n-\t\t\tocp_data |= FLOW_CTRL_PATCH_2;\n-\t\tocp_data \u0026= ~AUTO_SPEEDUP;\n-\t\tocp_write_word(tp, MCU_TYPE_USB, USB_FW_CTRL, ocp_data);\n+\tusb_enable_lpm(tp-\u003eudev);\n \n-\t\tocp_word_set_bits(tp, MCU_TYPE_USB, USB_FW_TASK, FC_PATCH_TASK);\n-\t}\n+\t/* Disable Auto Speed up */\n+\tocp_word_clr_bits(tp, MCU_TYPE_USB, USB_FW_CTRL, AUTO_SPEEDUP);\n \n \tr8156_mac_clk_spd(tp, true);\n \n-\tif (tp-\u003eversion \u003c RTL_VER_16)\n-\t\tocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, PLA_MCU_SPDWN_EN);\n-\n-\tocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS);\n \tif (rtl8152_get_speed(tp) \u0026 LINK_STATUS)\n-\t\tocp_data |= CUR_LINK_OK;\n+\t\tocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS,\n+\t\t\t\t  CUR_LINK_OK | POLL_LINK_CHG);\n \telse\n-\t\tocp_data \u0026= ~CUR_LINK_OK;\n-\tocp_data |= POLL_LINK_CHG;\n-\tocp_write_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS, ocp_data);\n+\t\tocp_word_w0w1(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS,\n+\t\t\t      CUR_LINK_OK, POLL_LINK_CHG);\n \n \tset_bit(GREEN_ETHERNET, \u0026tp-\u003eflags);\n \n-\t/* RX aggregation / 16 bytes RX descriptor\n-\t * BIT(11) is specific to RTL8159, with unknown meaning\n-\t */\n-\tif (tp-\u003eversion == RTL_VER_17)\n-\t\tocp_word_clr_bits(tp, MCU_TYPE_USB, USB_USB_CTRL,\n-\t\t\t\t  RX_AGG_DISABLE | RX_DESC_16B | BIT(11));\n-\telse if (tp-\u003eversion == RTL_VER_16)\n-\t\tocp_word_clr_bits(tp, MCU_TYPE_USB, USB_USB_CTRL, RX_AGG_DISABLE | RX_DESC_16B);\n-\telse\n-\t\tocp_word_clr_bits(tp, MCU_TYPE_USB, USB_USB_CTRL, RX_AGG_DISABLE | RX_ZERO_EN);\n+\t/* RX aggregation / 16 bytes RX descriptor / Bulk In End transfer */\n+\tocp_word_clr_bits(tp, MCU_TYPE_USB, USB_USB_CTRL,\n+\t\t\t  RX_AGG_DISABLE | RX_DESC_16B | RX_END_TRANSFER_EN);\n \n-\tif (tp-\u003eversion \u003c RTL_VER_12)\n-\t\tocp_byte_set_bits(tp, MCU_TYPE_USB, USB_BMU_CONFIG, ACT_ODMA);\n+\t/* Disable Rx Zero Len */\n+\trtl_bmu_clr_bits(tp, 0x2300, BIT(3));\n \n-\tif (tp-\u003eversion \u003e= RTL_VER_16) {\n-\t\t/* Disable Rx Zero Len */\n-\t\trtl_bmu_clr_bits(tp, 0x2300, BIT(3));\n-\t\t/* TX descriptor Signature */\n-\t\tocp_byte_clr_bits(tp, MCU_TYPE_USB, 0xd4ae, BIT(1));\n-\t}\n+\t/* TX descriptor Signature */\n+\tocp_byte_clr_bits(tp, MCU_TYPE_USB, 0xd4ae, BIT(1));\n+\n+\t/* Enable u2phy backup restore patch */\n+\tif (tp-\u003eversion == RTL_VER_17_QFN68)\n+\t\tocp_byte_set_bits(tp, MCU_TYPE_USB, 0xb99c, BIT(0));\n+\n+\t/* Enable u3phy patch backup */\n+\tocp_write_word(tp, MCU_TYPE_USB, 0xb9a2, 0x0448);\n \n \tr8156_mdio_force_mode(tp);\n \trtl_tally_reset(tp);\n@@ -8926,8 +9828,16 @@ int rtl8152_get_link_ksettings(struct net_device *netdev,\n \t\t\t cmd-\u003elink_modes.supported, tp-\u003esupport_10000full);\n \n \tif (tp-\u003esupport_2500full || tp-\u003esupport_5000full || tp-\u003esupport_10000full) {\n-\t\tu16 ocp_10gbt_ctrl = ocp_reg_read(tp, OCP_10GBT_CTRL);\n-\t\tu16 ocp_10gbt_stat = ocp_reg_read(tp, OCP_10GBT_STAT);\n+\t\tu16 ocp_10gbt_ctrl;\n+\t\tu16 ocp_10gbt_stat;\n+\n+\t\tret = ocp_reg_read(tp, OCP_10GBT_CTRL, \u0026ocp_10gbt_ctrl);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto out_unlock;\n+\n+\t\tret = ocp_reg_read(tp, OCP_10GBT_STAT, \u0026ocp_10gbt_stat);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto out_unlock;\n \n \t\tif (tp-\u003esupport_2500full) {\n \t\t\tlinkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,\n@@ -8969,12 +9879,13 @@ int rtl8152_get_link_ksettings(struct net_device *netdev,\n \t\t}\n \t}\n \n+out_unlock:\n \tmutex_unlock(\u0026tp-\u003econtrol);\n \n \tusb_autopm_put_interface(tp-\u003eintf);\n \n out:\n-\treturn ret;\n+\treturn ret \u003c 0 ? ret : 0;\n }\n \n static int rtl8152_set_link_ksettings(struct net_device *dev,\n@@ -9155,21 +10066,37 @@ static int r8153_get_eee(struct r8152 *tp, struct ethtool_keee *eee)\n \t__ETHTOOL_DECLARE_LINK_MODE_MASK(common) = {};\n \tu16 speed = rtl8152_get_speed(tp);\n \tu16 val;\n+\tint ret;\n+\n+\tret = ocp_reg_read(tp, OCP_EEE_ABLE, \u0026val);\n+\tif (ret \u003c 0)\n+\t\tgoto out;\n \n-\tval = ocp_reg_read(tp, OCP_EEE_ABLE);\n \tmii_eee_cap1_mod_linkmode_t(eee-\u003esupported, val);\n \n-\tval = ocp_reg_read(tp, OCP_EEE_ADV);\n+\tret = ocp_reg_read(tp, OCP_EEE_ADV, \u0026val);\n+\tif (ret \u003c 0)\n+\t\tgoto out;\n+\n \tmii_eee_cap1_mod_linkmode_t(eee-\u003eadvertised, val);\n \n-\tval = ocp_reg_read(tp, OCP_EEE_LPABLE);\n+\tret = ocp_reg_read(tp, OCP_EEE_LPABLE, \u0026val);\n+\tif (ret \u003c 0)\n+\t\tgoto out;\n+\n \tmii_eee_cap1_mod_linkmode_t(eee-\u003elp_advertised, val);\n \n \tif (tp-\u003esupport_2500full || tp-\u003esupport_5000full) {\n-\t\tval = ocp_reg_read(tp, OCP_EEE_ADV2);\n+\t\tret = ocp_reg_read(tp, OCP_EEE_ADV2, \u0026val);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto out;\n+\n \t\tmii_eee_cap2_mod_linkmode_adv_t(eee-\u003eadvertised, val);\n \n-\t\tval = ocp_reg_read(tp, OCP_EEE_LPABLE2);\n+\t\tret = ocp_reg_read(tp, OCP_EEE_LPABLE2, \u0026val);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto out;\n+\n \t\tmii_eee_cap2_mod_linkmode_adv_t(eee-\u003elp_advertised, val);\n \t}\n \n@@ -9205,7 +10132,8 @@ static int r8153_get_eee(struct r8152 *tp, struct ethtool_keee *eee)\n \tlinkmode_and(common, common, eee-\u003elp_advertised);\n \teee-\u003eeee_active = !linkmode_empty(common);\n \n-\treturn 0;\n+out:\n+\treturn ret \u003c 0 ? ret : 0;\n }\n \n static int\n@@ -9445,7 +10373,7 @@ static int rtl8152_set_ringparam(struct net_device *netdev,\n static void rtl8152_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause)\n {\n \tstruct r8152 *tp = netdev_priv(netdev);\n-\tu16 bmcr, lcladv, rmtadv;\n+\tint bmcr, lcladv, rmtadv;\n \tu8 cap;\n \n \tif (usb_autopm_get_interface(tp-\u003eintf) \u003c 0)\n@@ -9461,7 +10389,10 @@ static void rtl8152_get_pauseparam(struct net_device *netdev, struct ethtool_pau\n \n \tusb_autopm_put_interface(tp-\u003eintf);\n \n-\tif (!(bmcr \u0026 BMCR_ANENABLE)) {\n+\t/* Without a readable PHY, or with autoneg off, there is no flow\n+\t * control to report.\n+\t */\n+\tif (bmcr \u003c 0 || lcladv \u003c 0 || rmtadv \u003c 0 || !(bmcr \u0026 BMCR_ANENABLE)) {\n \t\tpause-\u003eautoneg = 0;\n \t\tpause-\u003erx_pause = 0;\n \t\tpause-\u003etx_pause = 0;\n@@ -9492,7 +10423,11 @@ static int rtl8152_set_pauseparam(struct net_device *netdev, struct ethtool_paus\n \n \tmutex_lock(\u0026tp-\u003econtrol);\n \n-\tif (pause-\u003eautoneg \u0026\u0026 !(r8152_mdio_read(tp, MII_BMCR) \u0026 BMCR_ANENABLE)) {\n+\tret = r8152_mdio_read(tp, MII_BMCR);\n+\tif (ret \u003c 0)\n+\t\tgoto out;\n+\n+\tif (pause-\u003eautoneg \u0026\u0026 !(ret \u0026 BMCR_ANENABLE)) {\n \t\tret = -EINVAL;\n \t\tgoto out;\n \t}\n@@ -9503,16 +10438,20 @@ static int rtl8152_set_pauseparam(struct net_device *netdev, struct ethtool_paus\n \tif (pause-\u003etx_pause)\n \t\tcap |= FLOW_CTRL_TX;\n \n-\told = r8152_mdio_read(tp, MII_ADVERTISE);\n+\tret = r8152_mdio_read(tp, MII_ADVERTISE);\n+\tif (ret \u003c 0)\n+\t\tgoto out;\n+\n+\told = ret;\n \tnew1 = (old \u0026 ~(ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM)) | mii_advertise_flowctrl(cap);\n \tif (old != new1)\n-\t\tr8152_mdio_write(tp, MII_ADVERTISE, new1);\n+\t\tret = r8152_mdio_write(tp, MII_ADVERTISE, new1);\n \n out:\n \tmutex_unlock(\u0026tp-\u003econtrol);\n \tusb_autopm_put_interface(tp-\u003eintf);\n \n-\treturn ret;\n+\treturn ret \u003c 0 ? ret : 0;\n }\n \n static const struct ethtool_ops ops = {\n@@ -9546,7 +10485,7 @@ static int rtl8152_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)\n {\n \tstruct r8152 *tp = netdev_priv(netdev);\n \tstruct mii_ioctl_data *data = if_mii(rq);\n-\tint res;\n+\tint res, val;\n \n \tif (test_bit(RTL8152_INACCESSIBLE, \u0026tp-\u003eflags))\n \t\treturn -ENODEV;\n@@ -9562,7 +10501,11 @@ static int rtl8152_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)\n \n \tcase SIOCGMIIREG:\n \t\tmutex_lock(\u0026tp-\u003econtrol);\n-\t\tdata-\u003eval_out = r8152_mdio_read(tp, data-\u003ereg_num);\n+\t\tval = r8152_mdio_read(tp, data-\u003ereg_num);\n+\t\tif (val \u003c 0)\n+\t\t\tres = val;\n+\t\telse\n+\t\t\tdata-\u003eval_out = val;\n \t\tmutex_unlock(\u0026tp-\u003econtrol);\n \t\tbreak;\n \n@@ -9572,7 +10515,7 @@ static int rtl8152_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)\n \t\t\tbreak;\n \t\t}\n \t\tmutex_lock(\u0026tp-\u003econtrol);\n-\t\tr8152_mdio_write(tp, data-\u003ereg_num, data-\u003eval_in);\n+\t\tres = r8152_mdio_write(tp, data-\u003ereg_num, data-\u003eval_in);\n \t\tmutex_unlock(\u0026tp-\u003econtrol);\n \t\tbreak;\n \n@@ -9663,11 +10606,6 @@ static void rtl8153_unload(struct r8152 *tp)\n \t\treturn;\n \n \tr8153_power_cut_en(tp, false);\n-\n-\tif (tp-\u003eversion \u003e= RTL_VER_16) {\n-\t\t/* Disable Interrupt Mitigation */\n-\t\tocp_byte_clr_bits(tp, MCU_TYPE_USB, 0xcf04, BIT(0) | BIT(1) | BIT(2) | BIT(7));\n-\t}\n }\n \n static void rtl8153b_unload(struct r8152 *tp)\n@@ -9678,6 +10616,16 @@ static void rtl8153b_unload(struct r8152 *tp)\n \tr8153b_power_cut_en(tp, false);\n }\n \n+static void rtl8157_unload(struct r8152 *tp)\n+{\n+\tif (test_bit(RTL8152_INACCESSIBLE, \u0026tp-\u003eflags))\n+\t\treturn;\n+\n+\tr8157_power_cut_en(tp, false);\n+\tocp_byte_clr_bits(tp, MCU_TYPE_USB, 0xcf04,\n+\t\t\t  BIT(0) | BIT(1) | BIT(2) | BIT(7));\n+}\n+\n static int r8152_desc_init(struct r8152 *tp)\n {\n \ttp-\u003erx_desc.size = sizeof(struct rx_desc);\n@@ -9730,6 +10678,8 @@ static int rtl_ops_init(struct r8152 *tp)\n \t\tops-\u003ein_nway\t\t= rtl8152_in_nway;\n \t\tops-\u003ehw_phy_cfg\t\t= r8152b_hw_phy_cfg;\n \t\tops-\u003eautosuspend_en\t= rtl_runtime_suspend_enable;\n+\t\tops-\u003ephy_read\t\t= r8152_phy_read;\n+\t\tops-\u003ephy_write\t\t= r8152_phy_write;\n \t\ttp-\u003erx_buf_sz\t\t= 16 * 1024;\n \t\ttp-\u003eeee_en\t\t= true;\n \t\ttp-\u003eeee_adv\t\t= MDIO_EEE_100TX;\n@@ -9752,6 +10702,8 @@ static int rtl_ops_init(struct r8152 *tp)\n \t\tops-\u003ehw_phy_cfg\t\t= r8153_hw_phy_cfg;\n \t\tops-\u003eautosuspend_en\t= rtl8153_runtime_enable;\n \t\tops-\u003echange_mtu\t\t= rtl8153_change_mtu;\n+\t\tops-\u003ephy_read\t\t= r8152_phy_read;\n+\t\tops-\u003ephy_write\t\t= r8152_phy_write;\n \t\tif (tp-\u003eudev-\u003espeed \u003c USB_SPEED_SUPER)\n \t\t\ttp-\u003erx_buf_sz\t= 16 * 1024;\n \t\telse\n@@ -9775,6 +10727,8 @@ static int rtl_ops_init(struct r8152 *tp)\n \t\tops-\u003ehw_phy_cfg\t\t= r8153b_hw_phy_cfg;\n \t\tops-\u003eautosuspend_en\t= rtl8153b_runtime_enable;\n \t\tops-\u003echange_mtu\t\t= rtl8153_change_mtu;\n+\t\tops-\u003ephy_read\t\t= r8152_phy_read;\n+\t\tops-\u003ephy_write\t\t= r8152_phy_write;\n \t\ttp-\u003erx_buf_sz\t\t= 32 * 1024;\n \t\ttp-\u003eeee_en\t\t= true;\n \t\ttp-\u003eeee_adv\t\t= MDIO_EEE_1000T | MDIO_EEE_100TX;\n@@ -9799,6 +10753,8 @@ static int rtl_ops_init(struct r8152 *tp)\n \t\tops-\u003ehw_phy_cfg\t\t= r8156_hw_phy_cfg;\n \t\tops-\u003eautosuspend_en\t= rtl8156_runtime_enable;\n \t\tops-\u003echange_mtu\t\t= rtl8156_change_mtu;\n+\t\tops-\u003ephy_read\t\t= r8152_phy_read;\n+\t\tops-\u003ephy_write\t\t= r8152_phy_write;\n \t\ttp-\u003erx_buf_sz\t\t= 48 * 1024;\n \t\ttp-\u003esupport_2500full\t= 1;\n \t\tr8152_desc_init(tp);\n@@ -9812,8 +10768,8 @@ static int rtl_ops_init(struct r8152 *tp)\n \t\ttp-\u003eeee_en\t\t= true;\n \t\ttp-\u003eeee_adv\t\t= MDIO_EEE_1000T | MDIO_EEE_100TX;\n \t\ttp-\u003eeee_adv2\t\t= MDIO_EEE_2_5GT;\n-\t\tops-\u003einit\t\t= r8156_init;\n-\t\tops-\u003eenable\t\t= rtl8156_enable;\n+\t\tops-\u003einit\t\t= r8156b_init;\n+\t\tops-\u003eenable\t\t= rtl8156b_enable;\n \t\tops-\u003edisable\t\t= rtl8153_disable;\n \t\tops-\u003eup\t\t\t= rtl8156_up;\n \t\tops-\u003edown\t\t= rtl8156_down;\n@@ -9824,6 +10780,8 @@ static int rtl_ops_init(struct r8152 *tp)\n \t\tops-\u003ehw_phy_cfg\t\t= r8156b_hw_phy_cfg;\n \t\tops-\u003eautosuspend_en\t= rtl8156_runtime_enable;\n \t\tops-\u003echange_mtu\t\t= rtl8156_change_mtu;\n+\t\tops-\u003ephy_read\t\t= r8152_phy_read;\n+\t\tops-\u003ephy_write\t\t= r8152_phy_write;\n \t\ttp-\u003erx_buf_sz\t\t= 48 * 1024;\n \t\tr8152_desc_init(tp);\n \t\tbreak;\n@@ -9841,6 +10799,8 @@ static int rtl_ops_init(struct r8152 *tp)\n \t\tops-\u003ehw_phy_cfg\t\t= r8153c_hw_phy_cfg;\n \t\tops-\u003eautosuspend_en\t= rtl8153c_runtime_enable;\n \t\tops-\u003echange_mtu\t\t= rtl8153c_change_mtu;\n+\t\tops-\u003ephy_read\t\t= r8152_phy_read;\n+\t\tops-\u003ephy_write\t\t= r8152_phy_write;\n \t\ttp-\u003erx_buf_sz\t\t= 32 * 1024;\n \t\ttp-\u003eeee_en\t\t= true;\n \t\ttp-\u003eeee_adv\t\t= MDIO_EEE_1000T | MDIO_EEE_100TX;\n@@ -9851,40 +10811,45 @@ static int rtl_ops_init(struct r8152 *tp)\n \t\ttp-\u003eeee_en\t\t= true;\n \t\ttp-\u003eeee_adv\t\t= MDIO_EEE_1000T | MDIO_EEE_100TX;\n \t\ttp-\u003eeee_adv2\t\t= MDIO_EEE_2_5GT | MDIO_EEE_5GT;\n-\t\tops-\u003einit\t\t= r8156_init;\n-\t\tops-\u003eenable\t\t= rtl8156_enable;\n+\t\tops-\u003einit\t\t= r8157_init;\n+\t\tops-\u003eenable\t\t= rtl8157_enable;\n \t\tops-\u003edisable\t\t= rtl8153_disable;\n-\t\tops-\u003eup\t\t\t= rtl8156_up;\n-\t\tops-\u003edown\t\t= rtl8156_down;\n-\t\tops-\u003eunload\t\t= rtl8153_unload;\n+\t\tops-\u003eup\t\t\t= rtl8157_up;\n+\t\tops-\u003edown\t\t= rtl8157_down;\n+\t\tops-\u003eunload\t\t= rtl8157_unload;\n \t\tops-\u003eeee_get\t\t= r8153_get_eee;\n \t\tops-\u003eeee_set\t\t= r8152_set_eee;\n \t\tops-\u003ein_nway\t\t= rtl8153_in_nway;\n \t\tops-\u003ehw_phy_cfg\t\t= r8157_hw_phy_cfg;\n \t\tops-\u003eautosuspend_en\t= rtl8157_runtime_enable;\n-\t\tops-\u003echange_mtu\t\t= rtl8156_change_mtu;\n+\t\tops-\u003echange_mtu\t\t= rtl8157_change_mtu;\n+\t\tops-\u003ephy_read\t\t= r8157_phy_read;\n+\t\tops-\u003ephy_write\t\t= r8157_phy_write;\n \t\ttp-\u003erx_buf_sz\t\t= 32 * 1024;\n \t\ttp-\u003esupport_2500full\t= 1;\n \t\ttp-\u003esupport_5000full\t= 1;\n \t\tr8157_desc_init(tp);\n \t\tbreak;\n \n-\tcase RTL_VER_17:\n+\tcase RTL_VER_17_QFN68:\n+\tcase RTL_VER_17_QFN100:\n \t\ttp-\u003eeee_en\t\t= true;\n \t\ttp-\u003eeee_adv\t\t= MDIO_EEE_100TX | MDIO_EEE_1000T | MDIO_EEE_10GT;\n \t\ttp-\u003eeee_adv2\t\t= MDIO_EEE_2_5GT | MDIO_EEE_5GT;\n-\t\tops-\u003einit\t\t= r8156_init;\n-\t\tops-\u003eenable\t\t= rtl8156_enable;\n+\t\tops-\u003einit\t\t= r8159_init;\n+\t\tops-\u003eenable\t\t= rtl8157_enable;\n \t\tops-\u003edisable\t\t= rtl8153_disable;\n-\t\tops-\u003eup\t\t\t= rtl8156_up;\n-\t\tops-\u003edown\t\t= rtl8156_down;\n-\t\tops-\u003eunload\t\t= rtl8153_unload;\n+\t\tops-\u003eup\t\t\t= rtl8157_up;\n+\t\tops-\u003edown\t\t= rtl8157_down;\n+\t\tops-\u003eunload\t\t= rtl8157_unload;\n \t\tops-\u003eeee_get\t\t= r8153_get_eee;\n \t\tops-\u003eeee_set\t\t= r8152_set_eee;\n \t\tops-\u003ein_nway\t\t= rtl8153_in_nway;\n-\t\tops-\u003ehw_phy_cfg\t\t= r8157_hw_phy_cfg;\n+\t\tops-\u003ehw_phy_cfg\t\t= r8159_hw_phy_cfg;\n \t\tops-\u003eautosuspend_en\t= rtl8157_runtime_enable;\n-\t\tops-\u003echange_mtu\t\t= rtl8156_change_mtu;\n+\t\tops-\u003echange_mtu\t\t= rtl8157_change_mtu;\n+\t\tops-\u003ephy_read\t\t= r8157_phy_read;\n+\t\tops-\u003ephy_write\t\t= r8157_phy_write;\n \t\ttp-\u003erx_buf_sz\t\t= 48 * 1024;\n \t\ttp-\u003esupport_2500full\t= 1;\n \t\ttp-\u003esupport_5000full\t= 1;\n@@ -9961,7 +10926,8 @@ static int rtl_fw_init(struct r8152 *tp)\n \tcase RTL_VER_16:\n \t\trtl_fw-\u003efw_name\t\t= FIRMWARE_8157_1;\n \t\tbreak;\n-\tcase RTL_VER_17:\n+\tcase RTL_VER_17_QFN68:\n+\tcase RTL_VER_17_QFN100:\n \t\trtl_fw-\u003efw_name\t\t= FIRMWARE_8159_1;\n \t\tbreak;\n \tdefault:\n@@ -9971,9 +10937,38 @@ static int rtl_fw_init(struct r8152 *tp)\n \treturn 0;\n }\n \n+static u32 __rtl_get_pkg_det(struct usb_device *udev)\n+{\n+\tu32 pkg_det = 0;\n+\t__le32 *tmp;\n+\tint ret, i;\n+\n+\ttmp = kmalloc_obj(*tmp);\n+\tif (!tmp)\n+\t\treturn 0;\n+\n+\tfor (i = 0, ret = 0; i \u003c 3 \u0026\u0026 ret != 4; i++)\n+\t\tret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),\n+\t\t\t\t      RTL8152_REQ_GET_REGS, RTL8152_REQT_READ,\n+\t\t\t\t      PLA_PKG_DET, MCU_TYPE_PLA, tmp,\n+\t\t\t\t      sizeof(*tmp), USB_CTRL_GET_TIMEOUT);\n+\n+\tif (ret == sizeof(*tmp)) {\n+\t\tif (i != 1)\n+\t\t\tdev_warn(\u0026udev-\u003edev,\n+\t\t\t\t \"Needed %d retries to read package\\n\", i);\n+\n+\t\tpkg_det = __le32_to_cpu(*tmp) \u0026 PKG_MASK;\n+\t}\n+\n+\tkfree(tmp);\n+\treturn pkg_det;\n+}\n+\n static u8 __rtl_get_hw_ver(struct usb_device *udev)\n {\n \tu32 ocp_data = 0;\n+\tu32 pkg_det = 0;\n \t__le32 *tmp;\n \tu8 version;\n \tint ret;\n@@ -10056,7 +11051,16 @@ static u8 __rtl_get_hw_ver(struct usb_device *udev)\n \t\tversion = RTL_VER_16;\n \t\tbreak;\n \tcase 0x2020:\n-\t\tversion = RTL_VER_17;\n+\t\tpkg_det = __rtl_get_pkg_det(udev);\n+\t\tif (pkg_det == 0x1e || pkg_det == 0x1c) {\n+\t\t\tversion = RTL_VER_17_QFN68;\n+\t\t} else if (pkg_det == 0x18 || pkg_det == 0x1a) {\n+\t\t\tversion = RTL_VER_17_QFN100;\n+\t\t} else {\n+\t\t\tversion = RTL_VER_UNKNOWN;\n+\t\t\tdev_info(\u0026udev-\u003edev, \"Unknown package 0x%04x\\n\",\n+\t\t\t\t pkg_det);\n+\t\t}\n \t\tbreak;\n \tdefault:\n \t\tversion = RTL_VER_UNKNOWN;\n@@ -10215,7 +11219,8 @@ static int rtl8152_probe_once(struct usb_interface *intf,\n \tcase RTL_VER_13:\n \tcase RTL_VER_15:\n \tcase RTL_VER_16:\n-\tcase RTL_VER_17:\n+\tcase RTL_VER_17_QFN68:\n+\tcase RTL_VER_17_QFN100:\n \t\tnetdev-\u003emax_mtu = size_to_mtu(16 * 1024);\n \t\tbreak;\n \tcase RTL_VER_01:\n"
}

2/1 2026/10/08 11:04 agent patch-evaluator
2m Model:
core

Args:
null

Results:
{
  "EnableConfigs": [
    "USB_RTL8152",
    "USB_NET_DRIVERS"
  ],
  "FocusSymbols": [
    "r8159_hw_phy_cfg",
    "r8157_hw_phy_cfg",
    "r8159_init",
    "r8157_init",
    "r8156b_init",
    "rtl8157_enable",
    "rtl8156b_enable",
    "rtl8157_up",
    "rtl8157_down",
    "rtl8157_change_mtu",
    "rtl_fc_pause_pkt_en",
    "rtl_tgphy_access",
    "r8157_ups_en",
    "__rtl_get_pkg_det"
  ],
  "Reasoning": "The patch adds support for newer Realtek RTL8157 and RTL8159 USB Ethernet controllers (splitting RTL_VER_17 into QFN68 and QFN100 variants), refactors PHY/SRAM read and write helpers to propagate errors, refactors polling loops, implements flow control pause packet limiting, and introduces new device initialization and PHY configuration logic. In addition, it adds a new assertion (WARN_ON_ONCE) in r8159_hw_phy_cfg(). The driver is fully reachable and fuzzable via USB emulation (such as Raw Gadget or dummy_hcd) and subsequent network device interface configuration and ethtool/ioctl operations.",
  "WorthFuzzing": true
}

Instruction:
You are an expert Linux kernel maintainer and security engineer.
Your job is to review a provided patch series and evaluate whether it warrants fuzzing with syzkaller.

IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in
your workspace. Do NOT rely on internal assumptions. You must actively use your code access
tools to inspect the actual source code, callers, and surrounding context.

================================================================================
1. CORE TRIAGE PHILOSOPHY
================================================================================
The goal of patch fuzzing is to discover crashes, regressions, exposed latent bugs,
and newly triggered assertions introduced by the patch series.

- REACHABILITY IS THE PRIMARY GATE:
  Fuzzing can only discover bugs in code that can actually execute in standard virtualized
  environments (GCE or QEMU, utilizing software-emulated devices like USB gadgets, netdev, tun/tap).
  If the modified code is structurally unreachable (see Section 2), it MUST NOT be fuzzed,
  regardless of whether it adds assertions or complex logic.

- DO NOT BLINDLY TRUST "NO FUNCTIONAL CHANGE" (NFCI) OR "REFACTORING" CLAIMS:
  Patch authors routinely label changes as "cleanups", "refactorings", or state
  "No functional change intended". Do NOT take these claims at face value.
  Code refactorings that rearrange logic, introduce helper functions, or alter state management
  in core subsystems frequently introduce subtle semantic shifts or uncover latent kernel bugs.
  If reachable executable code is modified or refactored, it MUST be fuzzed.

- NEW OR MODIFIED ASSERTIONS IN REACHABLE CODE MUST BE FUZZED:
  When a patch introduces or modifies runtime checks or assertions (e.g., WARN_ON*, VM_WARN_ON*,
  BUG_ON*, lockdep_assert*) in reachable code paths, it enforces new or stricter invariants.
  Even if the author believes the invariant always holds, fuzzing is essential to verify whether
  an unusual sequence of operations can violate it.

================================================================================
2. WHEN TO RETURN WorthFuzzing=false (NEGATIVE CRITERIA)
================================================================================
Return WorthFuzzing=false ONLY IF all modified code falls strictly into one or more of these categories:

- Non-kernel and non-executable changes:
  * Modifications to Documentation/, comments, or spelling fixes.
  * User-space directories, self-tests, samples, or scripts (e.g., tools/, samples/, scripts/, usr/)
    that do not affect the compiled kernel image (vmlinux) or kernel modules.
  * Purely decorative logging (e.g., message strings in pr_err, printk, dev_info) or tracepoints
    that do not alter control flow or data structures.
  * Build system or Kconfig changes that do not alter compiled C logic.
- Structurally unreachable hardware:
  * Vendor-specific PCIe switches, SmartNICs, or GPU drivers (e.g., mlxsw, pds_core, qed,
    ionic, amdgpu) requiring physical ASIC/PCIe cards not emulated in standard QEMU.
- Unreachable execution paths:
  * Driver teardown callbacks (.remove, .shutdown, pci_unregister_driver) executed only during
    physical PCI hot-unplug or manual sysfs driver unbinding.
  * Code paths exclusive to architectures other than the target architecture.

================================================================================
3. WHEN TO RETURN WorthFuzzing=true (POSITIVE CRITERIA)
================================================================================
Return WorthFuzzing=true whenever the patch touches reachable executable code, including:
- Core Subsystems:
  * Any logic modifications in memory management (mm/), synchronization/locking (kernel/locking/),
    BPF, scheduler, core networking, VFS, or syscall handling.
- Refactorings and Code Cleanups:
  * Any restructuring of reachable data structures, helper abstractions, or algorithm flows.
- Runtime Assertions and Defensive Checks:
  * Any introduction or alteration of assertions (WARN_ON*, VM_WARN_ON*, BUG_ON*, etc.) in reachable paths.
- Reachable Drivers and Protocols:
  * Drivers accessible via virtual buses (virtio, USB gadget, loopback, netlink, binder, sockets, etc.).

================================================================================
4. EXTRACTING FocusSymbols (PREVENTING DILUTION)
================================================================================
When WorthFuzzing=true, you must extract specific kernel functions into FocusSymbols to guide the fuzzer:

- AVOID UBIQUITOUS LIFECYCLE HOT-PATHS:
  Do NOT list generic, ubiquitous functions called by almost every program in the corpus
  (including, but not limited to: general memory allocators and deallocators, page fault
  and trap handlers, or core synchronization primitives; this is not an exhaustive list).
  Listing ubiquitous functions causes the fuzzer to classify thousands of unrelated tests as "focused",
  which severely dilutes fuzzing effort away from the actual changes.

- TARGET SPECIFIC FEATURE LOGIC AND ENTRYPOINTS:
  List functions that specifically implement the logic being added or altered, or direct API entrypoints
  for the subsystem feature under review.

- HANDLING STATIC INLINE FUNCTIONS IN HEADERS (.h):
  Compiler-inlined static functions (such as static inlines in mm/*.h or include/linux/*.h) lack
  distinct symbol addresses in vmlinux and cannot be targeted directly by symbol coverage filters.
  If the changes are primarily in static inline helpers, identify non-static, feature-specific caller
  functions in .c files that exercise them (avoiding ubiquitous lifecycle wrappers).

================================================================================
5. IDENTIFYING EnableConfigs
================================================================================
Identify any specific CONFIG_ options required to properly compile and reach the modified code:
- Inspect Kconfig files and #ifdef guards; do not make assumptions.
- Check "depends on" lines in Kconfig to include any non-standard parent subsystem configs needed.
- Strip any 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4").
Prefer calling several tools at the same time to save round-trips.


Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.

Prompt:
Target architecture: amd64

For your convenience, here is the diff of the changes:
commit 7c46fb3d692dd4fe361e4ece17399e3895e2c8a6
Author: syz-cluster <triage@syzkaller.com>
Date:   Thu Oct 8 11:04:01 2026 +0000

    syz-cluster: applied patch under review

diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index af3d7dcb2f141..fc75e263b0e4c 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -64,6 +64,7 @@
 #define PLA_MACDBG_POST		0xd38e	/* RTL_VER_04 only */
 #define PLA_EXTRA_STATUS	0xd398
 #define PLA_GPHY_CTRL		0xd3ae
+#define PLA_PKG_DET		0xdc48
 #define PLA_POL_GPIO_CTRL	0xdc6a
 #define PLA_EFUSE_DATA		0xdd00
 #define PLA_EFUSE_CMD		0xdd02
@@ -78,6 +79,7 @@
 #define PLA_EEE_TXTWSYS_2P5G	0xe058
 #define PLA_EEEP_CR		0xe080
 #define PLA_MAC_PWR_CTRL	0xe0c0
+#define PLA_RMT_WAKE		0xe0c8
 #define PLA_MAC_PWR_CTRL2	0xe0ca
 #define PLA_MAC_PWR_CTRL3	0xe0cc
 #define PLA_MAC_PWR_CTRL4	0xe0ce
@@ -87,6 +89,7 @@
 #define PLA_MTPS		0xe615
 #define PLA_TXFIFO_CTRL		0xe618
 #define PLA_TXFIFO_FULL		0xe61a
+#define PLA_PAUSE_LIMIT         0xe61e
 #define PLA_RSTTALLY		0xe800
 #define PLA_CR			0xe813
 #define PLA_CRWECR		0xe81c
@@ -129,6 +132,7 @@
 #define USB_BURST_SIZE		0xcfc0
 #define USB_FW_FIX_EN0		0xcfca
 #define USB_FW_FIX_EN1		0xcfcc
+#define USB_FW_USB_VER          0xcfd7
 #define USB_LPM_CONFIG		0xcfd8
 #define USB_ECM_OPTION		0xcfee
 #define USB_CSTMR		0xcfef	/* RTL8153A */
@@ -160,6 +164,9 @@
 #define USB_ADV_ADDR		0xd5d6
 #define USB_ADV_DATA		0xd5d8
 #define USB_ADV_CMD		0xd5dc
+#define USB_TGPHY_ADDR		0xd630
+#define USB_TGPHY_DATA		0xd632
+#define USB_TGPHY_CMD		0xd634
 #define USB_UPS_CTRL		0xd800
 #define USB_POWER_CUT		0xd80a
 #define USB_MISC_0		0xd81a
@@ -289,10 +296,17 @@
 #define IFG_144NS		BIT(9)
 #define IFG_96NS		(BIT(9) | BIT(8))
 
+/* PLA_PKG_DET */
+#define PKG_MASK		0x1e
+
 /* PLA_MTPS */
 #define MTPS_JUMBO		(12 * 1024 / 64)
 #define MTPS_DEFAULT		(6 * 1024 / 64)
 
+/* PLA_PAUSE_LIMIT */
+#define PAUSE_LIMIT_EN		BIT(3)
+#define PAUSE_LIMIT_MASK	0xf0
+
 /* PLA_RSTTALLY */
 #define TALLY_RESET		0x0001
 
@@ -371,6 +385,9 @@
 #define MCU_CLK_RATIO_MASK	0x0f0f0f0f
 #define ALDPS_SPDWN_RATIO	0x0f87
 
+/* PLA_RMT_WAKE */
+#define RMT_WAKE_EN		BIT(0)
+
 /* PLA_MAC_PWR_CTRL2 */
 #define EEE_SPDWN_RATIO		0x8007
 #define MAC_CLK_SPDWN_EN	BIT(15)
@@ -417,6 +434,7 @@
 
 /* PLA_INDICATE_FALG */
 #define UPCOMING_RUNTIME_D3	BIT(0)
+#define PREBOOT_OPTION		BIT(1)
 
 /* PLA_MACDBG_PRE and PLA_MACDBG_POST */
 #define DEBUG_OE		BIT(0)
@@ -502,6 +520,10 @@
 #define ADV_CMD_WR		BIT(1)
 #define ADV_CMD_IP		BIT(2)
 
+/* USB_TGPHY_CMD */
+#define TGPHY_CMD_BUSY		BIT(0)
+#define TGPHY_CMD_WR		BIT(1)
+
 /* USB_UPS_CTRL */
 #define POWER_CUT		0x0100
 
@@ -542,6 +564,7 @@
 #define RX_AGG_DISABLE		0x0010
 #define RX_ZERO_EN		0x0080
 #define RX_DESC_16B		0x0400
+#define RX_END_TRANSFER_EN	BIT(11)
 
 /* USB_U2P3_CTRL */
 #define U2P3_ENABLE		0x0001
@@ -597,6 +620,11 @@
 #define UPS_FLAGS_250M_CKDIV		BIT(2)
 #define UPS_FLAGS_EN_ALDPS		BIT(3)
 #define UPS_FLAGS_CTAP_SHORT_DIS	BIT(4)
+#define UPS_FLAGS_EN_100M_EEE		BIT(9)
+#define UPS_FLAGS_EN_1000M_EEE		BIT(10)
+#define UPS_FLAGS_EN_2500M_EEE		BIT(11)
+#define UPS_FLAGS_EN_5000M_EEE		BIT(12)
+#define UPS_FLAGS_EN_10G_EEE		BIT(13)
 #define UPS_FLAGS_SPEED_MASK		(0xf << 16)
 #define ups_flags_speed(x)		((x) << 16)
 #define UPS_FLAGS_EN_EEE		BIT(20)
@@ -645,6 +673,7 @@ enum spd_duplex {
 /* OCP_POWER_CFG */
 #define EEE_CLKDIV_EN		0x8000
 #define EN_ALDPS		0x0004
+#define EN_ALDPS_PLLOFF         0x0002
 #define EN_10M_PLLOFF		0x0001
 
 /* OCP_EEE_CONFIG1 */
@@ -948,6 +977,8 @@ struct r8152 {
 		void (*hw_phy_cfg)(struct r8152 *tp);
 		void (*autosuspend_en)(struct r8152 *tp, bool enable);
 		void (*change_mtu)(struct r8152 *tp);
+		int (*phy_read)(struct r8152 *tp, u16 addr, u16 *data);
+		int (*phy_write)(struct r8152 *tp, u16 addr, u16 data);
 	} rtl_ops;
 
 	struct ups_info {
@@ -1247,7 +1278,8 @@ enum rtl_version {
 	RTL_VER_14,
 	RTL_VER_15,
 	RTL_VER_16,
-	RTL_VER_17,
+	RTL_VER_17_QFN68,
+	RTL_VER_17_QFN100,
 
 	RTL_VER_MAX
 };
@@ -1626,7 +1658,7 @@ static void ocp_write_byte(struct r8152 *tp, u16 type, u16 index, u32 data)
 	generic_ocp_write(tp, index, byen, sizeof(tmp), &tmp, type);
 }
 
-static u16 ocp_reg_read(struct r8152 *tp, u16 addr)
+static int r8152_phy_read(struct r8152 *tp, u16 addr, u16 *data)
 {
 	u16 ocp_base, ocp_index;
 
@@ -1637,10 +1669,12 @@ static u16 ocp_reg_read(struct r8152 *tp, u16 addr)
 	}
 
 	ocp_index = (addr & 0x0fff) | 0xb000;
-	return ocp_read_word(tp, MCU_TYPE_PLA, ocp_index);
+	*data = ocp_read_word(tp, MCU_TYPE_PLA, ocp_index);
+
+	return 0;
 }
 
-static void ocp_reg_write(struct r8152 *tp, u16 addr, u16 data)
+static int r8152_phy_write(struct r8152 *tp, u16 addr, u16 data)
 {
 	u16 ocp_base, ocp_index;
 
@@ -1652,16 +1686,33 @@ static void ocp_reg_write(struct r8152 *tp, u16 addr, u16 data)
 
 	ocp_index = (addr & 0x0fff) | 0xb000;
 	ocp_write_word(tp, MCU_TYPE_PLA, ocp_index, data);
+
+	return 0;
 }
 
-static inline void r8152_mdio_write(struct r8152 *tp, u32 reg_addr, u32 value)
+static int ocp_reg_read(struct r8152 *tp, u16 addr, u16 *data)
 {
-	ocp_reg_write(tp, OCP_BASE_MII + reg_addr * 2, value);
+	return tp->rtl_ops.phy_read(tp, addr, data);
 }
 
-static inline int r8152_mdio_read(struct r8152 *tp, u32 reg_addr)
+static int ocp_reg_write(struct r8152 *tp, u16 addr, u16 data)
 {
-	return ocp_reg_read(tp, OCP_BASE_MII + reg_addr * 2);
+	return tp->rtl_ops.phy_write(tp, addr, data);
+}
+
+static inline int r8152_mdio_write(struct r8152 *tp, u32 reg_addr, u32 value)
+{
+	return ocp_reg_write(tp, OCP_BASE_MII + reg_addr * 2, value);
+}
+
+static int r8152_mdio_read(struct r8152 *tp, u32 reg_addr)
+{
+	u16 data;
+	int ret;
+
+	ret = ocp_reg_read(tp, OCP_BASE_MII + reg_addr * 2, &data);
+
+	return ret < 0 ? ret : data;
 }
 
 static int wait_cmd_ready(struct r8152 *tp, u16 cmd)
@@ -1780,16 +1831,32 @@ static int rtl_ip_set_bits(struct r8152 *tp, u16 addr, u32 set)
 	return rtl_ip_w0w1(tp, addr, 0, set);
 }
 
-static void sram_write(struct r8152 *tp, u16 addr, u16 data)
+static int sram_write(struct r8152 *tp, u16 addr, u16 data)
 {
-	ocp_reg_write(tp, OCP_SRAM_ADDR, addr);
-	ocp_reg_write(tp, OCP_SRAM_DATA, data);
+	int ret;
+
+	ret = ocp_reg_write(tp, OCP_SRAM_ADDR, addr);
+	if (ret < 0)
+		goto out;
+
+	ret = ocp_reg_write(tp, OCP_SRAM_DATA, data);
+
+out:
+	return ret;
 }
 
-static u16 sram_read(struct r8152 *tp, u16 addr)
+static int sram_read(struct r8152 *tp, u16 addr, u16 *data)
 {
-	ocp_reg_write(tp, OCP_SRAM_ADDR, addr);
-	return ocp_reg_read(tp, OCP_SRAM_DATA);
+	int ret;
+
+	ret = ocp_reg_write(tp, OCP_SRAM_ADDR, addr);
+	if (ret < 0)
+		goto out;
+
+	ret = ocp_reg_read(tp, OCP_SRAM_DATA, data);
+
+out:
+	return ret;
 }
 
 static int read_mii_word(struct net_device *netdev, int phy_id, int reg)
@@ -1894,90 +1961,217 @@ static void ocp_byte_set_bits(struct r8152 *tp, u16 type, u16 index, u8 set)
 	ocp_byte_w0w1(tp, type, index, 0, set);
 }
 
-static void ocp_reg_w0w1(struct r8152 *tp, u16 addr, u16 clear, u16 set)
+static int ocp_reg_w0w1(struct r8152 *tp, u16 addr, u16 clear, u16 set)
 {
 	u16 data;
+	int ret;
+
+	ret = ocp_reg_read(tp, addr, &data);
+	if (ret < 0)
+		goto out;
 
-	data = ocp_reg_read(tp, addr);
 	data = (data & ~clear) | set;
-	ocp_reg_write(tp, addr, data);
+	ret = ocp_reg_write(tp, addr, data);
+
+out:
+	return ret;
 }
 
-static void ocp_reg_clr_bits(struct r8152 *tp, u16 addr, u16 clear)
+static int ocp_reg_clr_bits(struct r8152 *tp, u16 addr, u16 clear)
 {
-	ocp_reg_w0w1(tp, addr, clear, 0);
+	return ocp_reg_w0w1(tp, addr, clear, 0);
 }
 
-static void ocp_reg_set_bits(struct r8152 *tp, u16 addr, u16 set)
+static int ocp_reg_set_bits(struct r8152 *tp, u16 addr, u16 set)
 {
-	ocp_reg_w0w1(tp, addr, 0, set);
+	return ocp_reg_w0w1(tp, addr, 0, set);
 }
 
-static void sram_write_w0w1(struct r8152 *tp, u16 addr, u16 clear, u16 set)
+static int sram_write_w0w1(struct r8152 *tp, u16 addr, u16 clear, u16 set)
 {
 	u16 data;
+	int ret;
+
+	ret = sram_read(tp, addr, &data);
+	if (ret < 0)
+		goto out;
 
-	data = sram_read(tp, addr);
 	data = (data & ~clear) | set;
-	ocp_reg_write(tp, OCP_SRAM_DATA, data);
+	ret = ocp_reg_write(tp, OCP_SRAM_DATA, data);
+
+out:
+	return ret;
 }
 
-static void sram_clr_bits(struct r8152 *tp, u16 addr, u16 clear)
+static int sram_clr_bits(struct r8152 *tp, u16 addr, u16 clear)
 {
-	sram_write_w0w1(tp, addr, clear, 0);
+	return sram_write_w0w1(tp, addr, clear, 0);
 }
 
-static void sram_set_bits(struct r8152 *tp, u16 addr, u16 set)
+static int sram_set_bits(struct r8152 *tp, u16 addr, u16 set)
 {
-	sram_write_w0w1(tp, addr, 0, set);
+	return sram_write_w0w1(tp, addr, 0, set);
 }
 
-static void sram2_write(struct r8152 *tp, u16 addr, u16 data)
+static int sram2_write(struct r8152 *tp, u16 addr, u16 data)
 {
-	ocp_reg_write(tp, OCP_SRAM2_ADDR, addr);
-	ocp_reg_write(tp, OCP_SRAM2_DATA, data);
+	int ret;
+
+	ret = ocp_reg_write(tp, OCP_SRAM2_ADDR, addr);
+	if (ret < 0)
+		goto out;
+
+	ret = ocp_reg_write(tp, OCP_SRAM2_DATA, data);
+
+out:
+	return ret;
 }
 
-static u16 sram2_read(struct r8152 *tp, u16 addr)
+static int sram2_read(struct r8152 *tp, u16 addr, u16 *data)
 {
-	ocp_reg_write(tp, OCP_SRAM2_ADDR, addr);
-	return ocp_reg_read(tp, OCP_SRAM2_DATA);
+	int ret;
+
+	ret = ocp_reg_write(tp, OCP_SRAM2_ADDR, addr);
+	if (ret < 0)
+		goto out;
+
+	ret = ocp_reg_read(tp, OCP_SRAM2_DATA, data);
+
+out:
+	return ret;
 }
 
-static void sram2_write_w0w1(struct r8152 *tp, u16 addr, u16 clear, u16 set)
+static int sram2_write_w0w1(struct r8152 *tp, u16 addr, u16 clear, u16 set)
 {
 	u16 data;
+	int ret;
+
+	ret = sram2_read(tp, addr, &data);
+	if (ret < 0)
+		goto out;
 
-	data = sram2_read(tp, addr);
 	data = (data & ~clear) | set;
-	ocp_reg_write(tp, OCP_SRAM2_DATA, data);
+	ret = ocp_reg_write(tp, OCP_SRAM2_DATA, data);
+
+out:
+	return ret;
 }
 
-static void r8152_mdio_clr_bit(struct r8152 *tp, u16 addr, u16 clear)
+static int sram2_set_bits(struct r8152 *tp, u16 addr, u16 set)
+{
+	return sram2_write_w0w1(tp, addr, 0, set);
+}
+
+static int sram2_clr_bits(struct r8152 *tp, u16 addr, u16 clear)
+{
+	return sram2_write_w0w1(tp, addr, clear, 0);
+}
+
+static int r8152_mdio_clr_bit(struct r8152 *tp, u16 addr, u16 clear)
 {
 	int data;
 
 	data = r8152_mdio_read(tp, addr);
-	r8152_mdio_write(tp, addr, data & ~clear);
+	if (data < 0)
+		goto out;
+
+	data = r8152_mdio_write(tp, addr, data & ~clear);
+
+out:
+	return data;
 }
 
-static void r8152_mdio_set_bit(struct r8152 *tp, u16 addr, u16 set)
+static int r8152_mdio_set_bit(struct r8152 *tp, u16 addr, u16 set)
 {
 	int data;
 
 	data = r8152_mdio_read(tp, addr);
-	r8152_mdio_write(tp, addr, data | set);
+	if (data < 0)
+		goto out;
+
+	data = r8152_mdio_write(tp, addr, data | set);
+
+out:
+	return data;
 }
 
 static int r8152_mdio_test_and_clr_bit(struct r8152 *tp, u16 addr, u16 clear)
 {
-	int data;
+	int data, ret;
 
-	data = r8152_mdio_read(tp, addr);
-	if (data & clear)
-		r8152_mdio_write(tp, addr, data & ~clear);
+	ret = r8152_mdio_read(tp, addr);
+	if (ret < 0)
+		goto out;
+
+	data = ret;
+	if (data & clear) {
+		ret = r8152_mdio_write(tp, addr, data & ~clear);
+		if (ret < 0)
+			goto out;
+	}
+
+	ret = !!(data & clear);
+
+out:
+	return ret;
+}
+
+static int wait_tgphy_cmd_ready(struct r8152 *tp)
+{
+	u16 ocp_data;
+	int ret;
+
+	ret = read_poll_timeout(ocp_read_word, ocp_data,
+				test_bit(RTL8152_INACCESSIBLE, &tp->flags) ||
+				!(ocp_data & TGPHY_CMD_BUSY),
+				2000, 20000, false, tp,
+				MCU_TYPE_USB, USB_TGPHY_CMD);
+
+	if (ret)
+		dev_err(&tp->intf->dev, "TGPHY cmd busy timeout\n");
+
+	return test_bit(RTL8152_INACCESSIBLE, &tp->flags) ? -ENODEV : ret;
+}
+
+static int rtl_tgphy_access(struct r8152 *tp, u16 addr, u16 *data, bool write)
+{
+	u16 cmd = 0;
+	int ret;
+
+	ret = wait_tgphy_cmd_ready(tp);
+	if (ret < 0)
+		goto out;
+
+	if (write) {
+		cmd |= TGPHY_CMD_WR;
+		ocp_write_word(tp, MCU_TYPE_USB, USB_TGPHY_DATA, *data);
+	}
+
+	ocp_write_word(tp, MCU_TYPE_USB, USB_TGPHY_ADDR, addr);
+
+	cmd |= TGPHY_CMD_BUSY;
+	ocp_write_word(tp, MCU_TYPE_USB, USB_TGPHY_CMD, cmd);
+
+	if (!write) {
+		ret = wait_tgphy_cmd_ready(tp);
+		if (ret < 0)
+			goto out;
+
+		*data = ocp_read_word(tp, MCU_TYPE_USB, USB_TGPHY_DATA);
+	}
+
+out:
+	return ret;
+}
+
+static int r8157_phy_read(struct r8152 *tp, u16 addr, u16 *data)
+{
+	return rtl_tgphy_access(tp, addr, data, false);
+}
 
-	return data & clear;
+static int r8157_phy_write(struct r8152 *tp, u16 addr, u16 data)
+{
+	return rtl_tgphy_access(tp, addr, &data, true);
 }
 
 static int
@@ -3412,7 +3606,8 @@ static void rtl8152_nic_reset(struct r8152 *tp)
 		break;
 
 	case RTL_VER_16:
-	case RTL_VER_17:
+	case RTL_VER_17_QFN68:
+	case RTL_VER_17_QFN100:
 		ocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_CR, CR_RE | CR_TE);
 		break;
 
@@ -3452,7 +3647,7 @@ static void rtl_eee_plus_en(struct r8152 *tp, bool enable)
 
 static void rtl_set_eee_plus(struct r8152 *tp)
 {
-	if (tp->version == RTL_VER_17)
+	if (tp->version == RTL_VER_17_QFN68 || tp->version == RTL_VER_17_QFN100)
 		return rtl_eee_plus_en(tp, false);
 
 	if (rtl8152_get_speed(tp) & _10bps)
@@ -3640,7 +3835,8 @@ static void r8153_set_rx_early_timeout(struct r8152 *tp)
 	case RTL_VER_13:
 	case RTL_VER_15:
 	case RTL_VER_16:
-	case RTL_VER_17:
+	case RTL_VER_17_QFN68:
+	case RTL_VER_17_QFN100:
 		ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EARLY_TIMEOUT,
 			       640 / 8);
 		ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EXTRA_AGGR_TMR,
@@ -3685,7 +3881,8 @@ static void r8153_set_rx_early_size(struct r8152 *tp)
 			       ocp_data / 8);
 		break;
 	case RTL_VER_16:
-	case RTL_VER_17:
+	case RTL_VER_17_QFN68:
+	case RTL_VER_17_QFN100:
 		ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EARLY_SIZE,
 			       ocp_data / 16);
 		break;
@@ -3801,6 +3998,8 @@ static void rtl_rx_vlan_en(struct r8152 *tp, bool enable)
 	case RTL_VER_13:
 	case RTL_VER_15:
 	case RTL_VER_16:
+	case RTL_VER_17_QFN68:
+	case RTL_VER_17_QFN100:
 	default:
 		if (enable)
 			ocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_RCR1,
@@ -4051,8 +4250,27 @@ static void r8156_ups_flags(struct r8152 *tp)
 	if (tp->ups_info.aldps)
 		ups_flags |= UPS_FLAGS_EN_ALDPS;
 
-	if (tp->ups_info.eee)
-		ups_flags |= UPS_FLAGS_EN_EEE;
+	if (tp->ups_info.eee) {
+		switch (tp->version) {
+		case RTL_VER_17_QFN68:
+			if (tp->eee_adv & MDIO_EEE_10GT)
+				ups_flags |= UPS_FLAGS_EN_10G_EEE;
+			fallthrough;
+		case RTL_VER_16:
+			if (tp->eee_adv & MDIO_EEE_100TX)
+				ups_flags |= UPS_FLAGS_EN_100M_EEE;
+			if (tp->eee_adv & MDIO_EEE_1000T)
+				ups_flags |= UPS_FLAGS_EN_1000M_EEE;
+			if (tp->eee_adv2 & MDIO_EEE_2_5GT)
+				ups_flags |= UPS_FLAGS_EN_2500M_EEE;
+			if (tp->eee_adv2 & MDIO_EEE_5GT)
+				ups_flags |= UPS_FLAGS_EN_5000M_EEE;
+			break;
+		default:
+			ups_flags |= UPS_FLAGS_EN_EEE;
+			break;
+		}
+	}
 
 	if (tp->ups_info.flow_control)
 		ups_flags |= UPS_FLAGS_EN_FLOW_CTR;
@@ -4103,20 +4321,33 @@ static void r8156_ups_flags(struct r8152 *tp)
 	case NWAY_2500M_FULL:
 		ups_flags |= ups_flags_speed(9);
 		break;
+	case NWAY_5000M_FULL:
+		ups_flags |= ups_flags_speed(10);
+		break;
+	case NWAY_10000M_FULL:
+		ups_flags |= ups_flags_speed(11);
+		break;
 	default:
 		break;
 	}
 
-	switch (tp->ups_info.lite_mode) {
-	case 1:
-		ups_flags |= 0 << 5;
-		break;
-	case 2:
-		ups_flags |= 2 << 5;
+	switch (tp->version) {
+	case RTL_VER_16:
+	case RTL_VER_17_QFN68:
 		break;
-	case 0:
 	default:
-		ups_flags |= 1 << 5;
+		switch (tp->ups_info.lite_mode) {
+		case 1:
+			ups_flags |= 0 << 5;
+			break;
+		case 2:
+			ups_flags |= 2 << 5;
+			break;
+		case 0:
+		default:
+			ups_flags |= 1 << 5;
+			break;
+		}
 		break;
 	}
 
@@ -4150,11 +4381,13 @@ static void r8153b_green_en(struct r8152 *tp, bool enable)
 
 static u16 r8153_phy_status(struct r8152 *tp, u16 desired)
 {
-	u16 data;
+	u16 data = 0;
 	int i;
 
 	for (i = 0; i < 500; i++) {
-		data = ocp_reg_read(tp, OCP_PHY_STATUS);
+		if (ocp_reg_read(tp, OCP_PHY_STATUS, &data) < 0)
+			break;
+
 		data &= PHY_STAT_MASK;
 		if (desired) {
 			if (data == desired)
@@ -4172,6 +4405,23 @@ static u16 r8153_phy_status(struct r8152 *tp, u16 desired)
 	return data;
 }
 
+static int wait_autoload_done(struct r8152 *tp)
+{
+	u16 ocp_data;
+	int ret;
+
+	ret = read_poll_timeout(ocp_read_word, ocp_data,
+				test_bit(RTL8152_INACCESSIBLE, &tp->flags) ||
+				(ocp_data & AUTOLOAD_DONE),
+				20000, 10 * USEC_PER_SEC, false, tp,
+				MCU_TYPE_PLA, PLA_BOOT_CTRL);
+
+	if (ret)
+		dev_err(&tp->intf->dev, "autoload done timeout\n");
+
+	return test_bit(RTL8152_INACCESSIBLE, &tp->flags) ? -ENODEV : 0;
+}
+
 static void r8153b_ups_en(struct r8152 *tp, bool enable)
 {
 	if (enable) {
@@ -4190,16 +4440,8 @@ static void r8153b_ups_en(struct r8152 *tp, bool enable)
 				  UPS_FORCE_PWR_DOWN);
 
 		if (ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0) & PCUT_STATUS) {
-			int i;
-
-			for (i = 0; i < 500; i++) {
-				if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
-					return;
-				if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) &
-				    AUTOLOAD_DONE)
-					break;
-				msleep(20);
-			}
+			if (wait_autoload_done(tp))
+				return;
 
 			tp->rtl_ops.hw_phy_cfg(tp);
 
@@ -4227,16 +4469,8 @@ static void r8153c_ups_en(struct r8152 *tp, bool enable)
 				  UPS_FORCE_PWR_DOWN);
 
 		if (ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0) & PCUT_STATUS) {
-			int i;
-
-			for (i = 0; i < 500; i++) {
-				if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
-					return;
-				if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) &
-				    AUTOLOAD_DONE)
-					break;
-				msleep(20);
-			}
+			if (wait_autoload_done(tp))
+				return;
 
 			tp->rtl_ops.hw_phy_cfg(tp);
 
@@ -4288,6 +4522,49 @@ static void r8156_ups_en(struct r8152 *tp, bool enable)
 	}
 }
 
+static void r8157_ups_en(struct r8152 *tp, bool enable)
+{
+	if (enable) {
+		r8156_ups_flags(tp);
+
+		ocp_byte_set_bits(tp, MCU_TYPE_USB, USB_POWER_CUT,
+				  UPS_EN | USP_PREWAKE | PHASE2_EN);
+
+		ocp_byte_set_bits(tp, MCU_TYPE_USB, USB_MISC_2,
+				  UPS_FORCE_PWR_DOWN);
+	} else {
+		ocp_byte_clr_bits(tp, MCU_TYPE_USB, USB_POWER_CUT,
+				  UPS_EN | USP_PREWAKE);
+
+		ocp_byte_clr_bits(tp, MCU_TYPE_USB, USB_MISC_2,
+				  UPS_FORCE_PWR_DOWN);
+
+		if (ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0) & PCUT_STATUS) {
+			u32 ocp_data;
+			int ret;
+
+			ret = read_poll_timeout(ocp_read_word, ocp_data,
+						ocp_data & BACKUP_RESTRORE, 200,
+						20000, false, tp, MCU_TYPE_USB,
+						USB_GPHY_CTRL);
+			if (ret) {
+				rtl_set_inaccessible(tp);
+				dev_err(&tp->intf->dev,
+					"backup-restore timed out\n");
+				return;
+			}
+
+			/* clear USB fw_ver_reg */
+			ocp_write_byte(tp, MCU_TYPE_USB, USB_FW_USB_VER, 0);
+
+			tp->rtl_ops.hw_phy_cfg(tp);
+
+			rtl8152_set_speed(tp, tp->autoneg, tp->speed,
+					  tp->duplex, tp->advertising);
+		}
+	}
+}
+
 static void r8153_power_cut_en(struct r8152 *tp, bool enable)
 {
 	if (enable)
@@ -4446,9 +4723,28 @@ static void rtl8157_runtime_enable(struct r8152 *tp, bool enable)
 		r8153b_u1u2en(tp, false);
 		r8157_u2p3en(tp, false);
 		rtl_runtime_suspend_enable(tp, true);
+
+		switch (tp->version) {
+		case RTL_VER_16:
+		case RTL_VER_17_QFN68:
+			r8157_ups_en(tp, true);
+			break;
+		default:
+			break;
+		}
 	} else {
 		r8153_queue_wake(tp, false);
 		rtl_runtime_suspend_enable(tp, false);
+
+		switch (tp->version) {
+		case RTL_VER_16:
+		case RTL_VER_17_QFN68:
+			r8157_ups_en(tp, false);
+			break;
+		default:
+			break;
+		}
+
 		r8157_u2p3en(tp, true);
 		if (tp->udev->speed >= USB_SPEED_SUPER)
 			r8153b_u1u2en(tp, true);
@@ -4480,6 +4776,8 @@ static void r8153_teredo_off(struct r8152 *tp)
 	case RTL_VER_14:
 	case RTL_VER_15:
 	case RTL_VER_16:
+	case RTL_VER_17_QFN68:
+	case RTL_VER_17_QFN100:
 	default:
 		/* The bit 0 ~ 7 are relative with teredo settings. They are
 		 * W1C (write 1 to clear), so set all 1 to disable it.
@@ -4534,7 +4832,8 @@ static void rtl_clear_bp(struct r8152 *tp, u16 type)
 		break;
 	case RTL_VER_14:
 	case RTL_VER_16:
-	case RTL_VER_17:
+	case RTL_VER_17_QFN68:
+	case RTL_VER_17_QFN100:
 	default:
 		ocp_write_word(tp, type, USB_BP2_EN, 0);
 		bp_num = 16;
@@ -4556,7 +4855,8 @@ static inline void rtl_reset_ocp_base(struct r8152 *tp)
 static int rtl_phy_patch_request(struct r8152 *tp, bool request, bool wait)
 {
 	u16 check;
-	int i;
+	u16 ocp_data;
+	int i, ret;
 
 	if (request) {
 		ocp_reg_set_bits(tp, OCP_PHY_PATCH_CMD, PATCH_REQUEST);
@@ -4567,25 +4867,29 @@ static int rtl_phy_patch_request(struct r8152 *tp, bool request, bool wait)
 	}
 
 	for (i = 0; wait && i < 5000; i++) {
-		u32 ocp_data;
-
 		if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
 			return -ENODEV;
 
 		usleep_range(1000, 2000);
-		ocp_data = ocp_reg_read(tp, OCP_PHY_PATCH_STAT);
-		if ((ocp_data & PATCH_READY) ^ check)
+		ret = ocp_reg_read(tp, OCP_PHY_PATCH_STAT, &ocp_data);
+		if (ret < 0)
+			return ret;
+		else if ((ocp_data & PATCH_READY) ^ check)
 			break;
 	}
 
-	if (request && wait &&
-	    !(ocp_reg_read(tp, OCP_PHY_PATCH_STAT) & PATCH_READY)) {
-		dev_err(&tp->intf->dev, "PHY patch request fail\n");
-		rtl_phy_patch_request(tp, false, false);
-		return -ETIME;
-	} else {
-		return 0;
+	if (request && wait) {
+		ret = ocp_reg_read(tp, OCP_PHY_PATCH_STAT, &ocp_data);
+		if (ret < 0) {
+			return ret;
+		} else if (!(ocp_data & PATCH_READY)) {
+			dev_err(&tp->intf->dev, "PHY patch request fail\n");
+			rtl_phy_patch_request(tp, false, false);
+			return -ETIME;
+		}
 	}
+
+	return 0;
 }
 
 static void rtl_patch_key_set(struct r8152 *tp, u16 key_addr, u16 patch_key)
@@ -4646,7 +4950,8 @@ static bool rtl8152_is_fw_phy_speed_up_ok(struct r8152 *tp, struct fw_phy_speed_
 	case RTL_VER_13:
 	case RTL_VER_15:
 	case RTL_VER_16:
-	case RTL_VER_17:
+	case RTL_VER_17_QFN68:
+	case RTL_VER_17_QFN100:
 	default:
 		break;
 	}
@@ -5299,10 +5604,14 @@ static void rtl_ram_code_speed_up(struct r8152 *tp, struct fw_phy_speed_up *phy,
 {
 	u32 len;
 	u8 *data;
+	u16 ver;
 
 	rtl_reset_ocp_base(tp);
 
-	if (sram_read(tp, SRAM_GPHY_FW_VER) >= __le16_to_cpu(phy->version)) {
+	if (sram_read(tp, SRAM_GPHY_FW_VER, &ver) < 0)
+		return;
+
+	if (ver >= __le16_to_cpu(phy->version)) {
 		dev_dbg(&tp->intf->dev, "PHY firmware has been the newest\n");
 		return;
 	}
@@ -5349,7 +5658,8 @@ static void rtl_ram_code_speed_up(struct r8152 *tp, struct fw_phy_speed_up *phy,
 
 	rtl_phy_patch_request(tp, false, wait);
 
-	if (sram_read(tp, SRAM_GPHY_FW_VER) == __le16_to_cpu(phy->version))
+	if (sram_read(tp, SRAM_GPHY_FW_VER, &ver) >= 0 &&
+	    ver == __le16_to_cpu(phy->version))
 		dev_dbg(&tp->intf->dev, "successfully applied %s\n", phy->info);
 	else
 		dev_err(&tp->intf->dev, "ram code speedup mode fail\n");
@@ -5357,14 +5667,17 @@ static void rtl_ram_code_speed_up(struct r8152 *tp, struct fw_phy_speed_up *phy,
 
 static int rtl8152_fw_phy_ver(struct r8152 *tp, struct fw_phy_ver *phy_ver)
 {
-	u16 ver_addr, ver;
+	u16 ver_addr, ver, cur_ver;
 
 	ver_addr = __le16_to_cpu(phy_ver->ver.addr);
 	ver = __le16_to_cpu(phy_ver->ver.data);
 
 	rtl_reset_ocp_base(tp);
 
-	if (sram_read(tp, ver_addr) >= ver) {
+	if (sram_read(tp, ver_addr, &cur_ver) < 0)
+		return 0;
+
+	if (cur_ver >= ver) {
 		dev_dbg(&tp->intf->dev, "PHY firmware has been the newest\n");
 		return 0;
 	}
@@ -5383,7 +5696,8 @@ static void rtl8152_fw_phy_fixup(struct r8152 *tp, struct fw_phy_fixup *fix)
 	rtl_reset_ocp_base(tp);
 
 	addr = __le16_to_cpu(fix->setting.addr);
-	data = ocp_reg_read(tp, addr);
+	if (ocp_reg_read(tp, addr, &data) < 0)
+		return;
 
 	switch (__le16_to_cpu(fix->bit_cmd)) {
 	case FW_FIXUP_AND:
@@ -5687,10 +6001,10 @@ static inline void r8152_mmd_indirect(struct r8152 *tp, u16 dev, u16 reg)
 
 static u16 r8152_mmd_read(struct r8152 *tp, u16 dev, u16 reg)
 {
-	u16 data;
+	u16 data = 0;
 
 	r8152_mmd_indirect(tp, dev, reg);
-	data = ocp_reg_read(tp, OCP_EEE_DATA);
+	ocp_reg_read(tp, OCP_EEE_DATA, &data);
 	ocp_reg_write(tp, OCP_EEE_AR, 0x0000);
 
 	return data;
@@ -5755,7 +6069,8 @@ static void r8156_eee_en(struct r8152 *tp, bool enable)
 
 	r8153_eee_en(tp, enable);
 
-	config = ocp_reg_read(tp, OCP_EEE_ADV2);
+	if (ocp_reg_read(tp, OCP_EEE_ADV2, &config) < 0)
+		return;
 
 	if (enable && (tp->eee_adv2 & MDIO_EEE_2_5GT))
 		config |= MDIO_EEE_2_5GT;
@@ -5806,7 +6121,8 @@ static void rtl_eee_enable(struct r8152 *tp, bool enable)
 	case RTL_VER_13:
 	case RTL_VER_15:
 	case RTL_VER_16:
-	case RTL_VER_17:
+	case RTL_VER_17_QFN68:
+	case RTL_VER_17_QFN100:
 		if (enable) {
 			r8156_eee_en(tp, true);
 			ocp_reg_write(tp, OCP_EEE_ADV, tp->eee_adv);
@@ -5961,27 +6277,125 @@ static void r8152b_enter_oob(struct r8152 *tp)
 			   RCR_APM | RCR_AM | RCR_AB);
 }
 
-static int r8153_pre_firmware_1(struct r8152 *tp)
+static void rtl_fc_pause_pkt_en(struct r8152 *tp, u16 speed)
 {
-	int i;
+	int log2_ratio, ratio;
+	u16 num_pause_pkts;
+	u32 ocp_data;
 
-	/* Wait till the WTD timer is ready. It would take at most 104 ms. */
-	for (i = 0; i < 104; i++) {
-		u32 ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_WDT1_CTRL);
+	switch (tp->version) {
+	case RTL_VER_10:
+	case RTL_VER_11:
+		ocp_write_word(tp, MCU_TYPE_USB, USB_FC_TIMER,
+			       CTRL_TIMER_EN | (1000 / 8));
 
-		if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
-			return -ENODEV;
-		if (!(ocp_data & WTD1_EN))
-			break;
-		usleep_range(1000, 2000);
-	}
+		ocp_word_set_bits(tp, MCU_TYPE_USB, USB_FW_CTRL,
+				  FLOW_CTRL_PATCH_OPT);
 
-	return 0;
-}
+		ocp_word_set_bits(tp, MCU_TYPE_USB, USB_FW_TASK, FC_PATCH_TASK);
+		break;
+	case RTL_VER_12:
+	case RTL_VER_13:
+	case RTL_VER_15:
+		ocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_RCR, SLOT_EN);
 
-static int r8153_post_firmware_1(struct r8152 *tp)
-{
-	/* set USB_BP_4 to support USB_SPEED_SUPER only */
+		ocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_CPCR, FLOW_CTRL_EN);
+
+		/* enable fc timer and set timer to 600 ms. */
+		ocp_write_word(tp, MCU_TYPE_USB, USB_FC_TIMER,
+			       CTRL_TIMER_EN | (600 / 8));
+
+		ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_POL_GPIO_CTRL);
+		if (!(ocp_data & DACK_DET_EN))
+			ocp_word_set_bits(tp, MCU_TYPE_USB, USB_FW_CTRL,
+					  FLOW_CTRL_PATCH_2);
+
+		ocp_word_set_bits(tp, MCU_TYPE_USB, USB_FW_TASK, FC_PATCH_TASK);
+		break;
+	case RTL_VER_16:
+	case RTL_VER_17_QFN68:
+	case RTL_VER_17_QFN100:
+		ocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_RCR, SLOT_EN);
+
+		num_pause_pkts = 0xa;
+		ratio = 10000;
+
+		if (speed & _10bps) {
+			ratio /= 10;
+		} else if (speed & _100bps) {
+			ratio /= 100;
+		} else if (speed & _1000bps) {
+			ratio /= 1000;
+		} else if (speed & _2500bps) {
+			ratio /= 2500;
+		} else if (speed & _5000bps) {
+			ratio /= 5000;
+		} else if (speed & _10000bps) {
+			ratio /= 10000;
+		} else {
+			/* No rate bit is set, e.g. a 500 or 1250 Mbit/s
+			 * sub-rate, which the driver does not advertise.
+			 * Disarm the limit.
+			 */
+			dev_err(&tp->intf->dev, "Unknown link speed\n");
+			ocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_PAUSE_LIMIT,
+					  PAUSE_LIMIT_EN);
+			break;
+		}
+
+		log2_ratio = ilog2(ratio);
+		num_pause_pkts -= log2_ratio;
+
+		/* Round ratio up to the next power of two if it is
+		 * more than halfway there. Floating-point is avoided
+		 * by rewriting ratio > 1.5 * 2^log2_ratio as
+		 * 2 * ratio > 3 * 2^log2_ratio.
+		 */
+		if (2 * ratio > 3 * (1 << log2_ratio))
+			num_pause_pkts--;
+
+		/* At most 2^num_pause_pkts pause packets would be sent.
+		 *
+		 *  10 Mbit/s -> 2^0
+		 * 100 Mbit/s -> 2^3
+		 *   1 Gbit/s -> 2^7
+		 * 2.5 Gbit/s -> 2^8
+		 *   5 Gbit/s -> 2^9
+		 *  10 Gbit/s -> 2^10
+		 */
+		ocp_word_w0w1(tp, MCU_TYPE_PLA, PLA_PAUSE_LIMIT,
+			      PAUSE_LIMIT_MASK | PAUSE_LIMIT_EN,
+			      num_pause_pkts << 4);
+
+		ocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_PAUSE_LIMIT,
+				  PAUSE_LIMIT_EN);
+		break;
+	default:
+		break;
+	}
+}
+
+static int r8153_pre_firmware_1(struct r8152 *tp)
+{
+	int i;
+
+	/* Wait till the WTD timer is ready. It would take at most 104 ms. */
+	for (i = 0; i < 104; i++) {
+		u32 ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_WDT1_CTRL);
+
+		if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
+			return -ENODEV;
+		if (!(ocp_data & WTD1_EN))
+			break;
+		usleep_range(1000, 2000);
+	}
+
+	return 0;
+}
+
+static int r8153_post_firmware_1(struct r8152 *tp)
+{
+	/* set USB_BP_4 to support USB_SPEED_SUPER only */
 	if (ocp_read_byte(tp, MCU_TYPE_USB, USB_CSTMR) & FORCE_SUPER)
 		ocp_write_word(tp, MCU_TYPE_USB, USB_BP_4, BP4_SUPER_ONLY);
 
@@ -6210,8 +6624,8 @@ static void r8153b_hw_phy_cfg(struct r8152 *tp)
 	 * rg_saw_cnt = OCP reg 0xC426 Bit[13:0]
 	 * swr_cnt_1ms_ini = 16000000 / rg_saw_cnt
 	 */
-	ocp_data = ocp_reg_read(tp, 0xc426);
-	ocp_data &= 0x3fff;
+	ocp_reg_read(tp, 0xc426, &data);
+	ocp_data = data & 0x3fff;
 	if (ocp_data) {
 		u32 swr_cnt_1ms_ini;
 
@@ -6391,24 +6805,16 @@ static int rtl8156_enable(struct r8152 *tp)
 	if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
 		return -ENODEV;
 
-	if (tp->version < RTL_VER_12)
-		r8156_fc_parameter(tp);
-
+	r8156_fc_parameter(tp);
 	set_tx_qlen(tp);
 	rtl_set_eee_plus(tp);
 
-	if (tp->version >= RTL_VER_12 && tp->version <= RTL_VER_17)
-		ocp_word_clr_bits(tp, MCU_TYPE_USB, USB_RX_AGGR_NUM, RX_AGGR_NUM_MASK);
-
 	r8153_set_rx_early_timeout(tp);
 	r8153_set_rx_early_size(tp);
 
 	speed = rtl8152_get_speed(tp);
 	rtl_set_ifg(tp, speed);
 
-	if (tp->version >= RTL_VER_16)
-		return rtl_enable(tp);
-
 	if (speed & _2500bps)
 		ocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4,
 				  IDLE_SPDWN_EN);
@@ -6416,12 +6822,10 @@ static int rtl8156_enable(struct r8152 *tp)
 		ocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4,
 				  IDLE_SPDWN_EN);
 
-	if (tp->version < RTL_VER_12) {
-		if (speed & _1000bps)
-			ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEE_TXTWSYS, 0x11);
-		else if (speed & _500bps)
-			ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEE_TXTWSYS, 0x3d);
-	}
+	if (speed & _1000bps)
+		ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEE_TXTWSYS, 0x11);
+	else if (speed & _500bps)
+		ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEE_TXTWSYS, 0x3d);
 
 	if (tp->udev->speed == USB_SPEED_HIGH) {
 		/* USB 0xb45e[3:0] l1_nyet_hird */
@@ -6446,6 +6850,69 @@ static void rtl8156_disable(struct r8152 *tp)
 	rtl8153_disable(tp);
 }
 
+static int rtl8156b_enable(struct r8152 *tp)
+{
+	u16 speed;
+
+	if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
+		return -ENODEV;
+
+	set_tx_qlen(tp);
+	rtl_set_eee_plus(tp);
+
+	ocp_word_clr_bits(tp, MCU_TYPE_USB, USB_RX_AGGR_NUM, RX_AGGR_NUM_MASK);
+
+	r8153_set_rx_early_timeout(tp);
+	r8153_set_rx_early_size(tp);
+
+	speed = rtl8152_get_speed(tp);
+	rtl_set_ifg(tp, speed);
+
+	if (speed & _2500bps)
+		ocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4,
+				  IDLE_SPDWN_EN);
+	else
+		ocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4,
+				  IDLE_SPDWN_EN);
+
+	if (tp->udev->speed == USB_SPEED_HIGH) {
+		/* USB 0xb45e[3:0] l1_nyet_hird */
+		if (is_flow_control(speed))
+			ocp_word_w0w1(tp, MCU_TYPE_USB, USB_L1_CTRL, 0xf, 0xf);
+		else
+			ocp_word_w0w1(tp, MCU_TYPE_USB, USB_L1_CTRL, 0xf, 0x1);
+	}
+
+	ocp_word_clr_bits(tp, MCU_TYPE_USB, USB_FW_TASK, FC_PATCH_TASK);
+	usleep_range(1000, 2000);
+	ocp_word_set_bits(tp, MCU_TYPE_USB, USB_FW_TASK, FC_PATCH_TASK);
+
+	return rtl_enable(tp);
+}
+
+static int rtl8157_enable(struct r8152 *tp)
+{
+	u16 speed;
+
+	if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
+		return -ENODEV;
+
+	set_tx_qlen(tp);
+	rtl_set_eee_plus(tp);
+
+	ocp_word_clr_bits(tp, MCU_TYPE_USB, USB_RX_AGGR_NUM, RX_AGGR_NUM_MASK);
+
+	r8153_set_rx_early_timeout(tp);
+	r8153_set_rx_early_size(tp);
+
+	speed = rtl8152_get_speed(tp);
+	rtl_fc_pause_pkt_en(tp, speed);
+
+	rtl_set_ifg(tp, speed);
+
+	return rtl_enable(tp);
+}
+
 static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex,
 			     u32 advertising)
 {
@@ -6517,7 +6984,11 @@ static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex,
 		if (!advertising)
 			return -EINVAL;
 
-		orig = r8152_mdio_read(tp, MII_ADVERTISE);
+		ret = r8152_mdio_read(tp, MII_ADVERTISE);
+		if (ret < 0)
+			goto out;
+
+		orig = ret;
 		new1 = orig & ~(ADVERTISE_10HALF | ADVERTISE_10FULL |
 				ADVERTISE_100HALF | ADVERTISE_100FULL);
 		if (advertising & RTL_ADVERTISED_10_HALF) {
@@ -6544,7 +7015,11 @@ static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex,
 		}
 
 		if (tp->mii.supports_gmii) {
-			orig = r8152_mdio_read(tp, MII_CTRL1000);
+			ret = r8152_mdio_read(tp, MII_CTRL1000);
+			if (ret < 0)
+				goto out;
+
+			orig = ret;
 			new1 = orig & ~(ADVERTISE_1000FULL |
 					ADVERTISE_1000HALF);
 
@@ -6558,7 +7033,10 @@ static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex,
 		}
 
 		if (tp->support_2500full || tp->support_5000full || tp->support_10000full) {
-			orig = ocp_reg_read(tp, OCP_10GBT_CTRL);
+			ret = ocp_reg_read(tp, OCP_10GBT_CTRL, &orig);
+			if (ret < 0)
+				goto out;
+
 			new1 = orig & ~(MDIO_AN_10GBT_CTRL_ADV2_5G | MDIO_AN_10GBT_CTRL_ADV5G
 					| MDIO_AN_10GBT_CTRL_ADV10G);
 
@@ -6589,20 +7067,23 @@ static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex,
 	if (test_and_clear_bit(PHY_RESET, &tp->flags))
 		bmcr |= BMCR_RESET;
 
-	r8152_mdio_write(tp, MII_BMCR, bmcr);
+	ret = r8152_mdio_write(tp, MII_BMCR, bmcr);
+	if (ret < 0)
+		goto out;
 
 	if (bmcr & BMCR_RESET) {
 		int i;
 
 		for (i = 0; i < 50; i++) {
 			msleep(20);
-			if ((r8152_mdio_read(tp, MII_BMCR) & BMCR_RESET) == 0)
+			ret = r8152_mdio_read(tp, MII_BMCR);
+			if (ret < 0 || !(ret & BMCR_RESET))
 				break;
 		}
 	}
 
 out:
-	return ret;
+	return ret < 0 ? ret : 0;
 }
 
 static void rtl8152_up(struct r8152 *tp)
@@ -6806,8 +7287,7 @@ static void rtl8156_up(struct r8152 *tp)
 		return;
 
 	r8153b_u1u2en(tp, false);
-	if (tp->version < RTL_VER_16)
-		r8153_u2p3en(tp, false);
+	r8153_u2p3en(tp, false);
 	r8153_aldps_en(tp, false);
 
 	rxdy_gated_en(tp, true);
@@ -6820,8 +7300,7 @@ static void rtl8156_up(struct r8152 *tp)
 
 	ocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, NOW_IS_OOB);
 
-	if (tp->version >= RTL_VER_16)
-		ocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_RCR1, BIT(3));
+	ocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_RCR1, BIT(3));
 
 	ocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, MCU_BORW_EN);
 
@@ -6845,9 +7324,8 @@ static void rtl8156_up(struct r8152 *tp)
 
 	ocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, PLA_MCU_SPDWN_EN);
 
-	if (tp->version < RTL_VER_16)
-		ocp_word_clr_bits(tp, MCU_TYPE_USB, USB_SPEED_OPTION,
-				  RG_PWRDN_EN | ALL_SPEED_OFF);
+	ocp_word_clr_bits(tp, MCU_TYPE_USB, USB_SPEED_OPTION,
+			  RG_PWRDN_EN | ALL_SPEED_OFF);
 
 	ocp_write_dword(tp, MCU_TYPE_USB, USB_RX_BUF_TH, 0x00600400);
 
@@ -6857,10 +7335,19 @@ static void rtl8156_up(struct r8152 *tp)
 	}
 
 	r8153_aldps_en(tp, true);
-	if (tp->version < RTL_VER_16)
-		r8153_u2p3en(tp, true);
+	r8153_u2p3en(tp, true);
+
+	switch (tp->version) {
+	case RTL_VER_13:
+	case RTL_VER_15:
+		/* Enable Clear_SDR */
+		ocp_word_set_bits(tp, MCU_TYPE_USB, 0xd3ca, BIT(15));
+		break;
+	default:
+		break;
+	}
 
-	if (tp->version < RTL_VER_16 && tp->udev->speed >= USB_SPEED_SUPER)
+	if (tp->udev->speed >= USB_SPEED_SUPER)
 		r8153b_u1u2en(tp, true);
 }
 
@@ -6873,12 +7360,9 @@ static void rtl8156_down(struct r8152 *tp)
 
 	ocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3,
 			  PLA_MCU_SPDWN_EN);
-
 	r8153b_u1u2en(tp, false);
-	if (tp->version < RTL_VER_16) {
-		r8153_u2p3en(tp, false);
-		r8153b_power_cut_en(tp, false);
-	}
+	r8153_u2p3en(tp, false);
+	r8153b_power_cut_en(tp, false);
 	r8153_aldps_en(tp, false);
 
 	ocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, NOW_IS_OOB);
@@ -6900,7 +7384,125 @@ static void rtl8156_down(struct r8152 *tp)
 	 */
 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_TEREDO_WAKE_BASE, 0x00ff);
 
-	ocp_byte_set_bits(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, NOW_IS_OOB);
+	ocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_BDC_CR, ALDPS_PROXY_MODE);
+
+	ocp_byte_set_bits(tp, MCU_TYPE_PLA, PLA_OOB_CTRL,
+			  NOW_IS_OOB | DIS_MCU_CLROOB);
+
+	ocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, MCU_BORW_EN);
+
+	rtl_rx_vlan_en(tp, true);
+	rxdy_gated_en(tp, false);
+
+	ocp_dword_set_bits(tp, MCU_TYPE_PLA, PLA_RCR,
+			   RCR_APM | RCR_AM | RCR_AB);
+
+	r8153_aldps_en(tp, true);
+}
+
+static void rtl8157_change_mtu(struct r8152 *tp)
+{
+	u32 max_pkt_size = mtu_to_size(tp->netdev->mtu);
+	u32 ocp_data;
+
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, max_pkt_size);
+
+	/* Use at least 10K for MTPS */
+	ocp_data = max_t(u32, max_pkt_size, 10 * 1024) / 64;
+
+	/* 16 * 1024 / 64 = 0x100, so the max is 0xff for 8 bits data */
+	ocp_data = min_t(u32, ocp_data, 0xff);
+
+	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_MTPS, ocp_data);
+	r8156_fc_parameter(tp);
+
+	/* TX share fifo free credit full threshold */
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_TXFIFO_CTRL, 512 / 64);
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_TXFIFO_FULL,
+		       ALIGN(max_pkt_size + tp->tx_desc.size, 1024) / 16);
+}
+
+static void rtl8157_up(struct r8152 *tp)
+{
+	if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
+		return;
+
+	r8153b_u1u2en(tp, false);
+	r8153_aldps_en(tp, false);
+
+	rxdy_gated_en(tp, true);
+	r8153_teredo_off(tp);
+
+	ocp_dword_clr_bits(tp, MCU_TYPE_PLA, PLA_RCR, RCR_ACPT_ALL);
+
+	rtl8152_nic_reset(tp);
+	rtl_reset_bmu(tp);
+
+	ocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, NOW_IS_OOB);
+
+	ocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_RCR1, BIT(3));
+
+	ocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, MCU_BORW_EN);
+
+	rtl_rx_vlan_en(tp, tp->netdev->features & NETIF_F_HW_VLAN_CTAG_RX);
+
+	rtl8157_change_mtu(tp);
+
+	/* share FIFO settings */
+	ocp_word_w0w1(tp, MCU_TYPE_PLA, PLA_RXFIFO_FULL, RXFIFO_FULL_MASK,
+		      0x08);
+
+	ocp_word_clr_bits(tp, MCU_TYPE_USB, USB_SPEED_OPTION,
+			  RG_PWRDN_EN | ALL_SPEED_OFF);
+
+	ocp_write_dword(tp, MCU_TYPE_USB, USB_RX_BUF_TH, 0x00600400);
+
+	if (tp->saved_wolopts != __rtl_get_wol(tp)) {
+		netif_warn(tp, ifup, tp->netdev, "wol setting is changed\n");
+		__rtl_set_wol(tp, tp->saved_wolopts);
+	}
+
+	r8153_aldps_en(tp, true);
+
+	/* Enable Clear_SDR */
+	ocp_byte_set_bits(tp, MCU_TYPE_USB, 0xd378, BIT(7));
+	/* Clear SDR bit */
+	ocp_word_clr_bits(tp, MCU_TYPE_USB, 0xcd06, BIT(15));
+}
+
+static void rtl8157_down(struct r8152 *tp)
+{
+	if (test_bit(RTL8152_INACCESSIBLE, &tp->flags)) {
+		rtl_drop_queued_tx(tp);
+		return;
+	}
+
+	r8153b_u1u2en(tp, false);
+	r8153_aldps_en(tp, false);
+
+	ocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, NOW_IS_OOB);
+
+	/* RX FIFO settings for OOB */
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RXFIFO_FULL, 64 / 16);
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RX_FIFO_FULL, 1024 / 16);
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RX_FIFO_EMPTY, 4096 / 16);
+
+	rtl_disable(tp);
+	rtl_reset_bmu(tp);
+
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, 1526);
+	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_MTPS, 10 * 1024 / 64);
+
+	/* Clear teredo wake event. bit[15:8] is the teredo wakeup
+	 * type. Set it to zero. bits[7:0] are the W1C bits about
+	 * the events. Set them to all 1 to clear them.
+	 */
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_TEREDO_WAKE_BASE, 0x00ff);
+
+	ocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_BDC_CR, ALDPS_PROXY_MODE);
+
+	ocp_byte_set_bits(tp, MCU_TYPE_PLA, PLA_OOB_CTRL,
+			  NOW_IS_OOB | DIS_MCU_CLROOB);
 
 	ocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, MCU_BORW_EN);
 
@@ -6931,7 +7533,12 @@ static bool rtl8152_in_nway(struct r8152 *tp)
 
 static bool rtl8153_in_nway(struct r8152 *tp)
 {
-	u16 phy_state = ocp_reg_read(tp, OCP_PHY_STATE) & 0xff;
+	u16 phy_state;
+
+	if (ocp_reg_read(tp, OCP_PHY_STATE, &phy_state) < 0)
+		return false;
+
+	phy_state &= 0xff;
 
 	if (phy_state == TXDIS_STATE || phy_state == ABD_STATE)
 		return false;
@@ -6947,7 +7554,9 @@ static void r8156_mdio_force_mode(struct r8152 *tp)
 	 * 0: MDIO force mode
 	 * 1: MMD force mode
 	 */
-	data = ocp_reg_read(tp, 0xa5b4);
+	if (ocp_reg_read(tp, 0xa5b4, &data) < 0)
+		return;
+
 	if (data & BIT(15)) {
 		data &= ~BIT(15);
 		ocp_reg_write(tp, 0xa5b4, data);
@@ -7225,22 +7834,14 @@ static void r8152b_init(struct r8152 *tp)
 static void r8153_init(struct r8152 *tp)
 {
 	u32 ocp_data;
-	int i;
 
 	if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
 		return;
 
 	r8153_u1u2en(tp, false);
 
-	for (i = 0; i < 500; i++) {
-		if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) &
-		    AUTOLOAD_DONE)
-			break;
-
-		msleep(20);
-		if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
-			break;
-	}
+	if (wait_autoload_done(tp))
+		return;
 
 	r8153_phy_status(tp, 0);
 
@@ -7341,22 +7942,13 @@ static void r8153_init(struct r8152 *tp)
 
 static void r8153b_init(struct r8152 *tp)
 {
-	int i;
-
 	if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
 		return;
 
 	r8153b_u1u2en(tp, false);
 
-	for (i = 0; i < 500; i++) {
-		if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) &
-		    AUTOLOAD_DONE)
-			break;
-
-		msleep(20);
-		if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
-			break;
-	}
+	if (wait_autoload_done(tp))
+		return;
 
 	r8153_phy_status(tp, 0);
 
@@ -7411,8 +8003,6 @@ static void r8153b_init(struct r8152 *tp)
 
 static void r8153c_init(struct r8152 *tp)
 {
-	int i;
-
 	if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
 		return;
 
@@ -7425,15 +8015,8 @@ static void r8153c_init(struct r8152 *tp)
 
 	ocp_word_set_bits(tp, MCU_TYPE_USB, 0xcbf0, BIT(1));
 
-	for (i = 0; i < 500; i++) {
-		if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) &
-		    AUTOLOAD_DONE)
-			break;
-
-		msleep(20);
-		if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
-			return;
-	}
+	if (wait_autoload_done(tp))
+		return;
 
 	r8153_phy_status(tp, 0);
 
@@ -7612,19 +8195,20 @@ static void r8156_hw_phy_cfg(struct r8152 *tp)
 		ocp_reg_clr_bits(tp, 0xa86a, BIT(0));
 
 		/* MDI SWAP */
+		ocp_reg_read(tp, 0xd068, &data);
 		if ((ocp_read_word(tp, MCU_TYPE_USB, USB_UPS_CFG) & MID_REVERSE) &&
-		    (ocp_reg_read(tp, 0xd068) & BIT(1))) {
+		    (data & BIT(1))) {
 			u16 swap_a, swap_b;
 
-			data = ocp_reg_read(tp, 0xd068);
+			ocp_reg_read(tp, 0xd068, &data);
 			data &= ~0x1f;
 			data |= 0x1; /* p0 */
 			ocp_reg_write(tp, 0xd068, data);
-			swap_a = ocp_reg_read(tp, 0xd06a);
+			ocp_reg_read(tp, 0xd06a, &swap_a);
 			data &= ~0x18;
 			data |= 0x18; /* p3 */
 			ocp_reg_write(tp, 0xd068, data);
-			swap_b = ocp_reg_read(tp, 0xd06a);
+			ocp_reg_read(tp, 0xd06a, &swap_b);
 			data &= ~0x18; /* p0 */
 			ocp_reg_write(tp, 0xd068, data);
 			ocp_reg_write(tp, 0xd06a,
@@ -7636,11 +8220,11 @@ static void r8156_hw_phy_cfg(struct r8152 *tp)
 			data &= ~0x18;
 			data |= 0x08; /* p1 */
 			ocp_reg_write(tp, 0xd068, data);
-			swap_a = ocp_reg_read(tp, 0xd06a);
+			ocp_reg_read(tp, 0xd06a, &swap_a);
 			data &= ~0x18;
 			data |= 0x10; /* p2 */
 			ocp_reg_write(tp, 0xd068, data);
-			swap_b = ocp_reg_read(tp, 0xd06a);
+			ocp_reg_read(tp, 0xd06a, &swap_b);
 			data &= ~0x18;
 			data |= 0x08; /* p1 */
 			ocp_reg_write(tp, 0xd068, data);
@@ -7651,16 +8235,16 @@ static void r8156_hw_phy_cfg(struct r8152 *tp)
 			ocp_reg_write(tp, 0xd068, data);
 			ocp_reg_write(tp, 0xd06a,
 				      (swap_b & ~0x7ff) | (swap_a & 0x7ff));
-			swap_a = ocp_reg_read(tp, 0xbd5a);
-			swap_b = ocp_reg_read(tp, 0xbd5c);
+			ocp_reg_read(tp, 0xbd5a, &swap_a);
+			ocp_reg_read(tp, 0xbd5c, &swap_b);
 			ocp_reg_write(tp, 0xbd5a, (swap_a & ~0x1f1f) |
 				      ((swap_b & 0x1f) << 8) |
 				      ((swap_b >> 8) & 0x1f));
 			ocp_reg_write(tp, 0xbd5c, (swap_b & ~0x1f1f) |
 				      ((swap_a & 0x1f) << 8) |
 				      ((swap_a >> 8) & 0x1f));
-			swap_a = ocp_reg_read(tp, 0xbc18);
-			swap_b = ocp_reg_read(tp, 0xbc1a);
+			ocp_reg_read(tp, 0xbc18, &swap_a);
+			ocp_reg_read(tp, 0xbc1a, &swap_b);
 			ocp_reg_write(tp, 0xbc18, (swap_a & ~0x1f1f) |
 				      ((swap_b & 0x1f) << 8) |
 				      ((swap_b >> 8) & 0x1f));
@@ -7985,11 +8569,14 @@ static void r8157_hw_phy_cfg(struct r8152 *tp)
 	ocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_PHY_PWR, PFM_PWM_SWITCH);
 
 	/* Advanced Power Saving parameter */
-	ocp_reg_set_bits(tp, 0xa430, BIT(0) | BIT(1));
+	ocp_reg_set_bits(tp, OCP_POWER_CFG, EN_10M_PLLOFF | EN_ALDPS_PLLOFF);
 
 	/* Disable ALDPS force mode */
 	ocp_reg_clr_bits(tp, 0xa44a, BIT(2));
 
+	/* Disable bypass_turn_off_clk_in_aldps */
+	ocp_byte_clr_bits(tp, MCU_TYPE_PLA, 0xd3c8, BIT(0));
+
 	switch (tp->version) {
 	case RTL_VER_16:
 		/* XG_INRX parameter */
@@ -8005,7 +8592,7 @@ static void r8157_hw_phy_cfg(struct r8152 *tp)
 		sram2_write_w0w1(tp, 0x8078, 0xff00, 0x3000);
 
 		/* green mode */
-		sram2_write_w0w1(tp, 0x89e9, 0xff00, 0);
+		sram2_clr_bits(tp, 0x89e9, 0xff00);
 		sram2_write_w0w1(tp, 0x8ffd, 0xff00, 0x0100);
 		sram2_write_w0w1(tp, 0x8ffe, 0xff00, 0x0200);
 		sram2_write_w0w1(tp, 0x8fff, 0xff00, 0x0400);
@@ -8111,11 +8698,85 @@ static void r8157_hw_phy_cfg(struct r8152 *tp)
 		sram2_write_w0w1(tp, 0x807c, 0xff00, 0x5000);
 		sram2_write_w0w1(tp, 0x809d, 0xff00, 0x5000);
 		break;
+	default:
+		break;
+	}
+
+	if (rtl_phy_patch_request(tp, true, true))
+		return;
+
+	ocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, EEE_SPDWN_EN);
+
+	ocp_reg_w0w1(tp, OCP_DOWN_SPEED, EN_EEE_100 | EN_EEE_1000, EN_10M_CLKDIV);
+
+	tp->ups_info._10m_ckdiv = true;
+	tp->ups_info.eee_plloff_100 = false;
+	tp->ups_info.eee_plloff_giga = false;
+
+	ocp_reg_set_bits(tp, OCP_POWER_CFG, EEE_CLKDIV_EN);
+	tp->ups_info.eee_ckdiv = true;
 
-	case RTL_VER_17:
-		/* Disable bypass turn off clk in ALDPS */
-		ocp_byte_clr_bits(tp, MCU_TYPE_PLA, 0xd3c8, BIT(0));
+	rtl_phy_patch_request(tp, false, true);
+
+	rtl_green_en(tp, test_bit(GREEN_ETHERNET, &tp->flags));
 
+	ocp_reg_clr_bits(tp, 0xa428, BIT(9));
+	ocp_reg_clr_bits(tp, 0xa5ea, BIT(0) | BIT(1));
+	tp->ups_info.lite_mode = 0;
+
+	if (tp->eee_en)
+		rtl_eee_enable(tp, true);
+
+	r8153_aldps_en(tp, true);
+	r8152b_enable_fc(tp);
+
+	set_bit(PHY_RESET, &tp->flags);
+}
+
+static void r8159_hw_phy_cfg(struct r8152 *tp)
+{
+	u16 data;
+
+	r8156b_wait_loading_flash(tp);
+
+	ocp_word_test_and_clr_bits(tp, MCU_TYPE_USB, USB_MISC_0, PCUT_STATUS);
+
+	data = r8153_phy_status(tp, 0);
+	switch (data) {
+	case PHY_STAT_EXT_INIT:
+		rtl8152_apply_firmware(tp, true);
+		ocp_reg_clr_bits(tp, 0xa466, BIT(0));
+		ocp_reg_clr_bits(tp, 0xa468, BIT(3) | BIT(1));
+		break;
+	case PHY_STAT_LAN_ON:
+	case PHY_STAT_PWRDN:
+	default:
+		rtl8152_apply_firmware(tp, false);
+		break;
+	}
+
+	r8152_mdio_test_and_clr_bit(tp, MII_BMCR, BMCR_PDOWN);
+
+	r8153_aldps_en(tp, false);
+
+	data = r8153_phy_status(tp, PHY_STAT_LAN_ON);
+	WARN_ON_ONCE(data != PHY_STAT_LAN_ON);
+
+	/* PFM mode */
+	ocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_PHY_PWR, PFM_PWM_SWITCH);
+
+	/* Advanced Power Saving parameter */
+	ocp_reg_set_bits(tp, OCP_POWER_CFG, EN_10M_PLLOFF | EN_ALDPS_PLLOFF);
+
+	/* Disable ALDPS force mode */
+	ocp_reg_clr_bits(tp, 0xa44a, BIT(2));
+
+	/* Disable bypass_turn_off_clk_in_aldps */
+	ocp_byte_clr_bits(tp, MCU_TYPE_PLA, 0xd3c8, BIT(0));
+
+	switch (tp->version) {
+	case RTL_VER_17_QFN68:
+	case RTL_VER_17_QFN100:
 		/* Power level tuning
 		 * test mode power level
 		 */
@@ -8125,22 +8786,35 @@ static void r8157_hw_phy_cfg(struct r8152 *tp)
 		sram_write_w0w1(tp, 0x81ae, 0xff00, 0x0f00);
 		sram_write_w0w1(tp, 0x81b9, 0xff00, 0xb900);
 		/* normal link TX filter */
-		sram2_write_w0w1(tp, 0x83b0, 0x0e00, 0);
-		sram2_write_w0w1(tp, 0x83c5, 0x0e00, 0);
-		sram2_write_w0w1(tp, 0x83da, 0x0e00, 0);
-		sram2_write_w0w1(tp, 0x83ef, 0x0e00, 0);
+		sram2_clr_bits(tp, 0x83b0, 0x0e00);
+		sram2_clr_bits(tp, 0x83c5, 0x0e00);
+		sram2_clr_bits(tp, 0x83da, 0x0e00);
+		sram2_clr_bits(tp, 0x83ef, 0x0e00);
+
+		ocp_reg_w0w1(tp, 0xbf38, 0x01f0, 0x0160);
+		ocp_reg_w0w1(tp, 0xbf3a, 0x001f, 0x0014);
+		/* shorten CLKS latency */
+		ocp_reg_clr_bits(tp, 0xbf28, BIT(14) | BIT(13));
+		ocp_reg_clr_bits(tp, 0xbf2c, BIT(15) | BIT(14));
+		/* CMP_Timer on MP_Timer=333
+		 * GPHY OCP 0xbf28 bit[0] = 0x1
+		 * GPHY OCP 0xbf28 bit[6:1] = 0x3
+		 * GPHY OCP 0xbf28 bit[12:7] = 0x3
+		 */
+		ocp_reg_w0w1(tp, 0xbf28, 0x1fff, 0x0187);
+		ocp_reg_w0w1(tp, 0xbf2a, 0x3f, 0x03);
 
 		/* AFE power saving for 2.5G & 5G */
 		sram_write(tp, 0x8173, 0x8620);
 		sram_write(tp, 0x8175, 0x8671);
 
-		sram_write_w0w1(tp, 0x817c, 0, BIT(13));
-		sram_write_w0w1(tp, 0x8187, 0, BIT(13));
-		sram_write_w0w1(tp, 0x8192, 0, BIT(13));
-		sram_write_w0w1(tp, 0x819d, 0, BIT(13));
-		sram_write_w0w1(tp, 0x81a8, BIT(13), 0);
-		sram_write_w0w1(tp, 0x81b3, BIT(13), 0);
-		sram_write_w0w1(tp, 0x81be, 0, BIT(13));
+		sram_set_bits(tp, 0x817c, BIT(13));
+		sram_set_bits(tp, 0x8187, BIT(13));
+		sram_set_bits(tp, 0x8192, BIT(13));
+		sram_set_bits(tp, 0x819d, BIT(13));
+		sram_clr_bits(tp, 0x81a8, BIT(13));
+		sram_clr_bits(tp, 0x81b3, BIT(13));
+		sram_set_bits(tp, 0x81be, BIT(13));
 
 		sram_write_w0w1(tp, 0x817d, 0xff00, 0xa600);
 		sram_write_w0w1(tp, 0x8188, 0xff00, 0xa600);
@@ -8204,10 +8878,10 @@ static void r8157_hw_phy_cfg(struct r8152 *tp)
 		sram2_write_w0w1(tp, 0x84b2, 0xff00, 0x6000);
 		/* Training AAGC PAR (with uc2 patch) */
 		sram2_write(tp, 0x8ffc, 0x6008);
-		sram2_write(tp, 0x8ffe, 0xf450);
+		sram2_write(tp, 0x8ffe, 0xf4ff);
 		/* DAC BGK */
-		sram2_write_w0w1(tp, 0x8015, 0, BIT(9));
-		sram2_write_w0w1(tp, 0x8016, 0, BIT(11));
+		sram2_set_bits(tp, 0x8015, BIT(9));
+		sram2_set_bits(tp, 0x8016, BIT(11));
 		sram2_write_w0w1(tp, 0x8fe6, 0xff00, 0x0800);
 		sram2_write(tp, 0x8fe4, 0x2114);
 		/* 10G PBO table */
@@ -8216,14 +8890,14 @@ static void r8157_hw_phy_cfg(struct r8152 *tp)
 		sram2_write_w0w1(tp, 0x864b, 0xff00, 0xdc00);
 		/* 2.5G ado power window size */
 		sram2_write_w0w1(tp, 0x8154, 0xc000, 0x4000);
-		sram2_write_w0w1(tp, 0x8158, 0xc000, 0);
+		sram2_clr_bits(tp, 0x8158, 0xc000);
 		/* 10G lock far */
 		sram2_write(tp, 0x826c, 0xffff);
 		sram2_write(tp, 0x826e, 0xffff);
 		/* XG INRX parameter */
 		sram2_write_w0w1(tp, 0x8872, 0xff00, 0x0e00);
-		sram_write_w0w1(tp, 0x8012, 0, BIT(11));
-		sram_write_w0w1(tp, 0x8012, 0, BIT(14));
+		sram_set_bits(tp, 0x8012, BIT(11));
+		sram_set_bits(tp, 0x8012, BIT(14));
 		ocp_reg_set_bits(tp, 0xb576, BIT(0));
 		sram_write_w0w1(tp, 0x834a, 0xff00, 0x0700);
 		sram2_write_w0w1(tp, 0x8217, 0x3f00, 0x2a00);
@@ -8234,100 +8908,372 @@ static void r8157_hw_phy_cfg(struct r8152 *tp)
 		/* improve UBE */
 		ocp_reg_set_bits(tp, 0xbf0c, 0x7 << 11);
 		/* close Sparse NEC, improve connect 5EUU cable performance */
-		sram2_write_w0w1(tp, 0x88de, 0xff00, 0);
+		sram2_clr_bits(tp, 0x88de, 0xff00);
 		/* 5G slave compatibility issue */
 		sram2_write(tp, 0x80b4, 0x5195);
 
-		/* XG Test Mode
-		 * xgtstm_map_tbl for mdi_cap_sel
-		 */
-		sram_write(tp, 0x8370, 0x8671);
-		sram_write(tp, 0x8372, 0x86c8);
-		/* xgtstm_amp_map_tbl for  REG_IBX_UP_SHIFT_L */
-		sram_write(tp, 0x8401, 0x86c8);
-		sram_write(tp, 0x8403, 0x86da);
-		sram_write_w0w1(tp, 0x8406, 0x1800, 0x1000);
-		sram_write_w0w1(tp, 0x8408, 0x1800, 0x1000);
-		sram_write_w0w1(tp, 0x840a, 0x1800, 0x1000);
-		sram_write_w0w1(tp, 0x840c, 0x1800, 0x1000);
-		sram_write_w0w1(tp, 0x840e, 0x1800, 0x1000);
-		sram_write_w0w1(tp, 0x8410, 0x1800, 0x1000);
-		sram_write_w0w1(tp, 0x8412, 0x1800, 0x1000);
-		sram_write_w0w1(tp, 0x8414, 0x1800, 0x1000);
-		sram_write_w0w1(tp, 0x8416, 0x1800, 0x1000);
+		/* XG Test Mode
+		 * xgtstm_map_tbl for mdi_cap_sel
+		 */
+		sram_write(tp, 0x8370, 0x8671);
+		sram_write(tp, 0x8372, 0x86c8);
+		/* xgtstm_amp_map_tbl for  REG_IBX_UP_SHIFT_L */
+		sram_write(tp, 0x8401, 0x86c8);
+		sram_write(tp, 0x8403, 0x86da);
+		sram_write_w0w1(tp, 0x8406, 0x1800, 0x1000);
+		sram_write_w0w1(tp, 0x8408, 0x1800, 0x1000);
+		sram_write_w0w1(tp, 0x840a, 0x1800, 0x1000);
+		sram_write_w0w1(tp, 0x840c, 0x1800, 0x1000);
+		sram_write_w0w1(tp, 0x840e, 0x1800, 0x1000);
+		sram_write_w0w1(tp, 0x8410, 0x1800, 0x1000);
+		sram_write_w0w1(tp, 0x8412, 0x1800, 0x1000);
+		sram_write_w0w1(tp, 0x8414, 0x1800, 0x1000);
+		sram_write_w0w1(tp, 0x8416, 0x1800, 0x1000);
+
+		/* Cable Test Patch */
+		sram_write(tp, 0x82bd, 0x1f40);
+
+		/* Thermal sensor parameters */
+		ocp_reg_w0w1(tp, 0xbfb4, 0x07ff, 0x0328);
+		ocp_reg_write(tp, 0xbfb6, 0x3e14);
+
+		/* spdchg_gtx_shape_100M */
+		ocp_reg_write(tp, OCP_SRAM_ADDR, 0x81c4);
+		ocp_reg_write(tp, OCP_SRAM_DATA, 0x003b);
+		ocp_reg_write(tp, OCP_SRAM_DATA, 0x0086);
+		ocp_reg_write(tp, OCP_SRAM_DATA, 0x00b7);
+		ocp_reg_write(tp, OCP_SRAM_DATA, 0x00db);
+		ocp_reg_write(tp, OCP_SRAM_DATA, 0x00fe);
+		ocp_reg_write(tp, OCP_SRAM_DATA, 0x00fe);
+		ocp_reg_write(tp, OCP_SRAM_DATA, 0x00fe);
+		ocp_reg_write(tp, OCP_SRAM_DATA, 0x00fe);
+		ocp_reg_write(tp, OCP_SRAM_DATA, 0x00c3);
+		ocp_reg_write(tp, OCP_SRAM_DATA, 0x0078);
+		ocp_reg_write(tp, OCP_SRAM_DATA, 0x0047);
+		ocp_reg_write(tp, OCP_SRAM_DATA, 0x0023);
+
+		/* lsbmsk_parameters
+		 * RL6961_lsbmsk_parameter_250207
+		 */
+		sram2_write(tp, 0x88d7, 0x01a0);
+		sram2_write(tp, 0x88d9, 0x01a0);
+		sram2_write(tp, 0x8ffa, 0x002a);
+
+		sram2_write(tp, 0x8fee, 0xffdf);
+		sram2_write(tp, 0x8ff0, 0xffff);
+		sram2_write(tp, 0x8ff2, 0x0a4a);
+		sram2_write(tp, 0x8ff4, 0xaa5a);
+		sram2_write(tp, 0x8ff6, 0x0a4a);
+		sram2_write(tp, 0x8ff8, 0xaa5a);
+
+		sram2_write_w0w1(tp, 0x88d5, 0xff00, 0x0200);
+
+		/* spdchg_pga1_lpf_cap */
+		sram_write_w0w1(tp, 0x84bb, 0xff00, 0x0a00);
+		sram_write_w0w1(tp, 0x84c0, 0xff00, 0x1600);
+
+		/* ENET PLL jitter improvement */
+		ocp_reg_w0w1(tp, 0xbf8a, 0xfc00, 0x2000);
+		ocp_reg_set_bits(tp, 0xbf88, BIT(2));
+		break;
+	default:
+		break;
+	}
+
+	if (rtl_phy_patch_request(tp, true, true))
+		return;
+
+	ocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, EEE_SPDWN_EN);
+
+	ocp_reg_clr_bits(tp, OCP_DOWN_SPEED,
+			 EN_EEE_100 | EN_EEE_1000 | EN_10M_CLKDIV);
+	tp->ups_info._10m_ckdiv = false;
+	tp->ups_info.eee_plloff_100 = false;
+	tp->ups_info.eee_plloff_giga = false;
+
+	ocp_reg_set_bits(tp, OCP_POWER_CFG, EEE_CLKDIV_EN);
+	tp->ups_info.eee_ckdiv = true;
+
+	rtl_phy_patch_request(tp, false, true);
+
+	rtl_green_en(tp, test_bit(GREEN_ETHERNET, &tp->flags));
+
+	ocp_reg_clr_bits(tp, 0xa428, BIT(9));
+	ocp_reg_clr_bits(tp, 0xa5ea, BIT(0) | BIT(1) | BIT(2));
+	tp->ups_info.lite_mode = 0;
+
+	rtl_eee_enable(tp, tp->eee_en);
+
+	r8153_aldps_en(tp, true);
+	r8152b_enable_fc(tp);
+
+	set_bit(PHY_RESET, &tp->flags);
+}
+
+static void r8156_init(struct r8152 *tp)
+{
+	u16 data;
+
+	if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
+		return;
+
+	ocp_byte_clr_bits(tp, MCU_TYPE_USB, USB_ECM_OP, EN_ALL_SPEED);
+
+	ocp_write_word(tp, MCU_TYPE_USB, USB_SPEED_OPTION, 0);
+
+	ocp_word_set_bits(tp, MCU_TYPE_USB, USB_ECM_OPTION, BYPASS_MAC_RESET);
+
+	r8153b_u1u2en(tp, false);
+
+	if (wait_autoload_done(tp))
+		return;
+
+	data = r8153_phy_status(tp, 0);
+	if (data == PHY_STAT_EXT_INIT)
+		ocp_reg_clr_bits(tp, 0xa468, BIT(3) | BIT(1));
+
+	r8152_mdio_test_and_clr_bit(tp, MII_BMCR, BMCR_PDOWN);
+
+	data = r8153_phy_status(tp, PHY_STAT_LAN_ON);
+
+	r8153_u2p3en(tp, false);
+
+	/* MSC timer = 0xfff * 8ms = 32760 ms */
+	ocp_write_word(tp, MCU_TYPE_USB, USB_MSC_TIMER, 0x0fff);
+
+	/* U1/U2/L1 idle timer. 500 us */
+	ocp_write_word(tp, MCU_TYPE_USB, USB_U1U2_TIMER, 500);
+
+	r8153b_power_cut_en(tp, false);
+	r8156_ups_en(tp, false);
+	r8153_queue_wake(tp, false);
+	rtl_runtime_suspend_enable(tp, false);
+
+	ocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_INDICATE_FALG, PREBOOT_OPTION);
+
+	ocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_RMT_WAKE, RMT_WAKE_EN);
+
+	if (tp->udev->speed >= USB_SPEED_SUPER)
+		r8153b_u1u2en(tp, true);
+
+	usb_enable_lpm(tp->udev);
+
+	rtl_fc_pause_pkt_en(tp, 0);
+
+	r8156_mac_clk_spd(tp, true);
+
+	ocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3,
+			  PLA_MCU_SPDWN_EN);
+
+	if (rtl8152_get_speed(tp) & LINK_STATUS)
+		ocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS,
+				  CUR_LINK_OK | POLL_LINK_CHG);
+	else
+		ocp_word_w0w1(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS, CUR_LINK_OK,
+			      POLL_LINK_CHG);
+
+	set_bit(GREEN_ETHERNET, &tp->flags);
+
+	ocp_word_clr_bits(tp, MCU_TYPE_USB, USB_USB_CTRL,
+			  RX_AGG_DISABLE | RX_ZERO_EN);
+
+	ocp_byte_set_bits(tp, MCU_TYPE_USB, USB_BMU_CONFIG, ACT_ODMA);
+
+	r8156_mdio_force_mode(tp);
+	rtl_tally_reset(tp);
+
+	tp->coalesce = 15000; /* 15 us */
+}
+
+static void r8156b_u2phy_backup(struct r8152 *tp)
+{
+	ocp_write_word(tp, MCU_TYPE_USB, 0xd3ce, 0x181b);
+	ocp_write_dword(tp, MCU_TYPE_USB, 0xd3d0, 0x616ccd99);
+	ocp_write_dword(tp, MCU_TYPE_USB, 0xd3d4, 0x08fc8101);
+	ocp_write_dword(tp, MCU_TYPE_USB, 0xd3d8, 0x159b1100);
+	ocp_write_word(tp, MCU_TYPE_USB, 0xd3dc, 0x0a00);
+}
+
+static void r8156b_init(struct r8152 *tp)
+{
+	u16 data;
+
+	if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
+		return;
+
+	ocp_byte_clr_bits(tp, MCU_TYPE_USB, USB_ECM_OP, EN_ALL_SPEED);
+
+	ocp_write_word(tp, MCU_TYPE_USB, USB_SPEED_OPTION, 0);
+
+	ocp_word_set_bits(tp, MCU_TYPE_USB, USB_ECM_OPTION, BYPASS_MAC_RESET);
+
+	ocp_word_set_bits(tp, MCU_TYPE_USB, USB_U2P3_CTRL, RX_DETECT8);
+
+	r8153b_u1u2en(tp, false);
+
+	switch (tp->version) {
+	case RTL_VER_13:
+	case RTL_VER_15:
+		r8156b_wait_loading_flash(tp);
+		break;
+	default:
+		break;
+	}
+
+	if (wait_autoload_done(tp))
+		return;
+
+	data = r8153_phy_status(tp, 0);
+	if (data == PHY_STAT_EXT_INIT) {
+		ocp_reg_clr_bits(tp, 0xa468, BIT(3) | BIT(1));
+		ocp_reg_clr_bits(tp, 0xa466, BIT(0));
+	}
+
+	r8152_mdio_test_and_clr_bit(tp, MII_BMCR, BMCR_PDOWN);
+
+	data = r8153_phy_status(tp, PHY_STAT_LAN_ON);
+
+	r8153_u2p3en(tp, false);
+
+	/* MSC timer = 0xfff * 8ms = 32760 ms */
+	ocp_write_word(tp, MCU_TYPE_USB, USB_MSC_TIMER, 0x0fff);
+
+	/* U1/U2/L1 idle timer. 500 us */
+	ocp_write_word(tp, MCU_TYPE_USB, USB_U1U2_TIMER, 500);
+
+	r8156b_u2phy_backup(tp);
+
+	r8153b_power_cut_en(tp, false);
+	r8156_ups_en(tp, false);
+	r8153_queue_wake(tp, false);
+	rtl_runtime_suspend_enable(tp, false);
+
+	ocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_INDICATE_FALG, PREBOOT_OPTION);
+
+	ocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_RMT_WAKE, RMT_WAKE_EN);
+
+	if (tp->udev->speed >= USB_SPEED_SUPER)
+		r8153b_u1u2en(tp, true);
+
+	usb_enable_lpm(tp->udev);
+
+	rtl_fc_pause_pkt_en(tp, 0);
+
+	/* Disable Auto Speed up */
+	ocp_word_clr_bits(tp, MCU_TYPE_USB, USB_FW_CTRL, AUTO_SPEEDUP);
+
+	r8156_mac_clk_spd(tp, true);
+
+	ocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3,
+			  PLA_MCU_SPDWN_EN);
+
+	if (rtl8152_get_speed(tp) & LINK_STATUS)
+		ocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS,
+				  CUR_LINK_OK | POLL_LINK_CHG);
+	else
+		ocp_word_w0w1(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS,
+			      CUR_LINK_OK, POLL_LINK_CHG);
+
+	set_bit(GREEN_ETHERNET, &tp->flags);
+
+	ocp_word_clr_bits(tp, MCU_TYPE_USB, USB_USB_CTRL,
+			  RX_AGG_DISABLE | RX_ZERO_EN);
+
+	r8156_mdio_force_mode(tp);
+	rtl_tally_reset(tp);
 
-		/* Cable Test Patch */
-		sram_write(tp, 0x82bd, 0x1f40);
+	tp->coalesce = 15000;	/* 15 us */
+}
 
-		/* Thermal sensor parameters */
-		ocp_reg_w0w1(tp, 0xbfb4, 0x07ff, 0x0328);
-		ocp_reg_write(tp, 0xbfb6, 0x3e14);
+static void r8157_init(struct r8152 *tp)
+{
+	u16 data;
 
-		/* spdchg_gtx_shape_100M */
-		ocp_reg_write(tp, OCP_SRAM_ADDR, 0x81c4);
-		ocp_reg_write(tp, OCP_SRAM_DATA, 0x003b);
-		ocp_reg_write(tp, OCP_SRAM_DATA, 0x0086);
-		ocp_reg_write(tp, OCP_SRAM_DATA, 0x00b7);
-		ocp_reg_write(tp, OCP_SRAM_DATA, 0x00db);
-		ocp_reg_write(tp, OCP_SRAM_DATA, 0x00fe);
-		ocp_reg_write(tp, OCP_SRAM_DATA, 0x00fe);
-		ocp_reg_write(tp, OCP_SRAM_DATA, 0x00fe);
-		ocp_reg_write(tp, OCP_SRAM_DATA, 0x00fe);
-		ocp_reg_write(tp, OCP_SRAM_DATA, 0x00c3);
-		ocp_reg_write(tp, OCP_SRAM_DATA, 0x0078);
-		ocp_reg_write(tp, OCP_SRAM_DATA, 0x0047);
-		ocp_reg_write(tp, OCP_SRAM_DATA, 0x0023);
+	if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
+		return;
 
-		/* lsbmsk_parameters
-		 * RL6961_lsbmsk_parameter_250207
-		 */
-		sram2_write(tp, 0x88d7, 0x01a0);
-		sram2_write(tp, 0x88d9, 0x01a0);
-		sram2_write(tp, 0x8ffa, 0x002a);
+	/* Enable SW reset */
+	ocp_byte_set_bits(tp, MCU_TYPE_USB, 0xcffe, BIT(3));
+	ocp_byte_clr_bits(tp, MCU_TYPE_USB, 0xd3ca, BIT(0));
 
-		sram2_write(tp, 0x8fee, 0xffdf);
-		sram2_write(tp, 0x8ff0, 0xffff);
-		sram2_write(tp, 0x8ff2, 0x0a4a);
-		sram2_write(tp, 0x8ff4, 0xaa5a);
-		sram2_write(tp, 0x8ff6, 0x0a4a);
-		sram2_write(tp, 0x8ff8, 0xaa5a);
+	ocp_byte_clr_bits(tp, MCU_TYPE_USB, USB_ECM_OP, EN_ALL_SPEED);
 
-		sram2_write_w0w1(tp, 0x88d5, 0xff00, 0x0200);
-		break;
+	ocp_word_set_bits(tp, MCU_TYPE_USB, USB_ECM_OPTION, BYPASS_MAC_RESET);
 
-	default:
-		break;
-	}
+	r8153b_u1u2en(tp, false);
 
-	if (rtl_phy_patch_request(tp, true, true))
+	r8156b_wait_loading_flash(tp);
+
+	if (wait_autoload_done(tp))
 		return;
 
-	ocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, EEE_SPDWN_EN);
+	data = r8153_phy_status(tp, 0);
+	if (data == PHY_STAT_EXT_INIT) {
+		ocp_reg_clr_bits(tp, 0xa468, BIT(3) | BIT(1));
+		ocp_reg_clr_bits(tp, 0xa466, BIT(0));
+	}
 
-	ocp_reg_w0w1(tp, OCP_DOWN_SPEED, EN_EEE_100 | EN_EEE_1000, EN_10M_CLKDIV);
+	r8152_mdio_test_and_clr_bit(tp, MII_BMCR, BMCR_PDOWN);
 
-	tp->ups_info._10m_ckdiv = true;
-	tp->ups_info.eee_plloff_100 = false;
-	tp->ups_info.eee_plloff_giga = false;
+	data = r8153_phy_status(tp, PHY_STAT_LAN_ON);
 
-	ocp_reg_set_bits(tp, OCP_POWER_CFG, EEE_CLKDIV_EN);
-	tp->ups_info.eee_ckdiv = true;
+	r8157_u2p3en(tp, false);
 
-	rtl_phy_patch_request(tp, false, true);
+	/* Disable Interrupt Mitigation */
+	ocp_byte_clr_bits(tp, MCU_TYPE_USB, 0xcf04,
+			  BIT(0) | BIT(1) | BIT(2) | BIT(7));
 
-	rtl_green_en(tp, test_bit(GREEN_ETHERNET, &tp->flags));
+	/* MSC timer = 0xfff * 8ms = 32760 ms */
+	ocp_write_word(tp, MCU_TYPE_USB, USB_MSC_TIMER, 0x0fff);
 
-	ocp_reg_clr_bits(tp, 0xa428, BIT(9));
-	ocp_reg_clr_bits(tp, 0xa5ea, BIT(0) | BIT(1));
-	tp->ups_info.lite_mode = 0;
+	/* U1/U2/L1 idle timer. 500 us */
+	ocp_write_word(tp, MCU_TYPE_USB, USB_U1U2_TIMER, 500);
 
-	if (tp->eee_en)
-		rtl_eee_enable(tp, true);
+	r8157_power_cut_en(tp, false);
+	r8157_ups_en(tp, false);
+	r8153_queue_wake(tp, false);
+	rtl_runtime_suspend_enable(tp, false);
 
-	r8153_aldps_en(tp, true);
-	r8152b_enable_fc(tp);
+	ocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_INDICATE_FALG, PREBOOT_OPTION);
 
-	set_bit(PHY_RESET, &tp->flags);
+	ocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_RMT_WAKE, RMT_WAKE_EN);
+
+	/* Clear Warm RST / Bus RST event flag */
+	ocp_word_clr_bits(tp, MCU_TYPE_USB, 0xcd06, BIT(11));
+
+	if (tp->udev->speed >= USB_SPEED_SUPER)
+		r8153b_u1u2en(tp, true);
+
+	usb_enable_lpm(tp->udev);
+
+	/* Disable Auto Speed up */
+	ocp_word_clr_bits(tp, MCU_TYPE_USB, USB_FW_CTRL, AUTO_SPEEDUP);
+
+	r8156_mac_clk_spd(tp, true);
+
+	if (rtl8152_get_speed(tp) & LINK_STATUS)
+		ocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS,
+				  CUR_LINK_OK | POLL_LINK_CHG);
+	else
+		ocp_word_w0w1(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS,
+			      CUR_LINK_OK, POLL_LINK_CHG);
+
+	set_bit(GREEN_ETHERNET, &tp->flags);
+
+	/* RX aggregation / 16 bytes RX descriptor / Bulk In End transfer */
+	ocp_word_clr_bits(tp, MCU_TYPE_USB, USB_USB_CTRL,
+			  RX_AGG_DISABLE | RX_DESC_16B | RX_END_TRANSFER_EN);
+
+	/* Disable Rx Zero Len */
+	rtl_bmu_clr_bits(tp, 0x2300, BIT(3));
+
+	/* TX descriptor Signature */
+	ocp_byte_clr_bits(tp, MCU_TYPE_USB, 0xd4ae, BIT(1));
+
+	r8156_mdio_force_mode(tp);
+	rtl_tally_reset(tp);
+
+	tp->coalesce = 15000;	/* 15 us */
 }
 
 static int r8159_wait_backup_restore(struct r8152 *tp)
@@ -8342,78 +9288,50 @@ static int r8159_wait_backup_restore(struct r8152 *tp)
 			       ocp_data & BACKUP_RESTRORE, 200, 20000, false);
 }
 
-static void r8156_init(struct r8152 *tp)
+static void r8159_init(struct r8152 *tp)
 {
-	u32 ocp_data;
 	u16 data;
-	int i;
 
 	if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
 		return;
 
-	if (tp->version == RTL_VER_16 || tp->version == RTL_VER_17) {
-		ocp_byte_set_bits(tp, MCU_TYPE_USB, 0xcffe, BIT(3));
-		ocp_byte_clr_bits(tp, MCU_TYPE_USB, 0xd3ca, BIT(0));
-	}
+	/* Enable SW reset */
+	ocp_byte_set_bits(tp, MCU_TYPE_USB, 0xcffe, BIT(3));
+	ocp_byte_clr_bits(tp, MCU_TYPE_USB, 0xd3ca, BIT(0));
 
 	ocp_byte_clr_bits(tp, MCU_TYPE_USB, USB_ECM_OP, EN_ALL_SPEED);
 
-	if (tp->version < RTL_VER_16)
-		ocp_write_word(tp, MCU_TYPE_USB, USB_SPEED_OPTION, 0);
-
 	ocp_word_set_bits(tp, MCU_TYPE_USB, USB_ECM_OPTION, BYPASS_MAC_RESET);
 
-	if (tp->version >= RTL_VER_12 && tp->version <= RTL_VER_15)
-		ocp_word_set_bits(tp, MCU_TYPE_USB, USB_U2P3_CTRL, RX_DETECT8);
-
 	r8153b_u1u2en(tp, false);
 
-	switch (tp->version) {
-	case RTL_VER_13:
-	case RTL_VER_15:
-	case RTL_VER_16:
-	case RTL_VER_17:
-		r8156b_wait_loading_flash(tp);
-		break;
-	default:
-		break;
-	}
-
-	for (i = 0; i < 500; i++) {
-		if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) &
-		    AUTOLOAD_DONE)
-			break;
+	r8156b_wait_loading_flash(tp);
 
-		msleep(20);
-		if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
-			return;
-	}
+	if (wait_autoload_done(tp))
+		return;
 
-	if (tp->version == RTL_VER_17 && r8159_wait_backup_restore(tp)) {
+	if (r8159_wait_backup_restore(tp)) {
 		rtl_set_inaccessible(tp);
-		dev_err(&tp->intf->dev, "init failed, backup-restore timed out\n");
+		dev_err(&tp->intf->dev,
+			"init failed, backup-restore timed out\n");
 		return;
 	}
 
 	data = r8153_phy_status(tp, 0);
 	if (data == PHY_STAT_EXT_INIT) {
 		ocp_reg_clr_bits(tp, 0xa468, BIT(3) | BIT(1));
-		if (tp->version >= RTL_VER_12)
-			ocp_reg_clr_bits(tp, 0xa466, BIT(0));
+		ocp_reg_clr_bits(tp, 0xa466, BIT(0));
 	}
 
-	data = r8152_mdio_read(tp, MII_BMCR);
-	if (data & BMCR_PDOWN) {
-		data &= ~BMCR_PDOWN;
-		r8152_mdio_write(tp, MII_BMCR, data);
-	}
+	r8152_mdio_test_and_clr_bit(tp, MII_BMCR, BMCR_PDOWN);
 
 	data = r8153_phy_status(tp, PHY_STAT_LAN_ON);
 
-	if (tp->version >= RTL_VER_16)
-		r8157_u2p3en(tp, false);
-	else
-		r8153_u2p3en(tp, false);
+	r8157_u2p3en(tp, false);
+
+	/* Disable Interrupt Mitigation */
+	ocp_byte_clr_bits(tp, MCU_TYPE_USB, 0xcf04,
+			  BIT(0) | BIT(1) | BIT(2) | BIT(7));
 
 	/* MSC timer = 0xfff * 8ms = 32760 ms */
 	ocp_write_word(tp, MCU_TYPE_USB, USB_MSC_TIMER, 0x0fff);
@@ -8421,72 +9339,56 @@ static void r8156_init(struct r8152 *tp)
 	/* U1/U2/L1 idle timer. 500 us */
 	ocp_write_word(tp, MCU_TYPE_USB, USB_U1U2_TIMER, 500);
 
-	if (tp->version >= RTL_VER_16)
-		r8157_power_cut_en(tp, false);
-	else
-		r8153b_power_cut_en(tp, false);
-
-	r8156_ups_en(tp, false);
+	r8157_power_cut_en(tp, false);
+	r8157_ups_en(tp, false);
 	r8153_queue_wake(tp, false);
 	rtl_runtime_suspend_enable(tp, false);
 
-	if (tp->udev->speed >= USB_SPEED_SUPER)
-		r8153b_u1u2en(tp, true);
+	ocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_INDICATE_FALG, PREBOOT_OPTION);
 
-	usb_enable_lpm(tp->udev);
+	ocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_RMT_WAKE, RMT_WAKE_EN);
 
-	if (tp->version >= RTL_VER_12 && tp->version <= RTL_VER_15) {
-		ocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_RCR, SLOT_EN);
+	/* Clear Warm RST / Bus RST event flag */
+	ocp_word_clr_bits(tp, MCU_TYPE_USB, 0xcd06, BIT(11));
 
-		ocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_CPCR, FLOW_CTRL_EN);
+	/* Disable FW u1u2 patch option */
+	ocp_byte_clr_bits(tp, MCU_TYPE_USB, 0xb9a6, BIT(0));
 
-		/* enable fc timer and set timer to 600 ms. */
-		ocp_write_word(tp, MCU_TYPE_USB, USB_FC_TIMER, CTRL_TIMER_EN | (600 / 8));
+	if (tp->udev->speed >= USB_SPEED_SUPER)
+		r8153b_u1u2en(tp, true);
 
-		ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_FW_CTRL);
-		if (!(ocp_read_word(tp, MCU_TYPE_PLA, PLA_POL_GPIO_CTRL) & DACK_DET_EN))
-			ocp_data |= FLOW_CTRL_PATCH_2;
-		ocp_data &= ~AUTO_SPEEDUP;
-		ocp_write_word(tp, MCU_TYPE_USB, USB_FW_CTRL, ocp_data);
+	usb_enable_lpm(tp->udev);
 
-		ocp_word_set_bits(tp, MCU_TYPE_USB, USB_FW_TASK, FC_PATCH_TASK);
-	}
+	/* Disable Auto Speed up */
+	ocp_word_clr_bits(tp, MCU_TYPE_USB, USB_FW_CTRL, AUTO_SPEEDUP);
 
 	r8156_mac_clk_spd(tp, true);
 
-	if (tp->version < RTL_VER_16)
-		ocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, PLA_MCU_SPDWN_EN);
-
-	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS);
 	if (rtl8152_get_speed(tp) & LINK_STATUS)
-		ocp_data |= CUR_LINK_OK;
+		ocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS,
+				  CUR_LINK_OK | POLL_LINK_CHG);
 	else
-		ocp_data &= ~CUR_LINK_OK;
-	ocp_data |= POLL_LINK_CHG;
-	ocp_write_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS, ocp_data);
+		ocp_word_w0w1(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS,
+			      CUR_LINK_OK, POLL_LINK_CHG);
 
 	set_bit(GREEN_ETHERNET, &tp->flags);
 
-	/* RX aggregation / 16 bytes RX descriptor
-	 * BIT(11) is specific to RTL8159, with unknown meaning
-	 */
-	if (tp->version == RTL_VER_17)
-		ocp_word_clr_bits(tp, MCU_TYPE_USB, USB_USB_CTRL,
-				  RX_AGG_DISABLE | RX_DESC_16B | BIT(11));
-	else if (tp->version == RTL_VER_16)
-		ocp_word_clr_bits(tp, MCU_TYPE_USB, USB_USB_CTRL, RX_AGG_DISABLE | RX_DESC_16B);
-	else
-		ocp_word_clr_bits(tp, MCU_TYPE_USB, USB_USB_CTRL, RX_AGG_DISABLE | RX_ZERO_EN);
+	/* RX aggregation / 16 bytes RX descriptor / Bulk In End transfer */
+	ocp_word_clr_bits(tp, MCU_TYPE_USB, USB_USB_CTRL,
+			  RX_AGG_DISABLE | RX_DESC_16B | RX_END_TRANSFER_EN);
 
-	if (tp->version < RTL_VER_12)
-		ocp_byte_set_bits(tp, MCU_TYPE_USB, USB_BMU_CONFIG, ACT_ODMA);
+	/* Disable Rx Zero Len */
+	rtl_bmu_clr_bits(tp, 0x2300, BIT(3));
 
-	if (tp->version >= RTL_VER_16) {
-		/* Disable Rx Zero Len */
-		rtl_bmu_clr_bits(tp, 0x2300, BIT(3));
-		/* TX descriptor Signature */
-		ocp_byte_clr_bits(tp, MCU_TYPE_USB, 0xd4ae, BIT(1));
-	}
+	/* TX descriptor Signature */
+	ocp_byte_clr_bits(tp, MCU_TYPE_USB, 0xd4ae, BIT(1));
+
+	/* Enable u2phy backup restore patch */
+	if (tp->version == RTL_VER_17_QFN68)
+		ocp_byte_set_bits(tp, MCU_TYPE_USB, 0xb99c, BIT(0));
+
+	/* Enable u3phy patch backup */
+	ocp_write_word(tp, MCU_TYPE_USB, 0xb9a2, 0x0448);
 
 	r8156_mdio_force_mode(tp);
 	rtl_tally_reset(tp);
@@ -8926,8 +9828,16 @@ int rtl8152_get_link_ksettings(struct net_device *netdev,
 			 cmd->link_modes.supported, tp->support_10000full);
 
 	if (tp->support_2500full || tp->support_5000full || tp->support_10000full) {
-		u16 ocp_10gbt_ctrl = ocp_reg_read(tp, OCP_10GBT_CTRL);
-		u16 ocp_10gbt_stat = ocp_reg_read(tp, OCP_10GBT_STAT);
+		u16 ocp_10gbt_ctrl;
+		u16 ocp_10gbt_stat;
+
+		ret = ocp_reg_read(tp, OCP_10GBT_CTRL, &ocp_10gbt_ctrl);
+		if (ret < 0)
+			goto out_unlock;
+
+		ret = ocp_reg_read(tp, OCP_10GBT_STAT, &ocp_10gbt_stat);
+		if (ret < 0)
+			goto out_unlock;
 
 		if (tp->support_2500full) {
 			linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
@@ -8969,12 +9879,13 @@ int rtl8152_get_link_ksettings(struct net_device *netdev,
 		}
 	}
 
+out_unlock:
 	mutex_unlock(&tp->control);
 
 	usb_autopm_put_interface(tp->intf);
 
 out:
-	return ret;
+	return ret < 0 ? ret : 0;
 }
 
 static int rtl8152_set_link_ksettings(struct net_device *dev,
@@ -9155,21 +10066,37 @@ static int r8153_get_eee(struct r8152 *tp, struct ethtool_keee *eee)
 	__ETHTOOL_DECLARE_LINK_MODE_MASK(common) = {};
 	u16 speed = rtl8152_get_speed(tp);
 	u16 val;
+	int ret;
+
+	ret = ocp_reg_read(tp, OCP_EEE_ABLE, &val);
+	if (ret < 0)
+		goto out;
 
-	val = ocp_reg_read(tp, OCP_EEE_ABLE);
 	mii_eee_cap1_mod_linkmode_t(eee->supported, val);
 
-	val = ocp_reg_read(tp, OCP_EEE_ADV);
+	ret = ocp_reg_read(tp, OCP_EEE_ADV, &val);
+	if (ret < 0)
+		goto out;
+
 	mii_eee_cap1_mod_linkmode_t(eee->advertised, val);
 
-	val = ocp_reg_read(tp, OCP_EEE_LPABLE);
+	ret = ocp_reg_read(tp, OCP_EEE_LPABLE, &val);
+	if (ret < 0)
+		goto out;
+
 	mii_eee_cap1_mod_linkmode_t(eee->lp_advertised, val);
 
 	if (tp->support_2500full || tp->support_5000full) {
-		val = ocp_reg_read(tp, OCP_EEE_ADV2);
+		ret = ocp_reg_read(tp, OCP_EEE_ADV2, &val);
+		if (ret < 0)
+			goto out;
+
 		mii_eee_cap2_mod_linkmode_adv_t(eee->advertised, val);
 
-		val = ocp_reg_read(tp, OCP_EEE_LPABLE2);
+		ret = ocp_reg_read(tp, OCP_EEE_LPABLE2, &val);
+		if (ret < 0)
+			goto out;
+
 		mii_eee_cap2_mod_linkmode_adv_t(eee->lp_advertised, val);
 	}
 
@@ -9205,7 +10132,8 @@ static int r8153_get_eee(struct r8152 *tp, struct ethtool_keee *eee)
 	linkmode_and(common, common, eee->lp_advertised);
 	eee->eee_active = !linkmode_empty(common);
 
-	return 0;
+out:
+	return ret < 0 ? ret : 0;
 }
 
 static int
@@ -9445,7 +10373,7 @@ static int rtl8152_set_ringparam(struct net_device *netdev,
 static void rtl8152_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause)
 {
 	struct r8152 *tp = netdev_priv(netdev);
-	u16 bmcr, lcladv, rmtadv;
+	int bmcr, lcladv, rmtadv;
 	u8 cap;
 
 	if (usb_autopm_get_interface(tp->intf) < 0)
@@ -9461,7 +10389,10 @@ static void rtl8152_get_pauseparam(struct net_device *netdev, struct ethtool_pau
 
 	usb_autopm_put_interface(tp->intf);
 
-	if (!(bmcr & BMCR_ANENABLE)) {
+	/* Without a readable PHY, or with autoneg off, there is no flow
+	 * control to report.
+	 */
+	if (bmcr < 0 || lcladv < 0 || rmtadv < 0 || !(bmcr & BMCR_ANENABLE)) {
 		pause->autoneg = 0;
 		pause->rx_pause = 0;
 		pause->tx_pause = 0;
@@ -9492,7 +10423,11 @@ static int rtl8152_set_pauseparam(struct net_device *netdev, struct ethtool_paus
 
 	mutex_lock(&tp->control);
 
-	if (pause->autoneg && !(r8152_mdio_read(tp, MII_BMCR) & BMCR_ANENABLE)) {
+	ret = r8152_mdio_read(tp, MII_BMCR);
+	if (ret < 0)
+		goto out;
+
+	if (pause->autoneg && !(ret & BMCR_ANENABLE)) {
 		ret = -EINVAL;
 		goto out;
 	}
@@ -9503,16 +10438,20 @@ static int rtl8152_set_pauseparam(struct net_device *netdev, struct ethtool_paus
 	if (pause->tx_pause)
 		cap |= FLOW_CTRL_TX;
 
-	old = r8152_mdio_read(tp, MII_ADVERTISE);
+	ret = r8152_mdio_read(tp, MII_ADVERTISE);
+	if (ret < 0)
+		goto out;
+
+	old = ret;
 	new1 = (old & ~(ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM)) | mii_advertise_flowctrl(cap);
 	if (old != new1)
-		r8152_mdio_write(tp, MII_ADVERTISE, new1);
+		ret = r8152_mdio_write(tp, MII_ADVERTISE, new1);
 
 out:
 	mutex_unlock(&tp->control);
 	usb_autopm_put_interface(tp->intf);
 
-	return ret;
+	return ret < 0 ? ret : 0;
 }
 
 static const struct ethtool_ops ops = {
@@ -9546,7 +10485,7 @@ static int rtl8152_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
 {
 	struct r8152 *tp = netdev_priv(netdev);
 	struct mii_ioctl_data *data = if_mii(rq);
-	int res;
+	int res, val;
 
 	if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
 		return -ENODEV;
@@ -9562,7 +10501,11 @@ static int rtl8152_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
 
 	case SIOCGMIIREG:
 		mutex_lock(&tp->control);
-		data->val_out = r8152_mdio_read(tp, data->reg_num);
+		val = r8152_mdio_read(tp, data->reg_num);
+		if (val < 0)
+			res = val;
+		else
+			data->val_out = val;
 		mutex_unlock(&tp->control);
 		break;
 
@@ -9572,7 +10515,7 @@ static int rtl8152_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
 			break;
 		}
 		mutex_lock(&tp->control);
-		r8152_mdio_write(tp, data->reg_num, data->val_in);
+		res = r8152_mdio_write(tp, data->reg_num, data->val_in);
 		mutex_unlock(&tp->control);
 		break;
 
@@ -9663,11 +10606,6 @@ static void rtl8153_unload(struct r8152 *tp)
 		return;
 
 	r8153_power_cut_en(tp, false);
-
-	if (tp->version >= RTL_VER_16) {
-		/* Disable Interrupt Mitigation */
-		ocp_byte_clr_bits(tp, MCU_TYPE_USB, 0xcf04, BIT(0) | BIT(1) | BIT(2) | BIT(7));
-	}
 }
 
 static void rtl8153b_unload(struct r8152 *tp)
@@ -9678,6 +10616,16 @@ static void rtl8153b_unload(struct r8152 *tp)
 	r8153b_power_cut_en(tp, false);
 }
 
+static void rtl8157_unload(struct r8152 *tp)
+{
+	if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
+		return;
+
+	r8157_power_cut_en(tp, false);
+	ocp_byte_clr_bits(tp, MCU_TYPE_USB, 0xcf04,
+			  BIT(0) | BIT(1) | BIT(2) | BIT(7));
+}
+
 static int r8152_desc_init(struct r8152 *tp)
 {
 	tp->rx_desc.size = sizeof(struct rx_desc);
@@ -9730,6 +10678,8 @@ static int rtl_ops_init(struct r8152 *tp)
 		ops->in_nway		= rtl8152_in_nway;
 		ops->hw_phy_cfg		= r8152b_hw_phy_cfg;
 		ops->autosuspend_en	= rtl_runtime_suspend_enable;
+		ops->phy_read		= r8152_phy_read;
+		ops->phy_write		= r8152_phy_write;
 		tp->rx_buf_sz		= 16 * 1024;
 		tp->eee_en		= true;
 		tp->eee_adv		= MDIO_EEE_100TX;
@@ -9752,6 +10702,8 @@ static int rtl_ops_init(struct r8152 *tp)
 		ops->hw_phy_cfg		= r8153_hw_phy_cfg;
 		ops->autosuspend_en	= rtl8153_runtime_enable;
 		ops->change_mtu		= rtl8153_change_mtu;
+		ops->phy_read		= r8152_phy_read;
+		ops->phy_write		= r8152_phy_write;
 		if (tp->udev->speed < USB_SPEED_SUPER)
 			tp->rx_buf_sz	= 16 * 1024;
 		else
@@ -9775,6 +10727,8 @@ static int rtl_ops_init(struct r8152 *tp)
 		ops->hw_phy_cfg		= r8153b_hw_phy_cfg;
 		ops->autosuspend_en	= rtl8153b_runtime_enable;
 		ops->change_mtu		= rtl8153_change_mtu;
+		ops->phy_read		= r8152_phy_read;
+		ops->phy_write		= r8152_phy_write;
 		tp->rx_buf_sz		= 32 * 1024;
 		tp->eee_en		= true;
 		tp->eee_adv		= MDIO_EEE_1000T | MDIO_EEE_100TX;
@@ -9799,6 +10753,8 @@ static int rtl_ops_init(struct r8152 *tp)
 		ops->hw_phy_cfg		= r8156_hw_phy_cfg;
 		ops->autosuspend_en	= rtl8156_runtime_enable;
 		ops->change_mtu		= rtl8156_change_mtu;
+		ops->phy_read		= r8152_phy_read;
+		ops->phy_write		= r8152_phy_write;
 		tp->rx_buf_sz		= 48 * 1024;
 		tp->support_2500full	= 1;
 		r8152_desc_init(tp);
@@ -9812,8 +10768,8 @@ static int rtl_ops_init(struct r8152 *tp)
 		tp->eee_en		= true;
 		tp->eee_adv		= MDIO_EEE_1000T | MDIO_EEE_100TX;
 		tp->eee_adv2		= MDIO_EEE_2_5GT;
-		ops->init		= r8156_init;
-		ops->enable		= rtl8156_enable;
+		ops->init		= r8156b_init;
+		ops->enable		= rtl8156b_enable;
 		ops->disable		= rtl8153_disable;
 		ops->up			= rtl8156_up;
 		ops->down		= rtl8156_down;
@@ -9824,6 +10780,8 @@ static int rtl_ops_init(struct r8152 *tp)
 		ops->hw_phy_cfg		= r8156b_hw_phy_cfg;
 		ops->autosuspend_en	= rtl8156_runtime_enable;
 		ops->change_mtu		= rtl8156_change_mtu;
+		ops->phy_read		= r8152_phy_read;
+		ops->phy_write		= r8152_phy_write;
 		tp->rx_buf_sz		= 48 * 1024;
 		r8152_desc_init(tp);
 		break;
@@ -9841,6 +10799,8 @@ static int rtl_ops_init(struct r8152 *tp)
 		ops->hw_phy_cfg		= r8153c_hw_phy_cfg;
 		ops->autosuspend_en	= rtl8153c_runtime_enable;
 		ops->change_mtu		= rtl8153c_change_mtu;
+		ops->phy_read		= r8152_phy_read;
+		ops->phy_write		= r8152_phy_write;
 		tp->rx_buf_sz		= 32 * 1024;
 		tp->eee_en		= true;
 		tp->eee_adv		= MDIO_EEE_1000T | MDIO_EEE_100TX;
@@ -9851,40 +10811,45 @@ static int rtl_ops_init(struct r8152 *tp)
 		tp->eee_en		= true;
 		tp->eee_adv		= MDIO_EEE_1000T | MDIO_EEE_100TX;
 		tp->eee_adv2		= MDIO_EEE_2_5GT | MDIO_EEE_5GT;
-		ops->init		= r8156_init;
-		ops->enable		= rtl8156_enable;
+		ops->init		= r8157_init;
+		ops->enable		= rtl8157_enable;
 		ops->disable		= rtl8153_disable;
-		ops->up			= rtl8156_up;
-		ops->down		= rtl8156_down;
-		ops->unload		= rtl8153_unload;
+		ops->up			= rtl8157_up;
+		ops->down		= rtl8157_down;
+		ops->unload		= rtl8157_unload;
 		ops->eee_get		= r8153_get_eee;
 		ops->eee_set		= r8152_set_eee;
 		ops->in_nway		= rtl8153_in_nway;
 		ops->hw_phy_cfg		= r8157_hw_phy_cfg;
 		ops->autosuspend_en	= rtl8157_runtime_enable;
-		ops->change_mtu		= rtl8156_change_mtu;
+		ops->change_mtu		= rtl8157_change_mtu;
+		ops->phy_read		= r8157_phy_read;
+		ops->phy_write		= r8157_phy_write;
 		tp->rx_buf_sz		= 32 * 1024;
 		tp->support_2500full	= 1;
 		tp->support_5000full	= 1;
 		r8157_desc_init(tp);
 		break;
 
-	case RTL_VER_17:
+	case RTL_VER_17_QFN68:
+	case RTL_VER_17_QFN100:
 		tp->eee_en		= true;
 		tp->eee_adv		= MDIO_EEE_100TX | MDIO_EEE_1000T | MDIO_EEE_10GT;
 		tp->eee_adv2		= MDIO_EEE_2_5GT | MDIO_EEE_5GT;
-		ops->init		= r8156_init;
-		ops->enable		= rtl8156_enable;
+		ops->init		= r8159_init;
+		ops->enable		= rtl8157_enable;
 		ops->disable		= rtl8153_disable;
-		ops->up			= rtl8156_up;
-		ops->down		= rtl8156_down;
-		ops->unload		= rtl8153_unload;
+		ops->up			= rtl8157_up;
+		ops->down		= rtl8157_down;
+		ops->unload		= rtl8157_unload;
 		ops->eee_get		= r8153_get_eee;
 		ops->eee_set		= r8152_set_eee;
 		ops->in_nway		= rtl8153_in_nway;
-		ops->hw_phy_cfg		= r8157_hw_phy_cfg;
+		ops->hw_phy_cfg		= r8159_hw_phy_cfg;
 		ops->autosuspend_en	= rtl8157_runtime_enable;
-		ops->change_mtu		= rtl8156_change_mtu;
+		ops->change_mtu		= rtl8157_change_mtu;
+		ops->phy_read		= r8157_phy_read;
+		ops->phy_write		= r8157_phy_write;
 		tp->rx_buf_sz		= 48 * 1024;
 		tp->support_2500full	= 1;
 		tp->support_5000full	= 1;
@@ -9961,7 +10926,8 @@ static int rtl_fw_init(struct r8152 *tp)
 	case RTL_VER_16:
 		rtl_fw->fw_name		= FIRMWARE_8157_1;
 		break;
-	case RTL_VER_17:
+	case RTL_VER_17_QFN68:
+	case RTL_VER_17_QFN100:
 		rtl_fw->fw_name		= FIRMWARE_8159_1;
 		break;
 	default:
@@ -9971,9 +10937,38 @@ static int rtl_fw_init(struct r8152 *tp)
 	return 0;
 }
 
+static u32 __rtl_get_pkg_det(struct usb_device *udev)
+{
+	u32 pkg_det = 0;
+	__le32 *tmp;
+	int ret, i;
+
+	tmp = kmalloc_obj(*tmp);
+	if (!tmp)
+		return 0;
+
+	for (i = 0, ret = 0; i < 3 && ret != 4; i++)
+		ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+				      RTL8152_REQ_GET_REGS, RTL8152_REQT_READ,
+				      PLA_PKG_DET, MCU_TYPE_PLA, tmp,
+				      sizeof(*tmp), USB_CTRL_GET_TIMEOUT);
+
+	if (ret == sizeof(*tmp)) {
+		if (i != 1)
+			dev_warn(&udev->dev,
+				 "Needed %d retries to read package\n", i);
+
+		pkg_det = __le32_to_cpu(*tmp) & PKG_MASK;
+	}
+
+	kfree(tmp);
+	return pkg_det;
+}
+
 static u8 __rtl_get_hw_ver(struct usb_device *udev)
 {
 	u32 ocp_data = 0;
+	u32 pkg_det = 0;
 	__le32 *tmp;
 	u8 version;
 	int ret;
@@ -10056,7 +11051,16 @@ static u8 __rtl_get_hw_ver(struct usb_device *udev)
 		version = RTL_VER_16;
 		break;
 	case 0x2020:
-		version = RTL_VER_17;
+		pkg_det = __rtl_get_pkg_det(udev);
+		if (pkg_det == 0x1e || pkg_det == 0x1c) {
+			version = RTL_VER_17_QFN68;
+		} else if (pkg_det == 0x18 || pkg_det == 0x1a) {
+			version = RTL_VER_17_QFN100;
+		} else {
+			version = RTL_VER_UNKNOWN;
+			dev_info(&udev->dev, "Unknown package 0x%04x\n",
+				 pkg_det);
+		}
 		break;
 	default:
 		version = RTL_VER_UNKNOWN;
@@ -10215,7 +11219,8 @@ static int rtl8152_probe_once(struct usb_interface *intf,
 	case RTL_VER_13:
 	case RTL_VER_15:
 	case RTL_VER_16:
-	case RTL_VER_17:
+	case RTL_VER_17_QFN68:
+	case RTL_VER_17_QFN100:
 		netdev->max_mtu = size_to_mtu(16 * 1024);
 		break;
 	case RTL_VER_01:

3/2 2026/10/08 11:04 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 46496
							output: 36
							thoughts: 414
						

Thoughts:
**Evaluating the Linux Kernel Patch**

Okay, so I'm being asked to evaluate this patch series for the Linux kernel. My first step is always to understand *exactly* what this patch is doing and what it's modifying. It looks like the patch targets `drivers/net/usb/r8152.c`. Alright, let's refresh: I know that `r8152.c` is the USB networking driver for Realtek RTL8152, RTL8153, and similar USB Ethernet adapters. Standard stuff.

Now, a key question jumps to mind: Can we effectively test this with syzkaller? Specifically, can syzkaller's USB emulation be used to reach this code? I know syzkaller *does* have USB emulation, using Raw Gadget, dummy_hcd, and vusb. Let's make sure that is the case, and double check Section 1 and Section 2/3 of those important instructions again: they are key.

The instructions say that *reachability* is paramount. Fuzzing only works on code that can execute in a standard virtualized environment. USB gadgets are explicitly mentioned as an example, alongside netdev, tun/tap, etc. If the code is unreachable, it's not even worth fuzzing. The instructions confirm that drivers accessible via virtual buses, and that *includes* USB gadget drivers. Perfect! USB drivers are reachable via syzkaller's USB emulation (dummy_hcd/raw-gadget/vusb) so we are safe.

So, the next question is: *Specifically*, can `r8152` be reached through syzkaller's USB fuzzer? We have to ensure it's properly supported, and that these types of USB network drivers are reachable. To check, I'll need to dig into syzkaller's USB descriptions or the kernel configs for any mention of `r8152`. Let's see if we can use `grepper` to inspect the Kconfig files and gather some more details. Hopefully, it shows `r8152` is available to the emulated USB fuzzer.



4/2 2026/10/08 11:04 tool grepper
0m Args:
{
  "Expression": "config USB_RTL8152",
  "PathPrefixes": [
    "drivers/net/usb/"
  ]
}

Results:
{
  "Output": "drivers/net/usb/Kconfig=88=config USB_RTL8150\n--\ndrivers/net/usb/Kconfig-98-\ndrivers/net/usb/Kconfig:99:config USB_RTL8152\ndrivers/net/usb/Kconfig-100-\ttristate \"Realtek RTL8152/RTL8153 Based USB Ethernet Adapters\"\n"
}

5/2 2026/10/08 11:04 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 47515
							output: 35
							thoughts: 25
						

Thoughts:
Okay, here's my take on those thoughts, tailored for an expert audience:

**Examining USB Networking Driver Configuration**

Right, let's dive in. I need to refresh my memory on the configuration options and dependencies for the USB networking drivers within the kernel. I'll head straight to `drivers/net/usb/Kconfig` and zero in around line 99. That's usually a good starting point to get a handle on the key choices – the core `CONFIG_USB_NET` and its related sub-options. I want to quickly see how it's structured, what other components are required, and what other platform-specific configurations it ties into. Is there anything unusual, or any recent commits impacting this section? This is where the real meat of the configuration magic happens; this Kconfig file is the true source of truth for the available drivers. I need to understand this to determine the cause, or any possible options, for my question.



6/2 2026/10/08 11:04 tool read-file
0m Args:
{
  "File": "drivers/net/usb/Kconfig",
  "FirstLine": 95,
  "LineCount": 25
}

Results:
{
  "Contents": "  95:\t\n  96:\t\t  To compile this driver as a module, choose M here: the\n  97:\t\t  module will be called rtl8150.\n  98:\t\n  99:\tconfig USB_RTL8152\n 100:\t\ttristate \"Realtek RTL8152/RTL8153 Based USB Ethernet Adapters\"\n 101:\t\tselect MII\n 102:\t\tselect PHYLIB\n 103:\t\tselect CRC32\n 104:\t\tselect CRYPTO_LIB_SHA256\n 105:\t\thelp\n 106:\t\t  This option adds support for Realtek RTL8152 based USB 2.0\n 107:\t\t  10/100 Ethernet adapters and RTL8153 based USB 3.0 10/100/1000\n 108:\t\t  Ethernet adapters.\n 109:\t\n 110:\t\t  To compile this driver as a module, choose M here: the\n 111:\t\t  module will be called r8152.\n 112:\t\n 113:\tconfig USB_LAN78XX\n 114:\t\ttristate \"Microchip LAN78XX Based USB Ethernet Adapters\"\n 115:\t\tselect MII\n 116:\t\tselect PHYLINK\n 117:\t\tselect MICROCHIP_PHY\n 118:\t\tselect CRC32\n 119:\t\timply NET_SELFTESTS\n"
}

7/2 2026/10/08 11:04 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 48168
							output: 34
							thoughts: 44
						

Thoughts:
Okay, let's dive into this. Here's how I'd approach this task, as if these were my internal thoughts:

**Investigating USB_RTL8152 Dependency**

Alright, my first step is to figure out what `USB_RTL8152` in `drivers/net/usb/Kconfig` relies on. Understanding its dependencies is crucial for any potential modifications or analysis. I'll need to trace back through that Kconfig file, essentially reconstructing the logical conditions that govern whether this driver gets built. I suspect there may be some broader USB or networking-related dependencies that I'll need to consider. A quick scan of `drivers/net/usb/Kconfig` will probably reveal the immediate dependencies and their hierarchical relationships. Knowing the broader context here will make the deeper dives much smoother.



8/2 2026/10/08 11:04 tool read-file
0m Args:
{
  "File": "drivers/net/usb/Kconfig",
  "FirstLine": 1,
  "LineCount": 40
}

Results:
{
  "Contents": "   1:\t# SPDX-License-Identifier: GPL-2.0-only\n   2:\t#\n   3:\t# USB Network devices configuration\n   4:\t#\n   5:\tcomment \"Host-side USB support is needed for USB Network Adapter support\"\n   6:\t\tdepends on !USB \u0026\u0026 NET\n   7:\t\n   8:\tmenuconfig USB_NET_DRIVERS\n   9:\t\ttristate \"USB Network Adapters\"\n  10:\t\tdefault USB if USB\n  11:\t\tdepends on USB \u0026\u0026 NET\n  12:\t\n  13:\tif USB_NET_DRIVERS\n  14:\t\n  15:\tconfig USB_CATC\n  16:\t\ttristate \"USB CATC NetMate-based Ethernet device support\"\n  17:\t\tselect CRC32\n  18:\t\thelp\n  19:\t\t  Say Y if you want to use one of the following 10Mbps USB Ethernet\n  20:\t\t  device based on the EL1210A chip. Supported devices are:\n  21:\t\t  Belkin F5U011\n  22:\t\t  Belkin F5U111\n  23:\t\t  CATC NetMate\n  24:\t\t  CATC NetMate II\n  25:\t\t  smartBridges smartNIC\n  26:\t\n  27:\t\t  This driver makes the adapter appear as a normal Ethernet interface,\n  28:\t\t  typically on eth0, if it is the only ethernet device, or perhaps on\n  29:\t\t  eth1, if you have a PCI or ISA ethernet card installed.\n  30:\t\n  31:\t\t  To compile this driver as a module, choose M here: the\n  32:\t\t  module will be called catc.\n  33:\t\n  34:\tconfig USB_KAWETH\n  35:\t\ttristate \"USB KLSI KL5USB101-based ethernet device support\"\n  36:\t\thelp\n  37:\t\t  Say Y here if you want to use one of the following 10Mbps only\n  38:\t\t  USB Ethernet adapters based on the KLSI KL5KUSB101B chipset:\n  39:\t\t  3Com 3C19250\n  40:\t\t  ADS USB-10BT\n"
}

9/2 2026/10/08 11:04 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 48983
							output: 36
							thoughts: 2701
						

Thoughts:
**Analysis of a Realtek RTL8152 USB Ethernet Driver Patch for Fuzzing**

Right, let's break this down. We've got a patch for `drivers/net/usb/r8152.c`, and the first thing I need to do is understand the context. The dependencies are clear: `USB_RTL8152` depends on `USB_NET_DRIVERS`, which in turn hinges on `USB` and `NET`.  Alright, got it. Standard network driver setup. The patch itself, judging by the diff, introduces a number of changes, the interesting part is the addition of assertions.

The commit message itself doesn't offer much insight, so we jumped right into the code changes.  The core changes involve phy access routines, phy reads/writes, error handling, new hardware support (RTL8157, RTL8159), and what looks like a refactoring of polling loops. Specifically, there are new `phy_read` and `phy_write` function pointers in the `rtl_ops` structure. We see extensive updates to read/write functions and also a number of `wait_tgphy_cmd_ready` functions, indicating new hardware support.

The crucial point, though, is the introduction of a `WARN_ON_ONCE` in `r8159_hw_phy_cfg`. This assertion checks `r8153_phy_status`, and the key here is that a fuzzed USB device *can* potentially trigger this `WARN_ON_ONCE`. The `r8153_phy_status` calls `OCP_PHY_STATUS` via USB control transfer, and syzkaller's USB fuzzing can send arbitrary data in response to that. Therefore, the warning *is* reachable, and it's a good target for fuzzing.

My primary concern, based on the fuzzing guidelines, is whether this code is reachable.  Since the driver's accessible via USB gadget emulation in syzkaller, we can fuzz it and trigger that warning! The key is that USB net devices are explicitly mentioned as reachable through software emulation, and syzkaller can emulate an RTL8152 device. We should be able to trigger this in a standard QEMU environment.  Once the device is enumerated, ioctls, ethtool calls, and up/down operations are all reachable.  The probe path itself calls `__rtl_get_hw_ver`, `__rtl_get_pkg_det`, etc. and calls the `r8159_init` and `r8159_hw_phy_cfg`.

Therefore, based on the fact that this code is reachable through a fuzzed USB device, it is *absolutely* worth fuzzing.

Now, for configuring this for fuzzing.  I need to identify the necessary kernel configs. `USB_RTL8152` is the obvious one, but let's check its dependencies. Inside `drivers/net/usb/Kconfig`, `USB_RTL8152` is part of `USB_NET_DRIVERS`, which depends on `USB` and `NET`. So the required configs are `USB_RTL8152`, `USB_NET_DRIVERS`, `USB`, and `NET`. However, since USB and NET are standard, including `USB_NET_DRIVERS` and `USB_RTL8152` is probably what we want.



10/2 2026/10/08 11:05 tool grepper
0m Args:
{
  "Expression": "CONFIG_",
  "PathPrefixes": [
    "drivers/net/usb/r8152.c"
  ]
}

Results:
{
  "Output": "drivers/net/usb/r8152.c=947=struct r8152 {\n--\ndrivers/net/usb/r8152.c-961-\tstruct mutex control;\t/* use for hw setting */\ndrivers/net/usb/r8152.c:962:#ifdef CONFIG_PM_SLEEP\ndrivers/net/usb/r8152.c-963-\tstruct notifier_block pm_notifier;\n--\ndrivers/net/usb/r8152.c=4616=static bool rtl_can_wakeup(struct r8152 *tp)\n--\ndrivers/net/usb/r8152.c-4619-\ndrivers/net/usb/r8152.c:4620:\treturn (udev-\u003eactconfig-\u003edesc.bmAttributes \u0026 USB_CONFIG_ATT_WAKEUP);\ndrivers/net/usb/r8152.c-4621-}\n--\ndrivers/net/usb/r8152.c=7645=static void rtl_hw_phy_work_func_t(struct work_struct *work)\n--\ndrivers/net/usb/r8152.c-7677-\ndrivers/net/usb/r8152.c:7678:#ifdef CONFIG_PM_SLEEP\ndrivers/net/usb/r8152.c-7679-static int rtl_notifier(struct notifier_block *nb, unsigned long action,\n--\ndrivers/net/usb/r8152.c=7705=static int rtl8152_open(struct net_device *netdev)\n--\ndrivers/net/usb/r8152.c-7744-\tusb_autopm_put_interface(tp-\u003eintf);\ndrivers/net/usb/r8152.c:7745:#ifdef CONFIG_PM_SLEEP\ndrivers/net/usb/r8152.c-7746-\ttp-\u003epm_notifier.notifier_call = rtl_notifier;\n--\ndrivers/net/usb/r8152.c=7760=static int rtl8152_close(struct net_device *netdev)\n--\ndrivers/net/usb/r8152.c-7764-\ndrivers/net/usb/r8152.c:7765:#ifdef CONFIG_PM_SLEEP\ndrivers/net/usb/r8152.c-7766-\tunregister_pm_notifier(\u0026tp-\u003epm_notifier);\n--\ndrivers/net/usb/r8152.c=11112=static int rtl8152_probe_once(struct usb_interface *intf,\n--\ndrivers/net/usb/r8152.c-11277-\ttp-\u003ertl_ops.init(tp);\ndrivers/net/usb/r8152.c:11278:#if IS_BUILTIN(CONFIG_USB_RTL8152)\ndrivers/net/usb/r8152.c-11279-\t/* Retry in case request_firmware() is not ready yet. */\n"
}

11/2 2026/10/08 11:05 llm patch-evaluator
1m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 53259
							output: 351
							thoughts: 2735
						

Thoughts:
**Analysis of Realtek USB Ethernet Driver Patch for Fuzzing**

Alright, let's break this down. First, it's clear this patch is targeting new Realtek USB Ethernet chipsets, specifically RTL8157 and RTL8159 variants (QFN68/QFN100). That's the core focus. The enabling configs are `USB_RTL8152` and `USB_NET_DRIVERS`, which makes sense.

Now, looking at the code, the changes are quite interesting. We're seeing additions for TGPHY register access via USB, a pause packet rate limiting function (`rtl_fc_pause_pkt_en`), package detection with `__rtl_get_pkg_det` – all key for new device support. Crucially, new initialization routines and PHY configuration functions are introduced:  `r8157_init`, `r8159_init`, `r8159_hw_phy_cfg`, etc.  This is where the new hardware support truly lies.

A significant improvement is the error handling.  We're seeing `ocp_reg_read`, `sram_read`, etc.  now returning error codes. Previously, they just ignored issues.  Timeout handling has also been refined, using `read_poll_timeout` and setting `RTL8152_INACCESSIBLE`. This is critical for robustness.

Then, there's `r8159_hw_phy_cfg` and that `WARN_ON_ONCE` – that's a red flag, and a potential target for fuzzing.  Specifically, if the emulated USB device returns something unexpected for `OCP_PHY_STATUS`, it triggers. This is prime fuzzing territory, particularly with syzkaller.

Reachability is key. We can trigger these functions through USB emulation (like syzkaller's Raw Gadget or a dummy HCD) and subsequent netdev operations: ioctl calls, ethtool commands, MTU adjustments, and bringing the interface up and down. Any emulated USB device with the right Realtek vendor/product IDs will hit this code path – probe, initialize, configure PHY, and then run. It's a nice, well-defined path.

Considering all this, we definitely want to fuzz this patch. WorthFuzzing = true, no question.

The important thing is targeting specific functions directly altered or added by the patch. No ubiquitous functions. The important functions are:

*   `rtl_fc_pause_pkt_en`
*   `r8159_hw_phy_cfg`
*   `r8157_hw_phy_cfg`
*   `r8157_init`
*   `r8159_init`
*   `r8156b_init`
*   `rtl8157_enable`
*   `rtl8156b_enable`
*   `rtl8157_up`
*   `rtl8157_down`
*   `rtl8157_change_mtu`
*   `rtl_tgphy_access`
*   `r8157_ups_en`
*   `__rtl_get_pkg_det`

These are all specific to the r8152 driver and changed by the patch.  No other files were touched besides `drivers/net/usb/r8152.c`.

With this focused set of symbols and enabling configs, we've got a solid plan for fuzzing.



12/2 2026/10/08 11:06 tool set-results
0m Args:
{
  "EnableConfigs": [
    "USB_RTL8152",
    "USB_NET_DRIVERS"
  ],
  "FocusSymbols": [
    "r8159_hw_phy_cfg",
    "r8157_hw_phy_cfg",
    "r8159_init",
    "r8157_init",
    "r8156b_init",
    "rtl8157_enable",
    "rtl8156b_enable",
    "rtl8157_up",
    "rtl8157_down",
    "rtl8157_change_mtu",
    "rtl_fc_pause_pkt_en",
    "rtl_tgphy_access",
    "r8157_ups_en",
    "__rtl_get_pkg_det"
  ],
  "Reasoning": "The patch adds support for newer Realtek RTL8157 and RTL8159 USB Ethernet controllers (splitting RTL_VER_17 into QFN68 and QFN100 variants), refactors PHY/SRAM read and write helpers to propagate errors, refactors polling loops, implements flow control pause packet limiting, and introduces new device initialization and PHY configuration logic. In addition, it adds a new assertion (WARN_ON_ONCE) in r8159_hw_phy_cfg(). The driver is fully reachable and fuzzable via USB emulation (such as Raw Gadget or dummy_hcd) and subsequent network device interface configuration and ethtool/ioctl operations.",
  "WorthFuzzing": true
}

Results:
{
  "EnableConfigs": [
    "USB_RTL8152",
    "USB_NET_DRIVERS"
  ],
  "FocusSymbols": [
    "r8159_hw_phy_cfg",
    "r8157_hw_phy_cfg",
    "r8159_init",
    "r8157_init",
    "r8156b_init",
    "rtl8157_enable",
    "rtl8156b_enable",
    "rtl8157_up",
    "rtl8157_down",
    "rtl8157_change_mtu",
    "rtl_fc_pause_pkt_en",
    "rtl_tgphy_access",
    "r8157_ups_en",
    "__rtl_get_pkg_det"
  ],
  "Reasoning": "The patch adds support for newer Realtek RTL8157 and RTL8159 USB Ethernet controllers (splitting RTL_VER_17 into QFN68 and QFN100 variants), refactors PHY/SRAM read and write helpers to propagate errors, refactors polling loops, implements flow control pause packet limiting, and introduces new device initialization and PHY configuration logic. In addition, it adds a new assertion (WARN_ON_ONCE) in r8159_hw_phy_cfg(). The driver is fully reachable and fuzzable via USB emulation (such as Raw Gadget or dummy_hcd) and subsequent network device interface configuration and ethtool/ioctl operations.",
  "WorthFuzzing": true
}

13/1 2026/10/08 11:06 action If
2m Args:
{
  "WorthFuzzing": true
}

Results:
null

14/2 2026/10/08 11:06 agent kmsan-evaluator
2m Model:
core

Args:
null

Results:
{
  "KMSANReasoning": "The patch refactors the r8152 USB Ethernet driver to support new hardware revisions (RTL8157 and RTL8159 variants) and updates register access helpers (ocp_reg_read, sram_read, etc.) to pass output data by pointer and return integer status codes for proper error handling.\n\nA careful examination of all modified and newly introduced code paths shows:\n1. No uninitialized kernel memory or structure padding is leaked to user space: ioctl and ethtool handlers (rtl8152_get_link_ksettings, r8153_get_eee, rtl8152_get_pauseparam, rtl8152_ioctl) now check return codes from register reads and abort or return appropriate errors instead of operating on or leaking uninitialized data.\n2. All out-parameters passed to register read functions are either guarded by return code checks or initialized prior to use.\n3. Heap allocations (such as in __rtl_get_pkg_det) only read the allocated buffer if usb_control_msg() returns the full expected size, and properly clean up afterwards.\n4. No network skb parsing or length manipulation is introduced that could lead to reading uninitialized bytes.\n\nConsequently, there are no uninitialized memory access or info-leak risks that would necessitate a dedicated KMSAN fuzzing session. Any potential issues (hardware timeouts, locking, logic bugs) are adequately addressed by standard testing and KASAN.",
  "NeedsKMSAN": false
}

Instruction:
You are an expert Linux kernel security engineer specializing in kernel memory
error detectors (KASAN and KMSAN). Your job is to review the provided patch series and
determine if the code changes justify spawning a dedicated KMSAN (KernelMemorySanitizer)
fuzzing session in addition to standard KASAN fuzzing.

CRITICAL DISTINCTION BETWEEN KASAN AND KMSAN:
- Standard KASAN kernel builds (upstream-apparmor-kasan.config) already enable
  a comprehensive suite of debugging tools and sanitizers, including KASAN
  (out-of-bounds accesses, use-after-free, double free, invalid free), LOCKDEP
  (locking bugs and deadlocks), UB-sanitizers, and memory corruption checks.
- KMSAN (KernelMemorySanitizer) detects reads of UNINITIALIZED memory (stack, heap,
  or page allocations) and kernel-to-user memory info-leaks.

Rule: THERE IS NO SENSE IN RUNNING A KMSAN SESSION IF A BUG CAN BE CAUGHT BY KASAN,
LOCKDEP, OR OTHER STANDARD BUG DETECTORS.
A dedicated KMSAN fuzzing session incurs significant resource costs. You must ONLY
set NeedsKMSAN=true if the code changes introduce or expose UNINITIALIZED MEMORY risks
that are detected ONLY by KMSAN.

Look holistically at the patch series and surrounding code. Even if no direct
uninitialized field accesses or new buffer allocations are added in the diff itself,
a patch may alter control flow, bounds checking, or data length calculations in ways
that change how the rest of the code operates on existing buffers (e.g. allowing
uninitialized stack/heap memory to be read, copied to user space, or used in control
flow). Do not hesitate to use your code access tools to inspect the surrounding code,
called functions, and callers.

Set NeedsKMSAN=true ONLY IF the patch introduces or modifies:
1. Kernel structures sent to user space (via copy_to_user, put_user, netlink skb
   attributes, ioctl output arguments, socket options, or BPF buffers) where fields
   or structure padding might not be fully initialized/zeroed.
2. Conditional logic or branching that depends on potentially uninitialized variables
   or struct fields.
3. Allocation or initialization of complex data structures where uninitialized fields
   could be read later in reachable code paths.
4. Bounds checks, lengths, or logic in a way that allows surrounding code to access
   uninitialized bytes of existing buffers.

Set NeedsKMSAN=false IF:
- The code changes primarily risk out-of-bounds access, array overflows, NULL pointer
  dereferences, locking deadlocks, or use-after-free bugs (these are already caught
  by KASAN, LOCKDEP, or standard bug detectors).
- All stack/heap structures touched or introduced by the patch are fully zeroed
  or initialized (e.g. using = {0}, memset, kzalloc) before being read or copied.
- The patch does not introduce any risk of uninitialized memory usage or info-leaks.

Use your code access tools to inspect the surrounding code if necessary, then provide
detailed KMSANReasoning contrasting KASAN vs KMSAN applicability for this patch.
Prefer calling several tools at the same time to save round-trips.


Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.

Prompt:
Target architecture: amd64

For your convenience, here is the diff of the changes:
commit 7c46fb3d692dd4fe361e4ece17399e3895e2c8a6
Author: syz-cluster <triage@syzkaller.com>
Date:   Thu Oct 8 11:04:01 2026 +0000

    syz-cluster: applied patch under review

diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index af3d7dcb2f141..fc75e263b0e4c 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -64,6 +64,7 @@
 #define PLA_MACDBG_POST		0xd38e	/* RTL_VER_04 only */
 #define PLA_EXTRA_STATUS	0xd398
 #define PLA_GPHY_CTRL		0xd3ae
+#define PLA_PKG_DET		0xdc48
 #define PLA_POL_GPIO_CTRL	0xdc6a
 #define PLA_EFUSE_DATA		0xdd00
 #define PLA_EFUSE_CMD		0xdd02
@@ -78,6 +79,7 @@
 #define PLA_EEE_TXTWSYS_2P5G	0xe058
 #define PLA_EEEP_CR		0xe080
 #define PLA_MAC_PWR_CTRL	0xe0c0
+#define PLA_RMT_WAKE		0xe0c8
 #define PLA_MAC_PWR_CTRL2	0xe0ca
 #define PLA_MAC_PWR_CTRL3	0xe0cc
 #define PLA_MAC_PWR_CTRL4	0xe0ce
@@ -87,6 +89,7 @@
 #define PLA_MTPS		0xe615
 #define PLA_TXFIFO_CTRL		0xe618
 #define PLA_TXFIFO_FULL		0xe61a
+#define PLA_PAUSE_LIMIT         0xe61e
 #define PLA_RSTTALLY		0xe800
 #define PLA_CR			0xe813
 #define PLA_CRWECR		0xe81c
@@ -129,6 +132,7 @@
 #define USB_BURST_SIZE		0xcfc0
 #define USB_FW_FIX_EN0		0xcfca
 #define USB_FW_FIX_EN1		0xcfcc
+#define USB_FW_USB_VER          0xcfd7
 #define USB_LPM_CONFIG		0xcfd8
 #define USB_ECM_OPTION		0xcfee
 #define USB_CSTMR		0xcfef	/* RTL8153A */
@@ -160,6 +164,9 @@
 #define USB_ADV_ADDR		0xd5d6
 #define USB_ADV_DATA		0xd5d8
 #define USB_ADV_CMD		0xd5dc
+#define USB_TGPHY_ADDR		0xd630
+#define USB_TGPHY_DATA		0xd632
+#define USB_TGPHY_CMD		0xd634
 #define USB_UPS_CTRL		0xd800
 #define USB_POWER_CUT		0xd80a
 #define USB_MISC_0		0xd81a
@@ -289,10 +296,17 @@
 #define IFG_144NS		BIT(9)
 #define IFG_96NS		(BIT(9) | BIT(8))
 
+/* PLA_PKG_DET */
+#define PKG_MASK		0x1e
+
 /* PLA_MTPS */
 #define MTPS_JUMBO		(12 * 1024 / 64)
 #define MTPS_DEFAULT		(6 * 1024 / 64)
 
+/* PLA_PAUSE_LIMIT */
+#define PAUSE_LIMIT_EN		BIT(3)
+#define PAUSE_LIMIT_MASK	0xf0
+
 /* PLA_RSTTALLY */
 #define TALLY_RESET		0x0001
 
@@ -371,6 +385,9 @@
 #define MCU_CLK_RATIO_MASK	0x0f0f0f0f
 #define ALDPS_SPDWN_RATIO	0x0f87
 
+/* PLA_RMT_WAKE */
+#define RMT_WAKE_EN		BIT(0)
+
 /* PLA_MAC_PWR_CTRL2 */
 #define EEE_SPDWN_RATIO		0x8007
 #define MAC_CLK_SPDWN_EN	BIT(15)
@@ -417,6 +434,7 @@
 
 /* PLA_INDICATE_FALG */
 #define UPCOMING_RUNTIME_D3	BIT(0)
+#define PREBOOT_OPTION		BIT(1)
 
 /* PLA_MACDBG_PRE and PLA_MACDBG_POST */
 #define DEBUG_OE		BIT(0)
@@ -502,6 +520,10 @@
 #define ADV_CMD_WR		BIT(1)
 #define ADV_CMD_IP		BIT(2)
 
+/* USB_TGPHY_CMD */
+#define TGPHY_CMD_BUSY		BIT(0)
+#define TGPHY_CMD_WR		BIT(1)
+
 /* USB_UPS_CTRL */
 #define POWER_CUT		0x0100
 
@@ -542,6 +564,7 @@
 #define RX_AGG_DISABLE		0x0010
 #define RX_ZERO_EN		0x0080
 #define RX_DESC_16B		0x0400
+#define RX_END_TRANSFER_EN	BIT(11)
 
 /* USB_U2P3_CTRL */
 #define U2P3_ENABLE		0x0001
@@ -597,6 +620,11 @@
 #define UPS_FLAGS_250M_CKDIV		BIT(2)
 #define UPS_FLAGS_EN_ALDPS		BIT(3)
 #define UPS_FLAGS_CTAP_SHORT_DIS	BIT(4)
+#define UPS_FLAGS_EN_100M_EEE		BIT(9)
+#define UPS_FLAGS_EN_1000M_EEE		BIT(10)
+#define UPS_FLAGS_EN_2500M_EEE		BIT(11)
+#define UPS_FLAGS_EN_5000M_EEE		BIT(12)
+#define UPS_FLAGS_EN_10G_EEE		BIT(13)
 #define UPS_FLAGS_SPEED_MASK		(0xf << 16)
 #define ups_flags_speed(x)		((x) << 16)
 #define UPS_FLAGS_EN_EEE		BIT(20)
@@ -645,6 +673,7 @@ enum spd_duplex {
 /* OCP_POWER_CFG */
 #define EEE_CLKDIV_EN		0x8000
 #define EN_ALDPS		0x0004
+#define EN_ALDPS_PLLOFF         0x0002
 #define EN_10M_PLLOFF		0x0001
 
 /* OCP_EEE_CONFIG1 */
@@ -948,6 +977,8 @@ struct r8152 {
 		void (*hw_phy_cfg)(struct r8152 *tp);
 		void (*autosuspend_en)(struct r8152 *tp, bool enable);
 		void (*change_mtu)(struct r8152 *tp);
+		int (*phy_read)(struct r8152 *tp, u16 addr, u16 *data);
+		int (*phy_write)(struct r8152 *tp, u16 addr, u16 data);
 	} rtl_ops;
 
 	struct ups_info {
@@ -1247,7 +1278,8 @@ enum rtl_version {
 	RTL_VER_14,
 	RTL_VER_15,
 	RTL_VER_16,
-	RTL_VER_17,
+	RTL_VER_17_QFN68,
+	RTL_VER_17_QFN100,
 
 	RTL_VER_MAX
 };
@@ -1626,7 +1658,7 @@ static void ocp_write_byte(struct r8152 *tp, u16 type, u16 index, u32 data)
 	generic_ocp_write(tp, index, byen, sizeof(tmp), &tmp, type);
 }
 
-static u16 ocp_reg_read(struct r8152 *tp, u16 addr)
+static int r8152_phy_read(struct r8152 *tp, u16 addr, u16 *data)
 {
 	u16 ocp_base, ocp_index;
 
@@ -1637,10 +1669,12 @@ static u16 ocp_reg_read(struct r8152 *tp, u16 addr)
 	}
 
 	ocp_index = (addr & 0x0fff) | 0xb000;
-	return ocp_read_word(tp, MCU_TYPE_PLA, ocp_index);
+	*data = ocp_read_word(tp, MCU_TYPE_PLA, ocp_index);
+
+	return 0;
 }
 
-static void ocp_reg_write(struct r8152 *tp, u16 addr, u16 data)
+static int r8152_phy_write(struct r8152 *tp, u16 addr, u16 data)
 {
 	u16 ocp_base, ocp_index;
 
@@ -1652,16 +1686,33 @@ static void ocp_reg_write(struct r8152 *tp, u16 addr, u16 data)
 
 	ocp_index = (addr & 0x0fff) | 0xb000;
 	ocp_write_word(tp, MCU_TYPE_PLA, ocp_index, data);
+
+	return 0;
 }
 
-static inline void r8152_mdio_write(struct r8152 *tp, u32 reg_addr, u32 value)
+static int ocp_reg_read(struct r8152 *tp, u16 addr, u16 *data)
 {
-	ocp_reg_write(tp, OCP_BASE_MII + reg_addr * 2, value);
+	return tp->rtl_ops.phy_read(tp, addr, data);
 }
 
-static inline int r8152_mdio_read(struct r8152 *tp, u32 reg_addr)
+static int ocp_reg_write(struct r8152 *tp, u16 addr, u16 data)
 {
-	return ocp_reg_read(tp, OCP_BASE_MII + reg_addr * 2);
+	return tp->rtl_ops.phy_write(tp, addr, data);
+}
+
+static inline int r8152_mdio_write(struct r8152 *tp, u32 reg_addr, u32 value)
+{
+	return ocp_reg_write(tp, OCP_BASE_MII + reg_addr * 2, value);
+}
+
+static int r8152_mdio_read(struct r8152 *tp, u32 reg_addr)
+{
+	u16 data;
+	int ret;
+
+	ret = ocp_reg_read(tp, OCP_BASE_MII + reg_addr * 2, &data);
+
+	return ret < 0 ? ret : data;
 }
 
 static int wait_cmd_ready(struct r8152 *tp, u16 cmd)
@@ -1780,16 +1831,32 @@ static int rtl_ip_set_bits(struct r8152 *tp, u16 addr, u32 set)
 	return rtl_ip_w0w1(tp, addr, 0, set);
 }
 
-static void sram_write(struct r8152 *tp, u16 addr, u16 data)
+static int sram_write(struct r8152 *tp, u16 addr, u16 data)
 {
-	ocp_reg_write(tp, OCP_SRAM_ADDR, addr);
-	ocp_reg_write(tp, OCP_SRAM_DATA, data);
+	int ret;
+
+	ret = ocp_reg_write(tp, OCP_SRAM_ADDR, addr);
+	if (ret < 0)
+		goto out;
+
+	ret = ocp_reg_write(tp, OCP_SRAM_DATA, data);
+
+out:
+	return ret;
 }
 
-static u16 sram_read(struct r8152 *tp, u16 addr)
+static int sram_read(struct r8152 *tp, u16 addr, u16 *data)
 {
-	ocp_reg_write(tp, OCP_SRAM_ADDR, addr);
-	return ocp_reg_read(tp, OCP_SRAM_DATA);
+	int ret;
+
+	ret = ocp_reg_write(tp, OCP_SRAM_ADDR, addr);
+	if (ret < 0)
+		goto out;
+
+	ret = ocp_reg_read(tp, OCP_SRAM_DATA, data);
+
+out:
+	return ret;
 }
 
 static int read_mii_word(struct net_device *netdev, int phy_id, int reg)
@@ -1894,90 +1961,217 @@ static void ocp_byte_set_bits(struct r8152 *tp, u16 type, u16 index, u8 set)
 	ocp_byte_w0w1(tp, type, index, 0, set);
 }
 
-static void ocp_reg_w0w1(struct r8152 *tp, u16 addr, u16 clear, u16 set)
+static int ocp_reg_w0w1(struct r8152 *tp, u16 addr, u16 clear, u16 set)
 {
 	u16 data;
+	int ret;
+
+	ret = ocp_reg_read(tp, addr, &data);
+	if (ret < 0)
+		goto out;
 
-	data = ocp_reg_read(tp, addr);
 	data = (data & ~clear) | set;
-	ocp_reg_write(tp, addr, data);
+	ret = ocp_reg_write(tp, addr, data);
+
+out:
+	return ret;
 }
 
-static void ocp_reg_clr_bits(struct r8152 *tp, u16 addr, u16 clear)
+static int ocp_reg_clr_bits(struct r8152 *tp, u16 addr, u16 clear)
 {
-	ocp_reg_w0w1(tp, addr, clear, 0);
+	return ocp_reg_w0w1(tp, addr, clear, 0);
 }
 
-static void ocp_reg_set_bits(struct r8152 *tp, u16 addr, u16 set)
+static int ocp_reg_set_bits(struct r8152 *tp, u16 addr, u16 set)
 {
-	ocp_reg_w0w1(tp, addr, 0, set);
+	return ocp_reg_w0w1(tp, addr, 0, set);
 }
 
-static void sram_write_w0w1(struct r8152 *tp, u16 addr, u16 clear, u16 set)
+static int sram_write_w0w1(struct r8152 *tp, u16 addr, u16 clear, u16 set)
 {
 	u16 data;
+	int ret;
+
+	ret = sram_read(tp, addr, &data);
+	if (ret < 0)
+		goto out;
 
-	data = sram_read(tp, addr);
 	data = (data & ~clear) | set;
-	ocp_reg_write(tp, OCP_SRAM_DATA, data);
+	ret = ocp_reg_write(tp, OCP_SRAM_DATA, data);
+
+out:
+	return ret;
 }
 
-static void sram_clr_bits(struct r8152 *tp, u16 addr, u16 clear)
+static int sram_clr_bits(struct r8152 *tp, u16 addr, u16 clear)
 {
-	sram_write_w0w1(tp, addr, clear, 0);
+	return sram_write_w0w1(tp, addr, clear, 0);
 }
 
-static void sram_set_bits(struct r8152 *tp, u16 addr, u16 set)
+static int sram_set_bits(struct r8152 *tp, u16 addr, u16 set)
 {
-	sram_write_w0w1(tp, addr, 0, set);
+	return sram_write_w0w1(tp, addr, 0, set);
 }
 
-static void sram2_write(struct r8152 *tp, u16 addr, u16 data)
+static int sram2_write(struct r8152 *tp, u16 addr, u16 data)
 {
-	ocp_reg_write(tp, OCP_SRAM2_ADDR, addr);
-	ocp_reg_write(tp, OCP_SRAM2_DATA, data);
+	int ret;
+
+	ret = ocp_reg_write(tp, OCP_SRAM2_ADDR, addr);
+	if (ret < 0)
+		goto out;
+
+	ret = ocp_reg_write(tp, OCP_SRAM2_DATA, data);
+
+out:
+	return ret;
 }
 
-static u16 sram2_read(struct r8152 *tp, u16 addr)
+static int sram2_read(struct r8152 *tp, u16 addr, u16 *data)
 {
-	ocp_reg_write(tp, OCP_SRAM2_ADDR, addr);
-	return ocp_reg_read(tp, OCP_SRAM2_DATA);
+	int ret;
+
+	ret = ocp_reg_write(tp, OCP_SRAM2_ADDR, addr);
+	if (ret < 0)
+		goto out;
+
+	ret = ocp_reg_read(tp, OCP_SRAM2_DATA, data);
+
+out:
+	return ret;
 }
 
-static void sram2_write_w0w1(struct r8152 *tp, u16 addr, u16 clear, u16 set)
+static int sram2_write_w0w1(struct r8152 *tp, u16 addr, u16 clear, u16 set)
 {
 	u16 data;
+	int ret;
+
+	ret = sram2_read(tp, addr, &data);
+	if (ret < 0)
+		goto out;
 
-	data = sram2_read(tp, addr);
 	data = (data & ~clear) | set;
-	ocp_reg_write(tp, OCP_SRAM2_DATA, data);
+	ret = ocp_reg_write(tp, OCP_SRAM2_DATA, data);
+
+out:
+	return ret;
 }
 
-static void r8152_mdio_clr_bit(struct r8152 *tp, u16 addr, u16 clear)
+static int sram2_set_bits(struct r8152 *tp, u16 addr, u16 set)
+{
+	return sram2_write_w0w1(tp, addr, 0, set);
+}
+
+static int sram2_clr_bits(struct r8152 *tp, u16 addr, u16 clear)
+{
+	return sram2_write_w0w1(tp, addr, clear, 0);
+}
+
+static int r8152_mdio_clr_bit(struct r8152 *tp, u16 addr, u16 clear)
 {
 	int data;
 
 	data = r8152_mdio_read(tp, addr);
-	r8152_mdio_write(tp, addr, data & ~clear);
+	if (data < 0)
+		goto out;
+
+	data = r8152_mdio_write(tp, addr, data & ~clear);
+
+out:
+	return data;
 }
 
-static void r8152_mdio_set_bit(struct r8152 *tp, u16 addr, u16 set)
+static int r8152_mdio_set_bit(struct r8152 *tp, u16 addr, u16 set)
 {
 	int data;
 
 	data = r8152_mdio_read(tp, addr);
-	r8152_mdio_write(tp, addr, data | set);
+	if (data < 0)
+		goto out;
+
+	data = r8152_mdio_write(tp, addr, data | set);
+
+out:
+	return data;
 }
 
 static int r8152_mdio_test_and_clr_bit(struct r8152 *tp, u16 addr, u16 clear)
 {
-	int data;
+	int data, ret;
 
-	data = r8152_mdio_read(tp, addr);
-	if (data & clear)
-		r8152_mdio_write(tp, addr, data & ~clear);
+	ret = r8152_mdio_read(tp, addr);
+	if (ret < 0)
+		goto out;
+
+	data = ret;
+	if (data & clear) {
+		ret = r8152_mdio_write(tp, addr, data & ~clear);
+		if (ret < 0)
+			goto out;
+	}
+
+	ret = !!(data & clear);
+
+out:
+	return ret;
+}
+
+static int wait_tgphy_cmd_ready(struct r8152 *tp)
+{
+	u16 ocp_data;
+	int ret;
+
+	ret = read_poll_timeout(ocp_read_word, ocp_data,
+				test_bit(RTL8152_INACCESSIBLE, &tp->flags) ||
+				!(ocp_data & TGPHY_CMD_BUSY),
+				2000, 20000, false, tp,
+				MCU_TYPE_USB, USB_TGPHY_CMD);
+
+	if (ret)
+		dev_err(&tp->intf->dev, "TGPHY cmd busy timeout\n");
+
+	return test_bit(RTL8152_INACCESSIBLE, &tp->flags) ? -ENODEV : ret;
+}
+
+static int rtl_tgphy_access(struct r8152 *tp, u16 addr, u16 *data, bool write)
+{
+	u16 cmd = 0;
+	int ret;
+
+	ret = wait_tgphy_cmd_ready(tp);
+	if (ret < 0)
+		goto out;
+
+	if (write) {
+		cmd |= TGPHY_CMD_WR;
+		ocp_write_word(tp, MCU_TYPE_USB, USB_TGPHY_DATA, *data);
+	}
+
+	ocp_write_word(tp, MCU_TYPE_USB, USB_TGPHY_ADDR, addr);
+
+	cmd |= TGPHY_CMD_BUSY;
+	ocp_write_word(tp, MCU_TYPE_USB, USB_TGPHY_CMD, cmd);
+
+	if (!write) {
+		ret = wait_tgphy_cmd_ready(tp);
+		if (ret < 0)
+			goto out;
+
+		*data = ocp_read_word(tp, MCU_TYPE_USB, USB_TGPHY_DATA);
+	}
+
+out:
+	return ret;
+}
+
+static int r8157_phy_read(struct r8152 *tp, u16 addr, u16 *data)
+{
+	return rtl_tgphy_access(tp, addr, data, false);
+}
 
-	return data & clear;
+static int r8157_phy_write(struct r8152 *tp, u16 addr, u16 data)
+{
+	return rtl_tgphy_access(tp, addr, &data, true);
 }
 
 static int
@@ -3412,7 +3606,8 @@ static void rtl8152_nic_reset(struct r8152 *tp)
 		break;
 
 	case RTL_VER_16:
-	case RTL_VER_17:
+	case RTL_VER_17_QFN68:
+	case RTL_VER_17_QFN100:
 		ocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_CR, CR_RE | CR_TE);
 		break;
 
@@ -3452,7 +3647,7 @@ static void rtl_eee_plus_en(struct r8152 *tp, bool enable)
 
 static void rtl_set_eee_plus(struct r8152 *tp)
 {
-	if (tp->version == RTL_VER_17)
+	if (tp->version == RTL_VER_17_QFN68 || tp->version == RTL_VER_17_QFN100)
 		return rtl_eee_plus_en(tp, false);
 
 	if (rtl8152_get_speed(tp) & _10bps)
@@ -3640,7 +3835,8 @@ static void r8153_set_rx_early_timeout(struct r8152 *tp)
 	case RTL_VER_13:
 	case RTL_VER_15:
 	case RTL_VER_16:
-	case RTL_VER_17:
+	case RTL_VER_17_QFN68:
+	case RTL_VER_17_QFN100:
 		ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EARLY_TIMEOUT,
 			       640 / 8);
 		ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EXTRA_AGGR_TMR,
@@ -3685,7 +3881,8 @@ static void r8153_set_rx_early_size(struct r8152 *tp)
 			       ocp_data / 8);
 		break;
 	case RTL_VER_16:
-	case RTL_VER_17:
+	case RTL_VER_17_QFN68:
+	case RTL_VER_17_QFN100:
 		ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EARLY_SIZE,
 			       ocp_data / 16);
 		break;
@@ -3801,6 +3998,8 @@ static void rtl_rx_vlan_en(struct r8152 *tp, bool enable)
 	case RTL_VER_13:
 	case RTL_VER_15:
 	case RTL_VER_16:
+	case RTL_VER_17_QFN68:
+	case RTL_VER_17_QFN100:
 	default:
 		if (enable)
 			ocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_RCR1,
@@ -4051,8 +4250,27 @@ static void r8156_ups_flags(struct r8152 *tp)
 	if (tp->ups_info.aldps)
 		ups_flags |= UPS_FLAGS_EN_ALDPS;
 
-	if (tp->ups_info.eee)
-		ups_flags |= UPS_FLAGS_EN_EEE;
+	if (tp->ups_info.eee) {
+		switch (tp->version) {
+		case RTL_VER_17_QFN68:
+			if (tp->eee_adv & MDIO_EEE_10GT)
+				ups_flags |= UPS_FLAGS_EN_10G_EEE;
+			fallthrough;
+		case RTL_VER_16:
+			if (tp->eee_adv & MDIO_EEE_100TX)
+				ups_flags |= UPS_FLAGS_EN_100M_EEE;
+			if (tp->eee_adv & MDIO_EEE_1000T)
+				ups_flags |= UPS_FLAGS_EN_1000M_EEE;
+			if (tp->eee_adv2 & MDIO_EEE_2_5GT)
+				ups_flags |= UPS_FLAGS_EN_2500M_EEE;
+			if (tp->eee_adv2 & MDIO_EEE_5GT)
+				ups_flags |= UPS_FLAGS_EN_5000M_EEE;
+			break;
+		default:
+			ups_flags |= UPS_FLAGS_EN_EEE;
+			break;
+		}
+	}
 
 	if (tp->ups_info.flow_control)
 		ups_flags |= UPS_FLAGS_EN_FLOW_CTR;
@@ -4103,20 +4321,33 @@ static void r8156_ups_flags(struct r8152 *tp)
 	case NWAY_2500M_FULL:
 		ups_flags |= ups_flags_speed(9);
 		break;
+	case NWAY_5000M_FULL:
+		ups_flags |= ups_flags_speed(10);
+		break;
+	case NWAY_10000M_FULL:
+		ups_flags |= ups_flags_speed(11);
+		break;
 	default:
 		break;
 	}
 
-	switch (tp->ups_info.lite_mode) {
-	case 1:
-		ups_flags |= 0 << 5;
-		break;
-	case 2:
-		ups_flags |= 2 << 5;
+	switch (tp->version) {
+	case RTL_VER_16:
+	case RTL_VER_17_QFN68:
 		break;
-	case 0:
 	default:
-		ups_flags |= 1 << 5;
+		switch (tp->ups_info.lite_mode) {
+		case 1:
+			ups_flags |= 0 << 5;
+			break;
+		case 2:
+			ups_flags |= 2 << 5;
+			break;
+		case 0:
+		default:
+			ups_flags |= 1 << 5;
+			break;
+		}
 		break;
 	}
 
@@ -4150,11 +4381,13 @@ static void r8153b_green_en(struct r8152 *tp, bool enable)
 
 static u16 r8153_phy_status(struct r8152 *tp, u16 desired)
 {
-	u16 data;
+	u16 data = 0;
 	int i;
 
 	for (i = 0; i < 500; i++) {
-		data = ocp_reg_read(tp, OCP_PHY_STATUS);
+		if (ocp_reg_read(tp, OCP_PHY_STATUS, &data) < 0)
+			break;
+
 		data &= PHY_STAT_MASK;
 		if (desired) {
 			if (data == desired)
@@ -4172,6 +4405,23 @@ static u16 r8153_phy_status(struct r8152 *tp, u16 desired)
 	return data;
 }
 
+static int wait_autoload_done(struct r8152 *tp)
+{
+	u16 ocp_data;
+	int ret;
+
+	ret = read_poll_timeout(ocp_read_word, ocp_data,
+				test_bit(RTL8152_INACCESSIBLE, &tp->flags) ||
+				(ocp_data & AUTOLOAD_DONE),
+				20000, 10 * USEC_PER_SEC, false, tp,
+				MCU_TYPE_PLA, PLA_BOOT_CTRL);
+
+	if (ret)
+		dev_err(&tp->intf->dev, "autoload done timeout\n");
+
+	return test_bit(RTL8152_INACCESSIBLE, &tp->flags) ? -ENODEV : 0;
+}
+
 static void r8153b_ups_en(struct r8152 *tp, bool enable)
 {
 	if (enable) {
@@ -4190,16 +4440,8 @@ static void r8153b_ups_en(struct r8152 *tp, bool enable)
 				  UPS_FORCE_PWR_DOWN);
 
 		if (ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0) & PCUT_STATUS) {
-			int i;
-
-			for (i = 0; i < 500; i++) {
-				if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
-					return;
-				if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) &
-				    AUTOLOAD_DONE)
-					break;
-				msleep(20);
-			}
+			if (wait_autoload_done(tp))
+				return;
 
 			tp->rtl_ops.hw_phy_cfg(tp);
 
@@ -4227,16 +4469,8 @@ static void r8153c_ups_en(struct r8152 *tp, bool enable)
 				  UPS_FORCE_PWR_DOWN);
 
 		if (ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0) & PCUT_STATUS) {
-			int i;
-
-			for (i = 0; i < 500; i++) {
-				if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
-					return;
-				if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) &
-				    AUTOLOAD_DONE)
-					break;
-				msleep(20);
-			}
+			if (wait_autoload_done(tp))
+				return;
 
 			tp->rtl_ops.hw_phy_cfg(tp);
 
@@ -4288,6 +4522,49 @@ static void r8156_ups_en(struct r8152 *tp, bool enable)
 	}
 }
 
+static void r8157_ups_en(struct r8152 *tp, bool enable)
+{
+	if (enable) {
+		r8156_ups_flags(tp);
+
+		ocp_byte_set_bits(tp, MCU_TYPE_USB, USB_POWER_CUT,
+				  UPS_EN | USP_PREWAKE | PHASE2_EN);
+
+		ocp_byte_set_bits(tp, MCU_TYPE_USB, USB_MISC_2,
+				  UPS_FORCE_PWR_DOWN);
+	} else {
+		ocp_byte_clr_bits(tp, MCU_TYPE_USB, USB_POWER_CUT,
+				  UPS_EN | USP_PREWAKE);
+
+		ocp_byte_clr_bits(tp, MCU_TYPE_USB, USB_MISC_2,
+				  UPS_FORCE_PWR_DOWN);
+
+		if (ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0) & PCUT_STATUS) {
+			u32 ocp_data;
+			int ret;
+
+			ret = read_poll_timeout(ocp_read_word, ocp_data,
+						ocp_data & BACKUP_RESTRORE, 200,
+						20000, false, tp, MCU_TYPE_USB,
+						USB_GPHY_CTRL);
+			if (ret) {
+				rtl_set_inaccessible(tp);
+				dev_err(&tp->intf->dev,
+					"backup-restore timed out\n");
+				return;
+			}
+
+			/* clear USB fw_ver_reg */
+			ocp_write_byte(tp, MCU_TYPE_USB, USB_FW_USB_VER, 0);
+
+			tp->rtl_ops.hw_phy_cfg(tp);
+
+			rtl8152_set_speed(tp, tp->autoneg, tp->speed,
+					  tp->duplex, tp->advertising);
+		}
+	}
+}
+
 static void r8153_power_cut_en(struct r8152 *tp, bool enable)
 {
 	if (enable)
@@ -4446,9 +4723,28 @@ static void rtl8157_runtime_enable(struct r8152 *tp, bool enable)
 		r8153b_u1u2en(tp, false);
 		r8157_u2p3en(tp, false);
 		rtl_runtime_suspend_enable(tp, true);
+
+		switch (tp->version) {
+		case RTL_VER_16:
+		case RTL_VER_17_QFN68:
+			r8157_ups_en(tp, true);
+			break;
+		default:
+			break;
+		}
 	} else {
 		r8153_queue_wake(tp, false);
 		rtl_runtime_suspend_enable(tp, false);
+
+		switch (tp->version) {
+		case RTL_VER_16:
+		case RTL_VER_17_QFN68:
+			r8157_ups_en(tp, false);
+			break;
+		default:
+			break;
+		}
+
 		r8157_u2p3en(tp, true);
 		if (tp->udev->speed >= USB_SPEED_SUPER)
 			r8153b_u1u2en(tp, true);
@@ -4480,6 +4776,8 @@ static void r8153_teredo_off(struct r8152 *tp)
 	case RTL_VER_14:
 	case RTL_VER_15:
 	case RTL_VER_16:
+	case RTL_VER_17_QFN68:
+	case RTL_VER_17_QFN100:
 	default:
 		/* The bit 0 ~ 7 are relative with teredo settings. They are
 		 * W1C (write 1 to clear), so set all 1 to disable it.
@@ -4534,7 +4832,8 @@ static void rtl_clear_bp(struct r8152 *tp, u16 type)
 		break;
 	case RTL_VER_14:
 	case RTL_VER_16:
-	case RTL_VER_17:
+	case RTL_VER_17_QFN68:
+	case RTL_VER_17_QFN100:
 	default:
 		ocp_write_word(tp, type, USB_BP2_EN, 0);
 		bp_num = 16;
@@ -4556,7 +4855,8 @@ static inline void rtl_reset_ocp_base(struct r8152 *tp)
 static int rtl_phy_patch_request(struct r8152 *tp, bool request, bool wait)
 {
 	u16 check;
-	int i;
+	u16 ocp_data;
+	int i, ret;
 
 	if (request) {
 		ocp_reg_set_bits(tp, OCP_PHY_PATCH_CMD, PATCH_REQUEST);
@@ -4567,25 +4867,29 @@ static int rtl_phy_patch_request(struct r8152 *tp, bool request, bool wait)
 	}
 
 	for (i = 0; wait && i < 5000; i++) {
-		u32 ocp_data;
-
 		if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
 			return -ENODEV;
 
 		usleep_range(1000, 2000);
-		ocp_data = ocp_reg_read(tp, OCP_PHY_PATCH_STAT);
-		if ((ocp_data & PATCH_READY) ^ check)
+		ret = ocp_reg_read(tp, OCP_PHY_PATCH_STAT, &ocp_data);
+		if (ret < 0)
+			return ret;
+		else if ((ocp_data & PATCH_READY) ^ check)
 			break;
 	}
 
-	if (request && wait &&
-	    !(ocp_reg_read(tp, OCP_PHY_PATCH_STAT) & PATCH_READY)) {
-		dev_err(&tp->intf->dev, "PHY patch request fail\n");
-		rtl_phy_patch_request(tp, false, false);
-		return -ETIME;
-	} else {
-		return 0;
+	if (request && wait) {
+		ret = ocp_reg_read(tp, OCP_PHY_PATCH_STAT, &ocp_data);
+		if (ret < 0) {
+			return ret;
+		} else if (!(ocp_data & PATCH_READY)) {
+			dev_err(&tp->intf->dev, "PHY patch request fail\n");
+			rtl_phy_patch_request(tp, false, false);
+			return -ETIME;
+		}
 	}
+
+	return 0;
 }
 
 static void rtl_patch_key_set(struct r8152 *tp, u16 key_addr, u16 patch_key)
@@ -4646,7 +4950,8 @@ static bool rtl8152_is_fw_phy_speed_up_ok(struct r8152 *tp, struct fw_phy_speed_
 	case RTL_VER_13:
 	case RTL_VER_15:
 	case RTL_VER_16:
-	case RTL_VER_17:
+	case RTL_VER_17_QFN68:
+	case RTL_VER_17_QFN100:
 	default:
 		break;
 	}
@@ -5299,10 +5604,14 @@ static void rtl_ram_code_speed_up(struct r8152 *tp, struct fw_phy_speed_up *phy,
 {
 	u32 len;
 	u8 *data;
+	u16 ver;
 
 	rtl_reset_ocp_base(tp);
 
-	if (sram_read(tp, SRAM_GPHY_FW_VER) >= __le16_to_cpu(phy->version)) {
+	if (sram_read(tp, SRAM_GPHY_FW_VER, &ver) < 0)
+		return;
+
+	if (ver >= __le16_to_cpu(phy->version)) {
 		dev_dbg(&tp->intf->dev, "PHY firmware has been the newest\n");
 		return;
 	}
@@ -5349,7 +5658,8 @@ static void rtl_ram_code_speed_up(struct r8152 *tp, struct fw_phy_speed_up *phy,
 
 	rtl_phy_patch_request(tp, false, wait);
 
-	if (sram_read(tp, SRAM_GPHY_FW_VER) == __le16_to_cpu(phy->version))
+	if (sram_read(tp, SRAM_GPHY_FW_VER, &ver) >= 0 &&
+	    ver == __le16_to_cpu(phy->version))
 		dev_dbg(&tp->intf->dev, "successfully applied %s\n", phy->info);
 	else
 		dev_err(&tp->intf->dev, "ram code speedup mode fail\n");
@@ -5357,14 +5667,17 @@ static void rtl_ram_code_speed_up(struct r8152 *tp, struct fw_phy_speed_up *phy,
 
 static int rtl8152_fw_phy_ver(struct r8152 *tp, struct fw_phy_ver *phy_ver)
 {
-	u16 ver_addr, ver;
+	u16 ver_addr, ver, cur_ver;
 
 	ver_addr = __le16_to_cpu(phy_ver->ver.addr);
 	ver = __le16_to_cpu(phy_ver->ver.data);
 
 	rtl_reset_ocp_base(tp);
 
-	if (sram_read(tp, ver_addr) >= ver) {
+	if (sram_read(tp, ver_addr, &cur_ver) < 0)
+		return 0;
+
+	if (cur_ver >= ver) {
 		dev_dbg(&tp->intf->dev, "PHY firmware has been the newest\n");
 		return 0;
 	}
@@ -5383,7 +5696,8 @@ static void rtl8152_fw_phy_fixup(struct r8152 *tp, struct fw_phy_fixup *fix)
 	rtl_reset_ocp_base(tp);
 
 	addr = __le16_to_cpu(fix->setting.addr);
-	data = ocp_reg_read(tp, addr);
+	if (ocp_reg_read(tp, addr, &data) < 0)
+		return;
 
 	switch (__le16_to_cpu(fix->bit_cmd)) {
 	case FW_FIXUP_AND:
@@ -5687,10 +6001,10 @@ static inline void r8152_mmd_indirect(struct r8152 *tp, u16 dev, u16 reg)
 
 static u16 r8152_mmd_read(struct r8152 *tp, u16 dev, u16 reg)
 {
-	u16 data;
+	u16 data = 0;
 
 	r8152_mmd_indirect(tp, dev, reg);
-	data = ocp_reg_read(tp, OCP_EEE_DATA);
+	ocp_reg_read(tp, OCP_EEE_DATA, &data);
 	ocp_reg_write(tp, OCP_EEE_AR, 0x0000);
 
 	return data;
@@ -5755,7 +6069,8 @@ static void r8156_eee_en(struct r8152 *tp, bool enable)
 
 	r8153_eee_en(tp, enable);
 
-	config = ocp_reg_read(tp, OCP_EEE_ADV2);
+	if (ocp_reg_read(tp, OCP_EEE_ADV2, &config) < 0)
+		return;
 
 	if (enable && (tp->eee_adv2 & MDIO_EEE_2_5GT))
 		config |= MDIO_EEE_2_5GT;
@@ -5806,7 +6121,8 @@ static void rtl_eee_enable(struct r8152 *tp, bool enable)
 	case RTL_VER_13:
 	case RTL_VER_15:
 	case RTL_VER_16:
-	case RTL_VER_17:
+	case RTL_VER_17_QFN68:
+	case RTL_VER_17_QFN100:
 		if (enable) {
 			r8156_eee_en(tp, true);
 			ocp_reg_write(tp, OCP_EEE_ADV, tp->eee_adv);
@@ -5961,27 +6277,125 @@ static void r8152b_enter_oob(struct r8152 *tp)
 			   RCR_APM | RCR_AM | RCR_AB);
 }
 
-static int r8153_pre_firmware_1(struct r8152 *tp)
+static void rtl_fc_pause_pkt_en(struct r8152 *tp, u16 speed)
 {
-	int i;
+	int log2_ratio, ratio;
+	u16 num_pause_pkts;
+	u32 ocp_data;
 
-	/* Wait till the WTD timer is ready. It would take at most 104 ms. */
-	for (i = 0; i < 104; i++) {
-		u32 ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_WDT1_CTRL);
+	switch (tp->version) {
+	case RTL_VER_10:
+	case RTL_VER_11:
+		ocp_write_word(tp, MCU_TYPE_USB, USB_FC_TIMER,
+			       CTRL_TIMER_EN | (1000 / 8));
 
-		if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
-			return -ENODEV;
-		if (!(ocp_data & WTD1_EN))
-			break;
-		usleep_range(1000, 2000);
-	}
+		ocp_word_set_bits(tp, MCU_TYPE_USB, USB_FW_CTRL,
+				  FLOW_CTRL_PATCH_OPT);
 
-	return 0;
-}
+		ocp_word_set_bits(tp, MCU_TYPE_USB, USB_FW_TASK, FC_PATCH_TASK);
+		break;
+	case RTL_VER_12:
+	case RTL_VER_13:
+	case RTL_VER_15:
+		ocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_RCR, SLOT_EN);
 
-static int r8153_post_firmware_1(struct r8152 *tp)
-{
-	/* set USB_BP_4 to support USB_SPEED_SUPER only */
+		ocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_CPCR, FLOW_CTRL_EN);
+
+		/* enable fc timer and set timer to 600 ms. */
+		ocp_write_word(tp, MCU_TYPE_USB, USB_FC_TIMER,
+			       CTRL_TIMER_EN | (600 / 8));
+
+		ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_POL_GPIO_CTRL);
+		if (!(ocp_data & DACK_DET_EN))
+			ocp_word_set_bits(tp, MCU_TYPE_USB, USB_FW_CTRL,
+					  FLOW_CTRL_PATCH_2);
+
+		ocp_word_set_bits(tp, MCU_TYPE_USB, USB_FW_TASK, FC_PATCH_TASK);
+		break;
+	case RTL_VER_16:
+	case RTL_VER_17_QFN68:
+	case RTL_VER_17_QFN100:
+		ocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_RCR, SLOT_EN);
+
+		num_pause_pkts = 0xa;
+		ratio = 10000;
+
+		if (speed & _10bps) {
+			ratio /= 10;
+		} else if (speed & _100bps) {
+			ratio /= 100;
+		} else if (speed & _1000bps) {
+			ratio /= 1000;
+		} else if (speed & _2500bps) {
+			ratio /= 2500;
+		} else if (speed & _5000bps) {
+			ratio /= 5000;
+		} else if (speed & _10000bps) {
+			ratio /= 10000;
+		} else {
+			/* No rate bit is set, e.g. a 500 or 1250 Mbit/s
+			 * sub-rate, which the driver does not advertise.
+			 * Disarm the limit.
+			 */
+			dev_err(&tp->intf->dev, "Unknown link speed\n");
+			ocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_PAUSE_LIMIT,
+					  PAUSE_LIMIT_EN);
+			break;
+		}
+
+		log2_ratio = ilog2(ratio);
+		num_pause_pkts -= log2_ratio;
+
+		/* Round ratio up to the next power of two if it is
+		 * more than halfway there. Floating-point is avoided
+		 * by rewriting ratio > 1.5 * 2^log2_ratio as
+		 * 2 * ratio > 3 * 2^log2_ratio.
+		 */
+		if (2 * ratio > 3 * (1 << log2_ratio))
+			num_pause_pkts--;
+
+		/* At most 2^num_pause_pkts pause packets would be sent.
+		 *
+		 *  10 Mbit/s -> 2^0
+		 * 100 Mbit/s -> 2^3
+		 *   1 Gbit/s -> 2^7
+		 * 2.5 Gbit/s -> 2^8
+		 *   5 Gbit/s -> 2^9
+		 *  10 Gbit/s -> 2^10
+		 */
+		ocp_word_w0w1(tp, MCU_TYPE_PLA, PLA_PAUSE_LIMIT,
+			      PAUSE_LIMIT_MASK | PAUSE_LIMIT_EN,
+			      num_pause_pkts << 4);
+
+		ocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_PAUSE_LIMIT,
+				  PAUSE_LIMIT_EN);
+		break;
+	default:
+		break;
+	}
+}
+
+static int r8153_pre_firmware_1(struct r8152 *tp)
+{
+	int i;
+
+	/* Wait till the WTD timer is ready. It would take at most 104 ms. */
+	for (i = 0; i < 104; i++) {
+		u32 ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_WDT1_CTRL);
+
+		if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
+			return -ENODEV;
+		if (!(ocp_data & WTD1_EN))
+			break;
+		usleep_range(1000, 2000);
+	}
+
+	return 0;
+}
+
+static int r8153_post_firmware_1(struct r8152 *tp)
+{
+	/* set USB_BP_4 to support USB_SPEED_SUPER only */
 	if (ocp_read_byte(tp, MCU_TYPE_USB, USB_CSTMR) & FORCE_SUPER)
 		ocp_write_word(tp, MCU_TYPE_USB, USB_BP_4, BP4_SUPER_ONLY);
 
@@ -6210,8 +6624,8 @@ static void r8153b_hw_phy_cfg(struct r8152 *tp)
 	 * rg_saw_cnt = OCP reg 0xC426 Bit[13:0]
 	 * swr_cnt_1ms_ini = 16000000 / rg_saw_cnt
 	 */
-	ocp_data = ocp_reg_read(tp, 0xc426);
-	ocp_data &= 0x3fff;
+	ocp_reg_read(tp, 0xc426, &data);
+	ocp_data = data & 0x3fff;
 	if (ocp_data) {
 		u32 swr_cnt_1ms_ini;
 
@@ -6391,24 +6805,16 @@ static int rtl8156_enable(struct r8152 *tp)
 	if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
 		return -ENODEV;
 
-	if (tp->version < RTL_VER_12)
-		r8156_fc_parameter(tp);
-
+	r8156_fc_parameter(tp);
 	set_tx_qlen(tp);
 	rtl_set_eee_plus(tp);
 
-	if (tp->version >= RTL_VER_12 && tp->version <= RTL_VER_17)
-		ocp_word_clr_bits(tp, MCU_TYPE_USB, USB_RX_AGGR_NUM, RX_AGGR_NUM_MASK);
-
 	r8153_set_rx_early_timeout(tp);
 	r8153_set_rx_early_size(tp);
 
 	speed = rtl8152_get_speed(tp);
 	rtl_set_ifg(tp, speed);
 
-	if (tp->version >= RTL_VER_16)
-		return rtl_enable(tp);
-
 	if (speed & _2500bps)
 		ocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4,
 				  IDLE_SPDWN_EN);
@@ -6416,12 +6822,10 @@ static int rtl8156_enable(struct r8152 *tp)
 		ocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4,
 				  IDLE_SPDWN_EN);
 
-	if (tp->version < RTL_VER_12) {
-		if (speed & _1000bps)
-			ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEE_TXTWSYS, 0x11);
-		else if (speed & _500bps)
-			ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEE_TXTWSYS, 0x3d);
-	}
+	if (speed & _1000bps)
+		ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEE_TXTWSYS, 0x11);
+	else if (speed & _500bps)
+		ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEE_TXTWSYS, 0x3d);
 
 	if (tp->udev->speed == USB_SPEED_HIGH) {
 		/* USB 0xb45e[3:0] l1_nyet_hird */
@@ -6446,6 +6850,69 @@ static void rtl8156_disable(struct r8152 *tp)
 	rtl8153_disable(tp);
 }
 
+static int rtl8156b_enable(struct r8152 *tp)
+{
+	u16 speed;
+
+	if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
+		return -ENODEV;
+
+	set_tx_qlen(tp);
+	rtl_set_eee_plus(tp);
+
+	ocp_word_clr_bits(tp, MCU_TYPE_USB, USB_RX_AGGR_NUM, RX_AGGR_NUM_MASK);
+
+	r8153_set_rx_early_timeout(tp);
+	r8153_set_rx_early_size(tp);
+
+	speed = rtl8152_get_speed(tp);
+	rtl_set_ifg(tp, speed);
+
+	if (speed & _2500bps)
+		ocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4,
+				  IDLE_SPDWN_EN);
+	else
+		ocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4,
+				  IDLE_SPDWN_EN);
+
+	if (tp->udev->speed == USB_SPEED_HIGH) {
+		/* USB 0xb45e[3:0] l1_nyet_hird */
+		if (is_flow_control(speed))
+			ocp_word_w0w1(tp, MCU_TYPE_USB, USB_L1_CTRL, 0xf, 0xf);
+		else
+			ocp_word_w0w1(tp, MCU_TYPE_USB, USB_L1_CTRL, 0xf, 0x1);
+	}
+
+	ocp_word_clr_bits(tp, MCU_TYPE_USB, USB_FW_TASK, FC_PATCH_TASK);
+	usleep_range(1000, 2000);
+	ocp_word_set_bits(tp, MCU_TYPE_USB, USB_FW_TASK, FC_PATCH_TASK);
+
+	return rtl_enable(tp);
+}
+
+static int rtl8157_enable(struct r8152 *tp)
+{
+	u16 speed;
+
+	if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
+		return -ENODEV;
+
+	set_tx_qlen(tp);
+	rtl_set_eee_plus(tp);
+
+	ocp_word_clr_bits(tp, MCU_TYPE_USB, USB_RX_AGGR_NUM, RX_AGGR_NUM_MASK);
+
+	r8153_set_rx_early_timeout(tp);
+	r8153_set_rx_early_size(tp);
+
+	speed = rtl8152_get_speed(tp);
+	rtl_fc_pause_pkt_en(tp, speed);
+
+	rtl_set_ifg(tp, speed);
+
+	return rtl_enable(tp);
+}
+
 static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex,
 			     u32 advertising)
 {
@@ -6517,7 +6984,11 @@ static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex,
 		if (!advertising)
 			return -EINVAL;
 
-		orig = r8152_mdio_read(tp, MII_ADVERTISE);
+		ret = r8152_mdio_read(tp, MII_ADVERTISE);
+		if (ret < 0)
+			goto out;
+
+		orig = ret;
 		new1 = orig & ~(ADVERTISE_10HALF | ADVERTISE_10FULL |
 				ADVERTISE_100HALF | ADVERTISE_100FULL);
 		if (advertising & RTL_ADVERTISED_10_HALF) {
@@ -6544,7 +7015,11 @@ static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex,
 		}
 
 		if (tp->mii.supports_gmii) {
-			orig = r8152_mdio_read(tp, MII_CTRL1000);
+			ret = r8152_mdio_read(tp, MII_CTRL1000);
+			if (ret < 0)
+				goto out;
+
+			orig = ret;
 			new1 = orig & ~(ADVERTISE_1000FULL |
 					ADVERTISE_1000HALF);
 
@@ -6558,7 +7033,10 @@ static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex,
 		}
 
 		if (tp->support_2500full || tp->support_5000full || tp->support_10000full) {
-			orig = ocp_reg_read(tp, OCP_10GBT_CTRL);
+			ret = ocp_reg_read(tp, OCP_10GBT_CTRL, &orig);
+			if (ret < 0)
+				goto out;
+
 			new1 = orig & ~(MDIO_AN_10GBT_CTRL_ADV2_5G | MDIO_AN_10GBT_CTRL_ADV5G
 					| MDIO_AN_10GBT_CTRL_ADV10G);
 
@@ -6589,20 +7067,23 @@ static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex,
 	if (test_and_clear_bit(PHY_RESET, &tp->flags))
 		bmcr |= BMCR_RESET;
 
-	r8152_mdio_write(tp, MII_BMCR, bmcr);
+	ret = r8152_mdio_write(tp, MII_BMCR, bmcr);
+	if (ret < 0)
+		goto out;
 
 	if (bmcr & BMCR_RESET) {
 		int i;
 
 		for (i = 0; i < 50; i++) {
 			msleep(20);
-			if ((r8152_mdio_read(tp, MII_BMCR) & BMCR_RESET) == 0)
+			ret = r8152_mdio_read(tp, MII_BMCR);
+			if (ret < 0 || !(ret & BMCR_RESET))
 				break;
 		}
 	}
 
 out:
-	return ret;
+	return ret < 0 ? ret : 0;
 }
 
 static void rtl8152_up(struct r8152 *tp)
@@ -6806,8 +7287,7 @@ static void rtl8156_up(struct r8152 *tp)
 		return;
 
 	r8153b_u1u2en(tp, false);
-	if (tp->version < RTL_VER_16)
-		r8153_u2p3en(tp, false);
+	r8153_u2p3en(tp, false);
 	r8153_aldps_en(tp, false);
 
 	rxdy_gated_en(tp, true);
@@ -6820,8 +7300,7 @@ static void rtl8156_up(struct r8152 *tp)
 
 	ocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, NOW_IS_OOB);
 
-	if (tp->version >= RTL_VER_16)
-		ocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_RCR1, BIT(3));
+	ocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_RCR1, BIT(3));
 
 	ocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, MCU_BORW_EN);
 
@@ -6845,9 +7324,8 @@ static void rtl8156_up(struct r8152 *tp)
 
 	ocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, PLA_MCU_SPDWN_EN);
 
-	if (tp->version < RTL_VER_16)
-		ocp_word_clr_bits(tp, MCU_TYPE_USB, USB_SPEED_OPTION,
-				  RG_PWRDN_EN | ALL_SPEED_OFF);
+	ocp_word_clr_bits(tp, MCU_TYPE_USB, USB_SPEED_OPTION,
+			  RG_PWRDN_EN | ALL_SPEED_OFF);
 
 	ocp_write_dword(tp, MCU_TYPE_USB, USB_RX_BUF_TH, 0x00600400);
 
@@ -6857,10 +7335,19 @@ static void rtl8156_up(struct r8152 *tp)
 	}
 
 	r8153_aldps_en(tp, true);
-	if (tp->version < RTL_VER_16)
-		r8153_u2p3en(tp, true);
+	r8153_u2p3en(tp, true);
+
+	switch (tp->version) {
+	case RTL_VER_13:
+	case RTL_VER_15:
+		/* Enable Clear_SDR */
+		ocp_word_set_bits(tp, MCU_TYPE_USB, 0xd3ca, BIT(15));
+		break;
+	default:
+		break;
+	}
 
-	if (tp->version < RTL_VER_16 && tp->udev->speed >= USB_SPEED_SUPER)
+	if (tp->udev->speed >= USB_SPEED_SUPER)
 		r8153b_u1u2en(tp, true);
 }
 
@@ -6873,12 +7360,9 @@ static void rtl8156_down(struct r8152 *tp)
 
 	ocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3,
 			  PLA_MCU_SPDWN_EN);
-
 	r8153b_u1u2en(tp, false);
-	if (tp->version < RTL_VER_16) {
-		r8153_u2p3en(tp, false);
-		r8153b_power_cut_en(tp, false);
-	}
+	r8153_u2p3en(tp, false);
+	r8153b_power_cut_en(tp, false);
 	r8153_aldps_en(tp, false);
 
 	ocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, NOW_IS_OOB);
@@ -6900,7 +7384,125 @@ static void rtl8156_down(struct r8152 *tp)
 	 */
 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_TEREDO_WAKE_BASE, 0x00ff);
 
-	ocp_byte_set_bits(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, NOW_IS_OOB);
+	ocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_BDC_CR, ALDPS_PROXY_MODE);
+
+	ocp_byte_set_bits(tp, MCU_TYPE_PLA, PLA_OOB_CTRL,
+			  NOW_IS_OOB | DIS_MCU_CLROOB);
+
+	ocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, MCU_BORW_EN);
+
+	rtl_rx_vlan_en(tp, true);
+	rxdy_gated_en(tp, false);
+
+	ocp_dword_set_bits(tp, MCU_TYPE_PLA, PLA_RCR,
+			   RCR_APM | RCR_AM | RCR_AB);
+
+	r8153_aldps_en(tp, true);
+}
+
+static void rtl8157_change_mtu(struct r8152 *tp)
+{
+	u32 max_pkt_size = mtu_to_size(tp->netdev->mtu);
+	u32 ocp_data;
+
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, max_pkt_size);
+
+	/* Use at least 10K for MTPS */
+	ocp_data = max_t(u32, max_pkt_size, 10 * 1024) / 64;
+
+	/* 16 * 1024 / 64 = 0x100, so the max is 0xff for 8 bits data */
+	ocp_data = min_t(u32, ocp_data, 0xff);
+
+	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_MTPS, ocp_data);
+	r8156_fc_parameter(tp);
+
+	/* TX share fifo free credit full threshold */
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_TXFIFO_CTRL, 512 / 64);
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_TXFIFO_FULL,
+		       ALIGN(max_pkt_size + tp->tx_desc.size, 1024) / 16);
+}
+
+static void rtl8157_up(struct r8152 *tp)
+{
+	if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
+		return;
+
+	r8153b_u1u2en(tp, false);
+	r8153_aldps_en(tp, false);
+
+	rxdy_gated_en(tp, true);
+	r8153_teredo_off(tp);
+
+	ocp_dword_clr_bits(tp, MCU_TYPE_PLA, PLA_RCR, RCR_ACPT_ALL);
+
+	rtl8152_nic_reset(tp);
+	rtl_reset_bmu(tp);
+
+	ocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, NOW_IS_OOB);
+
+	ocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_RCR1, BIT(3));
+
+	ocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, MCU_BORW_EN);
+
+	rtl_rx_vlan_en(tp, tp->netdev->features & NETIF_F_HW_VLAN_CTAG_RX);
+
+	rtl8157_change_mtu(tp);
+
+	/* share FIFO settings */
+	ocp_word_w0w1(tp, MCU_TYPE_PLA, PLA_RXFIFO_FULL, RXFIFO_FULL_MASK,
+		      0x08);
+
+	ocp_word_clr_bits(tp, MCU_TYPE_USB, USB_SPEED_OPTION,
+			  RG_PWRDN_EN | ALL_SPEED_OFF);
+
+	ocp_write_dword(tp, MCU_TYPE_USB, USB_RX_BUF_TH, 0x00600400);
+
+	if (tp->saved_wolopts != __rtl_get_wol(tp)) {
+		netif_warn(tp, ifup, tp->netdev, "wol setting is changed\n");
+		__rtl_set_wol(tp, tp->saved_wolopts);
+	}
+
+	r8153_aldps_en(tp, true);
+
+	/* Enable Clear_SDR */
+	ocp_byte_set_bits(tp, MCU_TYPE_USB, 0xd378, BIT(7));
+	/* Clear SDR bit */
+	ocp_word_clr_bits(tp, MCU_TYPE_USB, 0xcd06, BIT(15));
+}
+
+static void rtl8157_down(struct r8152 *tp)
+{
+	if (test_bit(RTL8152_INACCESSIBLE, &tp->flags)) {
+		rtl_drop_queued_tx(tp);
+		return;
+	}
+
+	r8153b_u1u2en(tp, false);
+	r8153_aldps_en(tp, false);
+
+	ocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, NOW_IS_OOB);
+
+	/* RX FIFO settings for OOB */
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RXFIFO_FULL, 64 / 16);
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RX_FIFO_FULL, 1024 / 16);
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RX_FIFO_EMPTY, 4096 / 16);
+
+	rtl_disable(tp);
+	rtl_reset_bmu(tp);
+
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, 1526);
+	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_MTPS, 10 * 1024 / 64);
+
+	/* Clear teredo wake event. bit[15:8] is the teredo wakeup
+	 * type. Set it to zero. bits[7:0] are the W1C bits about
+	 * the events. Set them to all 1 to clear them.
+	 */
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_TEREDO_WAKE_BASE, 0x00ff);
+
+	ocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_BDC_CR, ALDPS_PROXY_MODE);
+
+	ocp_byte_set_bits(tp, MCU_TYPE_PLA, PLA_OOB_CTRL,
+			  NOW_IS_OOB | DIS_MCU_CLROOB);
 
 	ocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, MCU_BORW_EN);
 
@@ -6931,7 +7533,12 @@ static bool rtl8152_in_nway(struct r8152 *tp)
 
 static bool rtl8153_in_nway(struct r8152 *tp)
 {
-	u16 phy_state = ocp_reg_read(tp, OCP_PHY_STATE) & 0xff;
+	u16 phy_state;
+
+	if (ocp_reg_read(tp, OCP_PHY_STATE, &phy_state) < 0)
+		return false;
+
+	phy_state &= 0xff;
 
 	if (phy_state == TXDIS_STATE || phy_state == ABD_STATE)
 		return false;
@@ -6947,7 +7554,9 @@ static void r8156_mdio_force_mode(struct r8152 *tp)
 	 * 0: MDIO force mode
 	 * 1: MMD force mode
 	 */
-	data = ocp_reg_read(tp, 0xa5b4);
+	if (ocp_reg_read(tp, 0xa5b4, &data) < 0)
+		return;
+
 	if (data & BIT(15)) {
 		data &= ~BIT(15);
 		ocp_reg_write(tp, 0xa5b4, data);
@@ -7225,22 +7834,14 @@ static void r8152b_init(struct r8152 *tp)
 static void r8153_init(struct r8152 *tp)
 {
 	u32 ocp_data;
-	int i;
 
 	if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
 		return;
 
 	r8153_u1u2en(tp, false);
 
-	for (i = 0; i < 500; i++) {
-		if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) &
-		    AUTOLOAD_DONE)
-			break;
-
-		msleep(20);
-		if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
-			break;
-	}
+	if (wait_autoload_done(tp))
+		return;
 
 	r8153_phy_status(tp, 0);
 
@@ -7341,22 +7942,13 @@ static void r8153_init(struct r8152 *tp)
 
 static void r8153b_init(struct r8152 *tp)
 {
-	int i;
-
 	if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
 		return;
 
 	r8153b_u1u2en(tp, false);
 
-	for (i = 0; i < 500; i++) {
-		if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) &
-		    AUTOLOAD_DONE)
-			break;
-
-		msleep(20);
-		if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
-			break;
-	}
+	if (wait_autoload_done(tp))
+		return;
 
 	r8153_phy_status(tp, 0);
 
@@ -7411,8 +8003,6 @@ static void r8153b_init(struct r8152 *tp)
 
 static void r8153c_init(struct r8152 *tp)
 {
-	int i;
-
 	if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
 		return;
 
@@ -7425,15 +8015,8 @@ static void r8153c_init(struct r8152 *tp)
 
 	ocp_word_set_bits(tp, MCU_TYPE_USB, 0xcbf0, BIT(1));
 
-	for (i = 0; i < 500; i++) {
-		if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) &
-		    AUTOLOAD_DONE)
-			break;
-
-		msleep(20);
-		if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
-			return;
-	}
+	if (wait_autoload_done(tp))
+		return;
 
 	r8153_phy_status(tp, 0);
 
@@ -7612,19 +8195,20 @@ static void r8156_hw_phy_cfg(struct r8152 *tp)
 		ocp_reg_clr_bits(tp, 0xa86a, BIT(0));
 
 		/* MDI SWAP */
+		ocp_reg_read(tp, 0xd068, &data);
 		if ((ocp_read_word(tp, MCU_TYPE_USB, USB_UPS_CFG) & MID_REVERSE) &&
-		    (ocp_reg_read(tp, 0xd068) & BIT(1))) {
+		    (data & BIT(1))) {
 			u16 swap_a, swap_b;
 
-			data = ocp_reg_read(tp, 0xd068);
+			ocp_reg_read(tp, 0xd068, &data);
 			data &= ~0x1f;
 			data |= 0x1; /* p0 */
 			ocp_reg_write(tp, 0xd068, data);
-			swap_a = ocp_reg_read(tp, 0xd06a);
+			ocp_reg_read(tp, 0xd06a, &swap_a);
 			data &= ~0x18;
 			data |= 0x18; /* p3 */
 			ocp_reg_write(tp, 0xd068, data);
-			swap_b = ocp_reg_read(tp, 0xd06a);
+			ocp_reg_read(tp, 0xd06a, &swap_b);
 			data &= ~0x18; /* p0 */
 			ocp_reg_write(tp, 0xd068, data);
 			ocp_reg_write(tp, 0xd06a,
@@ -7636,11 +8220,11 @@ static void r8156_hw_phy_cfg(struct r8152 *tp)
 			data &= ~0x18;
 			data |= 0x08; /* p1 */
 			ocp_reg_write(tp, 0xd068, data);
-			swap_a = ocp_reg_read(tp, 0xd06a);
+			ocp_reg_read(tp, 0xd06a, &swap_a);
 			data &= ~0x18;
 			data |= 0x10; /* p2 */
 			ocp_reg_write(tp, 0xd068, data);
-			swap_b = ocp_reg_read(tp, 0xd06a);
+			ocp_reg_read(tp, 0xd06a, &swap_b);
 			data &= ~0x18;
 			data |= 0x08; /* p1 */
 			ocp_reg_write(tp, 0xd068, data);
@@ -7651,16 +8235,16 @@ static void r8156_hw_phy_cfg(struct r8152 *tp)
 			ocp_reg_write(tp, 0xd068, data);
 			ocp_reg_write(tp, 0xd06a,
 				      (swap_b & ~0x7ff) | (swap_a & 0x7ff));
-			swap_a = ocp_reg_read(tp, 0xbd5a);
-			swap_b = ocp_reg_read(tp, 0xbd5c);
+			ocp_reg_read(tp, 0xbd5a, &swap_a);
+			ocp_reg_read(tp, 0xbd5c, &swap_b);
 			ocp_reg_write(tp, 0xbd5a, (swap_a & ~0x1f1f) |
 				      ((swap_b & 0x1f) << 8) |
 				      ((swap_b >> 8) & 0x1f));
 			ocp_reg_write(tp, 0xbd5c, (swap_b & ~0x1f1f) |
 				      ((swap_a & 0x1f) << 8) |
 				      ((swap_a >> 8) & 0x1f));
-			swap_a = ocp_reg_read(tp, 0xbc18);
-			swap_b = ocp_reg_read(tp, 0xbc1a);
+			ocp_reg_read(tp, 0xbc18, &swap_a);
+			ocp_reg_read(tp, 0xbc1a, &swap_b);
 			ocp_reg_write(tp, 0xbc18, (swap_a & ~0x1f1f) |
 				      ((swap_b & 0x1f) << 8) |
 				      ((swap_b >> 8) & 0x1f));
@@ -7985,11 +8569,14 @@ static void r8157_hw_phy_cfg(struct r8152 *tp)
 	ocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_PHY_PWR, PFM_PWM_SWITCH);
 
 	/* Advanced Power Saving parameter */
-	ocp_reg_set_bits(tp, 0xa430, BIT(0) | BIT(1));
+	ocp_reg_set_bits(tp, OCP_POWER_CFG, EN_10M_PLLOFF | EN_ALDPS_PLLOFF);
 
 	/* Disable ALDPS force mode */
 	ocp_reg_clr_bits(tp, 0xa44a, BIT(2));
 
+	/* Disable bypass_turn_off_clk_in_aldps */
+	ocp_byte_clr_bits(tp, MCU_TYPE_PLA, 0xd3c8, BIT(0));
+
 	switch (tp->version) {
 	case RTL_VER_16:
 		/* XG_INRX parameter */
@@ -8005,7 +8592,7 @@ static void r8157_hw_phy_cfg(struct r8152 *tp)
 		sram2_write_w0w1(tp, 0x8078, 0xff00, 0x3000);
 
 		/* green mode */
-		sram2_write_w0w1(tp, 0x89e9, 0xff00, 0);
+		sram2_clr_bits(tp, 0x89e9, 0xff00);
 		sram2_write_w0w1(tp, 0x8ffd, 0xff00, 0x0100);
 		sram2_write_w0w1(tp, 0x8ffe, 0xff00, 0x0200);
 		sram2_write_w0w1(tp, 0x8fff, 0xff00, 0x0400);
@@ -8111,11 +8698,85 @@ static void r8157_hw_phy_cfg(struct r8152 *tp)
 		sram2_write_w0w1(tp, 0x807c, 0xff00, 0x5000);
 		sram2_write_w0w1(tp, 0x809d, 0xff00, 0x5000);
 		break;
+	default:
+		break;
+	}
+
+	if (rtl_phy_patch_request(tp, true, true))
+		return;
+
+	ocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, EEE_SPDWN_EN);
+
+	ocp_reg_w0w1(tp, OCP_DOWN_SPEED, EN_EEE_100 | EN_EEE_1000, EN_10M_CLKDIV);
+
+	tp->ups_info._10m_ckdiv = true;
+	tp->ups_info.eee_plloff_100 = false;
+	tp->ups_info.eee_plloff_giga = false;
+
+	ocp_reg_set_bits(tp, OCP_POWER_CFG, EEE_CLKDIV_EN);
+	tp->ups_info.eee_ckdiv = true;
 
-	case RTL_VER_17:
-		/* Disable bypass turn off clk in ALDPS */
-		ocp_byte_clr_bits(tp, MCU_TYPE_PLA, 0xd3c8, BIT(0));
+	rtl_phy_patch_request(tp, false, true);
+
+	rtl_green_en(tp, test_bit(GREEN_ETHERNET, &tp->flags));
 
+	ocp_reg_clr_bits(tp, 0xa428, BIT(9));
+	ocp_reg_clr_bits(tp, 0xa5ea, BIT(0) | BIT(1));
+	tp->ups_info.lite_mode = 0;
+
+	if (tp->eee_en)
+		rtl_eee_enable(tp, true);
+
+	r8153_aldps_en(tp, true);
+	r8152b_enable_fc(tp);
+
+	set_bit(PHY_RESET, &tp->flags);
+}
+
+static void r8159_hw_phy_cfg(struct r8152 *tp)
+{
+	u16 data;
+
+	r8156b_wait_loading_flash(tp);
+
+	ocp_word_test_and_clr_bits(tp, MCU_TYPE_USB, USB_MISC_0, PCUT_STATUS);
+
+	data = r8153_phy_status(tp, 0);
+	switch (data) {
+	case PHY_STAT_EXT_INIT:
+		rtl8152_apply_firmware(tp, true);
+		ocp_reg_clr_bits(tp, 0xa466, BIT(0));
+		ocp_reg_clr_bits(tp, 0xa468, BIT(3) | BIT(1));
+		break;
+	case PHY_STAT_LAN_ON:
+	case PHY_STAT_PWRDN:
+	default:
+		rtl8152_apply_firmware(tp, false);
+		break;
+	}
+
+	r8152_mdio_test_and_clr_bit(tp, MII_BMCR, BMCR_PDOWN);
+
+	r8153_aldps_en(tp, false);
+
+	data = r8153_phy_status(tp, PHY_STAT_LAN_ON);
+	WARN_ON_ONCE(data != PHY_STAT_LAN_ON);
+
+	/* PFM mode */
+	ocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_PHY_PWR, PFM_PWM_SWITCH);
+
+	/* Advanced Power Saving parameter */
+	ocp_reg_set_bits(tp, OCP_POWER_CFG, EN_10M_PLLOFF | EN_ALDPS_PLLOFF);
+
+	/* Disable ALDPS force mode */
+	ocp_reg_clr_bits(tp, 0xa44a, BIT(2));
+
+	/* Disable bypass_turn_off_clk_in_aldps */
+	ocp_byte_clr_bits(tp, MCU_TYPE_PLA, 0xd3c8, BIT(0));
+
+	switch (tp->version) {
+	case RTL_VER_17_QFN68:
+	case RTL_VER_17_QFN100:
 		/* Power level tuning
 		 * test mode power level
 		 */
@@ -8125,22 +8786,35 @@ static void r8157_hw_phy_cfg(struct r8152 *tp)
 		sram_write_w0w1(tp, 0x81ae, 0xff00, 0x0f00);
 		sram_write_w0w1(tp, 0x81b9, 0xff00, 0xb900);
 		/* normal link TX filter */
-		sram2_write_w0w1(tp, 0x83b0, 0x0e00, 0);
-		sram2_write_w0w1(tp, 0x83c5, 0x0e00, 0);
-		sram2_write_w0w1(tp, 0x83da, 0x0e00, 0);
-		sram2_write_w0w1(tp, 0x83ef, 0x0e00, 0);
+		sram2_clr_bits(tp, 0x83b0, 0x0e00);
+		sram2_clr_bits(tp, 0x83c5, 0x0e00);
+		sram2_clr_bits(tp, 0x83da, 0x0e00);
+		sram2_clr_bits(tp, 0x83ef, 0x0e00);
+
+		ocp_reg_w0w1(tp, 0xbf38, 0x01f0, 0x0160);
+		ocp_reg_w0w1(tp, 0xbf3a, 0x001f, 0x0014);
+		/* shorten CLKS latency */
+		ocp_reg_clr_bits(tp, 0xbf28, BIT(14) | BIT(13));
+		ocp_reg_clr_bits(tp, 0xbf2c, BIT(15) | BIT(14));
+		/* CMP_Timer on MP_Timer=333
+		 * GPHY OCP 0xbf28 bit[0] = 0x1
+		 * GPHY OCP 0xbf28 bit[6:1] = 0x3
+		 * GPHY OCP 0xbf28 bit[12:7] = 0x3
+		 */
+		ocp_reg_w0w1(tp, 0xbf28, 0x1fff, 0x0187);
+		ocp_reg_w0w1(tp, 0xbf2a, 0x3f, 0x03);
 
 		/* AFE power saving for 2.5G & 5G */
 		sram_write(tp, 0x8173, 0x8620);
 		sram_write(tp, 0x8175, 0x8671);
 
-		sram_write_w0w1(tp, 0x817c, 0, BIT(13));
-		sram_write_w0w1(tp, 0x8187, 0, BIT(13));
-		sram_write_w0w1(tp, 0x8192, 0, BIT(13));
-		sram_write_w0w1(tp, 0x819d, 0, BIT(13));
-		sram_write_w0w1(tp, 0x81a8, BIT(13), 0);
-		sram_write_w0w1(tp, 0x81b3, BIT(13), 0);
-		sram_write_w0w1(tp, 0x81be, 0, BIT(13));
+		sram_set_bits(tp, 0x817c, BIT(13));
+		sram_set_bits(tp, 0x8187, BIT(13));
+		sram_set_bits(tp, 0x8192, BIT(13));
+		sram_set_bits(tp, 0x819d, BIT(13));
+		sram_clr_bits(tp, 0x81a8, BIT(13));
+		sram_clr_bits(tp, 0x81b3, BIT(13));
+		sram_set_bits(tp, 0x81be, BIT(13));
 
 		sram_write_w0w1(tp, 0x817d, 0xff00, 0xa600);
 		sram_write_w0w1(tp, 0x8188, 0xff00, 0xa600);
@@ -8204,10 +8878,10 @@ static void r8157_hw_phy_cfg(struct r8152 *tp)
 		sram2_write_w0w1(tp, 0x84b2, 0xff00, 0x6000);
 		/* Training AAGC PAR (with uc2 patch) */
 		sram2_write(tp, 0x8ffc, 0x6008);
-		sram2_write(tp, 0x8ffe, 0xf450);
+		sram2_write(tp, 0x8ffe, 0xf4ff);
 		/* DAC BGK */
-		sram2_write_w0w1(tp, 0x8015, 0, BIT(9));
-		sram2_write_w0w1(tp, 0x8016, 0, BIT(11));
+		sram2_set_bits(tp, 0x8015, BIT(9));
+		sram2_set_bits(tp, 0x8016, BIT(11));
 		sram2_write_w0w1(tp, 0x8fe6, 0xff00, 0x0800);
 		sram2_write(tp, 0x8fe4, 0x2114);
 		/* 10G PBO table */
@@ -8216,14 +8890,14 @@ static void r8157_hw_phy_cfg(struct r8152 *tp)
 		sram2_write_w0w1(tp, 0x864b, 0xff00, 0xdc00);
 		/* 2.5G ado power window size */
 		sram2_write_w0w1(tp, 0x8154, 0xc000, 0x4000);
-		sram2_write_w0w1(tp, 0x8158, 0xc000, 0);
+		sram2_clr_bits(tp, 0x8158, 0xc000);
 		/* 10G lock far */
 		sram2_write(tp, 0x826c, 0xffff);
 		sram2_write(tp, 0x826e, 0xffff);
 		/* XG INRX parameter */
 		sram2_write_w0w1(tp, 0x8872, 0xff00, 0x0e00);
-		sram_write_w0w1(tp, 0x8012, 0, BIT(11));
-		sram_write_w0w1(tp, 0x8012, 0, BIT(14));
+		sram_set_bits(tp, 0x8012, BIT(11));
+		sram_set_bits(tp, 0x8012, BIT(14));
 		ocp_reg_set_bits(tp, 0xb576, BIT(0));
 		sram_write_w0w1(tp, 0x834a, 0xff00, 0x0700);
 		sram2_write_w0w1(tp, 0x8217, 0x3f00, 0x2a00);
@@ -8234,100 +8908,372 @@ static void r8157_hw_phy_cfg(struct r8152 *tp)
 		/* improve UBE */
 		ocp_reg_set_bits(tp, 0xbf0c, 0x7 << 11);
 		/* close Sparse NEC, improve connect 5EUU cable performance */
-		sram2_write_w0w1(tp, 0x88de, 0xff00, 0);
+		sram2_clr_bits(tp, 0x88de, 0xff00);
 		/* 5G slave compatibility issue */
 		sram2_write(tp, 0x80b4, 0x5195);
 
-		/* XG Test Mode
-		 * xgtstm_map_tbl for mdi_cap_sel
-		 */
-		sram_write(tp, 0x8370, 0x8671);
-		sram_write(tp, 0x8372, 0x86c8);
-		/* xgtstm_amp_map_tbl for  REG_IBX_UP_SHIFT_L */
-		sram_write(tp, 0x8401, 0x86c8);
-		sram_write(tp, 0x8403, 0x86da);
-		sram_write_w0w1(tp, 0x8406, 0x1800, 0x1000);
-		sram_write_w0w1(tp, 0x8408, 0x1800, 0x1000);
-		sram_write_w0w1(tp, 0x840a, 0x1800, 0x1000);
-		sram_write_w0w1(tp, 0x840c, 0x1800, 0x1000);
-		sram_write_w0w1(tp, 0x840e, 0x1800, 0x1000);
-		sram_write_w0w1(tp, 0x8410, 0x1800, 0x1000);
-		sram_write_w0w1(tp, 0x8412, 0x1800, 0x1000);
-		sram_write_w0w1(tp, 0x8414, 0x1800, 0x1000);
-		sram_write_w0w1(tp, 0x8416, 0x1800, 0x1000);
+		/* XG Test Mode
+		 * xgtstm_map_tbl for mdi_cap_sel
+		 */
+		sram_write(tp, 0x8370, 0x8671);
+		sram_write(tp, 0x8372, 0x86c8);
+		/* xgtstm_amp_map_tbl for  REG_IBX_UP_SHIFT_L */
+		sram_write(tp, 0x8401, 0x86c8);
+		sram_write(tp, 0x8403, 0x86da);
+		sram_write_w0w1(tp, 0x8406, 0x1800, 0x1000);
+		sram_write_w0w1(tp, 0x8408, 0x1800, 0x1000);
+		sram_write_w0w1(tp, 0x840a, 0x1800, 0x1000);
+		sram_write_w0w1(tp, 0x840c, 0x1800, 0x1000);
+		sram_write_w0w1(tp, 0x840e, 0x1800, 0x1000);
+		sram_write_w0w1(tp, 0x8410, 0x1800, 0x1000);
+		sram_write_w0w1(tp, 0x8412, 0x1800, 0x1000);
+		sram_write_w0w1(tp, 0x8414, 0x1800, 0x1000);
+		sram_write_w0w1(tp, 0x8416, 0x1800, 0x1000);
+
+		/* Cable Test Patch */
+		sram_write(tp, 0x82bd, 0x1f40);
+
+		/* Thermal sensor parameters */
+		ocp_reg_w0w1(tp, 0xbfb4, 0x07ff, 0x0328);
+		ocp_reg_write(tp, 0xbfb6, 0x3e14);
+
+		/* spdchg_gtx_shape_100M */
+		ocp_reg_write(tp, OCP_SRAM_ADDR, 0x81c4);
+		ocp_reg_write(tp, OCP_SRAM_DATA, 0x003b);
+		ocp_reg_write(tp, OCP_SRAM_DATA, 0x0086);
+		ocp_reg_write(tp, OCP_SRAM_DATA, 0x00b7);
+		ocp_reg_write(tp, OCP_SRAM_DATA, 0x00db);
+		ocp_reg_write(tp, OCP_SRAM_DATA, 0x00fe);
+		ocp_reg_write(tp, OCP_SRAM_DATA, 0x00fe);
+		ocp_reg_write(tp, OCP_SRAM_DATA, 0x00fe);
+		ocp_reg_write(tp, OCP_SRAM_DATA, 0x00fe);
+		ocp_reg_write(tp, OCP_SRAM_DATA, 0x00c3);
+		ocp_reg_write(tp, OCP_SRAM_DATA, 0x0078);
+		ocp_reg_write(tp, OCP_SRAM_DATA, 0x0047);
+		ocp_reg_write(tp, OCP_SRAM_DATA, 0x0023);
+
+		/* lsbmsk_parameters
+		 * RL6961_lsbmsk_parameter_250207
+		 */
+		sram2_write(tp, 0x88d7, 0x01a0);
+		sram2_write(tp, 0x88d9, 0x01a0);
+		sram2_write(tp, 0x8ffa, 0x002a);
+
+		sram2_write(tp, 0x8fee, 0xffdf);
+		sram2_write(tp, 0x8ff0, 0xffff);
+		sram2_write(tp, 0x8ff2, 0x0a4a);
+		sram2_write(tp, 0x8ff4, 0xaa5a);
+		sram2_write(tp, 0x8ff6, 0x0a4a);
+		sram2_write(tp, 0x8ff8, 0xaa5a);
+
+		sram2_write_w0w1(tp, 0x88d5, 0xff00, 0x0200);
+
+		/* spdchg_pga1_lpf_cap */
+		sram_write_w0w1(tp, 0x84bb, 0xff00, 0x0a00);
+		sram_write_w0w1(tp, 0x84c0, 0xff00, 0x1600);
+
+		/* ENET PLL jitter improvement */
+		ocp_reg_w0w1(tp, 0xbf8a, 0xfc00, 0x2000);
+		ocp_reg_set_bits(tp, 0xbf88, BIT(2));
+		break;
+	default:
+		break;
+	}
+
+	if (rtl_phy_patch_request(tp, true, true))
+		return;
+
+	ocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, EEE_SPDWN_EN);
+
+	ocp_reg_clr_bits(tp, OCP_DOWN_SPEED,
+			 EN_EEE_100 | EN_EEE_1000 | EN_10M_CLKDIV);
+	tp->ups_info._10m_ckdiv = false;
+	tp->ups_info.eee_plloff_100 = false;
+	tp->ups_info.eee_plloff_giga = false;
+
+	ocp_reg_set_bits(tp, OCP_POWER_CFG, EEE_CLKDIV_EN);
+	tp->ups_info.eee_ckdiv = true;
+
+	rtl_phy_patch_request(tp, false, true);
+
+	rtl_green_en(tp, test_bit(GREEN_ETHERNET, &tp->flags));
+
+	ocp_reg_clr_bits(tp, 0xa428, BIT(9));
+	ocp_reg_clr_bits(tp, 0xa5ea, BIT(0) | BIT(1) | BIT(2));
+	tp->ups_info.lite_mode = 0;
+
+	rtl_eee_enable(tp, tp->eee_en);
+
+	r8153_aldps_en(tp, true);
+	r8152b_enable_fc(tp);
+
+	set_bit(PHY_RESET, &tp->flags);
+}
+
+static void r8156_init(struct r8152 *tp)
+{
+	u16 data;
+
+	if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
+		return;
+
+	ocp_byte_clr_bits(tp, MCU_TYPE_USB, USB_ECM_OP, EN_ALL_SPEED);
+
+	ocp_write_word(tp, MCU_TYPE_USB, USB_SPEED_OPTION, 0);
+
+	ocp_word_set_bits(tp, MCU_TYPE_USB, USB_ECM_OPTION, BYPASS_MAC_RESET);
+
+	r8153b_u1u2en(tp, false);
+
+	if (wait_autoload_done(tp))
+		return;
+
+	data = r8153_phy_status(tp, 0);
+	if (data == PHY_STAT_EXT_INIT)
+		ocp_reg_clr_bits(tp, 0xa468, BIT(3) | BIT(1));
+
+	r8152_mdio_test_and_clr_bit(tp, MII_BMCR, BMCR_PDOWN);
+
+	data = r8153_phy_status(tp, PHY_STAT_LAN_ON);
+
+	r8153_u2p3en(tp, false);
+
+	/* MSC timer = 0xfff * 8ms = 32760 ms */
+	ocp_write_word(tp, MCU_TYPE_USB, USB_MSC_TIMER, 0x0fff);
+
+	/* U1/U2/L1 idle timer. 500 us */
+	ocp_write_word(tp, MCU_TYPE_USB, USB_U1U2_TIMER, 500);
+
+	r8153b_power_cut_en(tp, false);
+	r8156_ups_en(tp, false);
+	r8153_queue_wake(tp, false);
+	rtl_runtime_suspend_enable(tp, false);
+
+	ocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_INDICATE_FALG, PREBOOT_OPTION);
+
+	ocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_RMT_WAKE, RMT_WAKE_EN);
+
+	if (tp->udev->speed >= USB_SPEED_SUPER)
+		r8153b_u1u2en(tp, true);
+
+	usb_enable_lpm(tp->udev);
+
+	rtl_fc_pause_pkt_en(tp, 0);
+
+	r8156_mac_clk_spd(tp, true);
+
+	ocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3,
+			  PLA_MCU_SPDWN_EN);
+
+	if (rtl8152_get_speed(tp) & LINK_STATUS)
+		ocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS,
+				  CUR_LINK_OK | POLL_LINK_CHG);
+	else
+		ocp_word_w0w1(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS, CUR_LINK_OK,
+			      POLL_LINK_CHG);
+
+	set_bit(GREEN_ETHERNET, &tp->flags);
+
+	ocp_word_clr_bits(tp, MCU_TYPE_USB, USB_USB_CTRL,
+			  RX_AGG_DISABLE | RX_ZERO_EN);
+
+	ocp_byte_set_bits(tp, MCU_TYPE_USB, USB_BMU_CONFIG, ACT_ODMA);
+
+	r8156_mdio_force_mode(tp);
+	rtl_tally_reset(tp);
+
+	tp->coalesce = 15000; /* 15 us */
+}
+
+static void r8156b_u2phy_backup(struct r8152 *tp)
+{
+	ocp_write_word(tp, MCU_TYPE_USB, 0xd3ce, 0x181b);
+	ocp_write_dword(tp, MCU_TYPE_USB, 0xd3d0, 0x616ccd99);
+	ocp_write_dword(tp, MCU_TYPE_USB, 0xd3d4, 0x08fc8101);
+	ocp_write_dword(tp, MCU_TYPE_USB, 0xd3d8, 0x159b1100);
+	ocp_write_word(tp, MCU_TYPE_USB, 0xd3dc, 0x0a00);
+}
+
+static void r8156b_init(struct r8152 *tp)
+{
+	u16 data;
+
+	if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
+		return;
+
+	ocp_byte_clr_bits(tp, MCU_TYPE_USB, USB_ECM_OP, EN_ALL_SPEED);
+
+	ocp_write_word(tp, MCU_TYPE_USB, USB_SPEED_OPTION, 0);
+
+	ocp_word_set_bits(tp, MCU_TYPE_USB, USB_ECM_OPTION, BYPASS_MAC_RESET);
+
+	ocp_word_set_bits(tp, MCU_TYPE_USB, USB_U2P3_CTRL, RX_DETECT8);
+
+	r8153b_u1u2en(tp, false);
+
+	switch (tp->version) {
+	case RTL_VER_13:
+	case RTL_VER_15:
+		r8156b_wait_loading_flash(tp);
+		break;
+	default:
+		break;
+	}
+
+	if (wait_autoload_done(tp))
+		return;
+
+	data = r8153_phy_status(tp, 0);
+	if (data == PHY_STAT_EXT_INIT) {
+		ocp_reg_clr_bits(tp, 0xa468, BIT(3) | BIT(1));
+		ocp_reg_clr_bits(tp, 0xa466, BIT(0));
+	}
+
+	r8152_mdio_test_and_clr_bit(tp, MII_BMCR, BMCR_PDOWN);
+
+	data = r8153_phy_status(tp, PHY_STAT_LAN_ON);
+
+	r8153_u2p3en(tp, false);
+
+	/* MSC timer = 0xfff * 8ms = 32760 ms */
+	ocp_write_word(tp, MCU_TYPE_USB, USB_MSC_TIMER, 0x0fff);
+
+	/* U1/U2/L1 idle timer. 500 us */
+	ocp_write_word(tp, MCU_TYPE_USB, USB_U1U2_TIMER, 500);
+
+	r8156b_u2phy_backup(tp);
+
+	r8153b_power_cut_en(tp, false);
+	r8156_ups_en(tp, false);
+	r8153_queue_wake(tp, false);
+	rtl_runtime_suspend_enable(tp, false);
+
+	ocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_INDICATE_FALG, PREBOOT_OPTION);
+
+	ocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_RMT_WAKE, RMT_WAKE_EN);
+
+	if (tp->udev->speed >= USB_SPEED_SUPER)
+		r8153b_u1u2en(tp, true);
+
+	usb_enable_lpm(tp->udev);
+
+	rtl_fc_pause_pkt_en(tp, 0);
+
+	/* Disable Auto Speed up */
+	ocp_word_clr_bits(tp, MCU_TYPE_USB, USB_FW_CTRL, AUTO_SPEEDUP);
+
+	r8156_mac_clk_spd(tp, true);
+
+	ocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3,
+			  PLA_MCU_SPDWN_EN);
+
+	if (rtl8152_get_speed(tp) & LINK_STATUS)
+		ocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS,
+				  CUR_LINK_OK | POLL_LINK_CHG);
+	else
+		ocp_word_w0w1(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS,
+			      CUR_LINK_OK, POLL_LINK_CHG);
+
+	set_bit(GREEN_ETHERNET, &tp->flags);
+
+	ocp_word_clr_bits(tp, MCU_TYPE_USB, USB_USB_CTRL,
+			  RX_AGG_DISABLE | RX_ZERO_EN);
+
+	r8156_mdio_force_mode(tp);
+	rtl_tally_reset(tp);
 
-		/* Cable Test Patch */
-		sram_write(tp, 0x82bd, 0x1f40);
+	tp->coalesce = 15000;	/* 15 us */
+}
 
-		/* Thermal sensor parameters */
-		ocp_reg_w0w1(tp, 0xbfb4, 0x07ff, 0x0328);
-		ocp_reg_write(tp, 0xbfb6, 0x3e14);
+static void r8157_init(struct r8152 *tp)
+{
+	u16 data;
 
-		/* spdchg_gtx_shape_100M */
-		ocp_reg_write(tp, OCP_SRAM_ADDR, 0x81c4);
-		ocp_reg_write(tp, OCP_SRAM_DATA, 0x003b);
-		ocp_reg_write(tp, OCP_SRAM_DATA, 0x0086);
-		ocp_reg_write(tp, OCP_SRAM_DATA, 0x00b7);
-		ocp_reg_write(tp, OCP_SRAM_DATA, 0x00db);
-		ocp_reg_write(tp, OCP_SRAM_DATA, 0x00fe);
-		ocp_reg_write(tp, OCP_SRAM_DATA, 0x00fe);
-		ocp_reg_write(tp, OCP_SRAM_DATA, 0x00fe);
-		ocp_reg_write(tp, OCP_SRAM_DATA, 0x00fe);
-		ocp_reg_write(tp, OCP_SRAM_DATA, 0x00c3);
-		ocp_reg_write(tp, OCP_SRAM_DATA, 0x0078);
-		ocp_reg_write(tp, OCP_SRAM_DATA, 0x0047);
-		ocp_reg_write(tp, OCP_SRAM_DATA, 0x0023);
+	if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
+		return;
 
-		/* lsbmsk_parameters
-		 * RL6961_lsbmsk_parameter_250207
-		 */
-		sram2_write(tp, 0x88d7, 0x01a0);
-		sram2_write(tp, 0x88d9, 0x01a0);
-		sram2_write(tp, 0x8ffa, 0x002a);
+	/* Enable SW reset */
+	ocp_byte_set_bits(tp, MCU_TYPE_USB, 0xcffe, BIT(3));
+	ocp_byte_clr_bits(tp, MCU_TYPE_USB, 0xd3ca, BIT(0));
 
-		sram2_write(tp, 0x8fee, 0xffdf);
-		sram2_write(tp, 0x8ff0, 0xffff);
-		sram2_write(tp, 0x8ff2, 0x0a4a);
-		sram2_write(tp, 0x8ff4, 0xaa5a);
-		sram2_write(tp, 0x8ff6, 0x0a4a);
-		sram2_write(tp, 0x8ff8, 0xaa5a);
+	ocp_byte_clr_bits(tp, MCU_TYPE_USB, USB_ECM_OP, EN_ALL_SPEED);
 
-		sram2_write_w0w1(tp, 0x88d5, 0xff00, 0x0200);
-		break;
+	ocp_word_set_bits(tp, MCU_TYPE_USB, USB_ECM_OPTION, BYPASS_MAC_RESET);
 
-	default:
-		break;
-	}
+	r8153b_u1u2en(tp, false);
 
-	if (rtl_phy_patch_request(tp, true, true))
+	r8156b_wait_loading_flash(tp);
+
+	if (wait_autoload_done(tp))
 		return;
 
-	ocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, EEE_SPDWN_EN);
+	data = r8153_phy_status(tp, 0);
+	if (data == PHY_STAT_EXT_INIT) {
+		ocp_reg_clr_bits(tp, 0xa468, BIT(3) | BIT(1));
+		ocp_reg_clr_bits(tp, 0xa466, BIT(0));
+	}
 
-	ocp_reg_w0w1(tp, OCP_DOWN_SPEED, EN_EEE_100 | EN_EEE_1000, EN_10M_CLKDIV);
+	r8152_mdio_test_and_clr_bit(tp, MII_BMCR, BMCR_PDOWN);
 
-	tp->ups_info._10m_ckdiv = true;
-	tp->ups_info.eee_plloff_100 = false;
-	tp->ups_info.eee_plloff_giga = false;
+	data = r8153_phy_status(tp, PHY_STAT_LAN_ON);
 
-	ocp_reg_set_bits(tp, OCP_POWER_CFG, EEE_CLKDIV_EN);
-	tp->ups_info.eee_ckdiv = true;
+	r8157_u2p3en(tp, false);
 
-	rtl_phy_patch_request(tp, false, true);
+	/* Disable Interrupt Mitigation */
+	ocp_byte_clr_bits(tp, MCU_TYPE_USB, 0xcf04,
+			  BIT(0) | BIT(1) | BIT(2) | BIT(7));
 
-	rtl_green_en(tp, test_bit(GREEN_ETHERNET, &tp->flags));
+	/* MSC timer = 0xfff * 8ms = 32760 ms */
+	ocp_write_word(tp, MCU_TYPE_USB, USB_MSC_TIMER, 0x0fff);
 
-	ocp_reg_clr_bits(tp, 0xa428, BIT(9));
-	ocp_reg_clr_bits(tp, 0xa5ea, BIT(0) | BIT(1));
-	tp->ups_info.lite_mode = 0;
+	/* U1/U2/L1 idle timer. 500 us */
+	ocp_write_word(tp, MCU_TYPE_USB, USB_U1U2_TIMER, 500);
 
-	if (tp->eee_en)
-		rtl_eee_enable(tp, true);
+	r8157_power_cut_en(tp, false);
+	r8157_ups_en(tp, false);
+	r8153_queue_wake(tp, false);
+	rtl_runtime_suspend_enable(tp, false);
 
-	r8153_aldps_en(tp, true);
-	r8152b_enable_fc(tp);
+	ocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_INDICATE_FALG, PREBOOT_OPTION);
 
-	set_bit(PHY_RESET, &tp->flags);
+	ocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_RMT_WAKE, RMT_WAKE_EN);
+
+	/* Clear Warm RST / Bus RST event flag */
+	ocp_word_clr_bits(tp, MCU_TYPE_USB, 0xcd06, BIT(11));
+
+	if (tp->udev->speed >= USB_SPEED_SUPER)
+		r8153b_u1u2en(tp, true);
+
+	usb_enable_lpm(tp->udev);
+
+	/* Disable Auto Speed up */
+	ocp_word_clr_bits(tp, MCU_TYPE_USB, USB_FW_CTRL, AUTO_SPEEDUP);
+
+	r8156_mac_clk_spd(tp, true);
+
+	if (rtl8152_get_speed(tp) & LINK_STATUS)
+		ocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS,
+				  CUR_LINK_OK | POLL_LINK_CHG);
+	else
+		ocp_word_w0w1(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS,
+			      CUR_LINK_OK, POLL_LINK_CHG);
+
+	set_bit(GREEN_ETHERNET, &tp->flags);
+
+	/* RX aggregation / 16 bytes RX descriptor / Bulk In End transfer */
+	ocp_word_clr_bits(tp, MCU_TYPE_USB, USB_USB_CTRL,
+			  RX_AGG_DISABLE | RX_DESC_16B | RX_END_TRANSFER_EN);
+
+	/* Disable Rx Zero Len */
+	rtl_bmu_clr_bits(tp, 0x2300, BIT(3));
+
+	/* TX descriptor Signature */
+	ocp_byte_clr_bits(tp, MCU_TYPE_USB, 0xd4ae, BIT(1));
+
+	r8156_mdio_force_mode(tp);
+	rtl_tally_reset(tp);
+
+	tp->coalesce = 15000;	/* 15 us */
 }
 
 static int r8159_wait_backup_restore(struct r8152 *tp)
@@ -8342,78 +9288,50 @@ static int r8159_wait_backup_restore(struct r8152 *tp)
 			       ocp_data & BACKUP_RESTRORE, 200, 20000, false);
 }
 
-static void r8156_init(struct r8152 *tp)
+static void r8159_init(struct r8152 *tp)
 {
-	u32 ocp_data;
 	u16 data;
-	int i;
 
 	if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
 		return;
 
-	if (tp->version == RTL_VER_16 || tp->version == RTL_VER_17) {
-		ocp_byte_set_bits(tp, MCU_TYPE_USB, 0xcffe, BIT(3));
-		ocp_byte_clr_bits(tp, MCU_TYPE_USB, 0xd3ca, BIT(0));
-	}
+	/* Enable SW reset */
+	ocp_byte_set_bits(tp, MCU_TYPE_USB, 0xcffe, BIT(3));
+	ocp_byte_clr_bits(tp, MCU_TYPE_USB, 0xd3ca, BIT(0));
 
 	ocp_byte_clr_bits(tp, MCU_TYPE_USB, USB_ECM_OP, EN_ALL_SPEED);
 
-	if (tp->version < RTL_VER_16)
-		ocp_write_word(tp, MCU_TYPE_USB, USB_SPEED_OPTION, 0);
-
 	ocp_word_set_bits(tp, MCU_TYPE_USB, USB_ECM_OPTION, BYPASS_MAC_RESET);
 
-	if (tp->version >= RTL_VER_12 && tp->version <= RTL_VER_15)
-		ocp_word_set_bits(tp, MCU_TYPE_USB, USB_U2P3_CTRL, RX_DETECT8);
-
 	r8153b_u1u2en(tp, false);
 
-	switch (tp->version) {
-	case RTL_VER_13:
-	case RTL_VER_15:
-	case RTL_VER_16:
-	case RTL_VER_17:
-		r8156b_wait_loading_flash(tp);
-		break;
-	default:
-		break;
-	}
-
-	for (i = 0; i < 500; i++) {
-		if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) &
-		    AUTOLOAD_DONE)
-			break;
+	r8156b_wait_loading_flash(tp);
 
-		msleep(20);
-		if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
-			return;
-	}
+	if (wait_autoload_done(tp))
+		return;
 
-	if (tp->version == RTL_VER_17 && r8159_wait_backup_restore(tp)) {
+	if (r8159_wait_backup_restore(tp)) {
 		rtl_set_inaccessible(tp);
-		dev_err(&tp->intf->dev, "init failed, backup-restore timed out\n");
+		dev_err(&tp->intf->dev,
+			"init failed, backup-restore timed out\n");
 		return;
 	}
 
 	data = r8153_phy_status(tp, 0);
 	if (data == PHY_STAT_EXT_INIT) {
 		ocp_reg_clr_bits(tp, 0xa468, BIT(3) | BIT(1));
-		if (tp->version >= RTL_VER_12)
-			ocp_reg_clr_bits(tp, 0xa466, BIT(0));
+		ocp_reg_clr_bits(tp, 0xa466, BIT(0));
 	}
 
-	data = r8152_mdio_read(tp, MII_BMCR);
-	if (data & BMCR_PDOWN) {
-		data &= ~BMCR_PDOWN;
-		r8152_mdio_write(tp, MII_BMCR, data);
-	}
+	r8152_mdio_test_and_clr_bit(tp, MII_BMCR, BMCR_PDOWN);
 
 	data = r8153_phy_status(tp, PHY_STAT_LAN_ON);
 
-	if (tp->version >= RTL_VER_16)
-		r8157_u2p3en(tp, false);
-	else
-		r8153_u2p3en(tp, false);
+	r8157_u2p3en(tp, false);
+
+	/* Disable Interrupt Mitigation */
+	ocp_byte_clr_bits(tp, MCU_TYPE_USB, 0xcf04,
+			  BIT(0) | BIT(1) | BIT(2) | BIT(7));
 
 	/* MSC timer = 0xfff * 8ms = 32760 ms */
 	ocp_write_word(tp, MCU_TYPE_USB, USB_MSC_TIMER, 0x0fff);
@@ -8421,72 +9339,56 @@ static void r8156_init(struct r8152 *tp)
 	/* U1/U2/L1 idle timer. 500 us */
 	ocp_write_word(tp, MCU_TYPE_USB, USB_U1U2_TIMER, 500);
 
-	if (tp->version >= RTL_VER_16)
-		r8157_power_cut_en(tp, false);
-	else
-		r8153b_power_cut_en(tp, false);
-
-	r8156_ups_en(tp, false);
+	r8157_power_cut_en(tp, false);
+	r8157_ups_en(tp, false);
 	r8153_queue_wake(tp, false);
 	rtl_runtime_suspend_enable(tp, false);
 
-	if (tp->udev->speed >= USB_SPEED_SUPER)
-		r8153b_u1u2en(tp, true);
+	ocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_INDICATE_FALG, PREBOOT_OPTION);
 
-	usb_enable_lpm(tp->udev);
+	ocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_RMT_WAKE, RMT_WAKE_EN);
 
-	if (tp->version >= RTL_VER_12 && tp->version <= RTL_VER_15) {
-		ocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_RCR, SLOT_EN);
+	/* Clear Warm RST / Bus RST event flag */
+	ocp_word_clr_bits(tp, MCU_TYPE_USB, 0xcd06, BIT(11));
 
-		ocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_CPCR, FLOW_CTRL_EN);
+	/* Disable FW u1u2 patch option */
+	ocp_byte_clr_bits(tp, MCU_TYPE_USB, 0xb9a6, BIT(0));
 
-		/* enable fc timer and set timer to 600 ms. */
-		ocp_write_word(tp, MCU_TYPE_USB, USB_FC_TIMER, CTRL_TIMER_EN | (600 / 8));
+	if (tp->udev->speed >= USB_SPEED_SUPER)
+		r8153b_u1u2en(tp, true);
 
-		ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_FW_CTRL);
-		if (!(ocp_read_word(tp, MCU_TYPE_PLA, PLA_POL_GPIO_CTRL) & DACK_DET_EN))
-			ocp_data |= FLOW_CTRL_PATCH_2;
-		ocp_data &= ~AUTO_SPEEDUP;
-		ocp_write_word(tp, MCU_TYPE_USB, USB_FW_CTRL, ocp_data);
+	usb_enable_lpm(tp->udev);
 
-		ocp_word_set_bits(tp, MCU_TYPE_USB, USB_FW_TASK, FC_PATCH_TASK);
-	}
+	/* Disable Auto Speed up */
+	ocp_word_clr_bits(tp, MCU_TYPE_USB, USB_FW_CTRL, AUTO_SPEEDUP);
 
 	r8156_mac_clk_spd(tp, true);
 
-	if (tp->version < RTL_VER_16)
-		ocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, PLA_MCU_SPDWN_EN);
-
-	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS);
 	if (rtl8152_get_speed(tp) & LINK_STATUS)
-		ocp_data |= CUR_LINK_OK;
+		ocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS,
+				  CUR_LINK_OK | POLL_LINK_CHG);
 	else
-		ocp_data &= ~CUR_LINK_OK;
-	ocp_data |= POLL_LINK_CHG;
-	ocp_write_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS, ocp_data);
+		ocp_word_w0w1(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS,
+			      CUR_LINK_OK, POLL_LINK_CHG);
 
 	set_bit(GREEN_ETHERNET, &tp->flags);
 
-	/* RX aggregation / 16 bytes RX descriptor
-	 * BIT(11) is specific to RTL8159, with unknown meaning
-	 */
-	if (tp->version == RTL_VER_17)
-		ocp_word_clr_bits(tp, MCU_TYPE_USB, USB_USB_CTRL,
-				  RX_AGG_DISABLE | RX_DESC_16B | BIT(11));
-	else if (tp->version == RTL_VER_16)
-		ocp_word_clr_bits(tp, MCU_TYPE_USB, USB_USB_CTRL, RX_AGG_DISABLE | RX_DESC_16B);
-	else
-		ocp_word_clr_bits(tp, MCU_TYPE_USB, USB_USB_CTRL, RX_AGG_DISABLE | RX_ZERO_EN);
+	/* RX aggregation / 16 bytes RX descriptor / Bulk In End transfer */
+	ocp_word_clr_bits(tp, MCU_TYPE_USB, USB_USB_CTRL,
+			  RX_AGG_DISABLE | RX_DESC_16B | RX_END_TRANSFER_EN);
 
-	if (tp->version < RTL_VER_12)
-		ocp_byte_set_bits(tp, MCU_TYPE_USB, USB_BMU_CONFIG, ACT_ODMA);
+	/* Disable Rx Zero Len */
+	rtl_bmu_clr_bits(tp, 0x2300, BIT(3));
 
-	if (tp->version >= RTL_VER_16) {
-		/* Disable Rx Zero Len */
-		rtl_bmu_clr_bits(tp, 0x2300, BIT(3));
-		/* TX descriptor Signature */
-		ocp_byte_clr_bits(tp, MCU_TYPE_USB, 0xd4ae, BIT(1));
-	}
+	/* TX descriptor Signature */
+	ocp_byte_clr_bits(tp, MCU_TYPE_USB, 0xd4ae, BIT(1));
+
+	/* Enable u2phy backup restore patch */
+	if (tp->version == RTL_VER_17_QFN68)
+		ocp_byte_set_bits(tp, MCU_TYPE_USB, 0xb99c, BIT(0));
+
+	/* Enable u3phy patch backup */
+	ocp_write_word(tp, MCU_TYPE_USB, 0xb9a2, 0x0448);
 
 	r8156_mdio_force_mode(tp);
 	rtl_tally_reset(tp);
@@ -8926,8 +9828,16 @@ int rtl8152_get_link_ksettings(struct net_device *netdev,
 			 cmd->link_modes.supported, tp->support_10000full);
 
 	if (tp->support_2500full || tp->support_5000full || tp->support_10000full) {
-		u16 ocp_10gbt_ctrl = ocp_reg_read(tp, OCP_10GBT_CTRL);
-		u16 ocp_10gbt_stat = ocp_reg_read(tp, OCP_10GBT_STAT);
+		u16 ocp_10gbt_ctrl;
+		u16 ocp_10gbt_stat;
+
+		ret = ocp_reg_read(tp, OCP_10GBT_CTRL, &ocp_10gbt_ctrl);
+		if (ret < 0)
+			goto out_unlock;
+
+		ret = ocp_reg_read(tp, OCP_10GBT_STAT, &ocp_10gbt_stat);
+		if (ret < 0)
+			goto out_unlock;
 
 		if (tp->support_2500full) {
 			linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
@@ -8969,12 +9879,13 @@ int rtl8152_get_link_ksettings(struct net_device *netdev,
 		}
 	}
 
+out_unlock:
 	mutex_unlock(&tp->control);
 
 	usb_autopm_put_interface(tp->intf);
 
 out:
-	return ret;
+	return ret < 0 ? ret : 0;
 }
 
 static int rtl8152_set_link_ksettings(struct net_device *dev,
@@ -9155,21 +10066,37 @@ static int r8153_get_eee(struct r8152 *tp, struct ethtool_keee *eee)
 	__ETHTOOL_DECLARE_LINK_MODE_MASK(common) = {};
 	u16 speed = rtl8152_get_speed(tp);
 	u16 val;
+	int ret;
+
+	ret = ocp_reg_read(tp, OCP_EEE_ABLE, &val);
+	if (ret < 0)
+		goto out;
 
-	val = ocp_reg_read(tp, OCP_EEE_ABLE);
 	mii_eee_cap1_mod_linkmode_t(eee->supported, val);
 
-	val = ocp_reg_read(tp, OCP_EEE_ADV);
+	ret = ocp_reg_read(tp, OCP_EEE_ADV, &val);
+	if (ret < 0)
+		goto out;
+
 	mii_eee_cap1_mod_linkmode_t(eee->advertised, val);
 
-	val = ocp_reg_read(tp, OCP_EEE_LPABLE);
+	ret = ocp_reg_read(tp, OCP_EEE_LPABLE, &val);
+	if (ret < 0)
+		goto out;
+
 	mii_eee_cap1_mod_linkmode_t(eee->lp_advertised, val);
 
 	if (tp->support_2500full || tp->support_5000full) {
-		val = ocp_reg_read(tp, OCP_EEE_ADV2);
+		ret = ocp_reg_read(tp, OCP_EEE_ADV2, &val);
+		if (ret < 0)
+			goto out;
+
 		mii_eee_cap2_mod_linkmode_adv_t(eee->advertised, val);
 
-		val = ocp_reg_read(tp, OCP_EEE_LPABLE2);
+		ret = ocp_reg_read(tp, OCP_EEE_LPABLE2, &val);
+		if (ret < 0)
+			goto out;
+
 		mii_eee_cap2_mod_linkmode_adv_t(eee->lp_advertised, val);
 	}
 
@@ -9205,7 +10132,8 @@ static int r8153_get_eee(struct r8152 *tp, struct ethtool_keee *eee)
 	linkmode_and(common, common, eee->lp_advertised);
 	eee->eee_active = !linkmode_empty(common);
 
-	return 0;
+out:
+	return ret < 0 ? ret : 0;
 }
 
 static int
@@ -9445,7 +10373,7 @@ static int rtl8152_set_ringparam(struct net_device *netdev,
 static void rtl8152_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause)
 {
 	struct r8152 *tp = netdev_priv(netdev);
-	u16 bmcr, lcladv, rmtadv;
+	int bmcr, lcladv, rmtadv;
 	u8 cap;
 
 	if (usb_autopm_get_interface(tp->intf) < 0)
@@ -9461,7 +10389,10 @@ static void rtl8152_get_pauseparam(struct net_device *netdev, struct ethtool_pau
 
 	usb_autopm_put_interface(tp->intf);
 
-	if (!(bmcr & BMCR_ANENABLE)) {
+	/* Without a readable PHY, or with autoneg off, there is no flow
+	 * control to report.
+	 */
+	if (bmcr < 0 || lcladv < 0 || rmtadv < 0 || !(bmcr & BMCR_ANENABLE)) {
 		pause->autoneg = 0;
 		pause->rx_pause = 0;
 		pause->tx_pause = 0;
@@ -9492,7 +10423,11 @@ static int rtl8152_set_pauseparam(struct net_device *netdev, struct ethtool_paus
 
 	mutex_lock(&tp->control);
 
-	if (pause->autoneg && !(r8152_mdio_read(tp, MII_BMCR) & BMCR_ANENABLE)) {
+	ret = r8152_mdio_read(tp, MII_BMCR);
+	if (ret < 0)
+		goto out;
+
+	if (pause->autoneg && !(ret & BMCR_ANENABLE)) {
 		ret = -EINVAL;
 		goto out;
 	}
@@ -9503,16 +10438,20 @@ static int rtl8152_set_pauseparam(struct net_device *netdev, struct ethtool_paus
 	if (pause->tx_pause)
 		cap |= FLOW_CTRL_TX;
 
-	old = r8152_mdio_read(tp, MII_ADVERTISE);
+	ret = r8152_mdio_read(tp, MII_ADVERTISE);
+	if (ret < 0)
+		goto out;
+
+	old = ret;
 	new1 = (old & ~(ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM)) | mii_advertise_flowctrl(cap);
 	if (old != new1)
-		r8152_mdio_write(tp, MII_ADVERTISE, new1);
+		ret = r8152_mdio_write(tp, MII_ADVERTISE, new1);
 
 out:
 	mutex_unlock(&tp->control);
 	usb_autopm_put_interface(tp->intf);
 
-	return ret;
+	return ret < 0 ? ret : 0;
 }
 
 static const struct ethtool_ops ops = {
@@ -9546,7 +10485,7 @@ static int rtl8152_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
 {
 	struct r8152 *tp = netdev_priv(netdev);
 	struct mii_ioctl_data *data = if_mii(rq);
-	int res;
+	int res, val;
 
 	if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
 		return -ENODEV;
@@ -9562,7 +10501,11 @@ static int rtl8152_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
 
 	case SIOCGMIIREG:
 		mutex_lock(&tp->control);
-		data->val_out = r8152_mdio_read(tp, data->reg_num);
+		val = r8152_mdio_read(tp, data->reg_num);
+		if (val < 0)
+			res = val;
+		else
+			data->val_out = val;
 		mutex_unlock(&tp->control);
 		break;
 
@@ -9572,7 +10515,7 @@ static int rtl8152_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
 			break;
 		}
 		mutex_lock(&tp->control);
-		r8152_mdio_write(tp, data->reg_num, data->val_in);
+		res = r8152_mdio_write(tp, data->reg_num, data->val_in);
 		mutex_unlock(&tp->control);
 		break;
 
@@ -9663,11 +10606,6 @@ static void rtl8153_unload(struct r8152 *tp)
 		return;
 
 	r8153_power_cut_en(tp, false);
-
-	if (tp->version >= RTL_VER_16) {
-		/* Disable Interrupt Mitigation */
-		ocp_byte_clr_bits(tp, MCU_TYPE_USB, 0xcf04, BIT(0) | BIT(1) | BIT(2) | BIT(7));
-	}
 }
 
 static void rtl8153b_unload(struct r8152 *tp)
@@ -9678,6 +10616,16 @@ static void rtl8153b_unload(struct r8152 *tp)
 	r8153b_power_cut_en(tp, false);
 }
 
+static void rtl8157_unload(struct r8152 *tp)
+{
+	if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
+		return;
+
+	r8157_power_cut_en(tp, false);
+	ocp_byte_clr_bits(tp, MCU_TYPE_USB, 0xcf04,
+			  BIT(0) | BIT(1) | BIT(2) | BIT(7));
+}
+
 static int r8152_desc_init(struct r8152 *tp)
 {
 	tp->rx_desc.size = sizeof(struct rx_desc);
@@ -9730,6 +10678,8 @@ static int rtl_ops_init(struct r8152 *tp)
 		ops->in_nway		= rtl8152_in_nway;
 		ops->hw_phy_cfg		= r8152b_hw_phy_cfg;
 		ops->autosuspend_en	= rtl_runtime_suspend_enable;
+		ops->phy_read		= r8152_phy_read;
+		ops->phy_write		= r8152_phy_write;
 		tp->rx_buf_sz		= 16 * 1024;
 		tp->eee_en		= true;
 		tp->eee_adv		= MDIO_EEE_100TX;
@@ -9752,6 +10702,8 @@ static int rtl_ops_init(struct r8152 *tp)
 		ops->hw_phy_cfg		= r8153_hw_phy_cfg;
 		ops->autosuspend_en	= rtl8153_runtime_enable;
 		ops->change_mtu		= rtl8153_change_mtu;
+		ops->phy_read		= r8152_phy_read;
+		ops->phy_write		= r8152_phy_write;
 		if (tp->udev->speed < USB_SPEED_SUPER)
 			tp->rx_buf_sz	= 16 * 1024;
 		else
@@ -9775,6 +10727,8 @@ static int rtl_ops_init(struct r8152 *tp)
 		ops->hw_phy_cfg		= r8153b_hw_phy_cfg;
 		ops->autosuspend_en	= rtl8153b_runtime_enable;
 		ops->change_mtu		= rtl8153_change_mtu;
+		ops->phy_read		= r8152_phy_read;
+		ops->phy_write		= r8152_phy_write;
 		tp->rx_buf_sz		= 32 * 1024;
 		tp->eee_en		= true;
 		tp->eee_adv		= MDIO_EEE_1000T | MDIO_EEE_100TX;
@@ -9799,6 +10753,8 @@ static int rtl_ops_init(struct r8152 *tp)
 		ops->hw_phy_cfg		= r8156_hw_phy_cfg;
 		ops->autosuspend_en	= rtl8156_runtime_enable;
 		ops->change_mtu		= rtl8156_change_mtu;
+		ops->phy_read		= r8152_phy_read;
+		ops->phy_write		= r8152_phy_write;
 		tp->rx_buf_sz		= 48 * 1024;
 		tp->support_2500full	= 1;
 		r8152_desc_init(tp);
@@ -9812,8 +10768,8 @@ static int rtl_ops_init(struct r8152 *tp)
 		tp->eee_en		= true;
 		tp->eee_adv		= MDIO_EEE_1000T | MDIO_EEE_100TX;
 		tp->eee_adv2		= MDIO_EEE_2_5GT;
-		ops->init		= r8156_init;
-		ops->enable		= rtl8156_enable;
+		ops->init		= r8156b_init;
+		ops->enable		= rtl8156b_enable;
 		ops->disable		= rtl8153_disable;
 		ops->up			= rtl8156_up;
 		ops->down		= rtl8156_down;
@@ -9824,6 +10780,8 @@ static int rtl_ops_init(struct r8152 *tp)
 		ops->hw_phy_cfg		= r8156b_hw_phy_cfg;
 		ops->autosuspend_en	= rtl8156_runtime_enable;
 		ops->change_mtu		= rtl8156_change_mtu;
+		ops->phy_read		= r8152_phy_read;
+		ops->phy_write		= r8152_phy_write;
 		tp->rx_buf_sz		= 48 * 1024;
 		r8152_desc_init(tp);
 		break;
@@ -9841,6 +10799,8 @@ static int rtl_ops_init(struct r8152 *tp)
 		ops->hw_phy_cfg		= r8153c_hw_phy_cfg;
 		ops->autosuspend_en	= rtl8153c_runtime_enable;
 		ops->change_mtu		= rtl8153c_change_mtu;
+		ops->phy_read		= r8152_phy_read;
+		ops->phy_write		= r8152_phy_write;
 		tp->rx_buf_sz		= 32 * 1024;
 		tp->eee_en		= true;
 		tp->eee_adv		= MDIO_EEE_1000T | MDIO_EEE_100TX;
@@ -9851,40 +10811,45 @@ static int rtl_ops_init(struct r8152 *tp)
 		tp->eee_en		= true;
 		tp->eee_adv		= MDIO_EEE_1000T | MDIO_EEE_100TX;
 		tp->eee_adv2		= MDIO_EEE_2_5GT | MDIO_EEE_5GT;
-		ops->init		= r8156_init;
-		ops->enable		= rtl8156_enable;
+		ops->init		= r8157_init;
+		ops->enable		= rtl8157_enable;
 		ops->disable		= rtl8153_disable;
-		ops->up			= rtl8156_up;
-		ops->down		= rtl8156_down;
-		ops->unload		= rtl8153_unload;
+		ops->up			= rtl8157_up;
+		ops->down		= rtl8157_down;
+		ops->unload		= rtl8157_unload;
 		ops->eee_get		= r8153_get_eee;
 		ops->eee_set		= r8152_set_eee;
 		ops->in_nway		= rtl8153_in_nway;
 		ops->hw_phy_cfg		= r8157_hw_phy_cfg;
 		ops->autosuspend_en	= rtl8157_runtime_enable;
-		ops->change_mtu		= rtl8156_change_mtu;
+		ops->change_mtu		= rtl8157_change_mtu;
+		ops->phy_read		= r8157_phy_read;
+		ops->phy_write		= r8157_phy_write;
 		tp->rx_buf_sz		= 32 * 1024;
 		tp->support_2500full	= 1;
 		tp->support_5000full	= 1;
 		r8157_desc_init(tp);
 		break;
 
-	case RTL_VER_17:
+	case RTL_VER_17_QFN68:
+	case RTL_VER_17_QFN100:
 		tp->eee_en		= true;
 		tp->eee_adv		= MDIO_EEE_100TX | MDIO_EEE_1000T | MDIO_EEE_10GT;
 		tp->eee_adv2		= MDIO_EEE_2_5GT | MDIO_EEE_5GT;
-		ops->init		= r8156_init;
-		ops->enable		= rtl8156_enable;
+		ops->init		= r8159_init;
+		ops->enable		= rtl8157_enable;
 		ops->disable		= rtl8153_disable;
-		ops->up			= rtl8156_up;
-		ops->down		= rtl8156_down;
-		ops->unload		= rtl8153_unload;
+		ops->up			= rtl8157_up;
+		ops->down		= rtl8157_down;
+		ops->unload		= rtl8157_unload;
 		ops->eee_get		= r8153_get_eee;
 		ops->eee_set		= r8152_set_eee;
 		ops->in_nway		= rtl8153_in_nway;
-		ops->hw_phy_cfg		= r8157_hw_phy_cfg;
+		ops->hw_phy_cfg		= r8159_hw_phy_cfg;
 		ops->autosuspend_en	= rtl8157_runtime_enable;
-		ops->change_mtu		= rtl8156_change_mtu;
+		ops->change_mtu		= rtl8157_change_mtu;
+		ops->phy_read		= r8157_phy_read;
+		ops->phy_write		= r8157_phy_write;
 		tp->rx_buf_sz		= 48 * 1024;
 		tp->support_2500full	= 1;
 		tp->support_5000full	= 1;
@@ -9961,7 +10926,8 @@ static int rtl_fw_init(struct r8152 *tp)
 	case RTL_VER_16:
 		rtl_fw->fw_name		= FIRMWARE_8157_1;
 		break;
-	case RTL_VER_17:
+	case RTL_VER_17_QFN68:
+	case RTL_VER_17_QFN100:
 		rtl_fw->fw_name		= FIRMWARE_8159_1;
 		break;
 	default:
@@ -9971,9 +10937,38 @@ static int rtl_fw_init(struct r8152 *tp)
 	return 0;
 }
 
+static u32 __rtl_get_pkg_det(struct usb_device *udev)
+{
+	u32 pkg_det = 0;
+	__le32 *tmp;
+	int ret, i;
+
+	tmp = kmalloc_obj(*tmp);
+	if (!tmp)
+		return 0;
+
+	for (i = 0, ret = 0; i < 3 && ret != 4; i++)
+		ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+				      RTL8152_REQ_GET_REGS, RTL8152_REQT_READ,
+				      PLA_PKG_DET, MCU_TYPE_PLA, tmp,
+				      sizeof(*tmp), USB_CTRL_GET_TIMEOUT);
+
+	if (ret == sizeof(*tmp)) {
+		if (i != 1)
+			dev_warn(&udev->dev,
+				 "Needed %d retries to read package\n", i);
+
+		pkg_det = __le32_to_cpu(*tmp) & PKG_MASK;
+	}
+
+	kfree(tmp);
+	return pkg_det;
+}
+
 static u8 __rtl_get_hw_ver(struct usb_device *udev)
 {
 	u32 ocp_data = 0;
+	u32 pkg_det = 0;
 	__le32 *tmp;
 	u8 version;
 	int ret;
@@ -10056,7 +11051,16 @@ static u8 __rtl_get_hw_ver(struct usb_device *udev)
 		version = RTL_VER_16;
 		break;
 	case 0x2020:
-		version = RTL_VER_17;
+		pkg_det = __rtl_get_pkg_det(udev);
+		if (pkg_det == 0x1e || pkg_det == 0x1c) {
+			version = RTL_VER_17_QFN68;
+		} else if (pkg_det == 0x18 || pkg_det == 0x1a) {
+			version = RTL_VER_17_QFN100;
+		} else {
+			version = RTL_VER_UNKNOWN;
+			dev_info(&udev->dev, "Unknown package 0x%04x\n",
+				 pkg_det);
+		}
 		break;
 	default:
 		version = RTL_VER_UNKNOWN;
@@ -10215,7 +11219,8 @@ static int rtl8152_probe_once(struct usb_interface *intf,
 	case RTL_VER_13:
 	case RTL_VER_15:
 	case RTL_VER_16:
-	case RTL_VER_17:
+	case RTL_VER_17_QFN68:
+	case RTL_VER_17_QFN100:
 		netdev->max_mtu = size_to_mtu(16 * 1024);
 		break;
 	case RTL_VER_01:

15/3 2026/10/08 11:06 llm kmsan-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 45708
							output: 42
							thoughts: 3597
						

Thoughts:
**KMSAN Patch Analysis for r8152.c**

Alright, let's dive into this patch for `drivers/net/usb/r8152.c`.  The goal here, as I understand it, is to meticulously determine if this patch introduces any uninitialized memory reads or information leaks. I'm operating under the guiding principle: if KASAN, LOCKDEP, or other standard debuggers can catch it, KMSAN is overkill and resource-intensive.  We want to reserve KMSAN for those truly elusive uninitialized memory reads.

This patch adds new register definitions, macros, and function pointers related to the RTL8156/8157/8159 chipsets. It also modifies several functions: `ocp_reg_read`, `ocp_reg_write`, `sram_read`, `sram2_read`, `r8152_phy_read`, `r8157_phy_read`, and so on. The core of my analysis revolves around whether these modifications, especially the revised function signatures (e.g., changing `ocp_reg_read` to return an `int` and take a pointer to the data), create opportunities for uninitialized data to leak to userspace.

The critical area I'm focusing on is the new error handling. I see that if a read operation in the `rtl_tgphy_access` function fails (returns a negative value), the `*data` variable, which is intended to store the read value, isn't written. This presents a clear vulnerability if the caller doesn't properly handle the error and subsequently uses the potentially uninitialized value.

I've gone through the code methodically. I've scrutinized every call site of these modified read functions, including `ocp_reg_read`, `sram_read`, `sram2_read`, `r8152_phy_read`, and so on. I'm paying close attention to whether the return values of these functions are checked and whether the caller initializes the data variable before calling the read function.

Specifically, I’ve checked these functions: `r8152_mdio_read`, `sram_read`, `sram2_read`, `ocp_reg_w0w1`, `sram_write_w0w1`, `sram2_write_w0w1`, `r8152_mdio_clr_bit`, `r8152_mdio_set_bit`, `r8152_mdio_test_and_clr_bit`, `r8153_phy_status`, `rtl_phy_patch_request`, `rtl_ram_code_speed_up`, `rtl8152_fw_phy_ver`, `rtl8152_fw_phy_fixup`, `r8152_mmd_read`, `r8156_eee_en` and `r8153b_hw_phy_cfg`. In each case, I was able to verify that the return value is properly handled, or that data is initialized before the read, which prevents the uninitialized memory issue.

After careful examination of all the call sites, I have NOT found any instances where a potentially uninitialized value from these read functions could be read by userspace.

Therefore, my determination is that **NeedsKMSAN=false** for this patch. While the changes are significant, the code appears robust in handling potential errors and ensuring that data used by calling functions is initialized.



16/3 2026/10/08 11:07 tool read-file
0m Args:
{
  "File": "drivers/net/usb/r8152.c",
  "FirstLine": 6615,
  "LineCount": 35
}

Results:
{
  "Contents": "6615:\t\t * bit (bit3) to rebuild the real 16-bit data. Write the data to the\n6616:\t\t * ADC ioffset.\n6617:\t\t */\n6618:\t\tocp_data = r8152_efuse_read(tp, 0x7d);\n6619:\t\tdata = (u16)(((ocp_data \u0026 0x1fff0) \u003e\u003e 1) | (ocp_data \u0026 0x7));\n6620:\t\tif (data != 0xffff)\n6621:\t\t\tocp_reg_write(tp, OCP_ADC_IOFFSET, data);\n6622:\t\n6623:\t\t/* ups mode tx-link-pulse timing adjustment:\n6624:\t\t * rg_saw_cnt = OCP reg 0xC426 Bit[13:0]\n6625:\t\t * swr_cnt_1ms_ini = 16000000 / rg_saw_cnt\n6626:\t\t */\n6627:\t\tocp_reg_read(tp, 0xc426, \u0026data);\n6628:\t\tocp_data = data \u0026 0x3fff;\n6629:\t\tif (ocp_data) {\n6630:\t\t\tu32 swr_cnt_1ms_ini;\n6631:\t\n6632:\t\t\tswr_cnt_1ms_ini = (16000000 / ocp_data) \u0026 SAW_CNT_1MS_MASK;\n6633:\t\t\tocp_word_w0w1(tp, MCU_TYPE_USB, USB_UPS_CFG, SAW_CNT_1MS_MASK,\n6634:\t\t\t\t      swr_cnt_1ms_ini);\n6635:\t\t}\n6636:\t\n6637:\t\tocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_PHY_PWR, PFM_PWM_SWITCH);\n6638:\t\n6639:\t\t/* Advnace EEE */\n6640:\t\tif (!rtl_phy_patch_request(tp, true, true)) {\n6641:\t\t\tocp_reg_set_bits(tp, OCP_POWER_CFG, EEE_CLKDIV_EN);\n6642:\t\t\ttp-\u003eups_info.eee_ckdiv = true;\n6643:\t\n6644:\t\t\tocp_reg_set_bits(tp, OCP_DOWN_SPEED,\n6645:\t\t\t\t\t EN_EEE_CMODE | EN_EEE_1000 | EN_10M_CLKDIV);\n6646:\t\t\ttp-\u003eups_info.eee_cmod_lv = true;\n6647:\t\t\ttp-\u003eups_info._10m_ckdiv = true;\n6648:\t\t\ttp-\u003eups_info.eee_plloff_giga = true;\n6649:\t\n"
}

17/3 2026/10/08 11:07 llm kmsan-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 50867
							output: 41
							thoughts: 558
						

Thoughts:
**Analyzing the Data Flow and Potential Issues in r8153b_hw_phy_cfg**

Okay, let me think this through. I'm focusing on `r8153b_hw_phy_cfg`. First, I need to confirm something crucial. Is the `data` variable initialized *before* the call to `ocp_reg_read(tp, 0xc426, &data)`? Yes, I see it's initialized on line 6619 with `data = (u16)...`, so `data` *is* written to before the read on line 6627! That's good.

Now, I need to understand what `ocp_reg_read` does in this context, specifically for the RTL8153b. Let's dig into that. I see that for the RTL8153b, `ops->phy_read = r8152_phy_read;`. Okay, so `r8152_phy_read` is the function being called. Let's see what *that* function does.

Looking at `r8152_phy_read`, I see that it does indeed assign a value to `*data`, the pointer passed to the function. Specifically, it reads from the OCP register space using `ocp_read_word`. So, I'm confident that `*data` *always* gets assigned a value, and the function returns 0. That confirms my understanding.

Now, I need to consider a different scenario. What if we were dealing with an RTL8157, and `ops->phy_read` was `r8157_phy_read` instead? Ah, but in that case, the `hw_phy_cfg` would be handled differently. For RTL_VER_16 or 17, `ops->hw_phy_cfg` would be `r8157_hw_phy_cfg` or `r8159_hw_phy_cfg`, not `r8153b_hw_phy_cfg`. Okay, that's a different code path altogether.

Still, one thing comes to mind, `rtl_tgphy_access`, which the other code calls, what if `wait_tgphy_cmd_ready` fails within `rtl_tgphy_access`? That would definitely be a point of failure and I should look out for it.

Just to be thorough, I should check where `r8157_phy_read` is used. I see that it is indeed set for RTL_VER_16 and RTL_VER_17.

Finally, just to ensure I haven't missed anything, let me quickly grep for any other calls to `ocp_reg_read` within `drivers/net/usb/r8152.c`. It's always a good idea to see the bigger picture.



18/3 2026/10/08 11:07 tool grepper
0m Args:
{
  "Expression": "ocp_reg_read\\(",
  "PathPrefixes": [
    "drivers/net/usb/r8152.c"
  ]
}

Results:
{
  "Output": "drivers/net/usb/r8152.c=1677=static int r8152_phy_write(struct r8152 *tp, u16 addr, u16 data)\n--\ndrivers/net/usb/r8152.c-1692-\ndrivers/net/usb/r8152.c:1693:static int ocp_reg_read(struct r8152 *tp, u16 addr, u16 *data)\ndrivers/net/usb/r8152.c-1694-{\n--\ndrivers/net/usb/r8152.c=1708=static int r8152_mdio_read(struct r8152 *tp, u32 reg_addr)\n--\ndrivers/net/usb/r8152.c-1712-\ndrivers/net/usb/r8152.c:1713:\tret = ocp_reg_read(tp, OCP_BASE_MII + reg_addr * 2, \u0026data);\ndrivers/net/usb/r8152.c-1714-\n--\ndrivers/net/usb/r8152.c=1848=static int sram_read(struct r8152 *tp, u16 addr, u16 *data)\n--\ndrivers/net/usb/r8152.c-1855-\ndrivers/net/usb/r8152.c:1856:\tret = ocp_reg_read(tp, OCP_SRAM_DATA, data);\ndrivers/net/usb/r8152.c-1857-\n--\ndrivers/net/usb/r8152.c=1964=static int ocp_reg_w0w1(struct r8152 *tp, u16 addr, u16 clear, u16 set)\n--\ndrivers/net/usb/r8152.c-1968-\ndrivers/net/usb/r8152.c:1969:\tret = ocp_reg_read(tp, addr, \u0026data);\ndrivers/net/usb/r8152.c-1970-\tif (ret \u003c 0)\n--\ndrivers/net/usb/r8152.c=2030=static int sram2_read(struct r8152 *tp, u16 addr, u16 *data)\n--\ndrivers/net/usb/r8152.c-2037-\ndrivers/net/usb/r8152.c:2038:\tret = ocp_reg_read(tp, OCP_SRAM2_DATA, data);\ndrivers/net/usb/r8152.c-2039-\n--\ndrivers/net/usb/r8152.c=4382=static u16 r8153_phy_status(struct r8152 *tp, u16 desired)\n--\ndrivers/net/usb/r8152.c-4387-\tfor (i = 0; i \u003c 500; i++) {\ndrivers/net/usb/r8152.c:4388:\t\tif (ocp_reg_read(tp, OCP_PHY_STATUS, \u0026data) \u003c 0)\ndrivers/net/usb/r8152.c-4389-\t\t\tbreak;\n--\ndrivers/net/usb/r8152.c=4855=static int rtl_phy_patch_request(struct r8152 *tp, bool request, bool wait)\n--\ndrivers/net/usb/r8152.c-4873-\t\tusleep_range(1000, 2000);\ndrivers/net/usb/r8152.c:4874:\t\tret = ocp_reg_read(tp, OCP_PHY_PATCH_STAT, \u0026ocp_data);\ndrivers/net/usb/r8152.c-4875-\t\tif (ret \u003c 0)\n--\ndrivers/net/usb/r8152.c-4881-\tif (request \u0026\u0026 wait) {\ndrivers/net/usb/r8152.c:4882:\t\tret = ocp_reg_read(tp, OCP_PHY_PATCH_STAT, \u0026ocp_data);\ndrivers/net/usb/r8152.c-4883-\t\tif (ret \u003c 0) {\n--\ndrivers/net/usb/r8152.c=5692=static void rtl8152_fw_phy_fixup(struct r8152 *tp, struct fw_phy_fixup *fix)\n--\ndrivers/net/usb/r8152.c-5698-\taddr = __le16_to_cpu(fix-\u003esetting.addr);\ndrivers/net/usb/r8152.c:5699:\tif (ocp_reg_read(tp, addr, \u0026data) \u003c 0)\ndrivers/net/usb/r8152.c-5700-\t\treturn;\n--\ndrivers/net/usb/r8152.c=6002=static u16 r8152_mmd_read(struct r8152 *tp, u16 dev, u16 reg)\n--\ndrivers/net/usb/r8152.c-6006-\tr8152_mmd_indirect(tp, dev, reg);\ndrivers/net/usb/r8152.c:6007:\tocp_reg_read(tp, OCP_EEE_DATA, \u0026data);\ndrivers/net/usb/r8152.c-6008-\tocp_reg_write(tp, OCP_EEE_AR, 0x0000);\n--\ndrivers/net/usb/r8152.c=6066=static void r8156_eee_en(struct r8152 *tp, bool enable)\n--\ndrivers/net/usb/r8152.c-6071-\ndrivers/net/usb/r8152.c:6072:\tif (ocp_reg_read(tp, OCP_EEE_ADV2, \u0026config) \u003c 0)\ndrivers/net/usb/r8152.c-6073-\t\treturn;\n--\ndrivers/net/usb/r8152.c=6576=static void r8153b_hw_phy_cfg(struct r8152 *tp)\n--\ndrivers/net/usb/r8152.c-6626-\t */\ndrivers/net/usb/r8152.c:6627:\tocp_reg_read(tp, 0xc426, \u0026data);\ndrivers/net/usb/r8152.c-6628-\tocp_data = data \u0026 0x3fff;\n--\ndrivers/net/usb/r8152.c=6916=static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex,\n--\ndrivers/net/usb/r8152.c-7035-\t\tif (tp-\u003esupport_2500full || tp-\u003esupport_5000full || tp-\u003esupport_10000full) {\ndrivers/net/usb/r8152.c:7036:\t\t\tret = ocp_reg_read(tp, OCP_10GBT_CTRL, \u0026orig);\ndrivers/net/usb/r8152.c-7037-\t\t\tif (ret \u003c 0)\n--\ndrivers/net/usb/r8152.c=7534=static bool rtl8153_in_nway(struct r8152 *tp)\n--\ndrivers/net/usb/r8152.c-7537-\ndrivers/net/usb/r8152.c:7538:\tif (ocp_reg_read(tp, OCP_PHY_STATE, \u0026phy_state) \u003c 0)\ndrivers/net/usb/r8152.c-7539-\t\treturn false;\n--\ndrivers/net/usb/r8152.c=7549=static void r8156_mdio_force_mode(struct r8152 *tp)\n--\ndrivers/net/usb/r8152.c-7556-\t */\ndrivers/net/usb/r8152.c:7557:\tif (ocp_reg_read(tp, 0xa5b4, \u0026data) \u003c 0)\ndrivers/net/usb/r8152.c-7558-\t\treturn;\n--\ndrivers/net/usb/r8152.c=8064=static void r8156_hw_phy_cfg(struct r8152 *tp)\n--\ndrivers/net/usb/r8152.c-8197-\t\t/* MDI SWAP */\ndrivers/net/usb/r8152.c:8198:\t\tocp_reg_read(tp, 0xd068, \u0026data);\ndrivers/net/usb/r8152.c-8199-\t\tif ((ocp_read_word(tp, MCU_TYPE_USB, USB_UPS_CFG) \u0026 MID_REVERSE) \u0026\u0026\n--\ndrivers/net/usb/r8152.c-8202-\ndrivers/net/usb/r8152.c:8203:\t\t\tocp_reg_read(tp, 0xd068, \u0026data);\ndrivers/net/usb/r8152.c-8204-\t\t\tdata \u0026= ~0x1f;\n--\ndrivers/net/usb/r8152.c-8206-\t\t\tocp_reg_write(tp, 0xd068, data);\ndrivers/net/usb/r8152.c:8207:\t\t\tocp_reg_read(tp, 0xd06a, \u0026swap_a);\ndrivers/net/usb/r8152.c-8208-\t\t\tdata \u0026= ~0x18;\n--\ndrivers/net/usb/r8152.c-8210-\t\t\tocp_reg_write(tp, 0xd068, data);\ndrivers/net/usb/r8152.c:8211:\t\t\tocp_reg_read(tp, 0xd06a, \u0026swap_b);\ndrivers/net/usb/r8152.c-8212-\t\t\tdata \u0026= ~0x18; /* p0 */\n--\ndrivers/net/usb/r8152.c-8222-\t\t\tocp_reg_write(tp, 0xd068, data);\ndrivers/net/usb/r8152.c:8223:\t\t\tocp_reg_read(tp, 0xd06a, \u0026swap_a);\ndrivers/net/usb/r8152.c-8224-\t\t\tdata \u0026= ~0x18;\n--\ndrivers/net/usb/r8152.c-8226-\t\t\tocp_reg_write(tp, 0xd068, data);\ndrivers/net/usb/r8152.c:8227:\t\t\tocp_reg_read(tp, 0xd06a, \u0026swap_b);\ndrivers/net/usb/r8152.c-8228-\t\t\tdata \u0026= ~0x18;\n--\ndrivers/net/usb/r8152.c-8237-\t\t\t\t      (swap_b \u0026 ~0x7ff) | (swap_a \u0026 0x7ff));\ndrivers/net/usb/r8152.c:8238:\t\t\tocp_reg_read(tp, 0xbd5a, \u0026swap_a);\ndrivers/net/usb/r8152.c:8239:\t\t\tocp_reg_read(tp, 0xbd5c, \u0026swap_b);\ndrivers/net/usb/r8152.c-8240-\t\t\tocp_reg_write(tp, 0xbd5a, (swap_a \u0026 ~0x1f1f) |\n--\ndrivers/net/usb/r8152.c-8245-\t\t\t\t      ((swap_a \u003e\u003e 8) \u0026 0x1f));\ndrivers/net/usb/r8152.c:8246:\t\t\tocp_reg_read(tp, 0xbc18, \u0026swap_a);\ndrivers/net/usb/r8152.c:8247:\t\t\tocp_reg_read(tp, 0xbc1a, \u0026swap_b);\ndrivers/net/usb/r8152.c-8248-\t\t\tocp_reg_write(tp, 0xbc18, (swap_a \u0026 ~0x1f1f) |\n--\ndrivers/net/usb/r8152.c=9804=int rtl8152_get_link_ksettings(struct net_device *netdev,\n--\ndrivers/net/usb/r8152.c-9833-\ndrivers/net/usb/r8152.c:9834:\t\tret = ocp_reg_read(tp, OCP_10GBT_CTRL, \u0026ocp_10gbt_ctrl);\ndrivers/net/usb/r8152.c-9835-\t\tif (ret \u003c 0)\n--\ndrivers/net/usb/r8152.c-9837-\ndrivers/net/usb/r8152.c:9838:\t\tret = ocp_reg_read(tp, OCP_10GBT_STAT, \u0026ocp_10gbt_stat);\ndrivers/net/usb/r8152.c-9839-\t\tif (ret \u003c 0)\n--\ndrivers/net/usb/r8152.c=10064=static int r8153_get_eee(struct r8152 *tp, struct ethtool_keee *eee)\n--\ndrivers/net/usb/r8152.c-10070-\ndrivers/net/usb/r8152.c:10071:\tret = ocp_reg_read(tp, OCP_EEE_ABLE, \u0026val);\ndrivers/net/usb/r8152.c-10072-\tif (ret \u003c 0)\n--\ndrivers/net/usb/r8152.c-10076-\ndrivers/net/usb/r8152.c:10077:\tret = ocp_reg_read(tp, OCP_EEE_ADV, \u0026val);\ndrivers/net/usb/r8152.c-10078-\tif (ret \u003c 0)\n--\ndrivers/net/usb/r8152.c-10082-\ndrivers/net/usb/r8152.c:10083:\tret = ocp_reg_read(tp, OCP_EEE_LPABLE, \u0026val);\ndrivers/net/usb/r8152.c-10084-\tif (ret \u003c 0)\n--\ndrivers/net/usb/r8152.c-10089-\tif (tp-\u003esupport_2500full || tp-\u003esupport_5000full) {\ndrivers/net/usb/r8152.c:10090:\t\tret = ocp_reg_read(tp, OCP_EEE_ADV2, \u0026val);\ndrivers/net/usb/r8152.c-10091-\t\tif (ret \u003c 0)\n--\ndrivers/net/usb/r8152.c-10095-\ndrivers/net/usb/r8152.c:10096:\t\tret = ocp_reg_read(tp, OCP_EEE_LPABLE2, \u0026val);\ndrivers/net/usb/r8152.c-10097-\t\tif (ret \u003c 0)\n"
}

19/3 2026/10/08 11:07 llm kmsan-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 56195
							output: 42
							thoughts: 870
						

Thoughts:
**Analyzing the RTL8152 Driver: A Deep Dive into Initialization and Control Flow**

Okay, let's break this down. First, I need to check lines 8195-8255 in `r8156_hw_phy_cfg`. I'm specifically looking at the `ocp_reg_read` function calls within that section, and for RTL8156, it's critical to determine what `tp->rtl_ops.phy_read` resolves to. Aha, it points to `r8152_phy_read`, which unconditionally sets `*data` using `ocp_read_word(...)` and then simply returns 0. That looks straightforward enough.

Now, let's shift gears and examine `__rtl_get_pkg_det`. Here's the code:

```c
static u32 __rtl_get_pkg_det(struct usb_device *udev)
{
	u32 pkg_det = 0;
	__le32 *tmp;
	int ret, i;

	tmp = kmalloc_obj(*tmp);
	if (!tmp)
		return 0;

	for (i = 0, ret = 0; i < 3 && ret != 4; i++)
		ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
				      RTL8152_REQ_GET_REGS, RTL8152_REQT_READ,
				      PLA_PKG_DET, MCU_TYPE_PLA, tmp,
				      sizeof(*tmp), USB_CTRL_GET_TIMEOUT);

	if (ret == sizeof(*tmp)) {
		if (i != 1)
			dev_warn(&udev->dev,
				 "Needed %d retries to read package\n", i);

		pkg_det = __le32_to_cpu(*tmp) & PKG_MASK;
	}

	kfree(tmp);
	return pkg_det;
}
```

Okay, the initialization is sound, starting with `pkg_det` initialized to zero. I see the allocation with `kmalloc_obj(*tmp)`. Excellent. Now, I need to focus. The critical point is that if `ret != sizeof(*tmp)` (e.g., if there's an error from `usb_control_msg` or a short read, it could be negative or less than 4): `pkg_det` remains initialized to zero. However, if the control message succeeds, `tmp` gets populated, then a conversion `__le32_to_cpu(*tmp)` occurs and the data is masked. Finally, `tmp` is freed, and the `pkg_det` value is returned. That flow appears completely safe.

Now, I'm checking `__rtl_get_hw_ver`:

```c
static u8 __rtl_get_hw_ver(struct usb_device *udev)
...
	case 0x2020:
		pkg_det = __rtl_get_pkg_det(udev);
		if (pkg_det == 0x1e || pkg_det == 0x1c) {
			version = RTL_VER_17_QFN68;
		} else if (pkg_det == 0x18 || pkg_det == 0x1a) {
			version = RTL_VER_17_QFN100;
		} else {
			version = RTL_VER_UNKNOWN;
			dev_info(&udev->dev, "Unknown package 0x%04x\n",
				 pkg_det);
		}
		break;
```

I can see that `__rtl_get_pkg_det` is called, and the returned value of `pkg_det` is used to determine the `version`. The flow looks safe here too: `pkg_det` is initialized and will remain as 0 if the control messages fail. This avoids the problem with using an uninitialized value!

Alright, it's time to check which user-facing interfaces were modified by the patch. Oh, it seems the patch modified `rtl8152_get_link_ksettings`. Let me look around line 9828 in `drivers/net/usb/r8152.c`. I have to confirm nothing broke on the surface!



20/3 2026/10/08 11:07 tool read-file
0m Args:
{
  "File": "drivers/net/usb/r8152.c",
  "FirstLine": 9820,
  "LineCount": 70
}

Results:
{
  "Contents": "9820:\t\n9821:\t\tlinkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,\n9822:\t\t\t\t cmd-\u003elink_modes.supported, tp-\u003esupport_2500full);\n9823:\t\n9824:\t\tlinkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,\n9825:\t\t\t\t cmd-\u003elink_modes.supported, tp-\u003esupport_5000full);\n9826:\t\n9827:\t\tlinkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,\n9828:\t\t\t\t cmd-\u003elink_modes.supported, tp-\u003esupport_10000full);\n9829:\t\n9830:\t\tif (tp-\u003esupport_2500full || tp-\u003esupport_5000full || tp-\u003esupport_10000full) {\n9831:\t\t\tu16 ocp_10gbt_ctrl;\n9832:\t\t\tu16 ocp_10gbt_stat;\n9833:\t\n9834:\t\t\tret = ocp_reg_read(tp, OCP_10GBT_CTRL, \u0026ocp_10gbt_ctrl);\n9835:\t\t\tif (ret \u003c 0)\n9836:\t\t\t\tgoto out_unlock;\n9837:\t\n9838:\t\t\tret = ocp_reg_read(tp, OCP_10GBT_STAT, \u0026ocp_10gbt_stat);\n9839:\t\t\tif (ret \u003c 0)\n9840:\t\t\t\tgoto out_unlock;\n9841:\t\n9842:\t\t\tif (tp-\u003esupport_2500full) {\n9843:\t\t\t\tlinkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,\n9844:\t\t\t\t\t\t cmd-\u003elink_modes.advertising,\n9845:\t\t\t\t\t\t ocp_10gbt_ctrl \u0026 MDIO_AN_10GBT_CTRL_ADV2_5G);\n9846:\t\n9847:\t\t\t\tlinkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,\n9848:\t\t\t\t\t\t cmd-\u003elink_modes.lp_advertising,\n9849:\t\t\t\t\t\t ocp_10gbt_stat \u0026 MDIO_AN_10GBT_STAT_LP2_5G);\n9850:\t\n9851:\t\t\t\tif (is_speed_2500(rtl8152_get_speed(tp)))\n9852:\t\t\t\t\tcmd-\u003ebase.speed = SPEED_2500;\n9853:\t\t\t}\n9854:\t\n9855:\t\t\tif (tp-\u003esupport_5000full) {\n9856:\t\t\t\tlinkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,\n9857:\t\t\t\t\t\t cmd-\u003elink_modes.advertising,\n9858:\t\t\t\t\t\t ocp_10gbt_ctrl \u0026 MDIO_AN_10GBT_CTRL_ADV5G);\n9859:\t\n9860:\t\t\t\tlinkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,\n9861:\t\t\t\t\t\t cmd-\u003elink_modes.lp_advertising,\n9862:\t\t\t\t\t\t ocp_10gbt_stat \u0026 MDIO_AN_10GBT_STAT_LP5G);\n9863:\t\n9864:\t\t\t\tif (is_speed_5000(rtl8152_get_speed(tp)))\n9865:\t\t\t\t\tcmd-\u003ebase.speed = SPEED_5000;\n9866:\t\t\t}\n9867:\t\n9868:\t\t\tif (tp-\u003esupport_10000full) {\n9869:\t\t\t\tlinkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,\n9870:\t\t\t\t\t\t cmd-\u003elink_modes.advertising,\n9871:\t\t\t\t\t\t ocp_10gbt_ctrl \u0026 MDIO_AN_10GBT_CTRL_ADV10G);\n9872:\t\n9873:\t\t\t\tlinkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,\n9874:\t\t\t\t\t\t cmd-\u003elink_modes.lp_advertising,\n9875:\t\t\t\t\t\t ocp_10gbt_stat \u0026 MDIO_AN_10GBT_STAT_LP10G);\n9876:\t\n9877:\t\t\t\tif (is_speed_10000(rtl8152_get_speed(tp)))\n9878:\t\t\t\t\tcmd-\u003ebase.speed = SPEED_10000;\n9879:\t\t\t}\n9880:\t\t}\n9881:\t\n9882:\tout_unlock:\n9883:\t\tmutex_unlock(\u0026tp-\u003econtrol);\n9884:\t\n9885:\t\tusb_autopm_put_interface(tp-\u003eintf);\n9886:\t\n9887:\tout:\n9888:\t\treturn ret \u003c 0 ? ret : 0;\n9889:\t}\n"
}

21/3 2026/10/08 11:07 llm kmsan-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 59429
							output: 20
							thoughts: 3313
						

Thoughts:
**Code Review: Ensuring Initialization and Error Handling**

Alright, let's go through this code with a fine-toothed comb, paying particular attention to variable initialization and error handling, especially when dealing with register reads and potentially uninitialized values.  My primary concern is preventing undefined behavior and ensuring the driver handles failures gracefully.

Starting with `rtl8152_get_link_ksettings`, the changes are a definite improvement.  Initializing `ocp_10gbt_ctrl` and `ocp_10gbt_stat` *before* the `ocp_reg_read` calls ensures that we avoid using uninitialized memory if those reads fail. The `goto out_unlock` on error also correctly propagates the error up the call chain, a standard and correct pattern in kernel code.  Excellent, the return codes are now properly checked.

Moving on to `r8153_get_eee`, this is a good example of robust error handling. Each `ocp_reg_read` is checked, and a `goto out` is used if it fails.  This ensures that we don't proceed with using potentially stale or invalid values from previous registers.  The same pattern applies whether we are reading the EEE capability registers, or the advertised and local partner advertisements. This also covers the more complex cases that include the optional 2.5G/5G capabilities. Well structured.

In `rtl8152_get_pauseparam`, the original code had a potential race condition and use of uninitialized variables.  Now, the `r8152_mdio_read` calls are properly checked, and if any of them return an error, the `pause` structure is safely zeroed out. This prevents sending garbage to userspace, and eliminates any undefined behavior in the case of a PHY read error. A clear improvement.

The `rtl8152_ioctl` case also has a fix that ensures that errors from `r8152_mdio_read` are propagated correctly back to the user space. The previous code could have potentially cast a negative integer error into a `u16` leading to unexpected behavior in user space. Now, the `res = val` is a clear and correct error pass-through. No uninitialized usage either, which is the main goal.

`rtl8152_set_pauseparam` shows careful handling of the PHY read with the added check to prevent setting autonegotiation if autoneg is disabled. Good defensive programming.

In `rtl_fc_pause_pkt_en`, all variables, including `num_pause_pkts` and `ratio`, are properly initialized within the `switch` statement, depending on the link speed. The `if` conditionals cover the cases that are set and cover any unset cases, including a reasonable error message and disarming of the limits to maintain a sane system state.

In `r8157_ups_en`, the `read_poll_timeout` macro is used, which does assign the variable `ocp_data`. It is clear that the assignment happens *before* the conditional check, so `ocp_data` is initialized before being used in the `cond` part. This is an important detail of this commonly-used function.

The uses of `read_poll_timeout` in `wait_tgphy_cmd_ready` and `wait_autoload_done` follow the same pattern, and the variables are initialized before being checked. The poll timeout is appropriate in these cases, because it indicates a possible hardware issue if it's not ready.

I went through other functions, like `r8159_hw_phy_cfg` and `r8157_hw_phy_cfg`, and confirmed there are no initialization gaps or cases where variables might be read without a prior write.

I also checked for any new kernel memory allocations or usage of buffers. The function `__rtl_get_pkg_det` appears to include a `kmalloc_obj(*tmp)`. This is correctly handled, as `kmalloc_obj(x)` is a macro or inline for `kmalloc(sizeof(x), GFP_KERNEL)`.

Overall, the code review reveals careful attention to variable initialization, error checking, and defensive programming practices. The changes are all positive, preventing undefined behavior and ensuring robust error handling. All good, all clear.



22/3 2026/10/08 11:08 tool grepper
0m Args:
{
  "Expression": "#define kmalloc_obj"
}

Results:
{
  "Output": "include/linux/slab.h=1073=void *kmalloc_nolock(size_t size, gfp_t gfp_flags, int node);\n--\ninclude/linux/slab.h-1123- */\ninclude/linux/slab.h:1124:#define kmalloc_obj(VAR_OR_TYPE, ...) \\\ninclude/linux/slab.h-1125-\t__alloc_objs(kmalloc, default_gfp(__VA_ARGS__), typeof(VAR_OR_TYPE), 1)\n--\ninclude/linux/slab.h-1135- */\ninclude/linux/slab.h:1136:#define kmalloc_objs(VAR_OR_TYPE, COUNT, ...) \\\ninclude/linux/slab.h-1137-\t__alloc_objs(kmalloc, default_gfp(__VA_ARGS__), typeof(VAR_OR_TYPE), COUNT)\n--\nlib/decompress_unxz.c-163-#undef vfree\nlib/decompress_unxz.c:164:#define kmalloc_obj(type) malloc(sizeof(type))\nlib/decompress_unxz.c-165-#define kfree(ptr) free(ptr)\n--\ntools/virtio/linux/kernel.h=63=static inline void *kmalloc_array(unsigned n, size_t s, gfp_t gfp)\n--\ntools/virtio/linux/kernel.h-67-\ntools/virtio/linux/kernel.h:68:#define kmalloc_obj(VAR_OR_TYPE, ...) \\\ntools/virtio/linux/kernel.h-69-\t((typeof(VAR_OR_TYPE) *)kmalloc(sizeof(typeof(VAR_OR_TYPE)), 0))\ntools/virtio/linux/kernel.h-70-\ntools/virtio/linux/kernel.h:71:#define kmalloc_objs(VAR_OR_TYPE, COUNT, ...) \\\ntools/virtio/linux/kernel.h-72-\t((typeof(VAR_OR_TYPE) *)kmalloc(sizeof(typeof(VAR_OR_TYPE)) * (COUNT), 0))\n"
}

23/3 2026/10/08 11:08 llm kmsan-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 64216
							output: 43
							thoughts: 358
						

Thoughts:
**Analyzing the USB Control Message for Package Detection**

Okay, so I'm looking at this `usb_control_msg` call within the `RTL8152` driver. I see that `kmalloc_obj(*tmp)` is used to allocate memory of size `sizeof(*tmp)`. Then, `tmp` is being used as a buffer in `usb_control_msg` with `RTL8152_REQT_READ`. The code then enters a loop, retrying up to three times.

The crucial part is the conditional `if (ret == sizeof(*tmp))`.  If the return value `ret` from `usb_control_msg` matches the size of `*tmp` (which is presumably 4 bytes), it means the device successfully filled the buffer. The contents of `tmp` are then safely read. In the case of success, a warning is issued if more than one retry was required.

Critically, if the `ret` isn't equal to the expected size, the contents of `tmp` are *never* read. The code just frees `tmp` with `kfree(tmp)` without dereferencing it if the read fails. Therefore, there's no potential for reading uninitialized memory. The only time the driver processes the buffer `tmp` is after a success with `ret == sizeof(*tmp)`.

Let me quickly cross-reference this with the implementation of `__rtl_get_hw_ver` to ensure this same pattern is followed. Gotta be thorough.



24/3 2026/10/08 11:08 tool read-file
0m Args:
{
  "File": "drivers/net/usb/r8152.c",
  "FirstLine": 10030,
  "LineCount": 40
}

Results:
{
  "Contents": "10030:\t\tmii_eee_cap1_mod_linkmode_t(eee-\u003eadvertised, val);\n10031:\t\n10032:\t\tval = r8152_mmd_read(tp, MDIO_MMD_AN, MDIO_AN_EEE_LPABLE);\n10033:\t\tmii_eee_cap1_mod_linkmode_t(eee-\u003elp_advertised, val);\n10034:\t\n10035:\t\teee-\u003eeee_enabled = tp-\u003eeee_en;\n10036:\t\n10037:\t\tif (speed \u0026 _1000bps)\n10038:\t\t\tlinkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, common);\n10039:\t\tif (speed \u0026 _100bps)\n10040:\t\t\tlinkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, common);\n10041:\t\n10042:\t\tlinkmode_and(common, common, eee-\u003eadvertised);\n10043:\t\tlinkmode_and(common, common, eee-\u003elp_advertised);\n10044:\t\teee-\u003eeee_active = !linkmode_empty(common);\n10045:\t\n10046:\t\treturn 0;\n10047:\t}\n10048:\t\n10049:\tstatic int r8152_set_eee(struct r8152 *tp, struct ethtool_keee *eee)\n10050:\t{\n10051:\t\tu16 val = linkmode_to_mii_eee_cap1_t(eee-\u003eadvertised);\n10052:\t\n10053:\t\ttp-\u003eeee_en = eee-\u003eeee_enabled;\n10054:\t\ttp-\u003eeee_adv = val;\n10055:\t\tif (tp-\u003esupport_2500full || tp-\u003esupport_5000full) {\n10056:\t\t\tval = linkmode_to_mii_eee_cap2_t(eee-\u003eadvertised);\n10057:\t\t\ttp-\u003eeee_adv2 = val;\n10058:\t\t}\n10059:\t\trtl_eee_enable(tp, tp-\u003eeee_en);\n10060:\t\n10061:\t\treturn 0;\n10062:\t}\n10063:\t\n10064:\tstatic int r8153_get_eee(struct r8152 *tp, struct ethtool_keee *eee)\n10065:\t{\n10066:\t\t__ETHTOOL_DECLARE_LINK_MODE_MASK(common) = {};\n10067:\t\tu16 speed = rtl8152_get_speed(tp);\n10068:\t\tu16 val;\n10069:\t\tint ret;\n"
}

25/3 2026/10/08 11:08 llm kmsan-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 65711
							output: 45
							thoughts: 14
						

Thoughts:
Here's my take on those thoughts, tailored for an expert audience:

**Diving into `__rtl_get_hw_ver`**

Okay, so we're looking at `__rtl_get_hw_ver`. My initial thought is to immediately consider the context of its use. What hardware platform are we dealing with? Is this related to a specific product line, a board revision, a silicon revision, or something else entirely? The naming convention suggests it's likely a Realtek function, so that narrows the field somewhat, which is useful.

The next thing I'm going to want to examine is where this function is called from, and what dependencies it has. What other modules or drivers rely on the hardware version information? Is it used for feature enablement, board bring-up, silicon identification, or something more obscure? Tracing the call graph will quickly show what systems depend on this information.

I'd want to also consider the method in which `__rtl_get_hw_ver` obtains the hardware version. Is it reading a register, using a JTAG interface, accessing a dedicated EEPROM, or perhaps parsing some system table? Are there any potential timing issues or lock contention I should consider? Are there any debug flags that could be relevant to understanding its behavior? Is this function thread-safe or does it need to be guarded to prevent conflicts when read by multiple processes or threads? Is the return value an integer, a bit-field, or a structured data type? The data type alone can often signal a possible level of complexity that needs to be considered. Are the different versions backward compatible? Can firmware be updated based on the hardware version?

If there is documentation, I'll be sure to read it. I'd expect to find some insight there, but I won't rely on it entirely, so I'll decompile the function, and analyze the code, carefully. I'll be looking for potential edge cases, error handling, and any subtle assumptions the developers made that might not be obvious from the external API. Also, what is the impact of a version change on the whole system?

Essentially, I'm thinking about the function's contract, its implementation, and its impact on the larger system. Time to dig in.



26/3 2026/10/08 11:08 tool grepper
0m Args:
{
  "Expression": "static u8 __rtl_get_hw_ver",
  "PathPrefixes": [
    "drivers/net/usb/r8152.c"
  ]
}

Results:
{
  "Output": "drivers/net/usb/r8152.c=10940=static u32 __rtl_get_pkg_det(struct usb_device *udev)\n--\ndrivers/net/usb/r8152.c-10967-\ndrivers/net/usb/r8152.c:10968:static u8 __rtl_get_hw_ver(struct usb_device *udev)\ndrivers/net/usb/r8152.c-10969-{\n"
}

27/3 2026/10/08 11:08 llm kmsan-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 66380
							output: 43
							thoughts: 28
						

Thoughts:
Okay, here's my interpretation of what's going on, formatted as you requested:

**Digging into the r8152.c Driver**

Alright, let's dive into the `drivers/net/usb/r8152.c` file. Specifically, I want to zero in on the area around line 10968. That's usually a good indicator of something interesting – either a critical function, a potentially problematic section, or perhaps a complex interaction within the driver's flow. My initial thought is to figure out what functionality is being handled there. I'll need to understand the surrounding code to grasp the broader context of what this section is doing. I'll be looking for clues about the hardware interaction, any error handling, or the data flow through this part of the USB network interface driver. Ultimately, I'm trying to quickly form a mental map of this section to identify anything that might be relevant to a specific issue I'm investigating, or just to deepen my general understanding of the driver's design.



28/3 2026/10/08 11:08 tool read-file
0m Args:
{
  "File": "drivers/net/usb/r8152.c",
  "FirstLine": 10968,
  "LineCount": 80
}

Results:
{
  "Contents": "10968:\tstatic u8 __rtl_get_hw_ver(struct usb_device *udev)\n10969:\t{\n10970:\t\tu32 ocp_data = 0;\n10971:\t\tu32 pkg_det = 0;\n10972:\t\t__le32 *tmp;\n10973:\t\tu8 version;\n10974:\t\tint ret;\n10975:\t\tint i;\n10976:\t\n10977:\t\ttmp = kmalloc_obj(*tmp);\n10978:\t\tif (!tmp)\n10979:\t\t\treturn 0;\n10980:\t\n10981:\t\t/* Retry up to 3 times in case there is a transitory error. We do this\n10982:\t\t * since retrying a read of the version is always safe and this\n10983:\t\t * function doesn't take advantage of r8152_control_msg().\n10984:\t\t */\n10985:\t\tfor (i = 0; i \u003c 3; i++) {\n10986:\t\t\tret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),\n10987:\t\t\t\t\t      RTL8152_REQ_GET_REGS, RTL8152_REQT_READ,\n10988:\t\t\t\t\t      PLA_TCR0, MCU_TYPE_PLA, tmp, sizeof(*tmp),\n10989:\t\t\t\t\t      USB_CTRL_GET_TIMEOUT);\n10990:\t\t\tif (ret \u003e 0) {\n10991:\t\t\t\tocp_data = (__le32_to_cpu(*tmp) \u003e\u003e 16) \u0026 VERSION_MASK;\n10992:\t\t\t\tbreak;\n10993:\t\t\t}\n10994:\t\t}\n10995:\t\n10996:\t\tif (i != 0 \u0026\u0026 ret \u003e 0)\n10997:\t\t\tdev_warn(\u0026udev-\u003edev, \"Needed %d retries to read version\\n\", i);\n10998:\t\n10999:\t\tkfree(tmp);\n11000:\t\n11001:\t\tswitch (ocp_data) {\n11002:\t\tcase 0x4c00:\n11003:\t\t\tversion = RTL_VER_01;\n11004:\t\t\tbreak;\n11005:\t\tcase 0x4c10:\n11006:\t\t\tversion = RTL_VER_02;\n11007:\t\t\tbreak;\n11008:\t\tcase 0x5c00:\n11009:\t\t\tversion = RTL_VER_03;\n11010:\t\t\tbreak;\n11011:\t\tcase 0x5c10:\n11012:\t\t\tversion = RTL_VER_04;\n11013:\t\t\tbreak;\n11014:\t\tcase 0x5c20:\n11015:\t\t\tversion = RTL_VER_05;\n11016:\t\t\tbreak;\n11017:\t\tcase 0x5c30:\n11018:\t\t\tversion = RTL_VER_06;\n11019:\t\t\tbreak;\n11020:\t\tcase 0x4800:\n11021:\t\t\tversion = RTL_VER_07;\n11022:\t\t\tbreak;\n11023:\t\tcase 0x6000:\n11024:\t\t\tversion = RTL_VER_08;\n11025:\t\t\tbreak;\n11026:\t\tcase 0x6010:\n11027:\t\t\tversion = RTL_VER_09;\n11028:\t\t\tbreak;\n11029:\t\tcase 0x7010:\n11030:\t\t\tversion = RTL_TEST_01;\n11031:\t\t\tbreak;\n11032:\t\tcase 0x7020:\n11033:\t\t\tversion = RTL_VER_10;\n11034:\t\t\tbreak;\n11035:\t\tcase 0x7030:\n11036:\t\t\tversion = RTL_VER_11;\n11037:\t\t\tbreak;\n11038:\t\tcase 0x7400:\n11039:\t\t\tversion = RTL_VER_12;\n11040:\t\t\tbreak;\n11041:\t\tcase 0x7410:\n11042:\t\t\tversion = RTL_VER_13;\n11043:\t\t\tbreak;\n11044:\t\tcase 0x6400:\n11045:\t\t\tversion = RTL_VER_14;\n11046:\t\t\tbreak;\n11047:\t\tcase 0x7420:\n"
}

29/3 2026/10/08 11:08 llm kmsan-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 67938
							output: 43
							thoughts: 18
						

Thoughts:
Okay, here's the summary, rendered in the first person, assuming the user is an expert and focusing on the thought process:

**Focusing In: Examining a Specific Segment**

Alright, I'm going to zero in on a specific section of the data to get a clearer picture. Let's start by isolating lines 11047 through 11065. I need to understand what's happening within that range, and how that small segment fits into the overall problem I'm trying to solve. I'm looking for anomalies, patterns, or critical data points that will help me interpret the wider dataset. This targeted approach is often the most effective way to identify the root cause of a specific problem, and provides a point of reference for testing hypotheses or predicting outcomes.



30/3 2026/10/08 11:08 tool read-file
0m Args:
{
  "File": "drivers/net/usb/r8152.c",
  "FirstLine": 11047,
  "LineCount": 25
}

Results:
{
  "Contents": "11047:\t\tcase 0x7420:\n11048:\t\t\tversion = RTL_VER_15;\n11049:\t\t\tbreak;\n11050:\t\tcase 0x1030:\n11051:\t\t\tversion = RTL_VER_16;\n11052:\t\t\tbreak;\n11053:\t\tcase 0x2020:\n11054:\t\t\tpkg_det = __rtl_get_pkg_det(udev);\n11055:\t\t\tif (pkg_det == 0x1e || pkg_det == 0x1c) {\n11056:\t\t\t\tversion = RTL_VER_17_QFN68;\n11057:\t\t\t} else if (pkg_det == 0x18 || pkg_det == 0x1a) {\n11058:\t\t\t\tversion = RTL_VER_17_QFN100;\n11059:\t\t\t} else {\n11060:\t\t\t\tversion = RTL_VER_UNKNOWN;\n11061:\t\t\t\tdev_info(\u0026udev-\u003edev, \"Unknown package 0x%04x\\n\",\n11062:\t\t\t\t\t pkg_det);\n11063:\t\t\t}\n11064:\t\t\tbreak;\n11065:\t\tdefault:\n11066:\t\t\tversion = RTL_VER_UNKNOWN;\n11067:\t\t\tdev_info(\u0026udev-\u003edev, \"Unknown version 0x%04x\\n\", ocp_data);\n11068:\t\t\tbreak;\n11069:\t\t}\n11070:\t\n11071:\t\treturn version;\n"
}

31/3 2026/10/08 11:08 llm kmsan-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 68600
							output: 337
							thoughts: 2057
						

Thoughts:
**KMSAN Check: No Need!**

Okay, let's break this down. My goal is to determine if this patch necessitates `NeedsKMSAN=true`. I need to rigorously review it against the four criteria:

1.  **User-space communication:** The patch touches several functions communicating with user space, like `rtl8152_get_link_ksettings`, `r8153_get_eee`, `rtl8152_get_pauseparam`, and `rtl8152_ioctl`. However, looking at the code, it looks like it improves error handling, returning early if there is an error. There are no changes which introduces potential leaks. These functions now *fix* situations where error values might not have been properly checked before and could have led to incorrect behaviour. This involves returning and erroring out before uninitialized data is sent.

2.  **Conditional logic and uninitialized variables:** I carefully traced every instance of `ocp_reg_read`, `sram_read`, `sram2_read`, `sram_write`, and their counterparts, which are the main functions added or modified by the patch. All of the variables passed by pointers to these functions are initialized, checked, or otherwise handled correctly. I went line-by-line through the added/modified functions, like `r8152_mdio_read`, `sram_write`, `sram_read`, etc., confirming that the return values of those functions are all checked before any variable is used. All branches based on these registers are covered, and all variables are read either before conditional branching or are initialized before.

3.  **Complex data structures:** I'm not seeing any new allocation or initialization of complex data structures that could lead to uninitialized fields being read.

4.  **Bounds checks:** There is no indication of any buffer-related operations or length manipulations that might expose uninitialized bytes.

Given that thorough review, there is no risk of uninitialized memory usage or information leaks that this patch introduces. All of this patch does is refactor the PHY/MDIO/SRAM register read/write operations to improve error handling and support a few new hardware revisions. Any issues that could possibly come up would have to do with logic or hardware interaction issues, such as hardware timeouts or incorrect register values, and would be covered by standard testing or KASAN if memory safety was relevant.

Therefore, `NeedsKMSAN=false`. Let's confirm our conclusion with `set-results`.



32/3 2026/10/08 11:09 tool set-results
0m Args:
{
  "KMSANReasoning": "The patch refactors the r8152 USB Ethernet driver to support new hardware revisions (RTL8157 and RTL8159 variants) and updates register access helpers (ocp_reg_read, sram_read, etc.) to pass output data by pointer and return integer status codes for proper error handling.\n\nA careful examination of all modified and newly introduced code paths shows:\n1. No uninitialized kernel memory or structure padding is leaked to user space: ioctl and ethtool handlers (rtl8152_get_link_ksettings, r8153_get_eee, rtl8152_get_pauseparam, rtl8152_ioctl) now check return codes from register reads and abort or return appropriate errors instead of operating on or leaking uninitialized data.\n2. All out-parameters passed to register read functions are either guarded by return code checks or initialized prior to use.\n3. Heap allocations (such as in __rtl_get_pkg_det) only read the allocated buffer if usb_control_msg() returns the full expected size, and properly clean up afterwards.\n4. No network skb parsing or length manipulation is introduced that could lead to reading uninitialized bytes.\n\nConsequently, there are no uninitialized memory access or info-leak risks that would necessitate a dedicated KMSAN fuzzing session. Any potential issues (hardware timeouts, locking, logic bugs) are adequately addressed by standard testing and KASAN.",
  "NeedsKMSAN": false
}

Results:
{
  "KMSANReasoning": "The patch refactors the r8152 USB Ethernet driver to support new hardware revisions (RTL8157 and RTL8159 variants) and updates register access helpers (ocp_reg_read, sram_read, etc.) to pass output data by pointer and return integer status codes for proper error handling.\n\nA careful examination of all modified and newly introduced code paths shows:\n1. No uninitialized kernel memory or structure padding is leaked to user space: ioctl and ethtool handlers (rtl8152_get_link_ksettings, r8153_get_eee, rtl8152_get_pauseparam, rtl8152_ioctl) now check return codes from register reads and abort or return appropriate errors instead of operating on or leaking uninitialized data.\n2. All out-parameters passed to register read functions are either guarded by return code checks or initialized prior to use.\n3. Heap allocations (such as in __rtl_get_pkg_det) only read the allocated buffer if usb_control_msg() returns the full expected size, and properly clean up afterwards.\n4. No network skb parsing or length manipulation is introduced that could lead to reading uninitialized bytes.\n\nConsequently, there are no uninitialized memory access or info-leak risks that would necessitate a dedicated KMSAN fuzzing session. Any potential issues (hardware timeouts, locking, logic bugs) are adequately addressed by standard testing and KASAN.",
  "NeedsKMSAN": false
}

LLM Calls Summary:
Total Calls Total Tokens Avg Tokens Total Duration (Seconds) Avg Duration (Seconds)
Tool Calls Summary:
Total Calls Total Duration (Seconds) Avg Duration (Seconds)