Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 20 Nov 2009 20:33:59 +0000 (UTC)
From:      Pyun YongHyeon <yongari@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r199611 - head/sys/dev/et
Message-ID:  <200911202033.nAKKXx58055723@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: yongari
Date: Fri Nov 20 20:33:59 2009
New Revision: 199611
URL: http://svn.freebsd.org/changeset/base/199611

Log:
  Add IPv4/TCP/UDP Tx checksum offloading support. It seems the
  controller also has support for IP/TCP checksum offloading for Rx
  path. But I failed to find to way to enable Rx MAC to compute the
  checksum of received frames.

Modified:
  head/sys/dev/et/if_et.c
  head/sys/dev/et/if_etvar.h

Modified: head/sys/dev/et/if_et.c
==============================================================================
--- head/sys/dev/et/if_et.c	Fri Nov 20 20:25:21 2009	(r199610)
+++ head/sys/dev/et/if_et.c	Fri Nov 20 20:33:59 2009	(r199611)
@@ -80,6 +80,8 @@ MODULE_DEPEND(et, miibus, 1, 1, 1);
 static int msi_disable = 0;
 TUNABLE_INT("hw.et.msi_disable", &msi_disable);
 
+#define	ET_CSUM_FEATURES	(CSUM_IP | CSUM_TCP | CSUM_UDP)
+
 static int	et_probe(device_t);
 static int	et_attach(device_t);
 static int	et_detach(device_t);
@@ -332,7 +334,7 @@ et_attach(device_t dev)
 	ifp->if_ioctl = et_ioctl;
 	ifp->if_start = et_start;
 	ifp->if_mtu = ETHERMTU;
-	ifp->if_capabilities = IFCAP_VLAN_MTU;
+	ifp->if_capabilities = /*IFCAP_TXCSUM*/IFCAP_HWCSUM | IFCAP_VLAN_MTU;
 	ifp->if_capenable = ifp->if_capabilities;
 	IFQ_SET_MAXLEN(&ifp->if_snd, ET_TX_NDESC);
 	IFQ_SET_READY(&ifp->if_snd);
@@ -1175,7 +1177,7 @@ et_ioctl(struct ifnet *ifp, u_long cmd, 
 	struct et_softc *sc = ifp->if_softc;
 	struct mii_data *mii = device_get_softc(sc->sc_miibus);
 	struct ifreq *ifr = (struct ifreq *)data;
-	int error = 0, max_framelen;
+	int error = 0, mask, max_framelen;
 
 /* XXX LOCKSUSED */
 	switch (cmd) {
@@ -1232,6 +1234,20 @@ et_ioctl(struct ifnet *ifp, u_long cmd, 
 		}
 		break;
 
+	case SIOCSIFCAP:
+		ET_LOCK(sc);
+		mask = ifr->ifr_reqcap ^ ifp->if_capenable;
+		if ((mask & IFCAP_TXCSUM) != 0 &&
+		    (IFCAP_TXCSUM & ifp->if_capabilities) != 0) {
+			ifp->if_capenable ^= IFCAP_TXCSUM;
+			if ((IFCAP_TXCSUM & ifp->if_capenable) != 0)
+				ifp->if_hwassist |= ET_CSUM_FEATURES;
+			else
+				ifp->if_hwassist &= ~ET_CSUM_FEATURES;
+		}
+		ET_UNLOCK(sc);
+		break;
+
 	default:
 		error = ether_ioctl(ifp, cmd, data);
 		break;
@@ -2026,7 +2042,7 @@ et_encap(struct et_softc *sc, struct mbu
 	struct et_txdesc *td;
 	bus_dmamap_t map;
 	int error, maxsegs, first_idx, last_idx, i;
-	uint32_t tx_ready_pos, last_td_ctrl2;
+	uint32_t csum_flags, tx_ready_pos, last_td_ctrl2;
 
 	maxsegs = ET_TX_NDESC - tbd->tbd_used;
 	if (maxsegs > ET_NSEG_MAX)
@@ -2088,6 +2104,15 @@ et_encap(struct et_softc *sc, struct mbu
 		last_td_ctrl2 |= ET_TDCTRL2_INTR;
 	}
 
+	csum_flags = 0;
+	if ((m->m_pkthdr.csum_flags & ET_CSUM_FEATURES) != 0) {
+		if ((m->m_pkthdr.csum_flags & CSUM_IP) != 0)
+			csum_flags |= ET_TDCTRL2_CSUM_IP;
+		if ((m->m_pkthdr.csum_flags & CSUM_UDP) != 0)
+			csum_flags |= ET_TDCTRL2_CSUM_UDP;
+		else if ((m->m_pkthdr.csum_flags & CSUM_TCP) != 0)
+			csum_flags |= ET_TDCTRL2_CSUM_TCP;
+	}
 	last_idx = -1;
 	for (i = 0; i < ctx.nsegs; ++i) {
 		int idx;
@@ -2097,11 +2122,11 @@ et_encap(struct et_softc *sc, struct mbu
 		td->td_addr_hi = htole32(ET_ADDR_HI(segs[i].ds_addr));
 		td->td_addr_lo = htole32(ET_ADDR_LO(segs[i].ds_addr));
 		td->td_ctrl1 =  htole32(segs[i].ds_len & ET_TDCTRL1_LEN_MASK);
-
 		if (i == ctx.nsegs - 1) {	/* Last frag */
-			td->td_ctrl2 = htole32(last_td_ctrl2);
+			td->td_ctrl2 = htole32(last_td_ctrl2 | csum_flags);
 			last_idx = idx;
-		}
+		} else
+			td->td_ctrl2 = htole32(csum_flags);
 
 		MPASS(tx_ring->tr_ready_index < ET_TX_NDESC);
 		if (++tx_ring->tr_ready_index == ET_TX_NDESC) {

Modified: head/sys/dev/et/if_etvar.h
==============================================================================
--- head/sys/dev/et/if_etvar.h	Fri Nov 20 20:25:21 2009	(r199610)
+++ head/sys/dev/et/if_etvar.h	Fri Nov 20 20:33:59 2009	(r199611)
@@ -111,6 +111,18 @@ struct et_txdesc {
 #define ET_TDCTRL2_LAST_FRAG	0x00000001
 #define ET_TDCTRL2_FIRST_FRAG	0x00000002
 #define ET_TDCTRL2_INTR		0x00000004
+#define ET_TDCTRL2_CTRL_WORD	0x00000008
+#define ET_TDCTRL2_HDX_BACKP	0x00000010
+#define ET_TDCTRL2_XMIT_PAUSE	0x00000020
+#define ET_TDCTRL2_FRAME_ERR	0x00000040
+#define ET_TDCTRL2_NO_CRC	0x00000080
+#define ET_TDCTRL2_MAC_OVRRD	0x00000100
+#define ET_TDCTRL2_PAD_PACKET	0x00000200
+#define ET_TDCTRL2_JUMBO_PACKET	0x00000400
+#define ET_TDCTRL2_INS_VLAN	0x00000800
+#define ET_TDCTRL2_CSUM_IP	0x00001000
+#define ET_TDCTRL2_CSUM_TCP	0x00002000
+#define ET_TDCTRL2_CSUM_UDP	0x00004000
 
 struct et_rxdesc {
 	uint32_t	rd_addr_lo;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200911202033.nAKKXx58055723>