[rtems-libbsd commit] ffec: Add checksum offload

Sebastian Huber sebh at rtems.org
Wed Oct 25 12:31:12 UTC 2017


Module:    rtems-libbsd
Branch:    master
Commit:    a8a9cf1847f2832e9e5ce54e862063d7907fc42d
Changeset: http://git.rtems.org/rtems-libbsd/commit/?id=a8a9cf1847f2832e9e5ce54e862063d7907fc42d

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Wed Oct 25 10:17:23 2017 +0200

ffec: Add checksum offload

Update #3090.

---

 freebsd/sys/dev/ffec/if_ffec.c    | 42 ++++++++++++++++++++++++++++++++++++---
 freebsd/sys/dev/ffec/if_ffecreg.h | 14 +++++++++++++
 2 files changed, 53 insertions(+), 3 deletions(-)

diff --git a/freebsd/sys/dev/ffec/if_ffec.c b/freebsd/sys/dev/ffec/if_ffec.c
index d44d6c5..6f505ac 100644
--- a/freebsd/sys/dev/ffec/if_ffec.c
+++ b/freebsd/sys/dev/ffec/if_ffec.c
@@ -81,6 +81,8 @@ __FBSDID("$FreeBSD$");
 #include <net/if_types.h>
 #include <net/if_var.h>
 #include <net/if_vlan_var.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
 
 #include <dev/ffec/if_ffecreg.h>
 #include <dev/ofw/ofw_bus.h>
@@ -620,7 +622,9 @@ ffec_encap(struct ifnet *ifp, struct ffec_softc *sc, struct mbuf *m0,
 	int error, i, nsegs;
 	struct ffec_bufmap *bmap;
 	uint32_t tx_idx;
+	int csum_flags;
 	uint32_t flags;
+	uint32_t flags2;
 
 	FFEC_ASSERT_LOCKED(sc);
 
@@ -653,6 +657,27 @@ ffec_encap(struct ifnet *ifp, struct ffec_softc *sc, struct mbuf *m0,
 #endif /* __rtems__ */
 	bmap->mbuf = m0;
 
+	flags2 = FEC_TXDESC_INT;
+	csum_flags = m0->m_pkthdr.csum_flags;
+
+	if ((csum_flags & CSUM_IP) != 0) {
+		struct mbuf *n;
+		int off;
+		int off2;
+		struct ip *ip;
+
+		flags2 |= FEC_TXDESC_IINS;
+		n = m_getptr(m0, sizeof(struct ether_header), &off);
+		ip = (struct ip *)mtodo(n, off);
+		ip->ip_sum = 0;
+
+		off2 = m0->m_pkthdr.csum_data;
+		if ((csum_flags & (CSUM_TCP | CSUM_UDP)) != 0 && off2 != 0) {
+			flags2 |= FEC_TXDESC_PINS;
+			*(uint16_t *)((caddr_t)(ip + 1) + off2) = 0;
+		}
+	}
+
 	/*
 	 * Fill in the TX descriptors back to front so that READY bit in first
 	 * descriptor is set last.
@@ -666,6 +691,7 @@ ffec_encap(struct ifnet *ifp, struct ffec_softc *sc, struct mbuf *m0,
 		tx_idx = prev_txidx(tx_idx);;
 		tx_desc = &sc->txdesc_ring[tx_idx];
 		tx_desc->buf_paddr = segs[i].ds_addr;
+		tx_desc->flags2 = flags2;
 #ifdef __rtems__
 		rtems_cache_flush_multiple_data_lines((void *)segs[i].ds_addr,
 		    segs[i].ds_len);
@@ -793,6 +819,7 @@ ffec_setup_rxdesc(struct ffec_softc *sc, int idx, bus_addr_t paddr)
 	 */
 	nidx = next_rxidx(idx);
 	sc->rxdesc_ring[idx].buf_paddr = (uint32_t)paddr;
+	sc->rxdesc_ring[idx].flags2 = FEC_RXDESC_INT;
 	wmb();
 	sc->rxdesc_ring[idx].flags_len = FEC_RXDESC_EMPTY | 
 		((nidx == 0) ? FEC_RXDESC_WRAP : 0);
@@ -851,7 +878,7 @@ ffec_alloc_mbufcl(struct ffec_softc *sc)
 }
 
 static void
-ffec_rxfinish_onebuf(struct ffec_softc *sc, int len)
+ffec_rxfinish_onebuf(struct ffec_softc *sc, int len, uint32_t flags2)
 {
 	struct mbuf *m, *newmbuf;
 	struct ffec_bufmap *bmap;
@@ -898,6 +925,12 @@ ffec_rxfinish_onebuf(struct ffec_softc *sc, int len)
 	m->m_pkthdr.len = len;
 	m->m_pkthdr.rcvif = sc->ifp;
 
+	if ((flags2 & (FEC_RXDESC_ICE | FEC_RXDESC_PCR)) == 0) {
+		m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED | CSUM_IP_VALID |
+		    CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
+		m->m_pkthdr.csum_data = 0xffff;
+	}
+
 	if (sc->fectype & FECFLAG_RACC) {
 		/* We use the RACC[SHIFT16] feature */
 		m->m_data = mtod(m, uint8_t *) + 2;
@@ -973,7 +1006,7 @@ ffec_rxfinish_locked(struct ffec_softc *sc)
 			/*
 			 *  Normal case: a good frame all in one buffer.
 			 */
-			ffec_rxfinish_onebuf(sc, len);
+			ffec_rxfinish_onebuf(sc, len, desc->flags2);
 		}
 		sc->rx_idx = next_rxidx(sc->rx_idx);
 	}
@@ -1305,6 +1338,7 @@ ffec_init_locked(struct ffec_softc *sc)
 	regval |= FEC_ECR_DBSWP;
 #endif
 	regval |= FEC_ECR_ETHEREN;
+	regval |= FEC_ECR_EN1588;
 	WR4(sc, FEC_ECR_REG, regval);
 
 	ifp->if_drv_flags |= IFF_DRV_RUNNING;
@@ -1962,8 +1996,10 @@ ffec_attach(device_t dev)
 	ifp->if_softc = sc;
 	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
-	ifp->if_capabilities = IFCAP_VLAN_MTU;
+	ifp->if_capabilities = IFCAP_HWCSUM | IFCAP_HWCSUM_IPV6 |
+	    IFCAP_VLAN_MTU;
 	ifp->if_capenable = ifp->if_capabilities;
+	ifp->if_hwassist = CSUM_IP | CSUM_TCP | CSUM_UDP;
 	ifp->if_start = ffec_txstart;
 	ifp->if_ioctl = ffec_ioctl;
 	ifp->if_init = ffec_init;
diff --git a/freebsd/sys/dev/ffec/if_ffecreg.h b/freebsd/sys/dev/ffec/if_ffecreg.h
index 481bc30..9ec5b37 100644
--- a/freebsd/sys/dev/ffec/if_ffecreg.h
+++ b/freebsd/sys/dev/ffec/if_ffecreg.h
@@ -295,6 +295,11 @@ struct ffec_hwdesc
 {
 	uint32_t	flags_len;
 	uint32_t	buf_paddr;
+	uint32_t	flags2;
+	uint32_t	hlen_proto;
+	uint32_t	bdu;
+	uint32_t	ts;
+	uint32_t	res[2];
 };
 
 #define	FEC_TXDESC_READY		(1U << 31)
@@ -306,6 +311,11 @@ struct ffec_hwdesc
 #define	FEC_TXDESC_ABC			(1 << 25)
 #define	FEC_TXDESC_LEN_MASK		(0xffff)
 
+#define	FEC_TXDESC_INT			(1 << 30)
+#define	FEC_TXDESC_TS			(1 << 29)
+#define	FEC_TXDESC_PINS			(1 << 28)
+#define	FEC_TXDESC_IINS			(1 << 27)
+
 #define	FEC_RXDESC_EMPTY		(1U << 31)
 #define	FEC_RXDESC_R01			(1 << 30)
 #define	FEC_RXDESC_WRAP			(1 << 29)
@@ -321,6 +331,10 @@ struct ffec_hwdesc
 #define	FEC_RXDESC_TR			(1 << 16)
 #define	FEC_RXDESC_LEN_MASK		(0xffff)
 
+#define	FEC_RXDESC_INT			(1 << 23)
+#define	FEC_RXDESC_ICE			(1 << 5)
+#define	FEC_RXDESC_PCR			(1 << 4)
+
 #define	FEC_RXDESC_ERROR_BITS	(FEC_RXDESC_LG | FEC_RXDESC_NO | \
     FEC_RXDESC_OV | FEC_RXDESC_TR)
 



More information about the vc mailing list