Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/usb Fix HW checksum offloading.
details: https://anonhg.NetBSD.org/src/rev/c2359e7cf383
branches: trunk
changeset: 447994:c2359e7cf383
user: rin <rin%NetBSD.org@localhost>
date: Wed Jan 30 11:13:25 2019 +0000
description:
Fix HW checksum offloading.
- Enable ones specified in if_capenable and remove AXEN_TOE macro.
- Check correct bit and set appropriate csum_flags.
- Pass packets of wrong checksum to upper layer instead of dropping them.
- Fix value of AXEN_RXHDR_L3_TYPE_MASK.
Tested on ASIX Elec. Corp. (0xb95) AX88179 (0x1790).
diffstat:
sys/dev/usb/if_axen.c | 151 +++++++++++++++++++++++++++++++++-------------
sys/dev/usb/if_axenreg.h | 4 +-
2 files changed, 109 insertions(+), 46 deletions(-)
diffs (252 lines):
diff -r e3dddae55812 -r c2359e7cf383 sys/dev/usb/if_axen.c
--- a/sys/dev/usb/if_axen.c Wed Jan 30 11:11:45 2019 +0000
+++ b/sys/dev/usb/if_axen.c Wed Jan 30 11:13:25 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_axen.c,v 1.18 2019/01/22 03:42:28 msaitoh Exp $ */
+/* $NetBSD: if_axen.c,v 1.19 2019/01/30 11:13:25 rin Exp $ */
/* $OpenBSD: if_axen.c,v 1.3 2013/10/21 10:10:22 yuo Exp $ */
/*
@@ -23,7 +23,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_axen.c,v 1.18 2019/01/22 03:42:28 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_axen.c,v 1.19 2019/01/30 11:13:25 rin Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -70,8 +70,6 @@
#define DPRINTFN(n,x)
#endif
-#define AXEN_TOE /* enable checksum offload function */
-
/*
* Various supported device vendors/products.
*/
@@ -98,6 +96,7 @@
static struct mbuf *axen_newbuf(void);
static int axen_encap(struct axen_softc *, struct mbuf *, int);
static void axen_rxeof(struct usbd_xfer *, void *, usbd_status);
+static int axen_csum_flags_rx(struct ifnet *, uint32_t);
static void axen_txeof(struct usbd_xfer *, void *, usbd_status);
static void axen_tick(void *);
static void axen_tick_task(void *);
@@ -122,6 +121,7 @@
static void axen_unlock_mii(struct axen_softc *);
static void axen_ax88179_init(struct axen_softc *);
+static void axen_setcoe(struct axen_softc *);
/* Get exclusive access to the MII registers */
static void
@@ -569,21 +569,7 @@
/* Set RX/TX configuration. */
/* Offloadng enable */
-#ifdef AXEN_TOE
- val = AXEN_RXCOE_IPv4 | AXEN_RXCOE_TCPv4 | AXEN_RXCOE_UDPv4 |
- AXEN_RXCOE_TCPv6 | AXEN_RXCOE_UDPv6;
-#else
- val = AXEN_RXCOE_OFF;
-#endif
- axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_RX_COE, &val);
-
-#ifdef AXEN_TOE
- val = AXEN_TXCOE_IPv4 | AXEN_TXCOE_TCPv4 | AXEN_TXCOE_UDPv4 |
- AXEN_TXCOE_TCPv6 | AXEN_TXCOE_UDPv6;
-#else
- val = AXEN_TXCOE_OFF;
-#endif
- axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_TX_COE, &val);
+ axen_setcoe(sc);
/* Set RX control register */
ctl = AXEN_RXCTL_IPE | AXEN_RXCTL_DROPCRCERR | AXEN_RXCTL_AUTOB;
@@ -633,6 +619,50 @@
#endif
}
+static void
+axen_setcoe(struct axen_softc *sc)
+{
+ struct ifnet *ifp = GET_IFP(sc);
+ uint64_t enabled = ifp->if_capenable;
+ uint8_t val;
+
+ if (enabled & (IFCAP_CSUM_IPv4_Rx |
+ IFCAP_CSUM_TCPv4_Rx | IFCAP_CSUM_UDPv4_Rx |
+ IFCAP_CSUM_TCPv6_Rx | IFCAP_CSUM_UDPv6_Rx)) {
+ val = 0;
+ if (enabled & IFCAP_CSUM_IPv4_Rx)
+ val |= AXEN_RXCOE_IPv4;
+ if (enabled & IFCAP_CSUM_TCPv4_Rx)
+ val |= AXEN_RXCOE_TCPv4;
+ if (enabled & IFCAP_CSUM_UDPv4_Rx)
+ val |= AXEN_RXCOE_UDPv4;
+ if (enabled & IFCAP_CSUM_TCPv6_Rx)
+ val |= AXEN_RXCOE_TCPv6;
+ if (enabled & IFCAP_CSUM_UDPv6_Rx)
+ val |= AXEN_RXCOE_UDPv6;
+ } else
+ val = AXEN_RXCOE_OFF;
+ axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_RX_COE, &val);
+
+ if (enabled & (IFCAP_CSUM_IPv4_Tx |
+ IFCAP_CSUM_TCPv4_Tx | IFCAP_CSUM_UDPv4_Tx |
+ IFCAP_CSUM_TCPv6_Tx | IFCAP_CSUM_UDPv6_Tx)) {
+ val = 0;
+ if (enabled & IFCAP_CSUM_IPv4_Tx)
+ val |= AXEN_TXCOE_IPv4;
+ if (enabled & IFCAP_CSUM_TCPv4_Tx)
+ val |= AXEN_TXCOE_TCPv4;
+ if (enabled & IFCAP_CSUM_UDPv4_Tx)
+ val |= AXEN_TXCOE_UDPv4;
+ if (enabled & IFCAP_CSUM_TCPv6_Tx)
+ val |= AXEN_TXCOE_TCPv6;
+ if (enabled & IFCAP_CSUM_UDPv6_Tx)
+ val |= AXEN_TXCOE_UDPv6;
+ } else
+ val = AXEN_TXCOE_OFF;
+ axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_TX_COE, &val);
+}
+
static int
axen_match(device_t parent, cfdata_t match, void *aux)
{
@@ -767,13 +797,11 @@
IFQ_SET_READY(&ifp->if_snd);
sc->axen_ec.ec_capabilities = ETHERCAP_VLAN_MTU;
-#ifdef AXEN_TOE
ifp->if_capabilities |= IFCAP_CSUM_IPv4_Rx | IFCAP_CSUM_IPv4_Tx |
IFCAP_CSUM_TCPv4_Rx | IFCAP_CSUM_TCPv4_Tx |
IFCAP_CSUM_UDPv4_Rx | IFCAP_CSUM_UDPv4_Tx |
IFCAP_CSUM_TCPv6_Rx | IFCAP_CSUM_TCPv6_Tx |
IFCAP_CSUM_UDPv6_Rx | IFCAP_CSUM_UDPv6_Tx;
-#endif
/* Initialize MII/media info. */
mii = &sc->axen_mii;
@@ -1079,27 +1107,7 @@
m_set_rcvif(m, ifp);
m->m_pkthdr.len = m->m_len = pkt_len - 6;
-#ifdef AXEN_TOE
- /* cheksum err */
- if ((pkt_hdr & AXEN_RXHDR_L3CSUM_ERR) ||
- (pkt_hdr & AXEN_RXHDR_L4CSUM_ERR)) {
- aprint_error_dev(sc->axen_dev,
- "checksum err (pkt#%d)\n", pkt_count);
- goto nextpkt;
- } else {
- m->m_pkthdr.csum_flags |= M_CSUM_IPv4;
- }
-
- int l4_type = (pkt_hdr & AXEN_RXHDR_L4_TYPE_MASK) >>
- AXEN_RXHDR_L4_TYPE_OFFSET;
-
- if ((l4_type == AXEN_RXHDR_L4_TYPE_TCP) ||
- (l4_type == AXEN_RXHDR_L4_TYPE_UDP)) {
- m->m_pkthdr.csum_flags |= M_CSUM_TCPv4 |
- M_CSUM_UDPv4; /* XXX v6? */
- }
-#endif
-
+ m->m_pkthdr.csum_flags = axen_csum_flags_rx(ifp, pkt_hdr);
memcpy(mtod(m, char *), buf + 2, pkt_len - 6);
/* push the packet up */
@@ -1131,6 +1139,51 @@
DPRINTFN(10,("%s: %s: start rx\n",device_xname(sc->axen_dev),__func__));
}
+static int
+axen_csum_flags_rx(struct ifnet *ifp, uint32_t pkt_hdr)
+{
+ int enabled_flags = ifp->if_csum_flags_rx;
+ int csum_flags = 0;
+ int l3_type, l4_type;
+
+ if (enabled_flags == 0)
+ return 0;
+
+ l3_type = (pkt_hdr & AXEN_RXHDR_L3_TYPE_MASK) >>
+ AXEN_RXHDR_L3_TYPE_OFFSET;
+
+ if (l3_type == AXEN_RXHDR_L3_TYPE_IPV4)
+ csum_flags |= M_CSUM_IPv4;
+
+ l4_type = (pkt_hdr & AXEN_RXHDR_L4_TYPE_MASK) >>
+ AXEN_RXHDR_L4_TYPE_OFFSET;
+
+ switch (l4_type) {
+ case AXEN_RXHDR_L4_TYPE_TCP:
+ if (l3_type == AXEN_RXHDR_L3_TYPE_IPV4)
+ csum_flags |= M_CSUM_TCPv4;
+ else
+ csum_flags |= M_CSUM_TCPv6;
+ break;
+ case AXEN_RXHDR_L4_TYPE_UDP:
+ if (l3_type == AXEN_RXHDR_L3_TYPE_IPV4)
+ csum_flags |= M_CSUM_UDPv4;
+ else
+ csum_flags |= M_CSUM_UDPv6;
+ break;
+ default:
+ break;
+ }
+
+ csum_flags &= enabled_flags;
+ if ((csum_flags & M_CSUM_IPv4) && (pkt_hdr & AXEN_RXHDR_L3CSUM_ERR))
+ csum_flags |= M_CSUM_IPv4_BAD;
+ if ((csum_flags & ~M_CSUM_IPv4) && (pkt_hdr & AXEN_RXHDR_L4CSUM_ERR))
+ csum_flags |= M_CSUM_TCP_UDP_BAD;
+
+ return csum_flags;
+}
+
/*
* A frame was downloaded to the chip. It's safe for us to clean up
* the list buffers.
@@ -1437,9 +1490,19 @@
break;
error = 0;
-
- if (cmd == SIOCADDMULTI || cmd == SIOCDELMULTI)
+ switch(cmd) {
+ case SIOCADDMULTI:
+ case SIOCDELMULTI:
axen_iff(sc);
+ break;
+ case SIOCSIFCAP:
+ axen_lock_mii(sc);
+ axen_setcoe(sc);
+ axen_unlock_mii(sc);
+ break;
+ default:
+ break;
+ }
break;
}
splx(s);
diff -r e3dddae55812 -r c2359e7cf383 sys/dev/usb/if_axenreg.h
--- a/sys/dev/usb/if_axenreg.h Wed Jan 30 11:11:45 2019 +0000
+++ b/sys/dev/usb/if_axenreg.h Wed Jan 30 11:13:25 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_axenreg.h,v 1.3 2016/04/23 10:15:31 skrll Exp $ */
+/* $NetBSD: if_axenreg.h,v 1.4 2019/01/30 11:13:25 rin Exp $ */
/* $OpenBSD: if_axenreg.h,v 1.1 2013/10/07 05:37:41 yuo Exp $ */
/*
@@ -72,7 +72,7 @@
#define AXEN_RXHDR_L4_TYPE_TCP 0x4
/* L3 packet type (2bit) */
-#define AXEN_RXHDR_L3_TYPE_MASK 0x00000600
+#define AXEN_RXHDR_L3_TYPE_MASK 0x00000060
#define AXEN_RXHDR_L3_TYPE_OFFSET 5
#define AXEN_RXHDR_L3_TYPE_UNDEF 0x0
#define AXEN_RXHDR_L3_TYPE_IPV4 0x1
Home |
Main Index |
Thread Index |
Old Index