tech-net archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: axen



On Tue, Aug 8, 2023 at 3:55 PM Robert Swindells <rjs%fdy2.co.uk@localhost> wrote:

> Nick Hudson <nick.hudson%gmx.co.uk@localhost> 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);


Home | Main Index | Thread Index | Old Index