Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/usb Support added for TCP segmentation offload (TSO).
details: https://anonhg.NetBSD.org/src/rev/d8be1f2879fc
branches: trunk
changeset: 366502:d8be1f2879fc
user: rin <rin%NetBSD.org@localhost>
date: Thu Aug 30 09:00:08 2018 +0000
description:
Support added for TCP segmentation offload (TSO).
Improve TX performance around 10% if enabled.
diffstat:
sys/dev/usb/if_mue.c | 99 +++++++++++++++++++++++++++++++++++++++++-------
sys/dev/usb/if_muereg.h | 23 ++++++++--
sys/dev/usb/if_muevar.h | 12 ++++-
3 files changed, 110 insertions(+), 24 deletions(-)
diffs (297 lines):
diff -r 9b8750459c9b -r d8be1f2879fc sys/dev/usb/if_mue.c
--- a/sys/dev/usb/if_mue.c Thu Aug 30 05:39:21 2018 +0000
+++ b/sys/dev/usb/if_mue.c Thu Aug 30 09:00:08 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_mue.c,v 1.2 2018/08/27 14:59:04 rin Exp $ */
+/* $NetBSD: if_mue.c,v 1.3 2018/08/30 09:00:08 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.2 2018/08/27 14:59:04 rin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_mue.c,v 1.3 2018/08/30 09:00:08 rin Exp $");
#ifdef _KERNEL_OPT
#include "opt_usb.h"
@@ -49,8 +49,11 @@
#include <net/bpf.h>
+#include <netinet/if_inarp.h>
#include <netinet/in.h>
-#include <netinet/if_inarp.h>
+#include <netinet/ip.h> /* XXX for struct ip */
+#include <netinet/ip6.h> /* XXX for struct ip6_hdr */
+#include <netinet/tcp.h> /* XXX for struct tcphdr */
#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
@@ -145,6 +148,7 @@
static void mue_start_rx(struct mue_softc *);
static int mue_encap(struct mue_softc *, struct mbuf *, int);
+static void mue_tx_offload(struct mue_softc *, struct mbuf *);
static void mue_setmulti(struct mue_softc *);
static void mue_sethwcsum(struct mue_softc *);
@@ -689,10 +693,10 @@
if (sc->mue_flags & LAN7500) {
if (sc->mue_udev->ud_speed == USB_SPEED_HIGH)
- val = MUE_7500_HS_BUFSIZE /
+ val = MUE_7500_HS_RX_BUFSIZE /
MUE_HS_USB_PKT_SIZE;
else
- val = MUE_7500_FS_BUFSIZE /
+ val = MUE_7500_FS_RX_BUFSIZE /
MUE_FS_USB_PKT_SIZE;
mue_csr_write(sc, MUE_7500_BURST_CAP, val);
mue_csr_write(sc, MUE_7500_BULKIN_DELAY,
@@ -709,7 +713,7 @@
/* Init LTM. */
mue_init_ltm(sc);
- val = MUE_7800_BUFSIZE;
+ val = MUE_7800_RX_BUFSIZE;
switch (sc->mue_udev->ud_speed) {
case USB_SPEED_SUPER:
val /= MUE_SS_USB_PKT_SIZE;
@@ -936,10 +940,11 @@
/* Decide on what our bufsize will be. */
if (sc->mue_flags & LAN7500)
- sc->mue_bufsz = (sc->mue_udev->ud_speed == USB_SPEED_HIGH) ?
- MUE_7500_HS_BUFSIZE : MUE_7500_FS_BUFSIZE;
+ sc->mue_rxbufsz = (sc->mue_udev->ud_speed == USB_SPEED_HIGH) ?
+ MUE_7500_HS_RX_BUFSIZE : MUE_7500_FS_RX_BUFSIZE;
else
- sc->mue_bufsz = MUE_7800_BUFSIZE;
+ sc->mue_rxbufsz = MUE_7800_RX_BUFSIZE;
+ sc->mue_txbufsz = MUE_TX_BUFSIZE;
/* Find endpoints. */
id = usbd_get_interface_descriptor(sc->mue_iface);
@@ -1003,6 +1008,8 @@
IFQ_SET_READY(&ifp->if_snd);
+ ifp->if_capabilities = IFCAP_TSOv4 | IFCAP_TSOv6;
+
sc->mue_ec.ec_capabilities = ETHERCAP_VLAN_MTU;
/* Initialize MII/media info. */
@@ -1120,7 +1127,7 @@
c->mue_idx = i;
if (c->mue_xfer == NULL) {
err = usbd_create_xfer(sc->mue_ep[MUE_ENDPT_RX],
- sc->mue_bufsz, 0, 0, &c->mue_xfer);
+ sc->mue_rxbufsz, 0, 0, &c->mue_xfer);
if (err)
return err;
c->mue_buf = usbd_get_buffer(c->mue_xfer);
@@ -1145,7 +1152,7 @@
c->mue_idx = i;
if (c->mue_xfer == NULL) {
err = usbd_create_xfer(sc->mue_ep[MUE_ENDPT_TX],
- sc->mue_bufsz, USBD_FORCE_SHORT_XFER, 0,
+ sc->mue_txbufsz, USBD_FORCE_SHORT_XFER, 0,
&c->mue_xfer);
if (err)
return err;
@@ -1186,7 +1193,7 @@
/* Start up the receive pipe. */
for (i = 0; i < __arraycount(sc->mue_cdata.mue_rx_chain); i++) {
c = &sc->mue_cdata.mue_rx_chain[i];
- usbd_setup_xfer(c->mue_xfer, c, c->mue_buf, sc->mue_bufsz,
+ usbd_setup_xfer(c->mue_xfer, c, c->mue_buf, sc->mue_rxbufsz,
USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, mue_rxeof);
usbd_transfer(c->mue_xfer);
}
@@ -1205,14 +1212,28 @@
hdr.tx_cmd_a = htole32((m->m_pkthdr.len & MUE_TX_CMD_A_LEN_MASK) |
MUE_TX_CMD_A_FCS);
- /* Disable segmentation offload. */
- hdr.tx_cmd_b = htole32(0);
+
+ if (m->m_pkthdr.csum_flags & (M_CSUM_TSOv4 | M_CSUM_TSOv6)) {
+ hdr.tx_cmd_a |= htole32(MUE_TX_CMD_A_LSO);
+ if (__predict_true(m->m_pkthdr.segsz > MUE_TX_MSS_MIN))
+ hdr.tx_cmd_b = htole32(m->m_pkthdr.segsz <<
+ MUE_TX_CMD_B_MSS_SHIFT);
+ else
+ hdr.tx_cmd_b = htole32(MUE_TX_MSS_MIN <<
+ MUE_TX_CMD_B_MSS_SHIFT);
+ hdr.tx_cmd_b &= htole32(MUE_TX_CMD_B_MSS_MASK);
+ mue_tx_offload(sc, m);
+ } else
+ hdr.tx_cmd_b = 0;
+
memcpy(c->mue_buf, &hdr, sizeof(hdr));
len = sizeof(hdr);
m_copydata(m, 0, m->m_pkthdr.len, c->mue_buf + len);
len += m->m_pkthdr.len;
+ KASSERT(len <= sc->mue_txbufsz);
+
usbd_setup_xfer(c->mue_xfer, c, c->mue_buf, len,
USBD_FORCE_SHORT_XFER, 10000, mue_txeof);
@@ -1230,6 +1251,52 @@
}
static void
+mue_tx_offload(struct mue_softc *sc, struct mbuf *m)
+{
+ struct ether_header *eh;
+ struct ip *ip;
+ struct ip6_hdr *ip6;
+ int offset;
+ bool v4;
+
+ eh = mtod(m, struct ether_header *);
+ switch (htons(eh->ether_type)) {
+ case ETHERTYPE_IP:
+ case ETHERTYPE_IPV6:
+ offset = ETHER_HDR_LEN;
+ break;
+ case ETHERTYPE_VLAN:
+ /* XXX not yet supported */
+ offset = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
+ break;
+ default:
+ /* XXX */
+ panic("%s: unsupported ethertype\n", __func__);
+ /* NOTREACHED */
+ }
+
+ v4 = (m->m_pkthdr.csum_flags & M_CSUM_TSOv4) != 0;
+
+#ifdef DIAGNOSTIC /* XXX */
+ int hlen = offset;
+ if (v4)
+ hlen += M_CSUM_DATA_IPv4_IPHL(m->m_pkthdr.csum_data);
+ else
+ hlen += M_CSUM_DATA_IPv6_IPHL(m->m_pkthdr.csum_data);
+ KASSERT(m->m_len >= hlen + sizeof(struct tcphdr));
+#endif
+
+ /* Packet length should be cleared. */
+ if (v4) {
+ ip = (void *)(mtod(m, char *) + offset);
+ ip->ip_len = 0;
+ } else {
+ ip6 = (void *)(mtod(m, char *) + offset);
+ ip6->ip6_plen = 0;
+ }
+}
+
+static void
mue_setmulti(struct mue_softc *sc)
{
struct ifnet *ifp = GET_IFP(sc);
@@ -1380,7 +1447,7 @@
usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
- if (__predict_false(total_len > sc->mue_bufsz)) {
+ if (__predict_false(total_len > sc->mue_rxbufsz)) {
DPRINTF(sc, "too large transfer\n");
goto done;
}
@@ -1442,7 +1509,7 @@
done:
/* Setup new transfer. */
- usbd_setup_xfer(xfer, c, c->mue_buf, sc->mue_bufsz,
+ usbd_setup_xfer(xfer, c, c->mue_buf, sc->mue_rxbufsz,
USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, mue_rxeof);
usbd_transfer(xfer);
}
diff -r 9b8750459c9b -r d8be1f2879fc sys/dev/usb/if_muereg.h
--- a/sys/dev/usb/if_muereg.h Thu Aug 30 05:39:21 2018 +0000
+++ b/sys/dev/usb/if_muereg.h Thu Aug 30 09:00:08 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_muereg.h,v 1.1 2018/08/25 20:12:22 rin Exp $ */
+/* $NetBSD: if_muereg.h,v 1.2 2018/08/30 09:00:08 rin Exp $ */
/* $OpenBSD: if_muereg.h,v 1.1 2018/08/03 01:50:15 kevlo Exp $ */
/*
@@ -20,6 +20,15 @@
#ifndef _IF_MUEREG_H_
#define _IF_MUEREG_H_
+/* XXX for ETHER_HDR_LEN and ETHER_VLAN_ENCAP_LEN */
+#include <net/if_ether.h>
+
+/* XXX for IP_MAXPACKET */
+#include <netinet/ip.h>
+
+/* XXX for struct mue_txbuf_hdr */
+#include <dev/usb/if_muevar.h>
+
/* USB vendor requests */
#define MUE_UR_WRITEREG 0xa0
#define MUE_UR_READREG 0xa1
@@ -104,15 +113,17 @@
#define MUE_SS_USB_PKT_SIZE 1024
#define MUE_HS_USB_PKT_SIZE 512
#define MUE_FS_USB_PKT_SIZE 64
-#define MUE_7500_HS_BUFSIZE \
+#define MUE_7500_HS_RX_BUFSIZE \
(16 * 1024 + 5 * MUE_HS_USB_PKT_SIZE)
-#define MUE_7500_FS_BUFSIZE \
+#define MUE_7500_FS_RX_BUFSIZE \
(6 * 1024 + 33 * MUE_FS_USB_PKT_SIZE)
#define MUE_7500_MAX_RX_FIFO_SIZE (20 * 1024)
#define MUE_7500_MAX_TX_FIFO_SIZE (12 * 1024)
-#define MUE_7800_BUFSIZE (12 * 1024)
-#define MUE_7800_MAX_RX_FIFO_SIZE MUE_7800_BUFSIZE
-#define MUE_7800_MAX_TX_FIFO_SIZE MUE_7800_BUFSIZE
+#define MUE_7800_RX_BUFSIZE (12 * 1024)
+#define MUE_7800_MAX_RX_FIFO_SIZE MUE_7800_RX_BUFSIZE
+#define MUE_7800_MAX_TX_FIFO_SIZE MUE_7800_RX_BUFSIZE
+#define MUE_TX_BUFSIZE (sizeof(struct mue_txbuf_hdr) + \
+ ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN + IP_MAXPACKET)
/* interrupt endpoint control register */
#define MUE_INT_EP_CTL_PHY_INT 0x20000
diff -r 9b8750459c9b -r d8be1f2879fc sys/dev/usb/if_muevar.h
--- a/sys/dev/usb/if_muevar.h Thu Aug 30 05:39:21 2018 +0000
+++ b/sys/dev/usb/if_muevar.h Thu Aug 30 09:00:08 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_muevar.h,v 1.1 2018/08/25 20:12:22 rin Exp $ */
+/* $NetBSD: if_muevar.h,v 1.2 2018/08/30 09:00:08 rin Exp $ */
/* $OpenBSD: if_muereg.h,v 1.1 2018/08/03 01:50:15 kevlo Exp $ */
/*
@@ -55,8 +55,15 @@
uint32_t tx_cmd_a;
#define MUE_TX_CMD_A_LEN_MASK 0x000fffff
#define MUE_TX_CMD_A_FCS 0x00400000
+#define MUE_TX_CMD_A_TPE 0x02000000
+#define MUE_TX_CMD_A_IPE 0x04000000
+#define MUE_TX_CMD_A_LSO 0x08000000
uint32_t tx_cmd_b;
+#define MUE_TX_MSS_MIN 8
+#define MUE_TX_CMD_B_MSS_SHIFT 16
+#define MUE_TX_CMD_B_MSS_MASK 0x3fff0000
+
} __packed;
struct mue_softc {
@@ -99,7 +106,8 @@
krndsource_t mue_rnd_source;
int mue_phyno;
- uint32_t mue_bufsz;
+ uint32_t mue_rxbufsz;
+ uint32_t mue_txbufsz;
int mue_link;
};
Home |
Main Index |
Thread Index |
Old Index