Module Name:    src
Committed By:   rin
Date:           Tue Dec 11 08:16:57 UTC 2018

Modified Files:
        src/sys/dev/usb: if_mue.c if_muevar.h

Log Message:
Support checksum offloading for mue(4) by Robert Swindells
and adjusted by myself.


To generate a diff of this commit:
cvs rdiff -u -r1.19 -r1.20 src/sys/dev/usb/if_mue.c
cvs rdiff -u -r1.2 -r1.3 src/sys/dev/usb/if_muevar.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/usb/if_mue.c
diff -u src/sys/dev/usb/if_mue.c:1.19 src/sys/dev/usb/if_mue.c:1.20
--- src/sys/dev/usb/if_mue.c:1.19	Tue Dec  4 01:35:15 2018
+++ src/sys/dev/usb/if_mue.c	Tue Dec 11 08:16:57 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_mue.c,v 1.19 2018/12/04 01:35:15 rin Exp $	*/
+/*	$NetBSD: if_mue.c,v 1.20 2018/12/11 08:16:57 rin Exp $	*/
 /*	$OpenBSD: if_mue.c,v 1.3 2018/08/04 16:42:46 jsg Exp $	*/
 
 /*
@@ -20,7 +20,7 @@
 /* Driver for Microchip LAN7500/LAN7800 chipsets. */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_mue.c,v 1.19 2018/12/04 01:35:15 rin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_mue.c,v 1.20 2018/12/11 08:16:57 rin Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -1009,7 +1009,12 @@ mue_attach(device_t parent, device_t sel
 
 	IFQ_SET_READY(&ifp->if_snd);
 
-	ifp->if_capabilities = IFCAP_TSOv4 | IFCAP_TSOv6;
+	ifp->if_capabilities = IFCAP_TSOv4 | IFCAP_TSOv6 |
+	    IFCAP_CSUM_IPv4_Tx | IFCAP_CSUM_IPv4_Rx |  
+	    IFCAP_CSUM_TCPv4_Tx | IFCAP_CSUM_TCPv4_Rx |
+	    IFCAP_CSUM_UDPv4_Tx | IFCAP_CSUM_UDPv4_Rx |
+	    IFCAP_CSUM_TCPv6_Tx | IFCAP_CSUM_TCPv6_Rx |
+	    IFCAP_CSUM_UDPv6_Tx | IFCAP_CSUM_UDPv6_Rx;
 
 	sc->mue_ec.ec_capabilities = ETHERCAP_VLAN_MTU;
 
@@ -1208,10 +1213,14 @@ mue_encap(struct mue_softc *sc, struct m
 	usbd_status err;
 	struct mue_txbuf_hdr hdr;
 	uint32_t tx_cmd_a, tx_cmd_b;
-	int len;
-	bool tso;
+	int csum, len;
+	bool tso, ipe, tpe;
 
-	tso = m->m_pkthdr.csum_flags & (M_CSUM_TSOv4 | M_CSUM_TSOv6);
+	csum = m->m_pkthdr.csum_flags;
+	tso = csum & (M_CSUM_TSOv4 | M_CSUM_TSOv6);
+	ipe = csum & M_CSUM_IPv4;
+	tpe = csum & (M_CSUM_TCPv4 | M_CSUM_UDPv4 |
+		      M_CSUM_TCPv6 | M_CSUM_UDPv6);
 
 	len = m->m_pkthdr.len;
 	if (__predict_false((!tso && len > MUE_MAX_TX_LEN) ||
@@ -1234,8 +1243,13 @@ mue_encap(struct mue_softc *sc, struct m
 		tx_cmd_b <<= MUE_TX_CMD_B_MSS_SHIFT;
 		KASSERT((tx_cmd_b & ~MUE_TX_CMD_B_MSS_MASK) == 0);
 		mue_tx_offload(sc, m);
-	} else
+	} else {
+		if (ipe)
+			tx_cmd_a |= MUE_TX_CMD_A_IPE;
+		if (tpe)
+			tx_cmd_a |= MUE_TX_CMD_A_TPE;
 		tx_cmd_b = 0;
+	}
 
 	hdr.tx_cmd_a = htole32(tx_cmd_a);
 	hdr.tx_cmd_b = htole32(tx_cmd_b);
@@ -1418,7 +1432,9 @@ mue_rxeof(struct usbd_xfer *xfer, void *
 	uint32_t rx_cmd_a, totlen;
 	uint16_t pktlen;
 	int s;
+	int csum;
 	char *buf = c->mue_buf;
+	bool v6;
 
 	if (__predict_false(sc->mue_dying)) {
 		DPRINTF(sc, "dying\n");
@@ -1457,15 +1473,17 @@ mue_rxeof(struct usbd_xfer *xfer, void *
 		hdrp = (struct mue_rxbuf_hdr *)buf;
 		rx_cmd_a = le32toh(hdrp->rx_cmd_a);
 
-		if (__predict_false(rx_cmd_a & MUE_RX_CMD_A_RED)) {
+		if (__predict_false(rx_cmd_a & MUE_RX_CMD_A_ERRORS)) {
+			/*
+			 * We cannot use MUE_RX_CMD_A_RED bit here;
+			 * it is turned on in the cases of L3/L4
+			 * checksum errors which we handle below.
+			 */
 			MUE_PRINTF(sc, "rx_cmd_a: 0x%x\n", rx_cmd_a);
 			ifp->if_ierrors++;
 			goto done;
 		}
 
-		/* XXX not yet */
-		KASSERT((rx_cmd_a & MUE_RX_CMD_A_ICSM) == 0);
-
 		pktlen = (uint16_t)(rx_cmd_a & MUE_RX_CMD_A_LEN_MASK);
 		if (sc->mue_flags & LAN7500)
 			pktlen -= 2;
@@ -1488,6 +1506,36 @@ mue_rxeof(struct usbd_xfer *xfer, void *
 		m_set_rcvif(m, ifp);
 		m->m_pkthdr.len = m->m_len = pktlen;
 		m->m_flags |= M_HASFCS;
+
+		if (__predict_false(rx_cmd_a & MUE_RX_CMD_A_ICSM)) {
+			csum = 0;
+		} else {
+			v6 = rx_cmd_a & MUE_RX_CMD_A_IPV;
+			switch (rx_cmd_a & MUE_RX_CMD_A_PID) {
+			case MUE_RX_CMD_A_PID_TCP:
+				csum = v6 ?
+				    M_CSUM_TCPv6 : M_CSUM_IPv4 | M_CSUM_TCPv4;
+				break;
+			case MUE_RX_CMD_A_PID_UDP:
+				csum = v6 ?
+				    M_CSUM_UDPv6 : M_CSUM_IPv4 | M_CSUM_UDPv4;
+				break;
+			case MUE_RX_CMD_A_PID_IP:
+				csum = v6 ? 0 : M_CSUM_IPv4;
+				break;
+			default:
+				csum = 0;
+				break;
+			}
+			csum &= ifp->if_csum_flags_rx;
+			if (__predict_false((csum & M_CSUM_IPv4) &&
+			    (rx_cmd_a & MUE_RX_CMD_A_ICE)))
+				csum |= M_CSUM_IPv4_BAD;
+			if (__predict_false((csum & ~M_CSUM_IPv4) &&
+			    (rx_cmd_a & MUE_RX_CMD_A_TCE)))
+				csum |= M_CSUM_TCP_UDP_BAD;
+		}
+		m->m_pkthdr.csum_flags = csum;
 		memcpy(mtod(m, char *), buf + sizeof(*hdrp), pktlen);
 
 		/* Attention: sizeof(hdr) = 10 */
@@ -1643,6 +1691,8 @@ mue_ioctl(struct ifnet *ifp, u_long cmd,
 		if ((error = ether_ioctl(ifp, cmd, data)) != ENETRESET)
 			break;
 		error = 0;
+		if (cmd == SIOCSIFCAP)
+			mue_sethwcsum(sc);
 		if (cmd == SIOCADDMULTI || cmd == SIOCDELMULTI)
 			mue_setmulti(sc);
 		break;

Index: src/sys/dev/usb/if_muevar.h
diff -u src/sys/dev/usb/if_muevar.h:1.2 src/sys/dev/usb/if_muevar.h:1.3
--- src/sys/dev/usb/if_muevar.h:1.2	Thu Aug 30 09:00:08 2018
+++ src/sys/dev/usb/if_muevar.h	Tue Dec 11 08:16:57 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_muevar.h,v 1.2 2018/08/30 09:00:08 rin Exp $	*/
+/*	$NetBSD: if_muevar.h,v 1.3 2018/12/11 08:16:57 rin Exp $	*/
 /*	$OpenBSD: if_muereg.h,v 1.1 2018/08/03 01:50:15 kevlo Exp $	*/
 
 /*
@@ -45,7 +45,15 @@ struct mue_rxbuf_hdr {
 	uint32_t		rx_cmd_a;
 #define MUE_RX_CMD_A_LEN_MASK	0x00003fff
 #define MUE_RX_CMD_A_ICSM	0x00004000
+#define MUE_RX_CMD_A_ERRORS	__BITS(16, 21)	/* non-checksum errors */
 #define MUE_RX_CMD_A_RED	0x00400000
+#define MUE_RX_CMD_A_PID	__BITS(28, 27)
+#define MUE_RX_CMD_A_PID_TCP	__SHIFTIN(1, MUE_RX_CMD_A_PID)
+#define MUE_RX_CMD_A_PID_UDP	__SHIFTIN(2, MUE_RX_CMD_A_PID)
+#define MUE_RX_CMD_A_PID_IP	__SHIFTIN(3, MUE_RX_CMD_A_PID)
+#define MUE_RX_CMD_A_IPV	__BIT(29)
+#define MUE_RX_CMD_A_TCE	__BIT(30)
+#define MUE_RX_CMD_A_ICE	__BIT(31)
 
 	uint32_t		rx_cmd_b;
 	uint16_t		rx_cmd_c;

Reply via email to