public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next v2 0/2] r8152: Add support for the RTL8157 5Gbit USB Ethernet chip
@ 2026-03-17 18:07 Birger Koblitz
  2026-03-17 18:07 ` [PATCH net-next v2 1/2] r8152: Add support for 5Gbit Link Speeds and EEE Birger Koblitz
                   ` (2 more replies)
  0 siblings, 3 replies; 17+ messages in thread
From: Birger Koblitz @ 2026-03-17 18:07 UTC (permalink / raw)
  To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni
  Cc: linux-usb, netdev, linux-kernel, Birger Koblitz

Add support for the RTL8157, which is a 5GBit USB-Ethernet adapter
chip in the RTL815x family of chips.

The RTL8157 uses a different frame descriptor format, and different
SRAM/ADV access methods, plus offers 5GBit/s Ethernet, so support for these
features is added in addition to chip initialization and configuration.

The module was tested with an OEM RTL8157 USB adapter:
[25758.328238] usb 4-1: new SuperSpeed Plus Gen 2x1 USB device number 2 using xhci_hcd
[25758.345565] usb 4-1: New USB device found, idVendor=0bda, idProduct=8157, bcdDevice=30.00
[25758.345585] usb 4-1: New USB device strings: Mfr=1, Product=2, SerialNumber=7
[25758.345593] usb 4-1: Product: USB 10/100/1G/2.5G/5G LAN
[25758.345599] usb 4-1: Manufacturer: Realtek
[25758.345605] usb 4-1: SerialNumber: 000300E04C68xxxx
[25758.534241] r8152-cfgselector 4-1: reset SuperSpeed Plus Gen 2x1 USB device number 2 using xhci_hcd
[25758.603511] r8152 4-1:1.0: skip request firmware
[25758.653351] r8152 4-1:1.0 eth0: v1.12.13
[25758.689271] r8152 4-1:1.0 enx00e04c68xxxx: renamed from eth0
[25763.271682] r8152 4-1:1.0 enx00e04c68xxxx: carrier on

The RTL8157 adapter was tested against an AQC107 PCIe-card supporting
10GBit/s and an RTL8126 5Gbit PCIe-card supporting 5GBit/s for
performance, link speed and EEE negotiation. Using USB3.2 Gen 1 with
the RTL8157 USB adapter and running iperf3 against the AQC107 PCIe
card resulted in 3.47 Gbits/sec, whereas using USB3.2 Gen2 resulted
in 4.70 Gbits/sec, speeds against the RTL8126-card were the same.

As the code integrates the RTL8157-specific code with existing RTL8156 code
in order to improve code maintainability (instead of adding RTL8157-specific
functions duplicaing most of the RTL8156 code), regression tests were done
with an Edimax EU-4307 V1.0 USB-Ethernet adapter with RTL8156.

The code is based on the out-of-tree r8152 driver published by Realtek under
the GPL.

This patch is on top of linux-next as the code re-uses the 2.5 Gbit EEE
recently added in r8152.c.

Signed-off-by: Birger Koblitz <mail@birger-koblitz.de>
---
Changes in v2:
- Fixed missing initialization of ret value in wait_cmd_ready()
- Combine all parts with RTL8157-specific code to avoid undefined functions
- Link to v1: https://lore.kernel.org/r/20260314-rtl8157_next-v1-0-9ba77b428afd@birger-koblitz.de

---
Birger Koblitz (2):
      r8152: Add support for 5Gbit Link Speeds and EEE
      r8152: Add support for the RTL8157 hardware

 drivers/net/usb/r8152.c | 1092 ++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 845 insertions(+), 247 deletions(-)
---
base-commit: 5c9e55fecf9365890c64f14761a80f9413a3b1d1
change-id: 20260314-rtl8157_next-ae18683eb4fa

Best regards,
-- 
Birger Koblitz <mail@birger-koblitz.de>


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH net-next v2 1/2] r8152: Add support for 5Gbit Link Speeds and EEE
  2026-03-17 18:07 [PATCH net-next v2 0/2] r8152: Add support for the RTL8157 5Gbit USB Ethernet chip Birger Koblitz
@ 2026-03-17 18:07 ` Birger Koblitz
  2026-03-19 16:29   ` Andrew Lunn
                     ` (2 more replies)
  2026-03-17 18:07 ` [PATCH net-next v2 2/2] r8152: Add support for the RTL8157 hardware Birger Koblitz
  2026-03-19 15:53 ` [PATCH net-next v2 0/2] r8152: Add support for the RTL8157 5Gbit USB Ethernet chip Andrew Lunn
  2 siblings, 3 replies; 17+ messages in thread
From: Birger Koblitz @ 2026-03-17 18:07 UTC (permalink / raw)
  To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni
  Cc: linux-usb, netdev, linux-kernel, Birger Koblitz

The RTL8157 supports 5GBit Link speeds. Add support for this speed
in the setup and setting/getting through ethool. Also add 5GBit EEE.
Add functionality for setup and ethtool get/set methods.

Signed-off-by: Birger Koblitz <mail@birger-koblitz.de>
---
 drivers/net/usb/r8152.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 53 insertions(+), 3 deletions(-)

diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index 3b6d4252d34c63ead8f11a120e212325a5f7d505..bab8e10e5f99afcb332e333c2739ed7509b03419 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -604,6 +604,7 @@ enum spd_duplex {
 	FORCE_100M_FULL,
 	FORCE_1000M_FULL,
 	NWAY_2500M_FULL,
+	NWAY_5000M_FULL,
 };
 
 /* OCP_ALDPS_CONFIG */
@@ -725,6 +726,7 @@ enum spd_duplex {
 #define BP4_SUPER_ONLY		0x1578	/* RTL_VER_04 only */
 
 enum rtl_register_content {
+	_5000bps	= BIT(12),
 	_2500bps	= BIT(10),
 	_1250bps	= BIT(9),
 	_500bps		= BIT(8),
@@ -738,6 +740,7 @@ enum rtl_register_content {
 };
 
 #define is_speed_2500(_speed)	(((_speed) & (_2500bps | LINK_STATUS)) == (_2500bps | LINK_STATUS))
+#define is_speed_5000(_speed)	(((_speed) & (_5000bps | LINK_STATUS)) == (_5000bps | LINK_STATUS))
 #define is_flow_control(_speed)	(((_speed) & (_tx_flow | _rx_flow)) == (_tx_flow | _rx_flow))
 
 #define RTL8152_MAX_TX		4
@@ -944,6 +947,7 @@ struct r8152 {
 	unsigned int pipe_in, pipe_out, pipe_intr, pipe_ctrl_in, pipe_ctrl_out;
 
 	u32 support_2500full:1;
+	u32 support_5000full:1;
 	u32 lenovo_macpassthru:1;
 	u32 dell_tb_rx_agg_bug:1;
 	u16 ocp_base;
@@ -1194,6 +1198,7 @@ enum tx_csum_stat {
 #define RTL_ADVERTISED_1000_HALF		BIT(4)
 #define RTL_ADVERTISED_1000_FULL		BIT(5)
 #define RTL_ADVERTISED_2500_FULL		BIT(6)
+#define RTL_ADVERTISED_5000_FULL		BIT(7)
 
 /* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
  * The RTL chips use a 64 element hash table based on the Ethernet CRC.
@@ -5400,6 +5405,11 @@ static void r8156_eee_en(struct r8152 *tp, bool enable)
 	else
 		config &= ~MDIO_EEE_2_5GT;
 
+	if (enable && (tp->eee_adv2 & MDIO_EEE_5GT))
+		config |= MDIO_EEE_5GT;
+	else
+		config &= ~MDIO_EEE_5GT;
+
 	ocp_reg_write(tp, OCP_EEE_ADV2, config);
 }
 
@@ -6298,6 +6308,9 @@ static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex,
 
 			if (tp->support_2500full)
 				support |= RTL_ADVERTISED_2500_FULL;
+
+			if (tp->support_5000full)
+				support |= RTL_ADVERTISED_5000_FULL;
 		}
 
 		if (!(advertising & support))
@@ -6343,15 +6356,20 @@ static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex,
 				r8152_mdio_write(tp, MII_CTRL1000, new1);
 		}
 
-		if (tp->support_2500full) {
+		if (tp->support_2500full || tp->support_5000full) {
 			orig = ocp_reg_read(tp, OCP_10GBT_CTRL);
-			new1 = orig & ~MDIO_AN_10GBT_CTRL_ADV2_5G;
+			new1 = orig & ~(MDIO_AN_10GBT_CTRL_ADV2_5G | MDIO_AN_10GBT_CTRL_ADV5G);
 
 			if (advertising & RTL_ADVERTISED_2500_FULL) {
 				new1 |= MDIO_AN_10GBT_CTRL_ADV2_5G;
 				tp->ups_info.speed_duplex = NWAY_2500M_FULL;
 			}
 
+			if (advertising & RTL_ADVERTISED_5000_FULL) {
+				new1 |= MDIO_AN_10GBT_CTRL_ADV5G;
+				tp->ups_info.speed_duplex = NWAY_5000M_FULL;
+			}
+
 			if (orig != new1)
 				ocp_reg_write(tp, OCP_10GBT_CTRL, new1);
 		}
@@ -8780,6 +8798,9 @@ int rtl8152_get_link_ksettings(struct net_device *netdev,
 	linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
 			 cmd->link_modes.supported, tp->support_2500full);
 
+	linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
+			 cmd->link_modes.supported, tp->support_5000full);
+
 	if (tp->support_2500full) {
 		linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
 				 cmd->link_modes.advertising,
@@ -8793,6 +8814,19 @@ int rtl8152_get_link_ksettings(struct net_device *netdev,
 			cmd->base.speed = SPEED_2500;
 	}
 
+	if (tp->support_5000full) {
+		linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
+				 cmd->link_modes.advertising,
+				 ocp_reg_read(tp, OCP_10GBT_CTRL) & MDIO_AN_10GBT_CTRL_ADV5G);
+
+		linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
+				 cmd->link_modes.lp_advertising,
+				 ocp_reg_read(tp, OCP_10GBT_STAT) & MDIO_AN_10GBT_STAT_LP5G);
+
+		if (is_speed_5000(rtl8152_get_speed(tp)))
+			cmd->base.speed = SPEED_5000;
+	}
+
 	mutex_unlock(&tp->control);
 
 	usb_autopm_put_interface(tp->intf);
@@ -8840,6 +8874,10 @@ static int rtl8152_set_link_ksettings(struct net_device *dev,
 		     cmd->link_modes.advertising))
 		advertising |= RTL_ADVERTISED_2500_FULL;
 
+	if (test_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
+		     cmd->link_modes.advertising))
+		advertising |= RTL_ADVERTISED_5000_FULL;
+
 	mutex_lock(&tp->control);
 
 	ret = rtl8152_set_speed(tp, cmd->base.autoneg, cmd->base.speed,
@@ -8957,7 +8995,7 @@ static int r8152_set_eee(struct r8152 *tp, struct ethtool_keee *eee)
 
 	tp->eee_en = eee->eee_enabled;
 	tp->eee_adv = val;
-	if (tp->support_2500full) {
+	if (tp->support_2500full || tp->support_5000full) {
 		val = linkmode_to_mii_eee_cap2_t(eee->advertised);
 		tp->eee_adv2 = val;
 	}
@@ -8994,6 +9032,13 @@ static int r8153_get_eee(struct r8152 *tp, struct ethtool_keee *eee)
 			linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, common);
 	}
 
+	if (tp->support_5000full) {
+		linkmode_set_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, eee->supported);
+
+		if (speed & _5000bps)
+			linkmode_set_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, common);
+	}
+
 	eee->eee_enabled = tp->eee_en;
 
 	if (speed & _1000bps)
@@ -9934,6 +9979,11 @@ static int rtl8152_probe_once(struct usb_interface *intf,
 		} else {
 			tp->speed = SPEED_1000;
 		}
+		if (tp->support_5000full &&
+		    tp->udev->speed >= USB_SPEED_SUPER) {
+			tp->speed = SPEED_5000;
+			tp->advertising |= RTL_ADVERTISED_5000_FULL;
+		}
 		tp->advertising |= RTL_ADVERTISED_1000_FULL;
 	}
 	tp->duplex = DUPLEX_FULL;

-- 
2.47.3


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH net-next v2 2/2] r8152: Add support for the RTL8157 hardware
  2026-03-17 18:07 [PATCH net-next v2 0/2] r8152: Add support for the RTL8157 5Gbit USB Ethernet chip Birger Koblitz
  2026-03-17 18:07 ` [PATCH net-next v2 1/2] r8152: Add support for 5Gbit Link Speeds and EEE Birger Koblitz
@ 2026-03-17 18:07 ` Birger Koblitz
  2026-03-19 16:42   ` Andrew Lunn
  2026-03-19 16:51   ` Simon Horman
  2026-03-19 15:53 ` [PATCH net-next v2 0/2] r8152: Add support for the RTL8157 5Gbit USB Ethernet chip Andrew Lunn
  2 siblings, 2 replies; 17+ messages in thread
From: Birger Koblitz @ 2026-03-17 18:07 UTC (permalink / raw)
  To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni
  Cc: linux-usb, netdev, linux-kernel, Birger Koblitz

The RTL8157 uses a different packet descriptor format compared to the
previous generation of chips. Add support for this format by adding a
descriptor format structure into the r8152 structure and corresponding
desc_ops functions which abstract the vlan-tag, tx/rx len and
tx/rx checksum algorithms.

Also, add support for the SRAM access interface of the RTL8157 and
the ADV indirect access interface and PHY setup.

For initialization of the RTL8157, combine the existing RTL8156B and
RTL8156 init functions and add RTL8157-specific functinality in order
to improve code readability and maintainability.
r8156_init() is now called with RTL_VER_10 and RTL_VER_11 for the RTL8156,
with RTL_VER_12, RTL_VER_13 and RTL_VER_15 for the RTL8156B and with
RTL_VER_16 for the RTL8157 and checks the version for chip-specific code.
Also add USB power control functions for the RTL8157.

Add support for the USB device ID of Realtek RTL8157-based adapters. Detect
the RTL8157 as RTL_VER_16 and set it up.

Signed-off-by: Birger Koblitz <mail@birger-koblitz.de>
---
 drivers/net/usb/r8152.c | 1036 ++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 792 insertions(+), 244 deletions(-)

diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index bab8e10e5f99afcb332e333c2739ed7509b03419..05531ea43791e3e66f5f99c1f772e4c1649cb078 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -123,6 +123,7 @@
 #define USB_CSR_DUMMY1		0xb464
 #define USB_CSR_DUMMY2		0xb466
 #define USB_DEV_STAT		0xb808
+#define USB_U2P3_V2_CTRL	0xc2c0
 #define USB_CONNECT_TIMER	0xcbf8
 #define USB_MSC_TIMER		0xcbfc
 #define USB_BURST_SIZE		0xcfc0
@@ -156,6 +157,9 @@
 #define USB_U1U2_TIMER		0xd4da
 #define USB_FW_TASK		0xd4e8	/* RTL8153B */
 #define USB_RX_AGGR_NUM		0xd4ee
+#define USB_ADV_ADDR		0xd5d6
+#define USB_ADV_DATA		0xd5d8
+#define USB_ADV_CMD		0xd5dc
 #define USB_UPS_CTRL		0xd800
 #define USB_POWER_CUT		0xd80a
 #define USB_MISC_0		0xd81a
@@ -213,6 +217,8 @@
 #define OCP_PHY_PATCH_STAT	0xb800
 #define OCP_PHY_PATCH_CMD	0xb820
 #define OCP_PHY_LOCK		0xb82e
+#define OCP_SRAM2_ADDR		0xb87c
+#define OCP_SRAM2_DATA		0xb87e
 #define OCP_ADC_IOFFSET		0xbcfc
 #define OCP_ADC_CFG		0xbc06
 #define OCP_SYSCLK_CFG		0xc416
@@ -490,6 +496,12 @@
 /* USB_RX_AGGR_NUM */
 #define RX_AGGR_NUM_MASK	0x1ff
 
+/* USB_ADV_CMD */
+#define ADV_CMD_BMU		0
+#define ADV_CMD_BUSY		BIT(0)
+#define ADV_CMD_WR		BIT(1)
+#define ADV_CMD_IP		BIT(2)
+
 /* USB_UPS_CTRL */
 #define POWER_CUT		0x0100
 
@@ -529,11 +541,15 @@
 #define CDC_ECM_EN		BIT(3)
 #define RX_AGG_DISABLE		0x0010
 #define RX_ZERO_EN		0x0080
+#define RX_DESC_16B		0x0400
 
 /* USB_U2P3_CTRL */
 #define U2P3_ENABLE		0x0001
 #define RX_DETECT8		BIT(3)
 
+/* USB_U2P3_V2_CTRL */
+#define U2P3_V2_ENABLE		BIT(29)
+
 /* USB_POWER_CUT */
 #define PWR_EN			0x0001
 #define PHASE2_EN		0x0008
@@ -746,8 +762,6 @@ enum rtl_register_content {
 #define RTL8152_MAX_TX		4
 #define RTL8152_MAX_RX		10
 #define INTBUFSIZE		2
-#define TX_ALIGN		4
-#define RX_ALIGN		8
 
 #define RTL8152_RX_MAX_PENDING	4096
 #define RTL8152_RXFG_HEADSZ	256
@@ -759,7 +773,6 @@ enum rtl_register_content {
 #define RTL8152_TX_TIMEOUT	(5 * HZ)
 #define mtu_to_size(m)		((m) + VLAN_ETH_HLEN + ETH_FCS_LEN)
 #define size_to_mtu(s)		((s) - VLAN_ETH_HLEN - ETH_FCS_LEN)
-#define rx_reserved_size(x)	(mtu_to_size(x) + sizeof(struct rx_desc) + RX_ALIGN)
 
 /* rtl8152 flags */
 enum rtl8152_flags {
@@ -844,6 +857,40 @@ struct tx_desc {
 #define TX_VLAN_TAG		BIT(16)
 };
 
+struct rx_desc_v2 {
+	__le32 opts1;
+#define RX_LEN_MASK_2			0xfffe0000
+#define rx_v2_get_len(x)		(((x) & RX_LEN_MASK_2) >> 17)
+#define RX_VLAN_TAG_2			BIT(3)
+#define RX_VER_MASK			0x3
+
+	__le32 opts2;
+
+	__le32 opts3;
+#define IPF_2				BIT(26) /* IP checksum fail */
+#define UDPF_2				BIT(25) /* UDP checksum fail */
+#define TCPF_2				BIT(24) /* TCP checksum fail */
+#define RD_IPV6_CS_2			BIT(15)
+#define RD_IPV4_CS_2			BIT(14)
+#define RD_UDP_CS_2			BIT(11)
+#define RD_TCP_CS_2			BIT(10)
+
+	__le32 opts4;
+};
+
+struct tx_desc_v2 {
+	__le32 opts1;
+
+	__le32 opts2;
+#define TCPHO_MAX_2		0x3ffU
+
+	__le32 opts3;
+#define tx_v2_set_len(x)	((x) << 4)
+
+	__le32 opts4;
+#define TX_SIG			(0x15 << 27)
+};
+
 struct r8152;
 
 struct rx_agg {
@@ -917,6 +964,19 @@ struct r8152 {
 		u32 ctap_short_off:1;
 	} ups_info;
 
+	struct desc_info {
+		void (*vlan_tag)(void *desc, struct sk_buff *skb);
+		u8 align;
+		u8 size;
+	} rx_desc, tx_desc;
+
+	struct desc_ops {
+		void (*tx_len)(struct r8152 *tp, void *desc, u32 len);
+		u32 (*rx_len)(struct r8152 *tp, void *desc);
+		u8 (*rx_csum)(struct r8152 *tp, void *desc);
+		int (*tx_csum)(struct r8152 *tp, void *desc, struct sk_buff *skb, u32 len);
+	} desc_ops;
+
 #define RTL_VER_SIZE		32
 
 	struct rtl_fw {
@@ -1181,6 +1241,7 @@ enum rtl_version {
 	RTL_VER_13,
 	RTL_VER_14,
 	RTL_VER_15,
+	RTL_VER_16,
 
 	RTL_VER_MAX
 };
@@ -1206,7 +1267,7 @@ enum tx_csum_stat {
 static const int multicast_filter_limit = 32;
 static unsigned int agg_buf_sz = 16384;
 
-#define RTL_LIMITED_TSO_SIZE	(size_to_mtu(agg_buf_sz) - sizeof(struct tx_desc))
+#define RTL_LIMITED_TSO_SIZE	(size_to_mtu(agg_buf_sz) - tp->tx_desc.size)
 
 /* If register access fails then we block access and issue a reset. If this
  * happens too many times in a row without a successful access then we stop
@@ -1541,6 +1602,22 @@ static void ocp_write_word(struct r8152 *tp, u16 type, u16 index, u32 data)
 	generic_ocp_write(tp, index, byen, sizeof(tmp), &tmp, type);
 }
 
+static void ocp_word_set_bits(struct r8152 *tp, u16 type, u16 index, u32 bits)
+{
+	u32 ocp_data = ocp_read_word(tp, type, index);
+
+	ocp_data |= bits;
+	ocp_write_word(tp, type, index, ocp_data);
+}
+
+static void ocp_word_clr_bits(struct r8152 *tp, u16 type, u16 index, u32 bits)
+{
+	u32 ocp_data = ocp_read_word(tp, type, index);
+
+	ocp_data &= ~bits;
+	ocp_write_word(tp, type, index, ocp_data);
+}
+
 static u8 ocp_read_byte(struct r8152 *tp, u16 type, u16 index)
 {
 	u32 data;
@@ -1579,6 +1656,22 @@ 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 void ocp_byte_clr_bits(struct r8152 *tp, u16 type, u16 index, u32 bits)
+{
+	u8 ocp_data = ocp_read_byte(tp, type, index);
+
+	ocp_data &= ~bits;
+	ocp_write_byte(tp, type, index, ocp_data);
+}
+
+static void ocp_byte_set_bits(struct r8152 *tp, u16 type, u16 index, u8 bits)
+{
+	u8 ocp_data = ocp_read_byte(tp, type, index);
+
+	ocp_data |= bits;
+	ocp_write_byte(tp, type, index, ocp_data);
+}
+
 static u16 ocp_reg_read(struct r8152 *tp, u16 addr)
 {
 	u16 ocp_base, ocp_index;
@@ -1607,6 +1700,30 @@ static void ocp_reg_write(struct r8152 *tp, u16 addr, u16 data)
 	ocp_write_word(tp, MCU_TYPE_PLA, ocp_index, data);
 }
 
+static void ocp_reg_w0w1(struct r8152 *tp, u16 addr, u16 clear, u16 set)
+{
+	u16 data = ocp_reg_read(tp, addr);
+
+	data = (data & ~clear) | set;
+	ocp_reg_write(tp, addr, data);
+}
+
+static void ocp_reg_clr_bits(struct r8152 *tp, u16 addr, u16 bits)
+{
+	u16 data = ocp_reg_read(tp, addr);
+
+	data &= ~bits;
+	ocp_reg_write(tp, addr, data);
+}
+
+static void ocp_reg_set_bits(struct r8152 *tp, u16 addr, u16 bits)
+{
+	u16 data = ocp_reg_read(tp, addr);
+
+	data |= bits;
+	ocp_reg_write(tp, addr, data);
+}
+
 static inline void r8152_mdio_write(struct r8152 *tp, u32 reg_addr, u32 value)
 {
 	ocp_reg_write(tp, OCP_BASE_MII + reg_addr * 2, value);
@@ -1617,6 +1734,134 @@ static inline int r8152_mdio_read(struct r8152 *tp, u32 reg_addr)
 	return ocp_reg_read(tp, OCP_BASE_MII + reg_addr * 2);
 }
 
+static int wait_cmd_ready(struct r8152 *tp, u16 cmd)
+{
+	int i, ret = 0;
+
+	for (i = 0; i < 10; i++) {
+		u16 ocp_data = ocp_read_word(tp, MCU_TYPE_USB, cmd);
+
+		if (!(ocp_data & ADV_CMD_BUSY))
+			break;
+		usleep_range(1000, 2000);
+	}
+
+	if (i == 10)
+		ret = -ETIMEDOUT;
+
+	return ret;
+}
+
+static u32 ocp_adv_read(struct r8152 *tp, u16 cmd, u16 addr, u32 *data)
+{
+	int ret;
+
+	ret = wait_cmd_ready(tp, USB_ADV_CMD);
+	if (ret < 0)
+		goto out;
+
+	ocp_write_word(tp, MCU_TYPE_USB, USB_ADV_ADDR, addr);
+
+	cmd |= ADV_CMD_BUSY;
+	ocp_write_word(tp, MCU_TYPE_USB, USB_ADV_CMD, cmd);
+
+	ret = wait_cmd_ready(tp, USB_ADV_CMD);
+	if (ret < 0)
+		goto out;
+
+	*data = ocp_read_dword(tp, MCU_TYPE_USB, USB_ADV_DATA);
+
+out:
+	return ret;
+}
+
+static int ocp_adv_write(struct r8152 *tp, u16 cmd, u16 addr, u32 data)
+{
+	int ret;
+
+	ret = wait_cmd_ready(tp, USB_ADV_CMD);
+	if (ret < 0)
+		goto out;
+
+	cmd |= ADV_CMD_WR;
+	ocp_write_dword(tp, MCU_TYPE_USB, USB_ADV_DATA, data);
+
+	ocp_write_word(tp, MCU_TYPE_USB, USB_ADV_ADDR, addr);
+
+	cmd |= ADV_CMD_BUSY;
+	ocp_write_word(tp, MCU_TYPE_USB, USB_ADV_CMD, cmd);
+
+out:
+	return ret;
+}
+
+static int rtl_bmu_read(struct r8152 *tp, u16 addr, u32 *data)
+{
+	return ocp_adv_read(tp, ADV_CMD_BMU, addr, data);
+}
+
+static int rtl_bmu_write(struct r8152 *tp, u16 addr, u32 data)
+{
+	return ocp_adv_write(tp, ADV_CMD_BMU, addr, data);
+}
+
+static int rtl_bmu_w0w1(struct r8152 *tp, u16 addr, u32 clear, u32 set)
+{
+	u32 bmu;
+	int ret;
+
+	ret = rtl_bmu_read(tp, addr, &bmu);
+	if (ret < 0)
+		goto out;
+
+	bmu = (bmu & ~clear) | set;
+	ret = rtl_bmu_write(tp, addr, bmu);
+
+out:
+	return ret;
+}
+
+static int rtl_bmu_clr_bits(struct r8152 *tp, u16 addr, u32 clear)
+{
+	return rtl_bmu_w0w1(tp, addr, clear, 0);
+}
+
+static int rtl_ip_read(struct r8152 *tp, u16 addr, u32 *data)
+{
+	return ocp_adv_read(tp, ADV_CMD_IP, addr, data);
+}
+
+static int rtl_ip_write(struct r8152 *tp, u16 addr, u32 data)
+{
+	return ocp_adv_write(tp, ADV_CMD_IP, addr, data);
+}
+
+static int rtl_ip_w0w1(struct r8152 *tp, u16 addr, u32 clear, u32 set)
+{
+	int ret;
+	u32 ip;
+
+	ret = rtl_ip_read(tp, addr, &ip);
+	if (ret < 0)
+		goto out;
+
+	ip = (ip & ~clear) | set;
+	ret = rtl_ip_write(tp, addr, ip);
+
+out:
+	return ret;
+}
+
+static int rtl_ip_clr_bits(struct r8152 *tp, u16 addr, u32 clear)
+{
+	return rtl_ip_w0w1(tp, addr, clear, 0);
+}
+
+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)
 {
 	ocp_reg_write(tp, OCP_SRAM_ADDR, addr);
@@ -1629,6 +1874,28 @@ static u16 sram_read(struct r8152 *tp, u16 addr)
 	return ocp_reg_read(tp, OCP_SRAM_DATA);
 }
 
+static void sram_write_w0w1(struct r8152 *tp, u16 addr, u16 clear, u16 set)
+{
+	u16 data = sram_read(tp, addr);
+
+	data = (data & ~clear) | set;
+	ocp_reg_write(tp, OCP_SRAM_DATA, data);
+}
+
+static u16 sram2_read(struct r8152 *tp, u16 addr)
+{
+	ocp_reg_write(tp, OCP_SRAM2_ADDR, addr);
+	return ocp_reg_read(tp, OCP_SRAM2_DATA);
+}
+
+static void sram2_write_w0w1(struct r8152 *tp, u16 addr, u16 clear, u16 set)
+{
+	u16 data = sram2_read(tp, addr);
+
+	data = (data & ~clear) | set;
+	ocp_reg_write(tp, OCP_SRAM2_DATA, data);
+}
+
 static int read_mii_word(struct net_device *netdev, int phy_id, int reg)
 {
 	struct r8152 *tp = netdev_priv(netdev);
@@ -2022,14 +2289,14 @@ static void intr_callback(struct urb *urb)
 	}
 }
 
-static inline void *rx_agg_align(void *data)
+static inline void *rx_agg_align(struct r8152 *tp, void *data)
 {
-	return (void *)ALIGN((uintptr_t)data, RX_ALIGN);
+	return (void *)ALIGN((uintptr_t)data, tp->rx_desc.align);
 }
 
-static inline void *tx_agg_align(void *data)
+static inline void *tx_agg_align(struct r8152 *tp, void *data)
 {
-	return (void *)ALIGN((uintptr_t)data, TX_ALIGN);
+	return (void *)ALIGN((uintptr_t)data, tp->tx_desc.align);
 }
 
 static void free_rx_agg(struct r8152 *tp, struct rx_agg *agg)
@@ -2147,9 +2414,9 @@ static int alloc_all_mem(struct r8152 *tp)
 		if (!buf)
 			goto err1;
 
-		if (buf != tx_agg_align(buf)) {
+		if (buf != tx_agg_align(tp, buf)) {
 			kfree(buf);
-			buf = kmalloc_node(agg_buf_sz + TX_ALIGN, GFP_KERNEL,
+			buf = kmalloc_node(agg_buf_sz + tp->tx_desc.align, GFP_KERNEL,
 					   node);
 			if (!buf)
 				goto err1;
@@ -2165,7 +2432,7 @@ static int alloc_all_mem(struct r8152 *tp)
 		tp->tx_info[i].context = tp;
 		tp->tx_info[i].urb = urb;
 		tp->tx_info[i].buffer = buf;
-		tp->tx_info[i].head = tx_agg_align(buf);
+		tp->tx_info[i].head = tx_agg_align(tp, buf);
 
 		list_add_tail(&tp->tx_info[i].list, &tp->tx_free);
 	}
@@ -2252,8 +2519,17 @@ static void r8152_csum_workaround(struct r8152 *tp, struct sk_buff *skb,
 	}
 }
 
-static inline void rtl_tx_vlan_tag(struct tx_desc *desc, struct sk_buff *skb)
+static void r8152_tx_len(struct r8152 *tp, void *tx_desc, u32 len)
 {
+	struct tx_desc *desc = tx_desc;
+
+	desc->opts1 |= cpu_to_le32(len);
+}
+
+static void r8152_tx_vlan_tag(void *d, struct sk_buff *skb)
+{
+	struct tx_desc *desc = d;
+
 	if (skb_vlan_tag_present(skb)) {
 		u32 opts2;
 
@@ -2262,8 +2538,10 @@ static inline void rtl_tx_vlan_tag(struct tx_desc *desc, struct sk_buff *skb)
 	}
 }
 
-static inline void rtl_rx_vlan_tag(struct rx_desc *desc, struct sk_buff *skb)
+static void r8152_rx_vlan_tag(void *d, struct sk_buff *skb)
 {
+	struct rx_desc *desc = d;
+
 	u32 opts2 = le32_to_cpu(desc->opts2);
 
 	if (opts2 & RX_VLAN_TAG)
@@ -2271,9 +2549,10 @@ static inline void rtl_rx_vlan_tag(struct rx_desc *desc, struct sk_buff *skb)
 				       swab16(opts2 & 0xffff));
 }
 
-static int r8152_tx_csum(struct r8152 *tp, struct tx_desc *desc,
+static int r8152_tx_csum(struct r8152 *tp, void *d,
 			 struct sk_buff *skb, u32 len)
 {
+	struct rx_desc *desc = d;
 	u32 mss = skb_shinfo(skb)->gso_size;
 	u32 opts1, opts2 = 0;
 	int ret = TX_CSUM_SUCCESS;
@@ -2359,6 +2638,73 @@ static int r8152_tx_csum(struct r8152 *tp, struct tx_desc *desc,
 	return ret;
 }
 
+static u32 r8152_rx_len(struct r8152 *tp, void *d)
+{
+	struct rx_desc *desc = d;
+
+	return le32_to_cpu(desc->opts1) & RX_LEN_MASK;
+}
+
+static u32 r8157_rx_len(struct r8152 *tp, void *d)
+{
+	struct rx_desc_v2 *desc = d;
+
+	return rx_v2_get_len(le32_to_cpu(desc->opts1));
+}
+
+static void r8157_rx_vlan_tag(void *desc, struct sk_buff *skb)
+{
+	struct rx_desc_v2 *d = desc;
+	u32 opts1 = le32_to_cpu(d->opts1);
+
+	if (opts1 & RX_VLAN_TAG_2) {
+		u32 opts2 = le32_to_cpu(d->opts2);
+
+		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
+				       swab16((opts2 >> 16) & 0xffff));
+	}
+}
+
+static int r8157_tx_csum(struct r8152 *tp, void *tx_desc, struct sk_buff *skb, u32 len)
+{
+	u32 mss = skb_shinfo(skb)->gso_size;
+
+	if (!mss && skb->ip_summed == CHECKSUM_PARTIAL) {
+		u32 transport_offset = (u32)skb_transport_offset(skb);
+
+		if (transport_offset > TCPHO_MAX_2) {
+			netif_warn(tp, tx_err, tp->netdev,
+				   "Invalid transport offset 0x%x\n",
+				   transport_offset);
+			return TX_CSUM_NONE;
+		}
+	}
+
+	return r8152_tx_csum(tp, tx_desc, skb, len);
+}
+
+static void r8157_tx_len(struct r8152 *tp, void *tx_desc, u32 len)
+{
+	struct tx_desc_v2 *desc = tx_desc;
+
+	desc->opts3 = cpu_to_le32(tx_v2_set_len(len));
+	desc->opts4 = cpu_to_le32(TX_SIG);
+}
+
+static int rtl_tx_csum(struct r8152 *tp, void *desc, struct sk_buff *skb,
+		       u32 len)
+{
+	int ret = TX_CSUM_SUCCESS;
+
+	WARN_ON_ONCE(len > TX_LEN_MAX);
+
+	ret = tp->desc_ops.tx_csum(tp, desc, skb, len);
+	if (!ret)
+		tp->desc_ops.tx_len(tp, desc, len);
+
+	return ret;
+}
+
 static int r8152_tx_agg_fill(struct r8152 *tp, struct tx_agg *agg)
 {
 	struct sk_buff_head skb_head, *tx_queue = &tp->tx_queue;
@@ -2375,33 +2721,33 @@ static int r8152_tx_agg_fill(struct r8152 *tp, struct tx_agg *agg)
 	agg->skb_len = 0;
 	remain = agg_buf_sz;
 
-	while (remain >= ETH_ZLEN + sizeof(struct tx_desc)) {
-		struct tx_desc *tx_desc;
+	while (remain >= ETH_ZLEN + tp->tx_desc.size) {
 		struct sk_buff *skb;
 		unsigned int len;
+		void *tx_desc;
 
 		skb = __skb_dequeue(&skb_head);
 		if (!skb)
 			break;
 
-		len = skb->len + sizeof(*tx_desc);
+		len = skb->len + tp->tx_desc.size;
 
 		if (len > remain) {
 			__skb_queue_head(&skb_head, skb);
 			break;
 		}
 
-		tx_data = tx_agg_align(tx_data);
-		tx_desc = (struct tx_desc *)tx_data;
+		tx_data = tx_agg_align(tp, tx_data);
+		tx_desc = (void *)tx_data;
 
-		if (r8152_tx_csum(tp, tx_desc, skb, skb->len)) {
+		if (rtl_tx_csum(tp, tx_desc, skb, skb->len)) {
 			r8152_csum_workaround(tp, skb, &skb_head);
 			continue;
 		}
 
-		rtl_tx_vlan_tag(tx_desc, skb);
+		tp->tx_desc.vlan_tag(tx_desc, skb);
 
-		tx_data += sizeof(*tx_desc);
+		tx_data += tp->tx_desc.size;
 
 		len = skb->len;
 		if (skb_copy_bits(skb, 0, tx_data, len) < 0) {
@@ -2409,7 +2755,7 @@ static int r8152_tx_agg_fill(struct r8152 *tp, struct tx_agg *agg)
 
 			stats->tx_dropped++;
 			dev_kfree_skb_any(skb);
-			tx_data -= sizeof(*tx_desc);
+			tx_data -= tp->tx_desc.size;
 			continue;
 		}
 
@@ -2419,7 +2765,7 @@ static int r8152_tx_agg_fill(struct r8152 *tp, struct tx_agg *agg)
 
 		dev_kfree_skb_any(skb);
 
-		remain = agg_buf_sz - (int)(tx_agg_align(tx_data) - agg->head);
+		remain = agg_buf_sz - (int)(tx_agg_align(tp, tx_data) - agg->head);
 
 		if (tp->dell_tb_rx_agg_bug)
 			break;
@@ -2457,8 +2803,9 @@ static int r8152_tx_agg_fill(struct r8152 *tp, struct tx_agg *agg)
 	return ret;
 }
 
-static u8 r8152_rx_csum(struct r8152 *tp, struct rx_desc *rx_desc)
+static u8 r8152_rx_csum(struct r8152 *tp, void *d)
 {
+	struct rx_desc *rx_desc = d;
 	u8 checksum = CHECKSUM_NONE;
 	u32 opts2, opts3;
 
@@ -2486,6 +2833,30 @@ static u8 r8152_rx_csum(struct r8152 *tp, struct rx_desc *rx_desc)
 	return checksum;
 }
 
+static u8 r8157_rx_csum(struct r8152 *tp, void *desc)
+{
+	struct rx_desc_v2 *d = desc;
+	u8 checksum = CHECKSUM_NONE;
+	u32 opts3;
+
+	if (!(tp->netdev->features & NETIF_F_RXCSUM))
+		goto return_result;
+
+	opts3 = le32_to_cpu(d->opts3);
+
+	if ((opts3 & (RD_IPV4_CS_2 | IPF_2)) == (RD_IPV4_CS_2 | IPF_2)) {
+		checksum = CHECKSUM_NONE;
+	} else if (opts3 & (RD_IPV4_CS_2 | RD_IPV6_CS_2)) {
+		if ((opts3 & (RD_UDP_CS_2 | UDPF_2)) ==  RD_UDP_CS_2)
+			checksum = CHECKSUM_UNNECESSARY;
+		else if ((opts3 & (RD_TCP_CS_2 | TCPF_2)) == RD_TCP_CS_2)
+			checksum = CHECKSUM_UNNECESSARY;
+	}
+
+return_result:
+	return  checksum;
+}
+
 static inline bool rx_count_exceed(struct r8152 *tp)
 {
 	return atomic_read(&tp->rx_count) > RTL8152_MAX_RX;
@@ -2561,10 +2932,10 @@ static int rx_bottom(struct r8152 *tp, int budget)
 	spin_unlock_irqrestore(&tp->rx_lock, flags);
 
 	list_for_each_safe(cursor, next, &rx_queue) {
-		struct rx_desc *rx_desc;
 		struct rx_agg *agg, *agg_free;
 		int len_used = 0;
 		struct urb *urb;
+		void *rx_desc;
 		u8 *rx_data;
 
 		/* A bulk transfer of USB may contain may packets, so the
@@ -2587,7 +2958,7 @@ static int rx_bottom(struct r8152 *tp, int budget)
 
 		rx_desc = agg->buffer;
 		rx_data = agg->buffer;
-		len_used += sizeof(struct rx_desc);
+		len_used += tp->rx_desc.size;
 
 		while (urb->actual_length > len_used) {
 			struct net_device *netdev = tp->netdev;
@@ -2598,7 +2969,7 @@ static int rx_bottom(struct r8152 *tp, int budget)
 
 			WARN_ON_ONCE(skb_queue_len(&tp->rx_queue) >= 1000);
 
-			pkt_len = le32_to_cpu(rx_desc->opts1) & RX_LEN_MASK;
+			pkt_len = tp->desc_ops.rx_len(tp, rx_desc);
 			if (pkt_len < ETH_ZLEN)
 				break;
 
@@ -2608,7 +2979,7 @@ static int rx_bottom(struct r8152 *tp, int budget)
 
 			pkt_len -= ETH_FCS_LEN;
 			len = pkt_len;
-			rx_data += sizeof(struct rx_desc);
+			rx_data += tp->rx_desc.size;
 
 			if (!agg_free || tp->rx_copybreak > len)
 				use_frags = false;
@@ -2639,8 +3010,8 @@ static int rx_bottom(struct r8152 *tp, int budget)
 				goto find_next_rx;
 			}
 
-			skb->ip_summed = r8152_rx_csum(tp, rx_desc);
-			rtl_rx_vlan_tag(rx_desc, skb);
+			skb->ip_summed = tp->desc_ops.rx_csum(tp, rx_desc);
+			tp->rx_desc.vlan_tag(rx_desc, skb);
 
 			if (use_frags) {
 				if (rx_frag_head_sz) {
@@ -2677,10 +3048,10 @@ static int rx_bottom(struct r8152 *tp, int budget)
 			}
 
 find_next_rx:
-			rx_data = rx_agg_align(rx_data + len + ETH_FCS_LEN);
-			rx_desc = (struct rx_desc *)rx_data;
+			rx_data = rx_agg_align(tp, rx_data + len + ETH_FCS_LEN);
+			rx_desc = rx_data;
 			len_used = agg_offset(agg, rx_data);
-			len_used += sizeof(struct rx_desc);
+			len_used += tp->rx_desc.size;
 		}
 
 		WARN_ON(!agg_free && page_count(agg->page) > 1);
@@ -2923,13 +3294,14 @@ static netdev_features_t
 rtl8152_features_check(struct sk_buff *skb, struct net_device *dev,
 		       netdev_features_t features)
 {
+	struct r8152 *tp = netdev_priv(dev);
 	u32 mss = skb_shinfo(skb)->gso_size;
 	int max_offset = mss ? GTTCPHO_MAX : TCPHO_MAX;
 
 	if ((mss || skb->ip_summed == CHECKSUM_PARTIAL) &&
 	    skb_transport_offset(skb) > max_offset)
 		features &= ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
-	else if ((skb->len + sizeof(struct tx_desc)) > agg_buf_sz)
+	else if ((skb->len + tp->tx_desc.size) > agg_buf_sz)
 		features &= ~NETIF_F_GSO_MASK;
 
 	return features;
@@ -3020,7 +3392,7 @@ static void rtl8152_nic_reset(struct r8152 *tp)
 
 static void set_tx_qlen(struct r8152 *tp)
 {
-	tp->tx_qlen = agg_buf_sz / (mtu_to_size(tp->netdev->mtu) + sizeof(struct tx_desc));
+	tp->tx_qlen = agg_buf_sz / (mtu_to_size(tp->netdev->mtu) + tp->tx_desc.size);
 }
 
 static inline u16 rtl8152_get_speed(struct r8152 *tp)
@@ -3242,6 +3614,7 @@ static void r8153_set_rx_early_timeout(struct r8152 *tp)
 	case RTL_VER_12:
 	case RTL_VER_13:
 	case RTL_VER_15:
+	case RTL_VER_16:
 		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,
@@ -3253,9 +3626,14 @@ static void r8153_set_rx_early_timeout(struct r8152 *tp)
 	}
 }
 
+static u32 rx_reserved_size(struct r8152 *tp, u32 mtu)
+{
+	return mtu_to_size(mtu) + tp->rx_desc.size + tp->rx_desc.align;
+}
+
 static void r8153_set_rx_early_size(struct r8152 *tp)
 {
-	u32 ocp_data = tp->rx_buf_sz - rx_reserved_size(tp->netdev->mtu);
+	u32 ocp_data = tp->rx_buf_sz - rx_reserved_size(tp, tp->netdev->mtu);
 
 	switch (tp->version) {
 	case RTL_VER_03:
@@ -3280,6 +3658,10 @@ static void r8153_set_rx_early_size(struct r8152 *tp)
 		ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EARLY_SIZE,
 			       ocp_data / 8);
 		break;
+	case RTL_VER_16:
+		ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EARLY_SIZE,
+			       ocp_data / 16);
+		break;
 	default:
 		WARN_ON_ONCE(1);
 		break;
@@ -3405,6 +3787,7 @@ static void rtl_rx_vlan_en(struct r8152 *tp, bool enable)
 	case RTL_VER_12:
 	case RTL_VER_13:
 	case RTL_VER_15:
+	case RTL_VER_16:
 	default:
 		ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_RCR1);
 		if (enable)
@@ -3577,6 +3960,14 @@ static void r8153_u2p3en(struct r8152 *tp, bool enable)
 	ocp_write_word(tp, MCU_TYPE_USB, USB_U2P3_CTRL, ocp_data);
 }
 
+static int r8157_u2p3en(struct r8152 *tp, bool enable)
+{
+	if (enable)
+		return rtl_ip_set_bits(tp, USB_U2P3_V2_CTRL, U2P3_V2_ENABLE);
+	else
+		return rtl_ip_clr_bits(tp, USB_U2P3_V2_CTRL, U2P3_V2_ENABLE);
+}
+
 static void r8153b_ups_flags(struct r8152 *tp)
 {
 	u32 ups_flags = 0;
@@ -3930,9 +4321,7 @@ static void r8153_power_cut_en(struct r8152 *tp, bool enable)
 		ocp_data &= ~(PWR_EN | PHASE2_EN);
 	ocp_write_word(tp, MCU_TYPE_USB, USB_POWER_CUT, ocp_data);
 
-	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0);
-	ocp_data &= ~PCUT_STATUS;
-	ocp_write_word(tp, MCU_TYPE_USB, USB_MISC_0, ocp_data);
+	ocp_word_clr_bits(tp, MCU_TYPE_USB, USB_MISC_0, PCUT_STATUS);
 }
 
 static void r8153b_power_cut_en(struct r8152 *tp, bool enable)
@@ -3946,9 +4335,19 @@ static void r8153b_power_cut_en(struct r8152 *tp, bool enable)
 		ocp_data &= ~PWR_EN;
 	ocp_write_word(tp, MCU_TYPE_USB, USB_POWER_CUT, ocp_data);
 
-	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0);
-	ocp_data &= ~PCUT_STATUS;
-	ocp_write_word(tp, MCU_TYPE_USB, USB_MISC_0, ocp_data);
+	ocp_word_clr_bits(tp, MCU_TYPE_USB, USB_MISC_0, PCUT_STATUS);
+}
+
+static void r8157_power_cut_en(struct r8152 *tp, bool enable)
+{
+	if (enable) {
+		ocp_word_set_bits(tp, MCU_TYPE_USB, USB_POWER_CUT, PWR_EN | PHASE2_EN);
+		ocp_byte_set_bits(tp, MCU_TYPE_USB, USB_MISC_2, BIT(1));
+	} else {
+		ocp_word_clr_bits(tp, MCU_TYPE_USB, USB_POWER_CUT, PWR_EN);
+		ocp_word_clr_bits(tp, MCU_TYPE_USB, USB_MISC_0, PCUT_STATUS);
+		ocp_byte_clr_bits(tp, MCU_TYPE_USB, USB_MISC_2, BIT(1));
+	}
 }
 
 static void r8153_queue_wake(struct r8152 *tp, bool enable)
@@ -4080,6 +4479,14 @@ static void rtl8156_runtime_enable(struct r8152 *tp, bool enable)
 	}
 }
 
+static void rtl8157_runtime_enable(struct r8152 *tp, bool enable)
+{
+	r8153_queue_wake(tp, enable);
+	r8153b_u1u2en(tp, false);
+	r8157_u2p3en(tp, false);
+	rtl_runtime_suspend_enable(tp, enable);
+}
+
 static void r8153_teredo_off(struct r8152 *tp)
 {
 	u32 ocp_data;
@@ -4107,6 +4514,7 @@ static void r8153_teredo_off(struct r8152 *tp)
 	case RTL_VER_13:
 	case RTL_VER_14:
 	case RTL_VER_15:
+	case RTL_VER_16:
 	default:
 		/* The bit 0 ~ 7 are relative with teredo settings. They are
 		 * W1C (write 1 to clear), so set all 1 to disable it.
@@ -4163,6 +4571,7 @@ static void rtl_clear_bp(struct r8152 *tp, u16 type)
 		bp_num = 8;
 		break;
 	case RTL_VER_14:
+	case RTL_VER_16:
 	default:
 		ocp_write_word(tp, type, USB_BP2_EN, 0);
 		bp_num = 16;
@@ -4278,6 +4687,7 @@ static bool rtl8152_is_fw_phy_speed_up_ok(struct r8152 *tp, struct fw_phy_speed_
 	case RTL_VER_11:
 	case RTL_VER_12:
 	case RTL_VER_14:
+	case RTL_VER_16:
 		goto out;
 	case RTL_VER_13:
 	case RTL_VER_15:
@@ -5448,6 +5858,7 @@ static void rtl_eee_enable(struct r8152 *tp, bool enable)
 	case RTL_VER_12:
 	case RTL_VER_13:
 	case RTL_VER_15:
+	case RTL_VER_16:
 		if (enable) {
 			r8156_eee_en(tp, true);
 			ocp_reg_write(tp, OCP_EEE_ADV, tp->eee_adv);
@@ -6151,15 +6562,24 @@ static int rtl8156_enable(struct r8152 *tp)
 	if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
 		return -ENODEV;
 
-	r8156_fc_parameter(tp);
+	if (tp->version < RTL_VER_12)
+		r8156_fc_parameter(tp);
+
 	set_tx_qlen(tp);
 	rtl_set_eee_plus(tp);
+
+	if (tp->version >= RTL_VER_12 && tp->version <= RTL_VER_16)
+		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);
+
 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4);
 	if (speed & _2500bps)
 		ocp_data &= ~IDLE_SPDWN_EN;
@@ -6167,10 +6587,12 @@ static int rtl8156_enable(struct r8152 *tp)
 		ocp_data |= IDLE_SPDWN_EN;
 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, ocp_data);
 
-	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->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 (tp->udev->speed == USB_SPEED_HIGH) {
 		/* USB 0xb45e[3:0] l1_nyet_hird */
@@ -6183,12 +6605,9 @@ static int rtl8156_enable(struct r8152 *tp)
 		ocp_write_word(tp, MCU_TYPE_USB, USB_L1_CTRL, ocp_data);
 	}
 
-	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_FW_TASK);
-	ocp_data &= ~FC_PATCH_TASK;
-	ocp_write_word(tp, MCU_TYPE_USB, USB_FW_TASK, ocp_data);
+	ocp_word_clr_bits(tp, MCU_TYPE_USB, USB_FW_TASK, FC_PATCH_TASK);
 	usleep_range(1000, 2000);
-	ocp_data |= FC_PATCH_TASK;
-	ocp_write_word(tp, MCU_TYPE_USB, USB_FW_TASK, ocp_data);
+	ocp_word_set_bits(tp, MCU_TYPE_USB, USB_FW_TASK, FC_PATCH_TASK);
 
 	return rtl_enable(tp);
 }
@@ -6201,54 +6620,6 @@ static void rtl8156_disable(struct r8152 *tp)
 	rtl8153_disable(tp);
 }
 
-static int rtl8156b_enable(struct r8152 *tp)
-{
-	u32 ocp_data;
-	u16 speed;
-
-	if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
-		return -ENODEV;
-
-	set_tx_qlen(tp);
-	rtl_set_eee_plus(tp);
-
-	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_RX_AGGR_NUM);
-	ocp_data &= ~RX_AGGR_NUM_MASK;
-	ocp_write_word(tp, MCU_TYPE_USB, USB_RX_AGGR_NUM, ocp_data);
-
-	r8153_set_rx_early_timeout(tp);
-	r8153_set_rx_early_size(tp);
-
-	speed = rtl8152_get_speed(tp);
-	rtl_set_ifg(tp, speed);
-
-	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4);
-	if (speed & _2500bps)
-		ocp_data &= ~IDLE_SPDWN_EN;
-	else
-		ocp_data |= IDLE_SPDWN_EN;
-	ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, ocp_data);
-
-	if (tp->udev->speed == USB_SPEED_HIGH) {
-		ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_L1_CTRL);
-		ocp_data &= ~0xf;
-		if (is_flow_control(speed))
-			ocp_data |= 0xf;
-		else
-			ocp_data |= 0x1;
-		ocp_write_word(tp, MCU_TYPE_USB, USB_L1_CTRL, ocp_data);
-	}
-
-	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_FW_TASK);
-	ocp_data &= ~FC_PATCH_TASK;
-	ocp_write_word(tp, MCU_TYPE_USB, USB_FW_TASK, ocp_data);
-	usleep_range(1000, 2000);
-	ocp_data |= FC_PATCH_TASK;
-	ocp_write_word(tp, MCU_TYPE_USB, USB_FW_TASK, ocp_data);
-
-	return rtl_enable(tp);
-}
-
 static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex,
 			     u32 advertising)
 {
@@ -6621,7 +6992,7 @@ static void rtl8156_change_mtu(struct r8152 *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(rx_max_size + sizeof(struct tx_desc), 1024) / 16);
+		       ALIGN(rx_max_size + tp->tx_desc.size, 1024) / 16);
 }
 
 static void rtl8156_up(struct r8152 *tp)
@@ -6632,26 +7003,24 @@ static void rtl8156_up(struct r8152 *tp)
 		return;
 
 	r8153b_u1u2en(tp, false);
-	r8153_u2p3en(tp, false);
+	if (tp->version != RTL_VER_16)
+		r8153_u2p3en(tp, false);
 	r8153_aldps_en(tp, false);
 
 	rxdy_gated_en(tp, true);
 	r8153_teredo_off(tp);
 
-	ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);
-	ocp_data &= ~RCR_ACPT_ALL;
-	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data);
+	ocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_RCR, RCR_ACPT_ALL);
 
 	rtl8152_nic_reset(tp);
 	rtl_reset_bmu(tp);
 
-	ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
-	ocp_data &= ~NOW_IS_OOB;
-	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
+	ocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, NOW_IS_OOB);
 
-	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7);
-	ocp_data &= ~MCU_BORW_EN;
-	ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data);
+	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_SFF_STS_7, MCU_BORW_EN);
 
 	rtl_rx_vlan_en(tp, tp->netdev->features & NETIF_F_HW_VLAN_CTAG_RX);
 
@@ -6661,9 +7030,7 @@ static void rtl8156_up(struct r8152 *tp)
 	case RTL_TEST_01:
 	case RTL_VER_10:
 	case RTL_VER_11:
-		ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_BMU_CONFIG);
-		ocp_data |= ACT_ODMA;
-		ocp_write_word(tp, MCU_TYPE_USB, USB_BMU_CONFIG, ocp_data);
+		ocp_word_set_bits(tp, MCU_TYPE_USB, USB_BMU_CONFIG, ACT_ODMA);
 		break;
 	default:
 		break;
@@ -6675,13 +7042,11 @@ static void rtl8156_up(struct r8152 *tp)
 	ocp_data |= 0x08;
 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RXFIFO_FULL, ocp_data);
 
-	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3);
-	ocp_data &= ~PLA_MCU_SPDWN_EN;
-	ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, ocp_data);
+	ocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, PLA_MCU_SPDWN_EN);
 
-	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_SPEED_OPTION);
-	ocp_data &= ~(RG_PWRDN_EN | ALL_SPEED_OFF);
-	ocp_write_word(tp, MCU_TYPE_USB, USB_SPEED_OPTION, ocp_data);
+	if (tp->version != RTL_VER_16)
+		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);
 
@@ -6693,7 +7058,7 @@ static void rtl8156_up(struct r8152 *tp)
 	r8153_aldps_en(tp, true);
 	r8153_u2p3en(tp, true);
 
-	if (tp->udev->speed >= USB_SPEED_SUPER)
+	if (tp->version != RTL_VER_16 && tp->udev->speed >= USB_SPEED_SUPER)
 		r8153b_u1u2en(tp, true);
 }
 
@@ -6706,13 +7071,13 @@ static void rtl8156_down(struct r8152 *tp)
 		return;
 	}
 
-	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3);
-	ocp_data |= PLA_MCU_SPDWN_EN;
-	ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, ocp_data);
+	ocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, PLA_MCU_SPDWN_EN);
 
 	r8153b_u1u2en(tp, false);
-	r8153_u2p3en(tp, false);
-	r8153b_power_cut_en(tp, false);
+	if (tp->version != RTL_VER_16) {
+		r8153_u2p3en(tp, false);
+		r8153b_power_cut_en(tp, false);
+	}
 	r8153_aldps_en(tp, false);
 
 	ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
@@ -6736,13 +7101,9 @@ static void rtl8156_down(struct r8152 *tp)
 	 */
 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_TEREDO_WAKE_BASE, 0x00ff);
 
-	ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
-	ocp_data |= NOW_IS_OOB;
-	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
+	ocp_byte_set_bits(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, NOW_IS_OOB);
 
-	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7);
-	ocp_data |= MCU_BORW_EN;
-	ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data);
+	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);
@@ -8147,42 +8508,33 @@ static void r8156b_hw_phy_cfg(struct r8152 *tp)
 	set_bit(PHY_RESET, &tp->flags);
 }
 
-static void r8156_init(struct r8152 *tp)
+static void r8157_hw_phy_cfg(struct r8152 *tp)
 {
 	u32 ocp_data;
 	u16 data;
-	int i;
-
-	if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
-		return;
-
-	ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_ECM_OP);
-	ocp_data &= ~EN_ALL_SPEED;
-	ocp_write_byte(tp, MCU_TYPE_USB, USB_ECM_OP, ocp_data);
-
-	ocp_write_word(tp, MCU_TYPE_USB, USB_SPEED_OPTION, 0);
-
-	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_ECM_OPTION);
-	ocp_data |= BYPASS_MAC_RESET;
-	ocp_write_word(tp, MCU_TYPE_USB, USB_ECM_OPTION, ocp_data);
+	int ret;
 
-	r8153b_u1u2en(tp, false);
+	r8156b_wait_loading_flash(tp);
 
-	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;
+	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0);
+	if (ocp_data & PCUT_STATUS) {
+		ocp_data &= ~PCUT_STATUS;
+		ocp_write_word(tp, MCU_TYPE_USB, USB_MISC_0, ocp_data);
 	}
 
-	data = r8153_phy_status(tp, 0);
-	if (data == PHY_STAT_EXT_INIT) {
-		data = ocp_reg_read(tp, 0xa468);
-		data &= ~(BIT(3) | BIT(1));
-		ocp_reg_write(tp, 0xa468, data);
+	ret = r8153_phy_status(tp, 0);
+	if (ret < 0)
+		return;
+
+	switch (ret) {
+	case PHY_STAT_EXT_INIT:
+		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:
+		break;
 	}
 
 	data = r8152_mdio_read(tp, MII_BMCR);
@@ -8191,59 +8543,180 @@ static void r8156_init(struct r8152 *tp)
 		r8152_mdio_write(tp, MII_BMCR, data);
 	}
 
-	data = r8153_phy_status(tp, PHY_STAT_LAN_ON);
-	WARN_ON_ONCE(data != PHY_STAT_LAN_ON);
+	r8153_aldps_en(tp, false);
+	rtl_eee_enable(tp, false);
 
-	r8153_u2p3en(tp, false);
+	ret = r8153_phy_status(tp, PHY_STAT_LAN_ON);
+	if (ret < 0)
+		return;
+	WARN_ON_ONCE(ret != PHY_STAT_LAN_ON);
 
-	/* MSC timer = 0xfff * 8ms = 32760 ms */
-	ocp_write_word(tp, MCU_TYPE_USB, USB_MSC_TIMER, 0x0fff);
+	/* PFM mode */
+	ocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_PHY_PWR, PFM_PWM_SWITCH);
 
-	/* U1/U2/L1 idle timer. 500 us */
-	ocp_write_word(tp, MCU_TYPE_USB, USB_U1U2_TIMER, 500);
+	/* Advanced Power Saving parameter */
+	ocp_reg_set_bits(tp, 0xa430, BIT(0) | BIT(1));
 
-	r8153b_power_cut_en(tp, false);
-	r8156_ups_en(tp, false);
-	r8153_queue_wake(tp, false);
-	rtl_runtime_suspend_enable(tp, false);
+	/* aldpsce force mode */
+	ocp_reg_clr_bits(tp, 0xa44a, BIT(2));
 
-	if (tp->udev->speed >= USB_SPEED_SUPER)
-		r8153b_u1u2en(tp, true);
+	switch (tp->version) {
+	case RTL_VER_16:
+		/* XG_INRX parameter */
+		sram_write_w0w1(tp, 0x8183, 0xff00, 0x5900);
+		ocp_reg_set_bits(tp, 0xa654, BIT(11));
+		ocp_reg_set_bits(tp, 0xb648, BIT(14));
+		ocp_reg_clr_bits(tp, 0xad2c, BIT(15));
+		ocp_reg_set_bits(tp, 0xad94, BIT(5));
+		ocp_reg_set_bits(tp, 0xada0, BIT(1));
+		ocp_reg_w0w1(tp, 0xae06, 0xfc00, 0x7c00);
+		sram2_write_w0w1(tp, 0x8647, 0xff00, 0xe600);
+		sram2_write_w0w1(tp, 0x8036, 0xff00, 0x3000);
+		sram2_write_w0w1(tp, 0x8078, 0xff00, 0x3000);
+
+		/* green mode */
+		sram2_write_w0w1(tp, 0x89e9, 0xff00, 0);
+		sram2_write_w0w1(tp, 0x8ffd, 0xff00, 0x0100);
+		sram2_write_w0w1(tp, 0x8ffe, 0xff00, 0x0200);
+		sram2_write_w0w1(tp, 0x8fff, 0xff00, 0x0400);
+
+		/* recognize AQC/Bcom function */
+		sram_write_w0w1(tp, 0x8018, 0xff00, 0x7700);
+		ocp_reg_write(tp, OCP_SRAM_ADDR, 0x8f9c);
+		ocp_reg_write(tp, OCP_SRAM_DATA, 0x0005);
+		ocp_reg_write(tp, OCP_SRAM_DATA, 0x0000);
+		ocp_reg_write(tp, OCP_SRAM_DATA, 0x00ed);
+		ocp_reg_write(tp, OCP_SRAM_DATA, 0x0502);
+		ocp_reg_write(tp, OCP_SRAM_DATA, 0x0b00);
+		ocp_reg_write(tp, OCP_SRAM_DATA, 0xd401);
+		sram_write_w0w1(tp, 0x8fa8, 0xff00, 0x2900);
+
+		/* RFI_corr_thd 5g */
+		sram2_write_w0w1(tp, 0x814b, 0xff00, 0x1100);
+		sram2_write_w0w1(tp, 0x814d, 0xff00, 0x1100);
+		sram2_write_w0w1(tp, 0x814f, 0xff00, 0x0b00);
+		sram2_write_w0w1(tp, 0x8142, 0xff00, 0x0100);
+		sram2_write_w0w1(tp, 0x8144, 0xff00, 0x0100);
+		sram2_write_w0w1(tp, 0x8150, 0xff00, 0x0100);
+
+		/* RFI_corr_thd 2p5g */
+		sram2_write_w0w1(tp, 0x8118, 0xff00, 0x0700);
+		sram2_write_w0w1(tp, 0x811a, 0xff00, 0x0700);
+		sram2_write_w0w1(tp, 0x811c, 0xff00, 0x0500);
+		sram2_write_w0w1(tp, 0x810f, 0xff00, 0x0100);
+		sram2_write_w0w1(tp, 0x8111, 0xff00, 0x0100);
+		sram2_write_w0w1(tp, 0x811d, 0xff00, 0x0100);
+
+		/* RFI parameter */
+		ocp_reg_clr_bits(tp, 0xad1c, BIT(8));
+		ocp_reg_w0w1(tp, 0xade8, 0xffc0, 0x1400);
+		sram2_write_w0w1(tp, 0x864b, 0xff00, 0x9d00);
+		sram2_write_w0w1(tp, 0x862c, 0xff00, 0x1200);
+		ocp_reg_write(tp, OCP_SRAM_ADDR, 0x8566);
+		ocp_reg_write(tp, OCP_SRAM_DATA, 0x003f);
+		ocp_reg_write(tp, OCP_SRAM_DATA, 0x3f02);
+		ocp_reg_write(tp, OCP_SRAM_DATA, 0x023c);
+		ocp_reg_write(tp, OCP_SRAM_DATA, 0x3b0a);
+		ocp_reg_write(tp, OCP_SRAM_DATA, 0x1c00);
+		ocp_reg_write(tp, OCP_SRAM_DATA, 0x0000);
+		ocp_reg_write(tp, OCP_SRAM_DATA, 0x0000);
+		ocp_reg_write(tp, OCP_SRAM_DATA, 0x0000);
+		ocp_reg_write(tp, OCP_SRAM_DATA, 0x0000);
+
+		/* RFI-color noise gen parameter 5g */
+		ocp_reg_set_bits(tp, 0xad9c, BIT(5));
+		sram2_write_w0w1(tp, 0x8122, 0xff00, 0x0c00);
+		ocp_reg_write(tp, OCP_SRAM2_ADDR, 0x82c8);
+		ocp_reg_write(tp, OCP_SRAM2_DATA, 0x03ed);
+		ocp_reg_write(tp, OCP_SRAM2_DATA, 0x03ff);
+		ocp_reg_write(tp, OCP_SRAM2_DATA, 0x0009);
+		ocp_reg_write(tp, OCP_SRAM2_DATA, 0x03fe);
+		ocp_reg_write(tp, OCP_SRAM2_DATA, 0x000b);
+		ocp_reg_write(tp, OCP_SRAM2_DATA, 0x0021);
+		ocp_reg_write(tp, OCP_SRAM2_DATA, 0x03f7);
+		ocp_reg_write(tp, OCP_SRAM2_DATA, 0x03b8);
+		ocp_reg_write(tp, OCP_SRAM2_DATA, 0x03e0);
+		ocp_reg_write(tp, OCP_SRAM2_DATA, 0x0049);
+		ocp_reg_write(tp, OCP_SRAM2_DATA, 0x0049);
+		ocp_reg_write(tp, OCP_SRAM2_DATA, 0x03e0);
+		ocp_reg_write(tp, OCP_SRAM2_DATA, 0x03b8);
+		ocp_reg_write(tp, OCP_SRAM2_DATA, 0x03f7);
+		ocp_reg_write(tp, OCP_SRAM2_DATA, 0x0021);
+		ocp_reg_write(tp, OCP_SRAM2_DATA, 0x000b);
+		ocp_reg_write(tp, OCP_SRAM2_DATA, 0x03fe);
+		ocp_reg_write(tp, OCP_SRAM2_DATA, 0x0009);
+		ocp_reg_write(tp, OCP_SRAM2_DATA, 0x03ff);
+		ocp_reg_write(tp, OCP_SRAM2_DATA, 0x03ed);
+
+		/* RFI-color noise gen parameter 2p5g */
+		sram2_write_w0w1(tp, 0x80ef, 0xff00, 0x0c00);
+		ocp_reg_write(tp, OCP_SRAM2_ADDR, 0x82a0);
+		ocp_reg_write(tp, OCP_SRAM2_DATA, 0x000e);
+		ocp_reg_write(tp, OCP_SRAM2_DATA, 0x03fe);
+		ocp_reg_write(tp, OCP_SRAM2_DATA, 0x03ed);
+		ocp_reg_write(tp, OCP_SRAM2_DATA, 0x0006);
+		ocp_reg_write(tp, OCP_SRAM2_DATA, 0x001a);
+		ocp_reg_write(tp, OCP_SRAM2_DATA, 0x03f1);
+		ocp_reg_write(tp, OCP_SRAM2_DATA, 0x03d8);
+		ocp_reg_write(tp, OCP_SRAM2_DATA, 0x0023);
+		ocp_reg_write(tp, OCP_SRAM2_DATA, 0x0054);
+		ocp_reg_write(tp, OCP_SRAM2_DATA, 0x0322);
+		ocp_reg_write(tp, OCP_SRAM2_DATA, 0x00dd);
+		ocp_reg_write(tp, OCP_SRAM2_DATA, 0x03ab);
+		ocp_reg_write(tp, OCP_SRAM2_DATA, 0x03dc);
+		ocp_reg_write(tp, OCP_SRAM2_DATA, 0x0027);
+		ocp_reg_write(tp, OCP_SRAM2_DATA, 0x000e);
+		ocp_reg_write(tp, OCP_SRAM2_DATA, 0x03e5);
+		ocp_reg_write(tp, OCP_SRAM2_DATA, 0x03f9);
+		ocp_reg_write(tp, OCP_SRAM2_DATA, 0x0012);
+		ocp_reg_write(tp, OCP_SRAM2_DATA, 0x0001);
+		ocp_reg_write(tp, OCP_SRAM2_DATA, 0x03f1);
+
+		/* modify thermal speed down threshold */
+		ocp_reg_w0w1(tp, 0xb54c, 0xffc0, 0x3700);
+
+		/* XG compatibility modification */
+		ocp_reg_set_bits(tp, 0xb648, BIT(6));
+		sram2_write_w0w1(tp, 0x8082, 0xff00, 0x5d00);
+		sram2_write_w0w1(tp, 0x807c, 0xff00, 0x5000);
+		sram2_write_w0w1(tp, 0x809d, 0xff00, 0x5000);
+		break;
+	default:
+		break;
+	}
 
-	usb_enable_lpm(tp->udev);
+	if (rtl_phy_patch_request(tp, true, true))
+		return;
 
-	r8156_mac_clk_spd(tp, true);
+	ocp_word_set_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, EEE_SPDWN_EN);
 
-	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3);
-	ocp_data &= ~PLA_MCU_SPDWN_EN;
-	ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, ocp_data);
+	ocp_reg_w0w1(tp, OCP_DOWN_SPEED, EN_EEE_100 | EN_EEE_1000, EN_10M_CLKDIV);
 
-	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS);
-	if (rtl8152_get_speed(tp) & LINK_STATUS)
-		ocp_data |= CUR_LINK_OK;
-	else
-		ocp_data &= ~CUR_LINK_OK;
-	ocp_data |= POLL_LINK_CHG;
-	ocp_write_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS, ocp_data);
+	tp->ups_info._10m_ckdiv = true;
+	tp->ups_info.eee_plloff_100 = false;
+	tp->ups_info.eee_plloff_giga = false;
 
-	set_bit(GREEN_ETHERNET, &tp->flags);
+	ocp_reg_set_bits(tp, OCP_POWER_CFG, EEE_CLKDIV_EN);
+	tp->ups_info.eee_ckdiv = true;
 
-	/* rx aggregation */
-	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL);
-	ocp_data &= ~(RX_AGG_DISABLE | RX_ZERO_EN);
-	ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data);
+	rtl_phy_patch_request(tp, false, true);
 
-	ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_BMU_CONFIG);
-	ocp_data |= ACT_ODMA;
-	ocp_write_byte(tp, MCU_TYPE_USB, USB_BMU_CONFIG, ocp_data);
+	rtl_green_en(tp, test_bit(GREEN_ETHERNET, &tp->flags));
 
-	r8156_mdio_force_mode(tp);
-	rtl_tally_reset(tp);
+	ocp_reg_clr_bits(tp, 0xa428, BIT(9));
+	ocp_reg_clr_bits(tp, 0xa5ea, BIT(0) | BIT(1));
+	tp->ups_info.lite_mode = 0;
 
-	tp->coalesce = 15000;	/* 15 us */
+	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 r8156b_init(struct r8152 *tp)
+static void r8156_init(struct r8152 *tp)
 {
 	u32 ocp_data;
 	u16 data;
@@ -8252,25 +8725,27 @@ static void r8156b_init(struct r8152 *tp)
 	if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
 		return;
 
-	ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_ECM_OP);
-	ocp_data &= ~EN_ALL_SPEED;
-	ocp_write_byte(tp, MCU_TYPE_USB, USB_ECM_OP, ocp_data);
+	if (tp->version == RTL_VER_16) {
+		ocp_byte_set_bits(tp, MCU_TYPE_USB, 0xcffe, BIT(3));
+		ocp_byte_clr_bits(tp, MCU_TYPE_USB, 0xd3ca, BIT(0));
+	}
 
-	ocp_write_word(tp, MCU_TYPE_USB, USB_SPEED_OPTION, 0);
+	ocp_byte_clr_bits(tp, MCU_TYPE_USB, USB_ECM_OP, EN_ALL_SPEED);
 
-	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_ECM_OPTION);
-	ocp_data |= BYPASS_MAC_RESET;
-	ocp_write_word(tp, MCU_TYPE_USB, USB_ECM_OPTION, ocp_data);
+	if (tp->version != RTL_VER_16)
+		ocp_write_word(tp, MCU_TYPE_USB, USB_SPEED_OPTION, 0);
 
-	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_U2P3_CTRL);
-	ocp_data |= RX_DETECT8;
-	ocp_write_word(tp, MCU_TYPE_USB, USB_U2P3_CTRL, ocp_data);
+	ocp_word_set_bits(tp, MCU_TYPE_USB, USB_ECM_OPTION, BYPASS_MAC_RESET);
+
+	if (tp->version >= RTL_VER_13 && 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:
 		r8156b_wait_loading_flash(tp);
 		break;
 	default:
@@ -8289,13 +8764,9 @@ static void r8156b_init(struct r8152 *tp)
 
 	data = r8153_phy_status(tp, 0);
 	if (data == PHY_STAT_EXT_INIT) {
-		data = ocp_reg_read(tp, 0xa468);
-		data &= ~(BIT(3) | BIT(1));
-		ocp_reg_write(tp, 0xa468, data);
-
-		data = ocp_reg_read(tp, 0xa466);
-		data &= ~BIT(0);
-		ocp_reg_write(tp, 0xa466, data);
+		ocp_reg_clr_bits(tp, 0xa468, BIT(3) | BIT(1));
+		if (tp->version >= RTL_VER_13)
+			ocp_reg_clr_bits(tp, 0xa466, BIT(0));
 	}
 
 	data = r8152_mdio_read(tp, MII_BMCR);
@@ -8306,7 +8777,10 @@ static void r8156b_init(struct r8152 *tp)
 
 	data = r8153_phy_status(tp, PHY_STAT_LAN_ON);
 
-	r8153_u2p3en(tp, false);
+	if (tp->version == RTL_VER_16)
+		r8157_u2p3en(tp, false);
+	else
+		r8153_u2p3en(tp, false);
 
 	/* MSC timer = 0xfff * 8ms = 32760 ms */
 	ocp_write_word(tp, MCU_TYPE_USB, USB_MSC_TIMER, 0x0fff);
@@ -8314,7 +8788,11 @@ static void r8156b_init(struct r8152 *tp)
 	/* U1/U2/L1 idle timer. 500 us */
 	ocp_write_word(tp, MCU_TYPE_USB, USB_U1U2_TIMER, 500);
 
-	r8153b_power_cut_en(tp, false);
+	if (tp->version == RTL_VER_16)
+		r8157_power_cut_en(tp, false);
+	else
+		r8153b_power_cut_en(tp, false);
+
 	r8156_ups_en(tp, false);
 	r8153_queue_wake(tp, false);
 	rtl_runtime_suspend_enable(tp, false);
@@ -8324,33 +8802,27 @@ static void r8156b_init(struct r8152 *tp)
 
 	usb_enable_lpm(tp->udev);
 
-	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_RCR);
-	ocp_data &= ~SLOT_EN;
-	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data);
+	if (tp->version >= RTL_VER_13 && tp->version <= RTL_VER_15) {
+		ocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_RCR, SLOT_EN);
 
-	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CPCR);
-	ocp_data |= FLOW_CTRL_EN;
-	ocp_write_word(tp, MCU_TYPE_PLA, PLA_CPCR, ocp_data);
+		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));
+		/* 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_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);
+		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);
 
-	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_FW_TASK);
-	ocp_data |= FC_PATCH_TASK;
-	ocp_write_word(tp, MCU_TYPE_USB, USB_FW_TASK, ocp_data);
+		ocp_word_set_bits(tp, MCU_TYPE_USB, USB_FW_TASK, FC_PATCH_TASK);
+	}
 
 	r8156_mac_clk_spd(tp, true);
 
-	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3);
-	ocp_data &= ~PLA_MCU_SPDWN_EN;
-	ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, ocp_data);
+	if (tp->version != RTL_VER_16)
+		ocp_byte_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)
@@ -8362,10 +8834,21 @@ static void r8156b_init(struct r8152 *tp)
 
 	set_bit(GREEN_ETHERNET, &tp->flags);
 
-	/* rx aggregation */
-	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL);
-	ocp_data &= ~(RX_AGG_DISABLE | RX_ZERO_EN);
-	ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data);
+	/* rx aggregation / 16 bytes Rx descriptor */
+	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);
+
+	if (tp->version < RTL_VER_13)
+		ocp_byte_set_bits(tp, MCU_TYPE_USB, USB_BMU_CONFIG, ACT_ODMA);
+
+	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));
+	}
 
 	r8156_mdio_force_mode(tp);
 	rtl_tally_reset(tp);
@@ -9518,6 +10001,38 @@ static void rtl8153b_unload(struct r8152 *tp)
 	r8153b_power_cut_en(tp, false);
 }
 
+static int r8152_desc_init(struct r8152 *tp)
+{
+	tp->rx_desc.size = sizeof(struct rx_desc);
+	tp->rx_desc.align = 8;
+	tp->rx_desc.vlan_tag = r8152_rx_vlan_tag;
+	tp->desc_ops.rx_csum = r8152_rx_csum;
+	tp->desc_ops.rx_len = r8152_rx_len;
+	tp->tx_desc.size = sizeof(struct tx_desc);
+	tp->tx_desc.align = 4;
+	tp->tx_desc.vlan_tag = r8152_tx_vlan_tag;
+	tp->desc_ops.tx_csum = r8152_tx_csum;
+	tp->desc_ops.tx_len = r8152_tx_len;
+
+	return 0;
+}
+
+static int r8157_desc_init(struct r8152 *tp)
+{
+	tp->rx_desc.size = sizeof(struct rx_desc_v2);
+	tp->rx_desc.align = 16;
+	tp->rx_desc.vlan_tag = r8157_rx_vlan_tag;
+	tp->desc_ops.rx_csum = r8157_rx_csum;
+	tp->desc_ops.rx_len = r8157_rx_len;
+	tp->tx_desc.size = sizeof(struct tx_desc_v2);
+	tp->tx_desc.align = 16;
+	tp->tx_desc.vlan_tag = r8152_tx_vlan_tag;
+	tp->desc_ops.tx_csum = r8157_tx_csum;
+	tp->desc_ops.tx_len = r8157_tx_len;
+
+	return 0;
+}
+
 static int rtl_ops_init(struct r8152 *tp)
 {
 	struct rtl_ops *ops = &tp->rtl_ops;
@@ -9541,6 +10056,7 @@ static int rtl_ops_init(struct r8152 *tp)
 		tp->rx_buf_sz		= 16 * 1024;
 		tp->eee_en		= true;
 		tp->eee_adv		= MDIO_EEE_100TX;
+		r8152_desc_init(tp);
 		break;
 
 	case RTL_VER_03:
@@ -9565,6 +10081,7 @@ static int rtl_ops_init(struct r8152 *tp)
 			tp->rx_buf_sz	= 32 * 1024;
 		tp->eee_en		= true;
 		tp->eee_adv		= MDIO_EEE_1000T | MDIO_EEE_100TX;
+		r8152_desc_init(tp);
 		break;
 
 	case RTL_VER_08:
@@ -9584,6 +10101,7 @@ static int rtl_ops_init(struct r8152 *tp)
 		tp->rx_buf_sz		= 32 * 1024;
 		tp->eee_en		= true;
 		tp->eee_adv		= MDIO_EEE_1000T | MDIO_EEE_100TX;
+		r8152_desc_init(tp);
 		break;
 
 	case RTL_VER_11:
@@ -9606,6 +10124,7 @@ static int rtl_ops_init(struct r8152 *tp)
 		ops->change_mtu		= rtl8156_change_mtu;
 		tp->rx_buf_sz		= 48 * 1024;
 		tp->support_2500full	= 1;
+		r8152_desc_init(tp);
 		break;
 
 	case RTL_VER_12:
@@ -9616,8 +10135,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		= r8156b_init;
-		ops->enable		= rtl8156b_enable;
+		ops->init		= r8156_init;
+		ops->enable		= rtl8156_enable;
 		ops->disable		= rtl8153_disable;
 		ops->up			= rtl8156_up;
 		ops->down		= rtl8156_down;
@@ -9629,6 +10148,7 @@ static int rtl_ops_init(struct r8152 *tp)
 		ops->autosuspend_en	= rtl8156_runtime_enable;
 		ops->change_mtu		= rtl8156_change_mtu;
 		tp->rx_buf_sz		= 48 * 1024;
+		r8152_desc_init(tp);
 		break;
 
 	case RTL_VER_14:
@@ -9647,6 +10167,29 @@ static int rtl_ops_init(struct r8152 *tp)
 		tp->rx_buf_sz		= 32 * 1024;
 		tp->eee_en		= true;
 		tp->eee_adv		= MDIO_EEE_1000T | MDIO_EEE_100TX;
+		r8152_desc_init(tp);
+		break;
+
+	case RTL_VER_16:
+		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->disable		= rtl8153_disable;
+		ops->up			= rtl8156_up;
+		ops->down		= rtl8156_down;
+		ops->unload		= rtl8153_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;
+		tp->rx_buf_sz		= 32 * 1024;
+		tp->support_2500full	= 1;
+		tp->support_5000full	= 1;
+		r8157_desc_init(tp);
 		break;
 
 	default:
@@ -9799,6 +10342,9 @@ static u8 __rtl_get_hw_ver(struct usb_device *udev)
 	case 0x7420:
 		version = RTL_VER_15;
 		break;
+	case 0x1030:
+		version = RTL_VER_16;
+		break;
 	default:
 		version = RTL_VER_UNKNOWN;
 		dev_info(&udev->dev, "Unknown version 0x%04x\n", ocp_data);
@@ -9950,6 +10496,7 @@ static int rtl8152_probe_once(struct usb_interface *intf,
 	case RTL_VER_12:
 	case RTL_VER_13:
 	case RTL_VER_15:
+	case RTL_VER_16:
 		netdev->max_mtu = size_to_mtu(16 * 1024);
 		break;
 	case RTL_VER_01:
@@ -10109,6 +10656,7 @@ static const struct usb_device_id rtl8152_table[] = {
 	{ USB_DEVICE(VENDOR_ID_REALTEK, 0x8153) },
 	{ USB_DEVICE(VENDOR_ID_REALTEK, 0x8155) },
 	{ USB_DEVICE(VENDOR_ID_REALTEK, 0x8156) },
+	{ USB_DEVICE(VENDOR_ID_REALTEK, 0x8157) },
 
 	/* Microsoft */
 	{ USB_DEVICE(VENDOR_ID_MICROSOFT, 0x07ab) },

-- 
2.47.3


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH net-next v2 0/2] r8152: Add support for the RTL8157 5Gbit USB Ethernet chip
  2026-03-17 18:07 [PATCH net-next v2 0/2] r8152: Add support for the RTL8157 5Gbit USB Ethernet chip Birger Koblitz
  2026-03-17 18:07 ` [PATCH net-next v2 1/2] r8152: Add support for 5Gbit Link Speeds and EEE Birger Koblitz
  2026-03-17 18:07 ` [PATCH net-next v2 2/2] r8152: Add support for the RTL8157 hardware Birger Koblitz
@ 2026-03-19 15:53 ` Andrew Lunn
  2026-03-19 16:31   ` Birger Koblitz
  2 siblings, 1 reply; 17+ messages in thread
From: Andrew Lunn @ 2026-03-19 15:53 UTC (permalink / raw)
  To: Birger Koblitz
  Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, linux-usb, netdev, linux-kernel

> This patch is on top of linux-next as the code re-uses the 2.5 Gbit EEE
> recently added in r8152.c.

Is 'linux-next' a typo? net-next should also have the EEE code, that
is the patch networking code takes.

	Andrew

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH net-next v2 1/2] r8152: Add support for 5Gbit Link Speeds and EEE
  2026-03-17 18:07 ` [PATCH net-next v2 1/2] r8152: Add support for 5Gbit Link Speeds and EEE Birger Koblitz
@ 2026-03-19 16:29   ` Andrew Lunn
  2026-03-19 16:51     ` Birger Koblitz
  2026-03-19 16:51   ` Simon Horman
  2026-03-19 21:43   ` Aleksander Jan Bajkowski
  2 siblings, 1 reply; 17+ messages in thread
From: Andrew Lunn @ 2026-03-19 16:29 UTC (permalink / raw)
  To: Birger Koblitz
  Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, linux-usb, netdev, linux-kernel

On Tue, Mar 17, 2026 at 07:07:14PM +0100, Birger Koblitz wrote:
> The RTL8157 supports 5GBit Link speeds. Add support for this speed
> in the setup and setting/getting through ethool. Also add 5GBit EEE.
> Add functionality for setup and ethtool get/set methods.
> 
> Signed-off-by: Birger Koblitz <mail@birger-koblitz.de>
> ---
>  drivers/net/usb/r8152.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++---
>  1 file changed, 53 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
> index 3b6d4252d34c63ead8f11a120e212325a5f7d505..bab8e10e5f99afcb332e333c2739ed7509b03419 100644
> --- a/drivers/net/usb/r8152.c
> +++ b/drivers/net/usb/r8152.c
> @@ -604,6 +604,7 @@ enum spd_duplex {
>  	FORCE_100M_FULL,
>  	FORCE_1000M_FULL,
>  	NWAY_2500M_FULL,
> +	NWAY_5000M_FULL,
>  };
>  
>  /* OCP_ALDPS_CONFIG */
> @@ -725,6 +726,7 @@ enum spd_duplex {
>  #define BP4_SUPER_ONLY		0x1578	/* RTL_VER_04 only */
>  
>  enum rtl_register_content {
> +	_5000bps	= BIT(12),
>  	_2500bps	= BIT(10),

Any idea what bit 11 is for? There is not normally any speed between
2.5G and 5G.

> @@ -9934,6 +9979,11 @@ static int rtl8152_probe_once(struct usb_interface *intf,
>  		} else {
>  			tp->speed = SPEED_1000;
>  		}
> +		if (tp->support_5000full &&
> +		    tp->udev->speed >= USB_SPEED_SUPER) {
> +			tp->speed = SPEED_5000;
> +			tp->advertising |= RTL_ADVERTISED_5000_FULL;
> +		}

Let me check i understand this.

ethtool supported will indicate 5G, independent of the USB speed? But
it will only advertise 5G if the USB bus is USB 3.0 or higher, which
can do 5G. The user can however use ethtool to advertise 5G, for USB
2.0?

I suppose the question is, are there any link partners which do 2.5G
and/or 5G, but not 1G? I guess not.

       Andrew

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH net-next v2 0/2] r8152: Add support for the RTL8157 5Gbit USB Ethernet chip
  2026-03-19 15:53 ` [PATCH net-next v2 0/2] r8152: Add support for the RTL8157 5Gbit USB Ethernet chip Andrew Lunn
@ 2026-03-19 16:31   ` Birger Koblitz
  0 siblings, 0 replies; 17+ messages in thread
From: Birger Koblitz @ 2026-03-19 16:31 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, linux-usb, netdev, linux-kernel

On 19/03/2026 16:53, Andrew Lunn wrote:
>> This patch is on top of linux-next as the code re-uses the 2.5 Gbit EEE
>> recently added in r8152.c.
> 
> Is 'linux-next' a typo? net-next should also have the EEE code, that
> is the patch networking code takes.
> 
> 	Andrew
I based it on linux-next, but the r8152.c driver file which is patched here,
is in both cases identical. The patch will work with net-next. I used
linux-next because I had planned to submit the patch for the next
kernel release cycle, but then was much faster than thought.

Birger

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH net-next v2 2/2] r8152: Add support for the RTL8157 hardware
  2026-03-17 18:07 ` [PATCH net-next v2 2/2] r8152: Add support for the RTL8157 hardware Birger Koblitz
@ 2026-03-19 16:42   ` Andrew Lunn
  2026-03-19 17:27     ` Birger Koblitz
  2026-03-19 16:51   ` Simon Horman
  1 sibling, 1 reply; 17+ messages in thread
From: Andrew Lunn @ 2026-03-19 16:42 UTC (permalink / raw)
  To: Birger Koblitz
  Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, linux-usb, netdev, linux-kernel

> +static int wait_cmd_ready(struct r8152 *tp, u16 cmd)
> +{
> +	int i, ret = 0;
> +
> +	for (i = 0; i < 10; i++) {
> +		u16 ocp_data = ocp_read_word(tp, MCU_TYPE_USB, cmd);
> +
> +		if (!(ocp_data & ADV_CMD_BUSY))
> +			break;
> +		usleep_range(1000, 2000);
> +	}
> +
> +	if (i == 10)
> +		ret = -ETIMEDOUT;
> +
> +	return ret;

It is better practice to use one of the helpers from linux/iopoll.h.

> -static int r8152_tx_csum(struct r8152 *tp, struct tx_desc *desc,
> +static int r8152_tx_csum(struct r8152 *tp, void *d,
>  			 struct sk_buff *skb, u32 len)
>  {
> +	struct rx_desc *desc = d;
>  	u32 mss = skb_shinfo(skb)->gso_size;
>  	u32 opts1, opts2 = 0;
>  	int ret = TX_CSUM_SUCCESS;

Reversed Christmas tree is already messed up here, but please don't
make it worse. Add desc after mss.

> +static void r8157_rx_vlan_tag(void *desc, struct sk_buff *skb)
> +{
> +	struct rx_desc_v2 *d = desc;
> +	u32 opts1 = le32_to_cpu(d->opts1);

And here you need to move the assignment into the body in order to
keep to reverse Christmas tree.

	Andrew

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH net-next v2 1/2] r8152: Add support for 5Gbit Link Speeds and EEE
  2026-03-17 18:07 ` [PATCH net-next v2 1/2] r8152: Add support for 5Gbit Link Speeds and EEE Birger Koblitz
  2026-03-19 16:29   ` Andrew Lunn
@ 2026-03-19 16:51   ` Simon Horman
  2026-03-20  5:29     ` Birger Koblitz
  2026-03-19 21:43   ` Aleksander Jan Bajkowski
  2 siblings, 1 reply; 17+ messages in thread
From: Simon Horman @ 2026-03-19 16:51 UTC (permalink / raw)
  To: mail
  Cc: Simon Horman, edumazet, linux-kernel, netdev, linux-usb, pabeni,
	kuba, andrew+netdev, davem

This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.

For local reproduction steps see https://netdev-ai.bots.linux.dev/ai-local.html
---
r8152: Add support for 5Gbit Link Speeds and EEE

The RTL8157 supports 5GBit Link speeds. This commit adds support for this
speed in the setup and setting/getting through ethtool, along with 5GBit
EEE functionality for setup and ethtool get/set methods.

> The RTL8157 supports 5GBit Link speeds. Add support for this speed
> in the setup and setting/getting through ethool. Also add 5GBit EEE.
                                          ^^^^^^
This isn't a bug, but there's a typo: 'ethool' should be 'ethtool'.

> diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
> index 3b6d4252d34c..bab8e10e5f99 100644
> --- a/drivers/net/usb/r8152.c
> +++ b/drivers/net/usb/r8152.c

[ ... ]

> @@ -6343,15 +6356,20 @@ static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex,
>  			r8152_mdio_write(tp, MII_CTRL1000, new1);
>  	}
>
> -	if (tp->support_2500full) {
> +	if (tp->support_2500full || tp->support_5000full) {
>  		orig = ocp_reg_read(tp, OCP_10GBT_CTRL);
> -		new1 = orig & ~MDIO_AN_10GBT_CTRL_ADV2_5G;
> +		new1 = orig & ~(MDIO_AN_10GBT_CTRL_ADV2_5G | MDIO_AN_10GBT_CTRL_ADV5G);
>
>  		if (advertising & RTL_ADVERTISED_2500_FULL) {
>  			new1 |= MDIO_AN_10GBT_CTRL_ADV2_5G;
>  			tp->ups_info.speed_duplex = NWAY_2500M_FULL;
>  		}
>
> +		if (advertising & RTL_ADVERTISED_5000_FULL) {
> +			new1 |= MDIO_AN_10GBT_CTRL_ADV5G;
> +			tp->ups_info.speed_duplex = NWAY_5000M_FULL;
> +		}
> +
>  		if (orig != new1)
>  			ocp_reg_write(tp, OCP_10GBT_CTRL, new1);
>  	}

Does r8156_ups_flags() handle the new NWAY_5000M_FULL value?

Looking at r8156_ups_flags() in drivers/net/usb/r8152.c, the function
switches on tp->ups_info.speed_duplex:

static u16 r8156_ups_flags(struct r8152 *tp)
{
	u16 ups_flags = 0;

	if (tp->ups_info.green)
		ups_flags |= UPS_FLAGS_EN_GREEN;

	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.flow_control)
		ups_flags |= UPS_FLAGS_EN_FLOW_CONTROL;

	if (tp->ups_info.eee_ckdiv)
		ups_flags |= UPS_FLAGS_EN_EEE_CKDIV;

	if (tp->ups_info._10m_ckdiv)
		ups_flags |= UPS_FLAGS_EN_10M_CKDIV;

	if (tp->ups_info.eee_cmod_lv)
		ups_flags |= UPS_FLAGS_EEE_CMOD_LV_EN;

	if (tp->ups_info._250m_ckdiv)
		ups_flags |= UPS_FLAGS_250M_CKDIV;

	switch (tp->ups_info.speed_duplex) {
	case FORCE_10M_HALF:
		ups_flags |= ups_flags_speed(0);
		break;
	case FORCE_10M_FULL:
		ups_flags |= ups_flags_speed(1);
		break;
	case FORCE_100M_HALF:
		ups_flags |= ups_flags_speed(2);
		break;
	case FORCE_100M_FULL:
		ups_flags |= ups_flags_speed(3);
		break;
	case NWAY_10M_HALF:
		ups_flags |= ups_flags_speed(4);
		break;
	case NWAY_10M_FULL:
		ups_flags |= ups_flags_speed(5);
		break;
	case NWAY_100M_HALF:
		ups_flags |= ups_flags_speed(6);
		break;
	case NWAY_100M_FULL:
		ups_flags |= ups_flags_speed(7);
		break;
	case NWAY_1000M_FULL:
		ups_flags |= ups_flags_speed(8);
		break;
	case NWAY_2500M_FULL:
		ups_flags |= ups_flags_speed(9);
		break;
	default:
		break;
	}

	return ups_flags;
}

When rtl8152_set_speed() sets tp->ups_info.speed_duplex = NWAY_5000M_FULL
and r8156_ups_en(enable=true) subsequently calls r8156_ups_flags(), the
switch falls through to the default case and no speed bits are set in the
UPS flags word.

Is the UPS power management configuration incorrect for 5Gbit link speeds
without a case for NWAY_5000M_FULL in r8156_ups_flags()?

This path is activated by the next commit in the series (58ba3b6c476d
'r8152: Add support for the RTL8157 hardware') which sets
support_5000full = 1.

[ ... ]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH net-next v2 2/2] r8152: Add support for the RTL8157 hardware
  2026-03-17 18:07 ` [PATCH net-next v2 2/2] r8152: Add support for the RTL8157 hardware Birger Koblitz
  2026-03-19 16:42   ` Andrew Lunn
@ 2026-03-19 16:51   ` Simon Horman
  2026-03-20  7:15     ` Birger Koblitz
  1 sibling, 1 reply; 17+ messages in thread
From: Simon Horman @ 2026-03-19 16:51 UTC (permalink / raw)
  To: mail
  Cc: Simon Horman, edumazet, linux-kernel, netdev, linux-usb, pabeni,
	kuba, andrew+netdev, davem

This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.

For local reproduction steps see https://netdev-ai.bots.linux.dev/ai-local.html
---
r8152: Add support for the RTL8157 hardware

The RTL8157 uses a different packet descriptor format compared to the
previous generation of chips. The commit adds support for the new format,
SRAM and ADV access interfaces, and consolidates RTL8156/RTL8156B/RTL8157
initialization into a single function.

> diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
> index bab8e10e5f99..05531ea43791 100644
> --- a/drivers/net/usb/r8152.c
> +++ b/drivers/net/usb/r8152.c

[ ... ]

> @@ -6151,15 +6562,24 @@ static void rtl8156_enable(struct r8152 *tp)
>  	u32 ocp_data;
>  	u16 speed;
>
> +	if (tp->version <= RTL_VER_16)
> +		return rtl_enable(tp);
> +
>  	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4);

Does this early return make the code after line 6581 unreachable for all
current versions? RTL_VER_16 has the value 17 in the enum (the highest
defined version), so 'tp->version <= RTL_VER_16' is always true for
VER_10, VER_11, VER_12, VER_13, VER_15, and VER_16 (all versions
assigned to use rtl8156_enable).

This skips several hardware configuration steps for existing RTL8156 and
RTL8156B devices that the old rtl8156_enable and rtl8156b_enable functions
performed:

1. PLA_MAC_PWR_CTRL4 IDLE_SPDWN_EN configuration (speed-dependent idle
   power management)
2. PLA_EEE_TXTWSYS configuration for VER_10/11 (EEE TX timer values)
3. USB_L1_CTRL L1 NYET HIRD configuration when USB speed is USB_SPEED_HIGH
4. USB_FW_TASK FC_PATCH_TASK clear/set cycle (firmware patch task toggle)

Before this patch, both rtl8156_enable (VER_10/11) and rtl8156b_enable
(VER_12/13/15) executed all of these operations unconditionally.

> @@ -6167,10 +6587,12 @@ static void rtl8156_enable(struct r8152 *tp)
>
>  	if (is_flow_control(speed))
>  		ocp_data |= IDLE_SPDWN_EN;
> +	else
> +		ocp_data &= ~IDLE_SPDWN_EN;
>
>  	ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, ocp_data);
>
> -	if (tp->version == RTL_VER_10 || tp->version == RTL_VER_11)
> +	if (tp->version <= RTL_VER_11)
>  		ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEE_TXTWSYS, 0x11);
>  	else
>  		ocp_write_word(tp, MCU_TYPE_PLA, 0xd4d4, 0);
> @@ -6183,12 +6605,9 @@ static void rtl8156_enable(struct r8152 *tp)
>  	ocp_byte_clr_bits(tp, MCU_TYPE_USB, USB_L1_CTRL, L1_NYET_HIRD_MASK);
>
>  	if (tp->udev->speed == USB_SPEED_HIGH) {
> -		u16 val = L1_NYET_HIRD_DEFAULT;
> -
>  		/* Bits [3:0] HIRD */
> -		ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_L1_CTRL);
> -		ocp_data &= ~L1_NYET_HIRD_MASK;
> -		ocp_data |= val & L1_NYET_HIRD_MASK;
> +		ocp_data = L1_NYET_HIRD_DEFAULT & L1_NYET_HIRD_MASK;
> +		ocp_byte_set_bits(tp, MCU_TYPE_USB, USB_L1_CTRL, ocp_data);
>  		ocp_write_byte(tp, MCU_TYPE_USB, USB_L1_CTRL, ocp_data);
>  	}

[ ... ]

> @@ -8252,25 +8725,27 @@ static int r8156b_init(struct r8152 *tp)
>  		}
>  	}
>
> -	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3);
> -	ocp_data &= ~PLA_MCU_SPDWN_EN;
> -	ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, ocp_data);
> +	if (tp->version != RTL_VER_16)
> +		ocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, PLA_MCU_SPDWN_EN);

Is ocp_byte_clr_bits() the correct function here? PLA_MCU_SPDWN_EN is
defined as BIT(14) (0x4000), which requires 16-bit access. ocp_byte_clr_bits()
performs an 8-bit read/modify/write via ocp_read_byte/ocp_write_byte,
accessing only bits 0-7 of the register. Bit 14 is outside the byte range.

All other call sites that manipulate PLA_MCU_SPDWN_EN in this file use
ocp_read_word/ocp_write_word or ocp_word_clr_bits for 16-bit access:

drivers/net/usb/r8152.c:rtl8156_down() {
    ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3);
    ocp_data |= PLA_MCU_SPDWN_EN;
    ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, ocp_data);
}

The old r8156_init code (and r8156b_init before consolidation) used
ocp_read_word/ocp_write_word.

This affects RTL_VER_12, RTL_VER_13, and RTL_VER_15 (RTL8156B) during
initialization, leaving the MCU speed-down feature incorrectly enabled.

[ ... ]

> @@ -8147,42 +8508,33 @@ static void r8157_hw_phy_cfg(struct r8152 *tp)
>  	rtl_phy_patch_request(tp, true, true);
>
>  	ret = r8153_phy_status(tp, 0);
> +	if (ret < 0)
> +		return;

Can this error check work correctly? r8153_phy_status() is declared as
returning u16:

drivers/net/usb/r8152.c:
static u16 r8153_phy_status(struct r8152 *tp, u16 desired)

but r8157_hw_phy_cfg() stores the result in 'int ret' and checks
'if (ret < 0)'. A u16 value assigned to int is always non-negative
(0-65535), so the condition can never be true.

drivers/net/usb/r8157_hw_phy_cfg() {
    int ret;
    ...
    ret = r8153_phy_status(tp, 0);
    if (ret < 0)  /* never true for u16 -> int */
        return;
    ...
    ret = r8153_phy_status(tp, PHY_STAT_LAN_ON);
    if (ret < 0)  /* never true for u16 -> int */
        return;
}

The other hw_phy_cfg functions (r8156_hw_phy_cfg, r8156b_hw_phy_cfg)
use 'u16 data' and don't attempt error handling on r8153_phy_status().

If the device becomes inaccessible during r8153_phy_status(), the function
continues to program PHY registers with potentially invalid values instead
of returning early.

[ ... ]

> @@ -8191,59 +8543,180 @@ static int r8156_init(struct r8152 *tp)
>
>  	ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_MISC_1);
>  	if (ocp_data & PCUT_STATUS) {

[ ... ]

> +	if (tp->version != RTL_VER_16)
> +		ocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, PLA_MCU_SPDWN_EN);

Same issue as above - is ocp_byte_clr_bits() the correct function for
clearing BIT(14)? PLA_MCU_SPDWN_EN is 0x4000, which exceeds the 8-bit range.

The bit clear operation will fail silently because the 8-bit value read by
ocp_byte_clr_bits() cannot represent bit 14. This leaves PLA_MCU_SPDWN_EN
set when it should be cleared for VER_10, VER_11, VER_12, VER_13, and
VER_15.

Should this be:
    ocp_word_clr_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, PLA_MCU_SPDWN_EN);

[ ... ]

> @@ -9541,6 +10056,7 @@ static void rtl_ops_init(struct r8152 *tp)
>  	case RTL_VER_12:
>  	case RTL_VER_13:
>  	case RTL_VER_15:
> +		ops->init		= r8156_init;
>  		ops->enable		= rtl8156_enable;
>  		ops->disable		= rtl8153_disable;

The ops->enable assignment changes from rtl8156b_enable to rtl8156_enable
for RTL_VER_12/13/15 (RTL8156B). Does the new rtl8156_enable provide the
same functionality?

As noted in the earlier issue, rtl8156_enable has an early return at line
6581 that causes it to skip the PLA_MAC_PWR_CTRL4, USB_L1_CTRL, and
FC_PATCH_TASK configuration for all current versions. The old
rtl8156b_enable performed these operations.

This could affect power management behavior, USB link stability at high
speed, and firmware flow-control configuration for RTL8156B devices.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH net-next v2 1/2] r8152: Add support for 5Gbit Link Speeds and EEE
  2026-03-19 16:29   ` Andrew Lunn
@ 2026-03-19 16:51     ` Birger Koblitz
  0 siblings, 0 replies; 17+ messages in thread
From: Birger Koblitz @ 2026-03-19 16:51 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, linux-usb, netdev, linux-kernel

On 19/03/2026 5:29 pm, Andrew Lunn wrote:
> On Tue, Mar 17, 2026 at 07:07:14PM +0100, Birger Koblitz wrote:
>> The RTL8157 supports 5GBit Link speeds. Add support for this speed
>> in the setup and setting/getting through ethool. Also add 5GBit EEE.
>> Add functionality for setup and ethtool get/set methods.
>>
>> Signed-off-by: Birger Koblitz <mail@birger-koblitz.de>
>> ---
>>   drivers/net/usb/r8152.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++---
>>   1 file changed, 53 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
>> index 3b6d4252d34c63ead8f11a120e212325a5f7d505..bab8e10e5f99afcb332e333c2739ed7509b03419 100644
>> --- a/drivers/net/usb/r8152.c
>> +++ b/drivers/net/usb/r8152.c
>> @@ -604,6 +604,7 @@ enum spd_duplex {
>>   	FORCE_100M_FULL,
>>   	FORCE_1000M_FULL,
>>   	NWAY_2500M_FULL,
>> +	NWAY_5000M_FULL,
>>   };
>>   
>>   /* OCP_ALDPS_CONFIG */
>> @@ -725,6 +726,7 @@ enum spd_duplex {
>>   #define BP4_SUPER_ONLY		0x1578	/* RTL_VER_04 only */
>>   
>>   enum rtl_register_content {
>> +	_5000bps	= BIT(12),
>>   	_2500bps	= BIT(10),
> 
> Any idea what bit 11 is for? There is not normally any speed between
> 2.5G and 5G.
No, I have no idea, and I puzzled about this, too, plus triple checked 
it. But this reflects a hardware register, hardware engineers sometimes 
leave bits out. _10000bps will be bit 14 for the RTL8159.

> 
>> @@ -9934,6 +9979,11 @@ static int rtl8152_probe_once(struct usb_interface *intf,
>>   		} else {
>>   			tp->speed = SPEED_1000;
>>   		}
>> +		if (tp->support_5000full &&
>> +		    tp->udev->speed >= USB_SPEED_SUPER) {
>> +			tp->speed = SPEED_5000;
>> +			tp->advertising |= RTL_ADVERTISED_5000_FULL;
>> +		}
> 
> Let me check i understand this.
> 
> ethtool supported will indicate 5G, independent of the USB speed? But
> it will only advertise 5G if the USB bus is USB 3.0 or higher, which
> can do 5G. The user can however use ethtool to advertise 5G, for USB
> 2.0?
I puzzled about this, too and then decided to leave it like this. The 
support for 5GBit is a hardware feature, so it is OK to state it is 
supported. But my tests with slower USB connections really show that it 
is better to rely on throttling the link speed itself, since flow 
control will do a rather bad job if the Ethernet connection can handle 
much more than the USB connection behind. However, if the user insists, 
they can advertise a higher speed.
> 
> I suppose the question is, are there any link partners which do 2.5G
> and/or 5G, but not 1G? I guess not.
That was my rationale, too.

Birger

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH net-next v2 2/2] r8152: Add support for the RTL8157 hardware
  2026-03-19 16:42   ` Andrew Lunn
@ 2026-03-19 17:27     ` Birger Koblitz
  0 siblings, 0 replies; 17+ messages in thread
From: Birger Koblitz @ 2026-03-19 17:27 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, linux-usb, netdev, linux-kernel

On 19/03/2026 5:42 pm, Andrew Lunn wrote:
>> +static int wait_cmd_ready(struct r8152 *tp, u16 cmd)
>> +{
>> +	int i, ret = 0;
>> +
>> +	for (i = 0; i < 10; i++) {
>> +		u16 ocp_data = ocp_read_word(tp, MCU_TYPE_USB, cmd);
>> +
>> +		if (!(ocp_data & ADV_CMD_BUSY))
>> +			break;
>> +		usleep_range(1000, 2000);
>> +	}
>> +
>> +	if (i == 10)
>> +		ret = -ETIMEDOUT;
>> +
>> +	return ret;
> 
> It is better practice to use one of the helpers from linux/iopoll.h.
Will do. I think poll_timeout_us should work nicely. Thanks for the pointer!

> 
>> -static int r8152_tx_csum(struct r8152 *tp, struct tx_desc *desc,
>> +static int r8152_tx_csum(struct r8152 *tp, void *d,
>>   			 struct sk_buff *skb, u32 len)
>>   {
>> +	struct rx_desc *desc = d;
>>   	u32 mss = skb_shinfo(skb)->gso_size;
>>   	u32 opts1, opts2 = 0;
>>   	int ret = TX_CSUM_SUCCESS;
> 
> Reversed Christmas tree is already messed up here, but please don't
> make it worse. Add desc after mss.
Will do.

> 
>> +static void r8157_rx_vlan_tag(void *desc, struct sk_buff *skb)
>> +{
>> +	struct rx_desc_v2 *d = desc;
>> +	u32 opts1 = le32_to_cpu(d->opts1);
> 
> And here you need to move the assignment into the body in order to
> keep to reverse Christmas tree.
Will do.

Thanks for your review, Andrew!

Birger

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH net-next v2 1/2] r8152: Add support for 5Gbit Link Speeds and EEE
  2026-03-17 18:07 ` [PATCH net-next v2 1/2] r8152: Add support for 5Gbit Link Speeds and EEE Birger Koblitz
  2026-03-19 16:29   ` Andrew Lunn
  2026-03-19 16:51   ` Simon Horman
@ 2026-03-19 21:43   ` Aleksander Jan Bajkowski
  2026-03-19 22:46     ` Andrew Lunn
  2 siblings, 1 reply; 17+ messages in thread
From: Aleksander Jan Bajkowski @ 2026-03-19 21:43 UTC (permalink / raw)
  To: Birger Koblitz, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni
  Cc: linux-usb, netdev, linux-kernel

Hi Birger,

W dniu 17.03.2026 o 19:07, Birger Koblitz pisze:
> The RTL8157 supports 5GBit Link speeds. Add support for this speed
> in the setup and setting/getting through ethool. Also add 5GBit EEE.
> Add functionality for setup and ethtool get/set methods.
>
> Signed-off-by: Birger Koblitz <mail@birger-koblitz.de>
> ---
>   drivers/net/usb/r8152.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++---
>   1 file changed, 53 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
> index 3b6d4252d34c63ead8f11a120e212325a5f7d505..bab8e10e5f99afcb332e333c2739ed7509b03419 100644
> --- a/drivers/net/usb/r8152.c
> +++ b/drivers/net/usb/r8152.c
> @@ -604,6 +604,7 @@ enum spd_duplex {
>   	FORCE_100M_FULL,
>   	FORCE_1000M_FULL,
>   	NWAY_2500M_FULL,
> +	NWAY_5000M_FULL,
>   };
>   
>   /* OCP_ALDPS_CONFIG */
> @@ -725,6 +726,7 @@ enum spd_duplex {
>   #define BP4_SUPER_ONLY		0x1578	/* RTL_VER_04 only */
>   
>   enum rtl_register_content {
> +	_5000bps	= BIT(12),

Based on other Realtek chips, I guess that BIT(11_ corresponds to 2500 Mbps
over two twisted pairs. Realtek calls this 5G Lite. Similarly, there are
2.5G Lite and 1G Lite, offering 1250 Mbps and 500 Mbps, respectively, over
two pairs of wires.


>   	_2500bps	= BIT(10),
>   	_1250bps	= BIT(9),
>   	_500bps		= BIT(8),
> @@ -738,6 +740,7 @@ enum rtl_register_content {
>   };
>   
>   #define is_speed_2500(_speed)	(((_speed) & (_2500bps | LINK_STATUS)) == (_2500bps | LINK_STATUS))
> +#define is_speed_5000(_speed)	(((_speed) & (_5000bps | LINK_STATUS)) == (_5000bps | LINK_STATUS))
>   #define is_flow_control(_speed)	(((_speed) & (_tx_flow | _rx_flow)) == (_tx_flow | _rx_flow))
>   
>   #define RTL8152_MAX_TX		4
> @@ -944,6 +947,7 @@ struct r8152 {
>   	unsigned int pipe_in, pipe_out, pipe_intr, pipe_ctrl_in, pipe_ctrl_out;
>   
>   	u32 support_2500full:1;
> +	u32 support_5000full:1;
>   	u32 lenovo_macpassthru:1;
>   	u32 dell_tb_rx_agg_bug:1;
>   	u16 ocp_base;
> @@ -1194,6 +1198,7 @@ enum tx_csum_stat {
>   #define RTL_ADVERTISED_1000_HALF		BIT(4)
>   #define RTL_ADVERTISED_1000_FULL		BIT(5)
>   #define RTL_ADVERTISED_2500_FULL		BIT(6)
> +#define RTL_ADVERTISED_5000_FULL		BIT(7)
>   
>   /* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
>    * The RTL chips use a 64 element hash table based on the Ethernet CRC.
> @@ -5400,6 +5405,11 @@ static void r8156_eee_en(struct r8152 *tp, bool enable)
>   	else
>   		config &= ~MDIO_EEE_2_5GT;
>   
> +	if (enable && (tp->eee_adv2 & MDIO_EEE_5GT))
> +		config |= MDIO_EEE_5GT;
> +	else
> +		config &= ~MDIO_EEE_5GT;
> +
>   	ocp_reg_write(tp, OCP_EEE_ADV2, config);
>   }
>   
> @@ -6298,6 +6308,9 @@ static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex,
>   
>   			if (tp->support_2500full)
>   				support |= RTL_ADVERTISED_2500_FULL;
> +
> +			if (tp->support_5000full)
> +				support |= RTL_ADVERTISED_5000_FULL;
>   		}
>   
>   		if (!(advertising & support))
> @@ -6343,15 +6356,20 @@ static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex,
>   				r8152_mdio_write(tp, MII_CTRL1000, new1);
>   		}
>   
> -		if (tp->support_2500full) {
> +		if (tp->support_2500full || tp->support_5000full) {
>   			orig = ocp_reg_read(tp, OCP_10GBT_CTRL);
> -			new1 = orig & ~MDIO_AN_10GBT_CTRL_ADV2_5G;
> +			new1 = orig & ~(MDIO_AN_10GBT_CTRL_ADV2_5G | MDIO_AN_10GBT_CTRL_ADV5G);
>   
>   			if (advertising & RTL_ADVERTISED_2500_FULL) {
>   				new1 |= MDIO_AN_10GBT_CTRL_ADV2_5G;
>   				tp->ups_info.speed_duplex = NWAY_2500M_FULL;
>   			}
>   
> +			if (advertising & RTL_ADVERTISED_5000_FULL) {
> +				new1 |= MDIO_AN_10GBT_CTRL_ADV5G;
> +				tp->ups_info.speed_duplex = NWAY_5000M_FULL;
> +			}
> +
>   			if (orig != new1)
>   				ocp_reg_write(tp, OCP_10GBT_CTRL, new1);
>   		}
> @@ -8780,6 +8798,9 @@ int rtl8152_get_link_ksettings(struct net_device *netdev,
>   	linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
>   			 cmd->link_modes.supported, tp->support_2500full);
>   
> +	linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
> +			 cmd->link_modes.supported, tp->support_5000full);
> +
>   	if (tp->support_2500full) {
>   		linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
>   				 cmd->link_modes.advertising,
> @@ -8793,6 +8814,19 @@ int rtl8152_get_link_ksettings(struct net_device *netdev,
>   			cmd->base.speed = SPEED_2500;
>   	}
>   
> +	if (tp->support_5000full) {
> +		linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
> +				 cmd->link_modes.advertising,
> +				 ocp_reg_read(tp, OCP_10GBT_CTRL) & MDIO_AN_10GBT_CTRL_ADV5G);
> +
> +		linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
> +				 cmd->link_modes.lp_advertising,
> +				 ocp_reg_read(tp, OCP_10GBT_STAT) & MDIO_AN_10GBT_STAT_LP5G);
> +
> +		if (is_speed_5000(rtl8152_get_speed(tp)))
> +			cmd->base.speed = SPEED_5000;
> +	}
> +
>   	mutex_unlock(&tp->control);
>   
>   	usb_autopm_put_interface(tp->intf);
> @@ -8840,6 +8874,10 @@ static int rtl8152_set_link_ksettings(struct net_device *dev,
>   		     cmd->link_modes.advertising))
>   		advertising |= RTL_ADVERTISED_2500_FULL;
>   
> +	if (test_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
> +		     cmd->link_modes.advertising))
> +		advertising |= RTL_ADVERTISED_5000_FULL;
> +
>   	mutex_lock(&tp->control);
>   
>   	ret = rtl8152_set_speed(tp, cmd->base.autoneg, cmd->base.speed,
> @@ -8957,7 +8995,7 @@ static int r8152_set_eee(struct r8152 *tp, struct ethtool_keee *eee)
>   
>   	tp->eee_en = eee->eee_enabled;
>   	tp->eee_adv = val;
> -	if (tp->support_2500full) {
> +	if (tp->support_2500full || tp->support_5000full) {
>   		val = linkmode_to_mii_eee_cap2_t(eee->advertised);
>   		tp->eee_adv2 = val;
>   	}
> @@ -8994,6 +9032,13 @@ static int r8153_get_eee(struct r8152 *tp, struct ethtool_keee *eee)
>   			linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, common);
>   	}
>   
> +	if (tp->support_5000full) {
> +		linkmode_set_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, eee->supported);
> +
> +		if (speed & _5000bps)
> +			linkmode_set_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, common);
> +	}
> +
>   	eee->eee_enabled = tp->eee_en;
>   
>   	if (speed & _1000bps)
> @@ -9934,6 +9979,11 @@ static int rtl8152_probe_once(struct usb_interface *intf,
>   		} else {
>   			tp->speed = SPEED_1000;
>   		}
> +		if (tp->support_5000full &&
> +		    tp->udev->speed >= USB_SPEED_SUPER) {
> +			tp->speed = SPEED_5000;
> +			tp->advertising |= RTL_ADVERTISED_5000_FULL;
> +		}
>   		tp->advertising |= RTL_ADVERTISED_1000_FULL;
>   	}
>   	tp->duplex = DUPLEX_FULL;


Best regards,
Aleksander


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH net-next v2 1/2] r8152: Add support for 5Gbit Link Speeds and EEE
  2026-03-19 21:43   ` Aleksander Jan Bajkowski
@ 2026-03-19 22:46     ` Andrew Lunn
  2026-03-19 23:12       ` Aleksander Jan Bajkowski
  0 siblings, 1 reply; 17+ messages in thread
From: Andrew Lunn @ 2026-03-19 22:46 UTC (permalink / raw)
  To: Aleksander Jan Bajkowski
  Cc: Birger Koblitz, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, linux-usb, netdev, linux-kernel

> > @@ -604,6 +604,7 @@ enum spd_duplex {
> >   	FORCE_100M_FULL,
> >   	FORCE_1000M_FULL,
> >   	NWAY_2500M_FULL,
> > +	NWAY_5000M_FULL,
> >   };
> >   /* OCP_ALDPS_CONFIG */
> > @@ -725,6 +726,7 @@ enum spd_duplex {
> >   #define BP4_SUPER_ONLY		0x1578	/* RTL_VER_04 only */
> >   enum rtl_register_content {
> > +	_5000bps	= BIT(12),
> 
> Based on other Realtek chips, I guess that BIT(11_ corresponds to 2500 Mbps
> over two twisted pairs. Realtek calls this 5G Lite. Similarly, there are
> 2.5G Lite and 1G Lite, offering 1250 Mbps and 500 Mbps, respectively, over
> two pairs of wires.

Oh, that is different. Normally for a -T2 link, you double the clock
frequency, so you keep the normal bandwidth. But you are saying it
does 500Base-T2, 1250Base-T2, 2500Base-T2?

Can it select these modes on its own, if the link partner is another
Realtek device? Many 1G PHYs will detect if a pair is broken and
downshift to 100Mbps, which only require two working pairs. But this
device has the option of downshifting to 500M.

	Andrew

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH net-next v2 1/2] r8152: Add support for 5Gbit Link Speeds and EEE
  2026-03-19 22:46     ` Andrew Lunn
@ 2026-03-19 23:12       ` Aleksander Jan Bajkowski
  0 siblings, 0 replies; 17+ messages in thread
From: Aleksander Jan Bajkowski @ 2026-03-19 23:12 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Birger Koblitz, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, linux-usb, netdev, linux-kernel

Hi Andrew,

On 19/03/2026 23:46, Andrew Lunn wrote:
>>> @@ -604,6 +604,7 @@ enum spd_duplex {
>>>    	FORCE_100M_FULL,
>>>    	FORCE_1000M_FULL,
>>>    	NWAY_2500M_FULL,
>>> +	NWAY_5000M_FULL,
>>>    };
>>>    /* OCP_ALDPS_CONFIG */
>>> @@ -725,6 +726,7 @@ enum spd_duplex {
>>>    #define BP4_SUPER_ONLY		0x1578	/* RTL_VER_04 only */
>>>    enum rtl_register_content {
>>> +	_5000bps	= BIT(12),
>> Based on other Realtek chips, I guess that BIT(11_ corresponds to 2500 Mbps
>> over two twisted pairs. Realtek calls this 5G Lite. Similarly, there are
>> 2.5G Lite and 1G Lite, offering 1250 Mbps and 500 Mbps, respectively, over
>> two pairs of wires.
> Oh, that is different. Normally for a -T2 link, you double the clock
> frequency, so you keep the normal bandwidth. But you are saying it
> does 500Base-T2, 1250Base-T2, 2500Base-T2?

It works exactly like you describe. It’s described in the RTL8156B
datasheet[1] if your interested. To be honest, I’ve never used Lite Mode.
I think it’s disabled by default in the driver.

1. https://www.lcsc.com/datasheet/C41376388.pdf

>
> Can it select these modes on its own, if the link partner is another
> Realtek device? Many 1G PHYs will detect if a pair is broken and
> downshift to 100Mbps, which only require two working pairs. But this
> device has the option of downshifting to 500M.
>
> 	Andrew


Best regards,
Aleksander


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH net-next v2 1/2] r8152: Add support for 5Gbit Link Speeds and EEE
  2026-03-19 16:51   ` Simon Horman
@ 2026-03-20  5:29     ` Birger Koblitz
  2026-03-20  8:28       ` Simon Horman
  0 siblings, 1 reply; 17+ messages in thread
From: Birger Koblitz @ 2026-03-20  5:29 UTC (permalink / raw)
  To: Simon Horman
  Cc: edumazet, linux-kernel, netdev, linux-usb, pabeni, kuba,
	andrew+netdev, davem

Hi Simon, thanks a lot for reviewing this patch!

On 19/03/2026 5:51 pm, Simon Horman wrote:
>> The RTL8157 supports 5GBit Link speeds. Add support for this speed
>> in the setup and setting/getting through ethool. Also add 5GBit EEE.
>                                            ^^^^^^
> This isn't a bug, but there's a typo: 'ethool' should be 'ethtool'.
Will be fixed in v3.

> When rtl8152_set_speed() sets tp->ups_info.speed_duplex = NWAY_5000M_FULL
> and r8156_ups_en(enable=true) subsequently calls r8156_ups_flags(), the
> switch falls through to the default case and no speed bits are set in the
> UPS flags word.
Yes, this analysis is correct.

> 
> Is the UPS power management configuration incorrect for 5Gbit link speeds
> without a case for NWAY_5000M_FULL in r8156_ups_flags()?
The out-of-tree driver also does not set any flags in USB_UPS_FLAGS in 
the 5000M case. Maybe this is an oversight in that driver, but according 
to my tests, the power management works. In any case, I would not be 
able to guess the correct register value with any confidence for the 
NWAY_5000M_FULL case: the bits are different from the speed bits in 
PLA_PHYSTATUS. The RTL8157 also has other differences in USB power 
management compared to previous generations, such as introducing 
register USB_U2P3_V2_CTRL. So, to the best of my knowledge, the proposed 
patch is correct.

> 
> This path is activated by the next commit in the series (58ba3b6c476d
> 'r8152: Add support for the RTL8157 hardware') which sets
> support_5000full = 1.
> 
> [ ... ]


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH net-next v2 2/2] r8152: Add support for the RTL8157 hardware
  2026-03-19 16:51   ` Simon Horman
@ 2026-03-20  7:15     ` Birger Koblitz
  0 siblings, 0 replies; 17+ messages in thread
From: Birger Koblitz @ 2026-03-20  7:15 UTC (permalink / raw)
  To: Simon Horman
  Cc: edumazet, linux-kernel, netdev, linux-usb, pabeni, kuba,
	andrew+netdev, davem

On 19/03/2026 5:51 pm, Simon Horman wrote:
> This is an AI-generated review of your patch. The human sending this
> email has considered the AI review valid, or at least plausible.
> 
> For local reproduction steps see https://netdev-ai.bots.linux.dev/ai-local.html
> ---
> r8152: Add support for the RTL8157 hardware
> 
> The RTL8157 uses a different packet descriptor format compared to the
> previous generation of chips. The commit adds support for the new format,
> SRAM and ADV access interfaces, and consolidates RTL8156/RTL8156B/RTL8157
> initialization into a single function.
> 
>> diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
>> index bab8e10e5f99..05531ea43791 100644
>> --- a/drivers/net/usb/r8152.c
>> +++ b/drivers/net/usb/r8152.c
> 
> [ ... ]
> 
>> @@ -6151,15 +6562,24 @@ static void rtl8156_enable(struct r8152 *tp)
>>   	u32 ocp_data;
>>   	u16 speed;
>>
>> +	if (tp->version <= RTL_VER_16)
>> +		return rtl_enable(tp);
>> +
>>   	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4);
> 
The comparison operation is indeed wrong, it should be
   tp->version >= RTL_VER_16
Note that RTL_VER_17 will be used for the RTL8159, and the enable 
functions for these chips are identical, so we are already using >= here.

> Before this patch, both rtl8156_enable (VER_10/11) and rtl8156b_enable
> (VER_12/13/15) executed all of these operations unconditionally.
Indeed, this will be again the case with the correction to
tp->version >= 16

I also verified that the new enable() function for the RTL8157 as found 
in the out-of-tree driver is indeed as short as implemented by the early 
return from rtl8156_enable() function, here.

This will be fixed in v3.

>> -	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3);
>> -	ocp_data &= ~PLA_MCU_SPDWN_EN;
>> -	ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, ocp_data);
>> +	if (tp->version != RTL_VER_16)
>> +		ocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, PLA_MCU_SPDWN_EN);
> 
> Is ocp_byte_clr_bits() the correct function here? PLA_MCU_SPDWN_EN is
> defined as BIT(14) (0x4000), which requires 16-bit access. ocp_byte_clr_bits()
> performs an 8-bit read/modify/write via ocp_read_byte/ocp_write_byte,
> accessing only bits 0-7 of the register. Bit 14 is outside the byte range.
Indeed, this is wrong, it should be ocp_word_clr_bits. Will be fixed in v3.

> The other hw_phy_cfg functions (r8156_hw_phy_cfg, r8156b_hw_phy_cfg)
> use 'u16 data' and don't attempt error handling on r8153_phy_status().
The analysis is correct and the code will not correctly handle errors.
I will use the same approach as in the other hw_phy_cfg functions and 
not attempt error handling. Will be fixed in v3.

> 
> If the device becomes inaccessible during r8153_phy_status(), the function
> continues to program PHY registers with potentially invalid values instead
> of returning early.
The driver uses a different approach to error handling. Once the device 
becomes inaccessible, this state is detected and the device reset.

> 
> [ ... ]
> 
>> @@ -8191,59 +8543,180 @@ static int r8156_init(struct r8152 *tp)
>>
>>   	ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_MISC_1);
>>   	if (ocp_data & PCUT_STATUS) {
> 
> [ ... ]
> 
>> +	if (tp->version != RTL_VER_16)
>> +		ocp_byte_clr_bits(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, PLA_MCU_SPDWN_EN);
> 
> Same issue as above - is ocp_byte_clr_bits() the correct function for
> clearing BIT(14)? PLA_MCU_SPDWN_EN is 0x4000, which exceeds the 8-bit range.
This is the same passage as above, found a second time by the AI. Will 
be fixed in v3.

>> @@ -9541,6 +10056,7 @@ static void rtl_ops_init(struct r8152 *tp)
>>   	case RTL_VER_12:
>>   	case RTL_VER_13:
>>   	case RTL_VER_15:
>> +		ops->init		= r8156_init;
>>   		ops->enable		= rtl8156_enable;
>>   		ops->disable		= rtl8153_disable;
> 
> The ops->enable assignment changes from rtl8156b_enable to rtl8156_enable
> for RTL_VER_12/13/15 (RTL8156B). Does the new rtl8156_enable provide the
> same functionality?
> 
> As noted in the earlier issue, rtl8156_enable has an early return at line
> 6581 that causes it to skip the PLA_MAC_PWR_CTRL4, USB_L1_CTRL, and
> FC_PATCH_TASK configuration for all current versions. The old
> rtl8156b_enable performed these operations.
This will be fixed with the correct comparison in rtl8156_enable as 
mentioned before, for that function. The function will then provide the 
same functionality as before for RTL_VER_12/13/15, so this will be fixed 
in v3.

Birger

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH net-next v2 1/2] r8152: Add support for 5Gbit Link Speeds and EEE
  2026-03-20  5:29     ` Birger Koblitz
@ 2026-03-20  8:28       ` Simon Horman
  0 siblings, 0 replies; 17+ messages in thread
From: Simon Horman @ 2026-03-20  8:28 UTC (permalink / raw)
  To: Birger Koblitz
  Cc: edumazet, linux-kernel, netdev, linux-usb, pabeni, kuba,
	andrew+netdev, davem

On Fri, Mar 20, 2026 at 06:29:20AM +0100, Birger Koblitz wrote:
> Hi Simon, thanks a lot for reviewing this patch!

...

> > Is the UPS power management configuration incorrect for 5Gbit link speeds
> > without a case for NWAY_5000M_FULL in r8156_ups_flags()?
> The out-of-tree driver also does not set any flags in USB_UPS_FLAGS in the
> 5000M case. Maybe this is an oversight in that driver, but according to my
> tests, the power management works. In any case, I would not be able to guess
> the correct register value with any confidence for the NWAY_5000M_FULL case:
> the bits are different from the speed bits in PLA_PHYSTATUS. The RTL8157
> also has other differences in USB power management compared to previous
> generations, such as introducing register USB_U2P3_V2_CTRL. So, to the best
> of my knowledge, the proposed patch is correct.

Thanks for the clarification.

Perhaps someone can provide insight here. But in lieu of that
I agree with your approach.

> 
> > 
> > This path is activated by the next commit in the series (58ba3b6c476d
> > 'r8152: Add support for the RTL8157 hardware') which sets
> > support_5000full = 1.
> > 
> > [ ... ]
> 

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2026-03-20  8:28 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-17 18:07 [PATCH net-next v2 0/2] r8152: Add support for the RTL8157 5Gbit USB Ethernet chip Birger Koblitz
2026-03-17 18:07 ` [PATCH net-next v2 1/2] r8152: Add support for 5Gbit Link Speeds and EEE Birger Koblitz
2026-03-19 16:29   ` Andrew Lunn
2026-03-19 16:51     ` Birger Koblitz
2026-03-19 16:51   ` Simon Horman
2026-03-20  5:29     ` Birger Koblitz
2026-03-20  8:28       ` Simon Horman
2026-03-19 21:43   ` Aleksander Jan Bajkowski
2026-03-19 22:46     ` Andrew Lunn
2026-03-19 23:12       ` Aleksander Jan Bajkowski
2026-03-17 18:07 ` [PATCH net-next v2 2/2] r8152: Add support for the RTL8157 hardware Birger Koblitz
2026-03-19 16:42   ` Andrew Lunn
2026-03-19 17:27     ` Birger Koblitz
2026-03-19 16:51   ` Simon Horman
2026-03-20  7:15     ` Birger Koblitz
2026-03-19 15:53 ` [PATCH net-next v2 0/2] r8152: Add support for the RTL8157 5Gbit USB Ethernet chip Andrew Lunn
2026-03-19 16:31   ` Birger Koblitz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox