git: e4a51dbf5d8d - stable/13 - axge: Add support for AX88179A

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Wed, 11 Oct 2023 13:18:43 UTC
The branch stable/13 has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=e4a51dbf5d8d75766519a8f775f30b5026227072

commit e4a51dbf5d8d75766519a8f775f30b5026227072
Author:     Damien Broka <git@damien.sh>
AuthorDate: 2023-09-19 16:26:06 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2023-10-11 13:18:25 +0000

    axge: Add support for AX88179A
    
    The AX88179A has two firmware modes, one of which is backward
    compatible with existing AX88178A/179 driver. The active firmware mode
    can be controlled through a register.
    
    Update axge(4) man page to mention 179A support and ensure that, when
    bound to a AX88179A, the driver activates the compatible firmware mode.
    
    Reviewed by:    markj
    Pull Request:   https://github.com/freebsd/freebsd-src/pull/854
    MFC after:      1 week
    
    (cherry picked from commit 6962da914dd511349b219241e92b32329be76fc6)
---
 share/man/man4/axge.4        | 12 ++++++------
 sys/dev/usb/net/if_axge.c    | 39 +++++++++++++++++++++++++++++++--------
 sys/dev/usb/net/if_axgereg.h |  7 +++++++
 3 files changed, 44 insertions(+), 14 deletions(-)

diff --git a/share/man/man4/axge.4 b/share/man/man4/axge.4
index d42a1a233c59..9ca268d6ff83 100644
--- a/share/man/man4/axge.4
+++ b/share/man/man4/axge.4
@@ -28,12 +28,12 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 .\" THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd November 24, 2015
+.Dd October 4, 2023
 .Dt AXGE 4
 .Os
 .Sh NAME
 .Nm axge
-.Nd "ASIX Electronics AX88178A/AX88179 USB Gigabit Ethernet driver"
+.Nd "ASIX Electronics AX88178A/179/179A USB Gigabit Ethernet driver"
 .Sh SYNOPSIS
 To compile this driver into the kernel,
 place the following lines in your
@@ -59,13 +59,13 @@ if_axge_load="YES"
 The
 .Nm
 driver provides support for USB Gigabit Ethernet adapters based on the ASIX
-Electronics AX88179 USB 3.0 and AX88178A USB 2.0 chipsets.
+Electronics AX88179/AX88179A USB 3.0 and AX88178A USB 2.0 chipsets.
 .Pp
-The AX88179 and AX88178A contain a 10/100/1000 Ethernet MAC with a GMII
-interface for interfacing with the Gigabit Ethernet PHY.
+The AX88179, AX88179A and AX88178A contain a 10/100/1000 Ethernet MAC with a
+GMII interface for interfacing with the Gigabit Ethernet PHY.
 .Pp
 These devices will operate with both USB 1.x and USB 2.0 controllers, and the
-AX88179 will operate with USB 3.0 controllers.
+AX88179/AX88179A will operate with USB 3.0 controllers.
 Packets are received and transmitted over separate USB bulk transfer endpoints.
 .Pp
 The
diff --git a/sys/dev/usb/net/if_axge.c b/sys/dev/usb/net/if_axge.c
index 5cabad95c07f..9cd9c15515cb 100644
--- a/sys/dev/usb/net/if_axge.c
+++ b/sys/dev/usb/net/if_axge.c
@@ -28,7 +28,8 @@
 
 #include <sys/cdefs.h>
 /*
- * ASIX Electronics AX88178A/AX88179 USB 2.0/3.0 gigabit ethernet driver.
+ * ASIX Electronics AX88178A/AX88179/AX88179A USB 2.0/3.0 gigabit ethernet
+ * driver.
  */
 
 #include <sys/param.h>
@@ -70,13 +71,15 @@
  */
 
 static const STRUCT_USB_HOST_ID axge_devs[] = {
-#define	AXGE_DEV(v,p) { USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p) }
-	AXGE_DEV(ASIX, AX88178A),
-	AXGE_DEV(ASIX, AX88179),
-	AXGE_DEV(BELKIN, B2B128),
-	AXGE_DEV(DLINK, DUB1312),
-	AXGE_DEV(LENOVO, GIGALAN),
-	AXGE_DEV(SITECOMEU, LN032),
+#define	AXGE_DEV(v,p,i,...)	\
+	{ USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i), __VA_ARGS__ }
+	AXGE_DEV(ASIX, AX88178A, AXGE_FLAG_178A),
+	AXGE_DEV(ASIX, AX88179, AXGE_FLAG_179, USB_DEV_BCD_LTEQ(0x0100)),
+	AXGE_DEV(ASIX, AX88179, AXGE_FLAG_179A, USB_DEV_BCD_GTEQ(0x0200)),
+	AXGE_DEV(BELKIN, B2B128, AXGE_FLAG_179),
+	AXGE_DEV(DLINK, DUB1312, AXGE_FLAG_179),
+	AXGE_DEV(LENOVO, GIGALAN, AXGE_FLAG_179),
+	AXGE_DEV(SITECOMEU, LN032, AXGE_FLAG_179),
 #undef AXGE_DEV
 };
 
@@ -412,6 +415,24 @@ axge_chip_init(struct axge_softc *sc)
 	axge_write_cmd_1(sc, AXGE_ACCESS_MAC, AXGE_CLK_SELECT,
 	    AXGE_CLK_SELECT_ACS | AXGE_CLK_SELECT_BCS);
 	uether_pause(&sc->sc_ue, hz / 10);
+
+	if ((sc->sc_flags & AXGE_FLAG_179A) != 0) {
+		/*
+		 * 179A chip has two firmware modes that each use different
+		 * transfer layouts for Ethernet over USB. The newer fw mode has
+		 * larger rx packet headers which seem to
+		 * accomodate for ethernet frames up to 9K length and a VLAN
+		 * field for hardware tagging, but is not backward compatible
+		 * with 178A/179 bulk transfer code due to the change in size
+		 * and field alignments. The other fw mode uses the same packet
+		 * headers as the older 178A/179 chips, which this driver uses.
+		 *
+		 * As we do not currently have VLAN hw tagging or jumbo support
+		 * in this driver anyway, we're ok forcing 179A into its compat
+		 * mode by default.
+		 */
+		axge_write_cmd_1(sc, AXGE_FW_MODE, AXGE_FW_MODE_178A179, 0);
+	}
 }
 
 static void
@@ -554,6 +575,8 @@ axge_attach(device_t dev)
 	device_set_usb_desc(dev);
 	mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
 
+	sc->sc_flags = USB_GET_DRIVER_INFO(uaa);
+
 	iface_index = AXGE_IFACE_IDX;
 	error = usbd_transfer_setup(uaa->device, &iface_index,
 	    sc->sc_xfer, axge_config, AXGE_N_TRANSFER, sc, &sc->sc_mtx);
diff --git a/sys/dev/usb/net/if_axgereg.h b/sys/dev/usb/net/if_axgereg.h
index ea7a2c4a98b8..87e662b6cbc1 100644
--- a/sys/dev/usb/net/if_axgereg.h
+++ b/sys/dev/usb/net/if_axgereg.h
@@ -32,10 +32,14 @@
 #define	AXGE_ACCESS_EEPROM		0x04
 #define	AXGE_ACCESS_EFUSE		0x05
 #define	AXGE_RELOAD_EEPROM_EFUSE	0x06
+#define	AXGE_FW_MODE			0x08
 #define	AXGE_WRITE_EFUSE_EN		0x09
 #define	AXGE_WRITE_EFUSE_DIS		0x0A
 #define	AXGE_ACCESS_MFAB		0x10
 
+#define	AXGE_FW_MODE_178A179		0x0000
+#define	AXGE_FW_MODE_179A		0x0001
+
 /* Physical link status register */
 #define	AXGE_PLSR			0x02
 #define	PLSR_USB_FS			0x01
@@ -202,6 +206,9 @@ struct axge_softc {
 
 	int			sc_flags;
 #define	AXGE_FLAG_LINK		0x0001	/* got a link */
+#define	AXGE_FLAG_178A		0x1000	/* AX88178A */
+#define	AXGE_FLAG_179		0x2000	/* AX88179 */
+#define	AXGE_FLAG_179A		0x4000	/* AX88179A */
 };
 
 #define	AXGE_LOCK(_sc)			mtx_lock(&(_sc)->sc_mtx)