Re: axen

[email protected]
Newsgroups gmane.os.netbsd.devel.network
Message-ID <[email protected]>
On Tue, Aug 8, 2023 at 3:55 PM Robert Swindells <[email protected]> wrote:

> Nick Hudson <[email protected]> wrote:
> >On 04/08/2023 18:52, Robert Swindells wrote:
> >>
> >> Has anyone used axen(4) recently?
> >>
> >> I needed to make some changes to get it to work for a USB-C Ethernet
> >> adapter but would like to know if the driver in the tree works for any
> >> older devices.

I've noticed axen driver doesn't work correctly, it drops many ping
replies, extremely slow on NFS, and invalid hdr messages, etc.
I made some patches, too. [1]
Comparing with FreeBSD AX88179 driver axge, I assume axen needed to
to change RX_BULKIN_QCTRL params depending on usb bus speed and
ethernet link speed, as TX part works.
This works on super-speed, but not on high-speed.
I don't understand how QCTRL params effect, but manage to work it
by mofifying QCTRL parameters and RX buffer size. [2]
I'm not sure why axen gets upset when buf size exceeds cetain value.
MIIF_DOPAUSE flag works well. It improves transfer rate incredibly.
(Why most of usb ethernet drivers don't set this flag?)
However, flow control is not enabled when ifconfig it up. I have to do
ifconfig axen media utp
ifconfig axen media auto
to enable flowcontrol,rxpause,txpause.

BTW AXEN_BUFSZ_LS should be AXEN_BUFSZ_FS, as AX88179 doesn't
look supporting low-speed.
Its wSpeedsSupported reports only FS, HS, SS speed.

> >
> > thunderx# dmesg | egrep "(NetBSD 10|axen)"
> > [     1.000000] NetBSD 10.99.4 (GENERIC64) #138: Thu Apr 27 18:33:42 BST
> > 2023
> > [     4.320147] axen0 at uhub6 port 3
> > [     4.320147] axen0: ASIX Elec. Corp. (0x0b95) AX88179 (0x1790), rev
> > 3.00/1.00, addr 4
> > [     4.819877] axen0: AX88179
> > [     4.819877] rgephy0 at axen0 phy 3: RTL8211E 1000BASE-T media interface
> > [     4.889879] axen0: Ethernet address 00:13:3b:79:92:71
> > thunderx#
> 
> What kind of USB port is that connected to?
> 
> The driver currently defaults to the smallest buffer size if the device
> is on a speed 5 (USB_SPEED_SUPER_PLUS) port.
> 
> The diffs that I'm using are attached, can try moving the check in #if 0
> to after the check for 'pkt_len == 0'.

When AXEN_RXCTL_IPE (RCR_IPE in FreeBSD) is set, the frame that
doesn't have double 0xee is broken. So driver should check them.

> It doesn't work for me at all without the change to the length argument
> to usbnet_enqueue().

original axen_uno_rx_loop looks good to me.
With patch, I got `discarding oversize frame (len=1518)'
message too when `ping -s1472 dest.'

> 
> 
> Index: if_axen.c
> ===================================================================
> RCS file: /cvsroot/src/sys/dev/usb/if_axen.c,v
> retrieving revision 1.94
> diff -u -r1.94 if_axen.c
> --- if_axen.c	20 Aug 2022 14:08:59 -0000	1.94
> +++ if_axen.c	7 Aug 2023 20:58:37 -0000
> @@ -614,6 +614,7 @@
>  
>  	/* decide on what our bufsize will be */
>  	switch (dev->ud_speed) {
> +	case USB_SPEED_SUPER_PLUS:
>  	case USB_SPEED_SUPER:
>  		un->un_rx_bufsz = AXEN_BUFSZ_SS * 1024;
>  		break;
> @@ -759,6 +760,9 @@
>  	hdr_offset = (uint16_t)(rx_hdr >> 16);
>  	pkt_count  = (uint16_t)(rx_hdr & 0xffff);
>  
> +	if (pkt_count == 0)
> +		return;
> +
>  	/* sanity check */
>  	if (hdr_offset > total_len) {
>  		aprint_error_dev(un->un_dev,
> @@ -790,15 +794,20 @@
>  		rnd_add_uint32(usbnet_rndsrc(un), pkt_count);
>  
>  	do {
> +#if 0
>  		if ((buf[0] != 0xee) || (buf[1] != 0xee)) {
>  			aprint_error_dev(un->un_dev,
>  			    "invalid buffer(pkt#%d), continue\n", pkt_count);
>  			if_statadd(ifp, if_ierrors, pkt_count);
>  			return;
>  		}
> -
> +#endif
>  		pkt_hdr = le32toh(*hdr_p);
>  		pkt_len = (pkt_hdr >> 16) & 0x1fff;
> +
> +		if (pkt_len == 0)
> +			goto nextpkt;
> +
>  		DPRINTFN(10,
>  		    ("%s: rxeof: packet#%d, pkt_hdr 0x%08x, pkt_len %zu\n",
>  		   device_xname(un->un_dev), pkt_count, pkt_hdr, pkt_len));
> @@ -813,7 +822,7 @@
>  			goto nextpkt;
>  		}
>  
> -		usbnet_enqueue(un, buf + ETHER_ALIGN, pkt_len - 6,
> +		usbnet_enqueue(un, buf + ETHER_ALIGN, pkt_len - 2,
>  			       axen_csum_flags_rx(ifp, pkt_hdr), 0, 0);

Cheers,
--

[1]
--- sys/dev/usb/if_axen.c	2022-08-20 23:30:49.194557768 +0000
+++ sys/dev/usb/if_axen.c	2023-11-04 21:56:52.018478467 +0000
@@ -67,6 +67,13 @@ static const struct axen_type axen_devs[
 
 #define axen_lookup(v, p) ((const struct axen_type *)usb_lookup(axen_devs, v, p))
 
+static struct axen_qctrl axen_bulk_size[] = {
+	{ 7, 0x4f, 0x00, 0x12, 0xff },
+	{ 7, 0x20, 0x03, 0x16, 0xff },
+	{ 7, 0xae, 0x07, 0x18, 0xff },
+	{ 7, 0xcc, 0x4c, 0x18, 0x08 }
+};
+
 static int	axen_match(device_t, cfdata_t, void *);
 static void	axen_attach(device_t, device_t, void *);
 
@@ -176,6 +183,7 @@ axen_uno_mii_statchg(struct ifnet *ifp)
 	struct usbnet * const un = ifp->if_softc;
 	struct mii_data * const mii = usbnet_mii(un);
 	int err;
+	size_t qctrl;
 	uint16_t val;
 	uint16_t wval;
 
@@ -201,25 +209,57 @@ axen_uno_mii_statchg(struct ifnet *ifp)
 	if (!usbnet_havelink(un))
 		return;
 
+	uint8_t link_status;
+	err = axen_cmd(un, AXEN_CMD_MAC_READ, 1, AXEN_USB_UPLINK, &link_status);
+	if (err)
+		return;
+	DPRINTF(("%s: link status: 0x%x\n", device_xname(un->un_dev),
+	    link_status));
+
 	val = 0;
-	if ((mii->mii_media_active & IFM_FDX) != 0)
+	if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) {
 		val |= AXEN_MEDIUM_FDX;
+		if ((IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_TXPAUSE) != 0)
+			val |= AXEN_MEDIUM_TXFLOW_CTRL_EN;
+		if ((IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_RXPAUSE) != 0)
+			val |= AXEN_MEDIUM_RXFLOW_CTRL_EN;
+	}
+	val |= AXEN_MEDIUM_RECV_EN;
 
-	val |= AXEN_MEDIUM_RXFLOW_CTRL_EN | AXEN_MEDIUM_TXFLOW_CTRL_EN |
-	    AXEN_MEDIUM_RECV_EN;
 	switch (IFM_SUBTYPE(mii->mii_media_active)) {
 	case IFM_1000_T:
 		val |= AXEN_MEDIUM_GIGA | AXEN_MEDIUM_EN_125MHZ;
+		if (link_status & AXEN_USB_SS)
+			qctrl = 0;
+		else if (link_status & AXEN_USB_HS)
+			qctrl = 1;
+		else
+			qctrl = 3;
 		break;
 	case IFM_100_TX:
 		val |= AXEN_MEDIUM_PS;
+		if (link_status & (AXEN_USB_SS | AXEN_USB_HS))
+			qctrl = 2;
+		else
+			qctrl = 3;
 		break;
 	case IFM_10_T:
-		/* doesn't need to be handled */
+	case 0x02: /* cable not connected */
+		qctrl = 3;
+		break;
+	default:
+		device_printf(un->un_dev, "unknown uplink bus: 0x%02x\n",
+		    link_status);
+		qctrl = 3;
 		break;
 	}
 
-	DPRINTF(("%s: val=%#x\n", __func__, val));
+	DPRINTF(("%s: val=%#x qctrl=%zu usb=%#x media_active=%#x\n", __func__,
+	    val, qctrl, link_status, mii->mii_media_active));
+	err = axen_cmd(un, AXEN_CMD_MAC_SET_RXSR, 5, AXEN_RX_BULKIN_QCTRL,
+	    &axen_bulk_size[qctrl]);
+	if (err)
+		device_printf(un->un_dev, "set bulkin qctrl failed\n");
 	wval = htole16(val);
 	err = axen_cmd(un, AXEN_CMD_MAC_WRITE2, 2, AXEN_MEDIUM_STATUS, &wval);
 	if (err)
@@ -614,14 +654,16 @@ axen_attach(device_t parent, device_t se
 
 	/* decide on what our bufsize will be */
 	switch (dev->ud_speed) {
-	case USB_SPEED_SUPER:
-		un->un_rx_bufsz = AXEN_BUFSZ_SS * 1024;
+	case USB_SPEED_FULL:
+		un->un_rx_bufsz = AXEN_BUFSZ_LS * 1024;
 		break;
 	case USB_SPEED_HIGH:
 		un->un_rx_bufsz = AXEN_BUFSZ_HS * 1024;
 		break;
+	case USB_SPEED_SUPER:
+	case USB_SPEED_SUPER_PLUS:
 	default:
-		un->un_rx_bufsz = AXEN_BUFSZ_LS * 1024;
+		un->un_rx_bufsz = AXEN_BUFSZ_SS * 1024;
 		break;
 	}
 	un->un_tx_bufsz = IP_MAXPACKET + ETHER_HDR_LEN + ETHER_CRC_LEN +
@@ -683,6 +725,7 @@ axen_attach(device_t parent, device_t se
 	    IFCAP_CSUM_TCPv6_Rx | IFCAP_CSUM_TCPv6_Tx |
 	    IFCAP_CSUM_UDPv6_Rx | IFCAP_CSUM_UDPv6_Tx;
 
+	unm.un_mii_flags = MIIF_DOPAUSE;
 	usbnet_attach_ifp(un, IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST,
 	    0, &unm);
 }

[2]
--- sys/dev/usb/if_axen.c	2023-11-04 21:56:52.018478467 +0000
+++ sys/dev/usb/if_axen.c	2023-11-04 21:58:21.351252690 +0000
@@ -69,9 +69,9 @@ static const struct axen_type axen_devs[
 
 static struct axen_qctrl axen_bulk_size[] = {
 	{ 7, 0x4f, 0x00, 0x12, 0xff },
-	{ 7, 0x20, 0x03, 0x16, 0xff },
-	{ 7, 0xae, 0x07, 0x18, 0xff },
-	{ 7, 0xcc, 0x4c, 0x18, 0x08 }
+	{ 7, 0xae, 0x00, 0x16, 0xff },
+	{ 7, 0xae, 0x00, 0x18, 0xff },
+	{ 7, 0xcc, 0x0c, 0x18, 0x08 }
 };
 
 static int	axen_match(device_t, cfdata_t, void *);
@@ -655,19 +655,21 @@ axen_attach(device_t parent, device_t se
 	/* decide on what our bufsize will be */
 	switch (dev->ud_speed) {
 	case USB_SPEED_FULL:
-		un->un_rx_bufsz = AXEN_BUFSZ_LS * 1024;
+		un->un_rx_bufsz = /*AXEN_BUFSZ_LS*/ 20 * 1024;
 		break;
 	case USB_SPEED_HIGH:
-		un->un_rx_bufsz = AXEN_BUFSZ_HS * 1024;
+		un->un_rx_bufsz = /*AXEN_BUFSZ_HS*/ 20 * 1024;
 		break;
 	case USB_SPEED_SUPER:
 	case USB_SPEED_SUPER_PLUS:
 	default:
-		un->un_rx_bufsz = AXEN_BUFSZ_SS * 1024;
+		un->un_rx_bufsz = /*AXEN_BUFSZ_SS*/ 64 * 1024;
 		break;
 	}
 	un->un_tx_bufsz = IP_MAXPACKET + ETHER_HDR_LEN + ETHER_CRC_LEN +
 	    ETHER_VLAN_ENCAP_LEN + sizeof(struct axen_sframe_hdr);
+	aprint_normal_dev(un->un_dev, "speed %u rx_bufsz %#x tx_bufsz %#x\n",
+	    dev->ud_speed, un->un_rx_bufsz, un->un_tx_bufsz);
 
 	/* Find endpoints. */
 	id = usbd_get_interface_descriptor(un->un_iface);
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.