Index | Thread | Search

From:
Kirill A. Korinsky <kirill@korins.ky>
Subject:
sys/ure: add support of RTL8159
To:
OpenBSD tech <tech@openbsd.org>, Kevin Lo <kevlo@openbsd.org>
Date:
Mon, 05 Oct 2026 13:20:58 +0200

Download raw body.

Thread
  • Kirill A. Korinsky:

    sys/ure: add support of RTL8159

Kevin, tech@,

this is stright forward implementation of support of RTL8159 which reuses
RTL8157 logic and claim support of 10Gb PHY.

Tested on Ocnvlia RTL8159 with direct connect to USW Flex 2.5G 8 PoE, it
claims on OpenBSD side:

    media: Ethernet autoselect (10GbaseT full-duplex)

and I see 10Gb connection in Unifi UI as well.

But I haven't got the second 10Gb NIC here, so that speed is untested.

Anyway, Linux folks claimed that 10Gb PHY requires a firmware which is
missed at linux-firmware, but I found some extractor
https://gitlab.com/koblitz-rtlnic/rtlnic_fw
with very unclear license policy.

Thus, adding firmware to ure brings more complexity which I avoided.

Notable to say that this linux patch series was very helpful with
explanation how that chip should be implemented:
https://patchew.org/linux/20260505-rtl8159._5Fnet._5Fnext-v4-0-1a648a9c4d8d@birger-koblitz.de/

Ok?

Index: sys/dev/usb/if_ure.c
===================================================================
RCS file: /home/cvs/src/sys/dev/usb/if_ure.c,v
diff -u -p -r1.37 if_ure.c
--- sys/dev/usb/if_ure.c	4 Jun 2025 00:06:17 -0000	1.37
+++ sys/dev/usb/if_ure.c	1 Oct 2026 20:55:39 -0000
@@ -120,6 +120,7 @@ const struct usb_devno ure_devs[] = {
 	{ USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8153 },
 	{ USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8156 },
 	{ USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8157 },
+	{ USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8159 },
 	{ USB_VENDOR_SAMSUNG2, USB_PRODUCT_SAMSUNG2_RTL8153 },
 	{ USB_VENDOR_TOSHIBA, USB_PRODUCT_TOSHIBA_RTL8153B },
 	{ USB_VENDOR_TPLINK, USB_PRODUCT_TPLINK_EU300 },
@@ -602,21 +603,22 @@ ure_ifmedia_init(struct ifnet *ifp)
 	ure_write_1(sc, URE_PLA_CRWECR, URE_MCU_TYPE_PLA, URE_CRWECR_NORAML);
 
 	if (!(sc->ure_flags & URE_FLAG_8152)) {
-		if (sc->ure_flags & (URE_FLAG_8156B | URE_FLAG_8157))
+		if (sc->ure_flags &
+		    (URE_FLAG_8156B | URE_FLAG_8157 | URE_FLAG_8159))
 			URE_CLRBIT_2(sc, URE_USB_RX_AGGR_NUM, URE_MCU_TYPE_USB,
 			    URE_RX_AGGR_NUM_MASK);
 
 		reg = sc->ure_rxbufsz - URE_FRAMELEN(ifp->if_mtu);
-		if (sc->ure_flags & URE_FLAG_8157)
+		if (sc->ure_flags & (URE_FLAG_8157 | URE_FLAG_8159))
 			reg -= sizeof(struct ure_rxpkt_v2) + URE_8157_BUF_ALIGN;
 		else
 			reg -= sizeof(struct ure_rxpkt) + URE_RX_BUF_ALIGN;
 
 		if (sc->ure_flags &
 		    (URE_FLAG_8153B | URE_FLAG_8156 | URE_FLAG_8156B |
-		    URE_FLAG_8157)) {
+		    URE_FLAG_8157 | URE_FLAG_8159)) {
 			ure_write_2(sc, URE_USB_RX_EARLY_SIZE, URE_MCU_TYPE_USB,
-			    (sc->ure_flags & URE_FLAG_8157) ?
+			    (sc->ure_flags & (URE_FLAG_8157 | URE_FLAG_8159)) ?
 			    reg / URE_8157_BUF_ALIGN : reg / URE_RX_BUF_ALIGN);
 
 			ure_write_2(sc, URE_USB_RX_EARLY_AGG, URE_MCU_TYPE_USB,
@@ -672,7 +674,8 @@ ure_ifmedia_init(struct ifnet *ifp)
 	URE_SETBIT_1(sc, URE_PLA_CR, URE_MCU_TYPE_PLA, URE_CR_RE | URE_CR_TE);
 
 	if (sc->ure_flags &
-	    (URE_FLAG_8153B | URE_FLAG_8156 | URE_FLAG_8156B | URE_FLAG_8157)) {
+	    (URE_FLAG_8153B | URE_FLAG_8156 | URE_FLAG_8156B | URE_FLAG_8157 |
+	    URE_FLAG_8159)) {
 		ure_write_1(sc, URE_USB_UPT_RXDMA_OWN, URE_MCU_TYPE_USB,
 		    URE_OWN_UPDATE | URE_OWN_CLEAR);
 	}
@@ -688,7 +691,8 @@ ure_ifmedia_upd(struct ifnet *ifp)
 	struct ifmedia		*ifm = &sc->ure_ifmedia;
 	int			anar, gig, err, reg;
 
-	if (sc->ure_flags & (URE_FLAG_8156 | URE_FLAG_8156B | URE_FLAG_8157)) {
+	if (sc->ure_flags & (URE_FLAG_8156 | URE_FLAG_8156B | URE_FLAG_8157 |
+	    URE_FLAG_8159)) {
 		if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
 			return (EINVAL);
 
@@ -698,8 +702,10 @@ ure_ifmedia_upd(struct ifnet *ifp)
 				return (EINVAL);
 			reg &= ~URE_ADV_2500TFDX;
 		}
-		if (sc->ure_flags & URE_FLAG_8157)
+		if (sc->ure_flags & (URE_FLAG_8157 | URE_FLAG_8159))
 			reg &= ~URE_ADV_5000TFDX;
+		if (sc->ure_flags & URE_FLAG_8159)
+			reg &= ~URE_ADV_10000TFDX;
 
 		anar = ANAR_TX_FD | ANAR_TX | ANAR_10_FD | ANAR_10;
 		gig = GTCR_ADV_1000TFDX | GTCR_ADV_1000THDX;
@@ -708,8 +714,15 @@ ure_ifmedia_upd(struct ifnet *ifp)
 		case IFM_AUTO:
 			if (!(sc->ure_chip & URE_CHIP_VER_7420))
 				reg |= URE_ADV_2500TFDX;
-			if (sc->ure_flags & URE_FLAG_8157)
+			if (sc->ure_flags & (URE_FLAG_8157 | URE_FLAG_8159))
 				reg |= URE_ADV_5000TFDX;
+			if (sc->ure_flags & URE_FLAG_8159)
+				reg |= URE_ADV_10000TFDX;
+			break;
+		case IFM_10G_T:
+			reg |= URE_ADV_2500TFDX | URE_ADV_5000TFDX |
+			    URE_ADV_10000TFDX;
+			ifp->if_baudrate = IF_Gbps(10);
 			break;
 		case IFM_5000_T:
 			reg |= URE_ADV_2500TFDX | URE_ADV_5000TFDX;
@@ -769,7 +782,8 @@ ure_ifmedia_sts(struct ifnet *ifp, struc
 	struct mii_data		*mii = &sc->ure_mii;
 	uint16_t		status = 0;
 
-	if (sc->ure_flags & (URE_FLAG_8156 | URE_FLAG_8156B | URE_FLAG_8157)) {
+	if (sc->ure_flags & (URE_FLAG_8156 | URE_FLAG_8156B | URE_FLAG_8157 |
+	    URE_FLAG_8159)) {
 		ifmr->ifm_status = IFM_AVALID;
 		if (ure_get_link_status(sc)) {
 			ifmr->ifm_status |= IFM_ACTIVE;
@@ -778,7 +792,8 @@ ure_ifmedia_sts(struct ifnet *ifp, struc
 			    URE_MCU_TYPE_PLA);
 			if ((status & URE_PHYSTATUS_FDX) ||
 			    (status & URE_PHYSTATUS_2500MBPS) ||
-			    (status & URE_PHYSTATUS_5000MBPS))
+			    (status & URE_PHYSTATUS_5000MBPS) ||
+			    (status & URE_PHYSTATUS_10000MBPS))
 				ifmr->ifm_active |= IFM_FDX;
 			else
 				ifmr->ifm_active |= IFM_HDX;
@@ -792,6 +807,8 @@ ure_ifmedia_sts(struct ifnet *ifp, struc
 				ifmr->ifm_active |= IFM_2500_T;
 			else if (status & URE_PHYSTATUS_5000MBPS)
 				ifmr->ifm_active |= IFM_5000_T;
+			else if (status & URE_PHYSTATUS_10000MBPS)
+				ifmr->ifm_active |= IFM_10G_T;
 		}
 		return;
 	}
@@ -817,11 +834,16 @@ ure_add_media_types(struct ure_softc *sc
 		ifmedia_add(&sc->ure_ifmedia, IFM_ETHER | IFM_2500_T | IFM_FDX,
 		    0, NULL);
 	}
-	if (sc->ure_flags & URE_FLAG_8157) {
+	if (sc->ure_flags & (URE_FLAG_8157 | URE_FLAG_8159)) {
 		ifmedia_add(&sc->ure_ifmedia, IFM_ETHER | IFM_5000_T, 0, NULL);
 		ifmedia_add(&sc->ure_ifmedia, IFM_ETHER | IFM_5000_T | IFM_FDX,
 		    0, NULL);
 	}
+	if (sc->ure_flags & URE_FLAG_8159) {
+		ifmedia_add(&sc->ure_ifmedia, IFM_ETHER | IFM_10G_T, 0, NULL);
+		ifmedia_add(&sc->ure_ifmedia, IFM_ETHER | IFM_10G_T | IFM_FDX,
+		    0, NULL);
+	}
 }
 
 void
@@ -916,7 +938,8 @@ ure_rxvlan(struct ure_softc *sc)
 	struct ifnet	*ifp = &sc->ure_ac.ac_if;
 	uint16_t	reg;
 
-	if (sc->ure_flags & (URE_FLAG_8156 | URE_FLAG_8156B | URE_FLAG_8157)) {
+	if (sc->ure_flags & (URE_FLAG_8156 | URE_FLAG_8156B | URE_FLAG_8157 |
+	    URE_FLAG_8159)) {
 		reg = ure_read_2(sc, URE_PLA_RCR1, URE_MCU_TYPE_PLA);
 		reg &= ~(URE_INNER_VLAN | URE_OUTER_VLAN);
 		if (ifp->if_capabilities & IFCAP_VLAN_HWTAGGING)
@@ -936,7 +959,7 @@ ure_reset(struct ure_softc *sc)
 {
 	int	i;
 
-	if (sc->ure_flags & URE_FLAG_8157)
+	if (sc->ure_flags & (URE_FLAG_8157 | URE_FLAG_8159))
 		URE_CLRBIT_1(sc, URE_PLA_CR, URE_MCU_TYPE_PLA,
 		    URE_CR_TE | URE_CR_RE);
 	else if (sc->ure_flags & URE_FLAG_8156) {
@@ -1118,7 +1141,7 @@ ure_start(struct ifnet *ifp)
 
 		mlen = m->m_pkthdr.len;
 
-		descsize = (sc->ure_flags & URE_FLAG_8157) ?
+		descsize = (sc->ure_flags & (URE_FLAG_8157 | URE_FLAG_8159)) ?
 		    sizeof(struct ure_txpkt_v2) : sizeof(struct ure_txpkt);
 		/* Discard packet larger than buffer. */
 		if (mlen + descsize >= c->uc_bufmax) {
@@ -1133,7 +1156,7 @@ ure_start(struct ifnet *ifp)
 		 * continue.
 		 */
 		new_buflen = roundup(c->uc_buflen,
-		    (sc->ure_flags & URE_FLAG_8157) ?
+		    (sc->ure_flags & (URE_FLAG_8157 | URE_FLAG_8159)) ?
 		    URE_8157_BUF_ALIGN : URE_TX_BUF_ALIGN);
 		if (new_buflen + descsize + mlen >= c->uc_bufmax) {
 			ifq_deq_rollback(&ifp->if_snd, m);
@@ -1665,8 +1688,10 @@ ure_rtl8157_init(struct ure_softc *sc)
 	    reg | URE_POLL_LINK_CHG);
 
 	/* Enable Rx aggregation. */
-	URE_CLRBIT_2(sc, URE_USB_USB_CTRL, URE_MCU_TYPE_USB,
-	    URE_RX_AGG_DISABLE | 0x0400);
+	reg = URE_RX_AGG_DISABLE | URE_RX_DESC_16B;
+	if (sc->ure_flags & URE_FLAG_8159)
+		reg |= URE_RX_END_TRANSFER_EN;
+	URE_CLRBIT_2(sc, URE_USB_USB_CTRL, URE_MCU_TYPE_USB, reg);
 
 	/*  Disable Rx zero len. */
 	URE_OCP_CMD_CLRBIT(sc, 0x2300, URE_CMD_TYPE_BMU, 0x00000008);
@@ -1777,6 +1802,7 @@ ure_rtl8153_nic_reset(struct ure_softc *
 	case URE_FLAG_8156:
 	case URE_FLAG_8156B:
 	case URE_FLAG_8157:
+	case URE_FLAG_8159:
 		URE_CLRBIT_2(sc, URE_USB_LPM_CONFIG, URE_MCU_TYPE_USB,
 		    LPM_U1U2_EN);
 		break;
@@ -1809,7 +1835,8 @@ ure_rtl8153_nic_reset(struct ure_softc *
 	URE_CLRBIT_2(sc, URE_PLA_SFF_STS_7, URE_MCU_TYPE_PLA, URE_MCU_BORW_EN);
 
 	if (!(sc->ure_flags &
-	    (URE_FLAG_8156 | URE_FLAG_8156B | URE_FLAG_8157))) {
+	    (URE_FLAG_8156 | URE_FLAG_8156B | URE_FLAG_8157 |
+	    URE_FLAG_8159))) {
 		for (i = 0; i < URE_TIMEOUT; i++) {
 			if (ure_read_1(sc, URE_PLA_OOB_CTRL, URE_MCU_TYPE_PLA) &
 			    URE_LINK_LIST_READY)
@@ -1841,9 +1868,11 @@ ure_rtl8153_nic_reset(struct ure_softc *
 	ure_write_2(sc, URE_PLA_RMS, URE_MCU_TYPE_PLA,
 	    URE_FRAMELEN(ifp->if_mtu));
 	ure_write_1(sc, URE_PLA_MTPS, URE_MCU_TYPE_PLA,
-	    (sc->ure_flags & URE_FLAG_8157) ? MTPS_MAX : MTPS_JUMBO);
+	    (sc->ure_flags & (URE_FLAG_8157 | URE_FLAG_8159)) ?
+	    MTPS_MAX : MTPS_JUMBO);
 
-	if (sc->ure_flags & (URE_FLAG_8156 | URE_FLAG_8156B | URE_FLAG_8157)) {
+	if (sc->ure_flags & (URE_FLAG_8156 | URE_FLAG_8156B | URE_FLAG_8157 |
+	    URE_FLAG_8159)) {
 		ure_write_2(sc, URE_PLA_RX_FIFO_FULL, URE_MCU_TYPE_PLA,
 		    (sc->ure_flags & URE_FLAG_8156) ? 1024 : 512);
 		ure_write_2(sc, URE_PLA_RX_FIFO_EMPTY, URE_MCU_TYPE_PLA,
@@ -1866,7 +1895,7 @@ ure_rtl8153_nic_reset(struct ure_softc *
 		URE_CLRBIT_2(sc, URE_PLA_MAC_PWR_CTRL3, URE_MCU_TYPE_PLA,
 		    URE_PLA_MCU_SPDWN_EN);
 
-		if (!(sc->ure_flags & URE_FLAG_8157))
+		if (!(sc->ure_flags & (URE_FLAG_8157 | URE_FLAG_8159)))
 			URE_CLRBIT_2(sc, URE_USB_SPEED_OPTION, URE_MCU_TYPE_USB,
 			    URE_RG_PWRDN_EN | URE_ALL_SPEED_OFF);
 
@@ -1909,7 +1938,7 @@ ure_rtl8153_nic_reset(struct ure_softc *
 	ure_phy_write(sc, URE_OCP_POWER_CFG,
 	    ure_phy_read(sc, URE_OCP_POWER_CFG) | URE_EN_ALDPS);
 
-	if (sc->ure_flags & URE_FLAG_8157) {
+	if (sc->ure_flags & (URE_FLAG_8157 | URE_FLAG_8159)) {
 		/* Clear SDR. */
 		URE_SETBIT_1(sc, 0xd378, URE_MCU_TYPE_USB, 0x0080);
 		URE_CLRBIT_2(sc, 0xcd06, URE_MCU_TYPE_USB, 0x8000);
@@ -1923,7 +1952,7 @@ ure_rtl8153_nic_reset(struct ure_softc *
 		if (sc->ure_udev->speed == USB_SPEED_SUPER)
 			URE_SETBIT_2(sc, URE_USB_LPM_CONFIG, URE_MCU_TYPE_USB,
 			    LPM_U1U2_EN);
-	} else if (!(sc->ure_flags & URE_FLAG_8157)) {
+	} else if (!(sc->ure_flags & (URE_FLAG_8157 | URE_FLAG_8159))) {
 		memset(u1u2, 0xff, sizeof(u1u2));
 		ure_write_mem(sc, URE_USB_TOLERANCE, URE_BYTE_EN_SIX_BYTES,
 		    u1u2, sizeof(u1u2));
@@ -1989,7 +2018,7 @@ ure_reset_bmu(struct ure_softc *sc)
 {
 	uint8_t	reg;
 
-	if (sc->ure_flags & URE_FLAG_8157) {
+	if (sc->ure_flags & (URE_FLAG_8157 | URE_FLAG_8159)) {
 		URE_OCP_CMD_SETBIT(sc, 0x2350, URE_CMD_TYPE_BMU, 0x00000002);
 		URE_OCP_CMD_SETBIT(sc, 0x2360, URE_CMD_TYPE_BMU, 0x00000001);
 		URE_OCP_CMD_SETBIT(sc, 0x2350, URE_CMD_TYPE_BMU, 0x00000001);
@@ -2009,7 +2038,8 @@ void
 ure_disable_teredo(struct ure_softc *sc)
 {
 	if (sc->ure_flags &
-	    (URE_FLAG_8153B | URE_FLAG_8156 | URE_FLAG_8156B | URE_FLAG_8157))
+	    (URE_FLAG_8153B | URE_FLAG_8156 | URE_FLAG_8156B | URE_FLAG_8157 |
+	    URE_FLAG_8159))
 		ure_write_1(sc, URE_PLA_TEREDO_CFG, URE_MCU_TYPE_PLA, 0xff);
 	else {
 		URE_CLRBIT_2(sc, URE_PLA_TEREDO_CFG, URE_MCU_TYPE_PLA,
@@ -2052,7 +2082,8 @@ ure_ioctl(struct ifnet *ifp, u_long cmd,
 	case SIOCGIFMEDIA:
 	case SIOCSIFMEDIA:
 		if (sc->ure_flags &
-		    (URE_FLAG_8156 | URE_FLAG_8156B | URE_FLAG_8157))
+		    (URE_FLAG_8156 | URE_FLAG_8156B | URE_FLAG_8157 |
+		    URE_FLAG_8159))
 			error = ifmedia_ioctl(ifp, ifr, &sc->ure_ifmedia, cmd);
 		else
 			error = ifmedia_ioctl(ifp, ifr, &sc->ure_mii.mii_media,
@@ -2141,6 +2172,13 @@ ure_attach(struct device *parent, struct
 		sc->ure_phy_write = ure_rtl8157_ocp_reg_write;
 		printf("RTL8157 (0x1030)");
 		break;
+	case 0x2020:
+		sc->ure_flags = URE_FLAG_8159;
+		sc->ure_txbufsz = URE_8156_TX_BUFSZ;
+		sc->ure_phy_read = ure_rtl8157_ocp_reg_read;
+		sc->ure_phy_write = ure_rtl8157_ocp_reg_write;
+		printf("RTL8159 (0x2020)");
+		break;
 	case 0x4c00:
 		sc->ure_flags = URE_FLAG_8152;
 		sc->ure_rxbufsz = URE_8152_RX_BUFSZ;
@@ -2213,6 +2251,7 @@ ure_attach(struct device *parent, struct
 			return;
 		break;
 	case URE_FLAG_8157:
+	case URE_FLAG_8159:
 		if (ure_rtl8157_init(sc) != 0)
 			return;
 		break;
@@ -2248,7 +2287,8 @@ ure_attach(struct device *parent, struct
 	ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING;
 #endif
 
-	if (sc->ure_flags & (URE_FLAG_8156 | URE_FLAG_8156B | URE_FLAG_8157)) {
+	if (sc->ure_flags & (URE_FLAG_8156 | URE_FLAG_8156B | URE_FLAG_8157 |
+	    URE_FLAG_8159)) {
 		ifmedia_init(&sc->ure_ifmedia, IFM_IMASK, ure_ifmedia_upd,
 		    ure_ifmedia_sts);
 		ure_add_media_types(sc);
@@ -2341,7 +2381,8 @@ ure_tick_task(void *xsc)
 	mii = &sc->ure_mii;
 
 	s = splnet();
-	if (sc->ure_flags & (URE_FLAG_8156 | URE_FLAG_8156B | URE_FLAG_8157))
+	if (sc->ure_flags & (URE_FLAG_8156 | URE_FLAG_8156B | URE_FLAG_8157 |
+	    URE_FLAG_8159))
 		ure_link_state(sc);
 	else {
 		mii_tick(mii);
@@ -2521,9 +2562,9 @@ ure_decap(struct ure_softc *sc, struct u
 	struct ure_rxpkt	rxhdr;
 	struct ure_rxpkt_v2	rxhdr2;
 
-	align = (sc->ure_flags & URE_FLAG_8157) ?
+	align = (sc->ure_flags & (URE_FLAG_8157 | URE_FLAG_8159)) ?
 	    URE_8157_BUF_ALIGN : URE_RX_BUF_ALIGN;
-	hdrsize = (sc->ure_flags & URE_FLAG_8157) ?
+	hdrsize = (sc->ure_flags & (URE_FLAG_8157 | URE_FLAG_8159)) ?
 	    sizeof(rxhdr2) : sizeof(rxhdr);
 
 	do {
@@ -2535,7 +2576,7 @@ ure_decap(struct ure_softc *sc, struct u
 
 		buf += roundup(pktlen, align);
 
-		if (sc->ure_flags & URE_FLAG_8157) {
+		if (sc->ure_flags & (URE_FLAG_8157 | URE_FLAG_8159)) {
 			memcpy(&rxhdr2, buf, hdrsize);
 			pktlen =
 			    letoh32(rxhdr2.ure_pktlen) & URE_RXPKT_V2_LEN_MASK;
@@ -2563,7 +2604,7 @@ ure_decap(struct ure_softc *sc, struct u
 			break;
 		}
 
-		if (sc->ure_flags & URE_FLAG_8157)
+		if (sc->ure_flags & (URE_FLAG_8157 | URE_FLAG_8159))
 			ure_rxcsum_v2(&rxhdr2, m);
 		else
 			ure_rxcsum(&rxhdr, m);
@@ -2585,7 +2626,8 @@ ure_encap_txpkt(struct ure_softc *sc, st
 	struct ure_txpkt_v2	txhdr2;
 	uint32_t		len, cflags = 0;
 
-	len = (sc->ure_flags & URE_FLAG_8157) ? sizeof(txhdr2) : sizeof(txhdr);
+	len = (sc->ure_flags & (URE_FLAG_8157 | URE_FLAG_8159)) ?
+	    sizeof(txhdr2) : sizeof(txhdr);
 	if (len + m->m_pkthdr.len > maxlen)
 		return (-1);
 
@@ -2603,7 +2645,7 @@ ure_encap_txpkt(struct ure_softc *sc, st
 		cflags |= URE_TXPKT_VLAN_TAG | swap16(m->m_pkthdr.ether_vtag);
 #endif
 
-	if (sc->ure_flags & URE_FLAG_8157) {
+	if (sc->ure_flags & (URE_FLAG_8157 | URE_FLAG_8159)) {
 		txhdr2.ure_cmdstat = htole32(URE_TXPKT_TX_FS | URE_TXPKT_TX_LS);
 		txhdr2.ure_vlan = htole32(cflags);
 		txhdr2.ure_pktlen = htole32(m->m_pkthdr.len << 4);
Index: sys/dev/usb/if_urereg.h
===================================================================
RCS file: /home/cvs/src/sys/dev/usb/if_urereg.h,v
diff -u -p -r1.14 if_urereg.h
--- sys/dev/usb/if_urereg.h	23 May 2025 03:06:09 -0000	1.14
+++ sys/dev/usb/if_urereg.h	1 Oct 2026 20:55:39 -0000
@@ -371,6 +371,7 @@
 #define URE_PHYSTATUS_1000MBPS	0x0010
 #define URE_PHYSTATUS_2500MBPS	0x0400
 #define URE_PHYSTATUS_5000MBPS	0x1000
+#define URE_PHYSTATUS_10000MBPS	0x4000
 
 /* URE_PLA_CONFIG6 */
 #define	URE_LANWAKE_CLR_EN	0x01
@@ -476,6 +477,8 @@
 #define	URE_CDC_ECM_EN		0x0008
 #define	URE_RX_AGG_DISABLE	0x0010
 #define	URE_RX_ZERO_EN		0x0080
+#define	URE_RX_DESC_16B		0x0400
+#define	URE_RX_END_TRANSFER_EN	0x0800
 
 /* URE_USB_U2P3_CTRL */
 #define	URE_U2P3_ENABLE		0x0001
@@ -552,6 +555,7 @@
 
 #define URE_ADV_2500TFDX	0x0080
 #define URE_ADV_5000TFDX	0x0100
+#define URE_ADV_10000TFDX	0x1000
 
 #define	URE_MCU_TYPE_PLA	0x0100
 #define	URE_MCU_TYPE_USB	0x0000
@@ -697,7 +701,8 @@ struct ure_softc {
 #define	URE_FLAG_8156		0x0040	/* RTL8156 */
 #define	URE_FLAG_8156B		0x0080	/* RTL8156B */
 #define	URE_FLAG_8157		0x0100	/* RTL8157 */
-#define	URE_FLAG_CHIP_MASK	0x01f0
+#define	URE_FLAG_8159		0x0200	/* RTL8159 */
+#define	URE_FLAG_CHIP_MASK	0x03f0
 
 	u_int			ure_chip;
 #define	URE_CHIP_VER_4C00	0x01
Index: sys/dev/usb/usbdevs
===================================================================
RCS file: /home/cvs/src/sys/dev/usb/usbdevs,v
diff -u -p -r1.790 usbdevs
--- sys/dev/usb/usbdevs	9 Sep 2026 03:51:32 -0000	1.790
+++ sys/dev/usb/usbdevs	30 Sep 2026 12:01:17 -0000
@@ -3859,6 +3859,7 @@ product REALTEK RTL8152		0x8152	RTL8152
 product REALTEK RTL8153		0x8153	RTL8153
 product REALTEK RTL8156		0x8156	RTL8156
 product REALTEK RTL8157		0x8157	RTL8157
+product REALTEK RTL8159		0x815a	RTL8159
 product REALTEK RTL8188CE_0	0x8170	RTL8188CE
 product REALTEK RTL8171		0x8171	RTL8171
 product REALTEK RTL8172		0x8172	RTL8172
Index: share/man/man4/ure.4
===================================================================
RCS file: /home/cvs/src/share/man/man4/ure.4,v
diff -u -p -r1.11 ure.4
--- share/man/man4/ure.4	23 May 2025 03:06:09 -0000	1.11
+++ share/man/man4/ure.4	1 Oct 2026 21:41:58 -0000
@@ -31,8 +31,8 @@
 .Os
 .Sh NAME
 .Nm ure
-.Nd Realtek RTL8152/RTL8153/RTL8156/RTL8157 10/100/1Gb/2.5Gb/5Gb \
-USB Ethernet device
+.Nd Realtek RTL8152/RTL8153/RTL8156/RTL8157/RTL8159 \
+10/100/1Gb/2.5Gb/5Gb/10Gb USB Ethernet device
 .Sh SYNOPSIS
 .Cd "ure*   at uhub?"
 .Cd "rgephy* at mii?"
@@ -41,7 +41,8 @@ USB Ethernet device
 The
 .Nm
 driver provides support for USB Ethernet adapters based on the Realtek
-RTL8152, RTL8153, RTL8153B, RTL8153D, RTL8156, RTL8156B and RTL8157 chipsets.
+RTL8152, RTL8153, RTL8153B, RTL8153D, RTL8156, RTL8156B, RTL8157 and
+RTL8159 chipsets.
 .Pp
 The RTL8152 contains an integrated Fast Ethernet MAC, which supports
 both 10 and 100Mbps speeds in either full or half duplex.
@@ -51,6 +52,8 @@ NICs based on the RTL8156 and RTL8156B a
 2500Mbps operation.
 The RTL8157 is a USB 3.0 device, which contains a 10/100/1Gb/2.5Gb/5Gb
 Ethernet MAC.
+The RTL8159 is a USB 3.2 device with a 10/100/1Gb/2.5Gb/5Gb/10Gb
+Ethernet MAC.
 .Pp
 For more information on configuring this device, see
 .Xr ifconfig 8 .
@@ -75,3 +78,8 @@ The
 .Nm
 driver was written by
 .An Kevin Lo Aq Mt kevlo@FreeBSD.org .
+.Sh CAVEATS
+RTL8159 adapters require firmware for 10Gb operation.
+The
+.Nm
+driver does not support loading this firmware.


-- 
wbr, Kirill