Module Name:    src
Committed By:   rjs
Date:           Mon Aug 24 18:51:37 UTC 2015

Modified Files:
        src/sys/dev/cadence: cemacreg.h if_cemac.c

Log Message:
Add hardware checksumming support.


To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 src/sys/dev/cadence/cemacreg.h
cvs rdiff -u -r1.6 -r1.7 src/sys/dev/cadence/if_cemac.c

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/cadence/cemacreg.h
diff -u src/sys/dev/cadence/cemacreg.h:1.2 src/sys/dev/cadence/cemacreg.h:1.3
--- src/sys/dev/cadence/cemacreg.h:1.2	Thu Aug 13 14:51:35 2015
+++ src/sys/dev/cadence/cemacreg.h	Mon Aug 24 18:51:37 2015
@@ -1,4 +1,4 @@
-/*      $NetBSD: cemacreg.h,v 1.2 2015/08/13 14:51:35 rjs Exp $	*/
+/*      $NetBSD: cemacreg.h,v 1.3 2015/08/24 18:51:37 rjs Exp $	*/
 
 /*-
  * Copyright (c) 2015  Genetec Corporation.  All rights reserved.
@@ -164,6 +164,7 @@
 #define GEM_CFG_CLK_64	__SHIFTIN(4, GEM_CFG_CLK)
 #define GEM_CFG_CLK_96	__SHIFTIN(5, GEM_CFG_CLK)
 #define GEM_CFG_DBW	__BITS(22, 21)
+#define	GEM_CFG_RX_CHKSUM_OFFLD_EN	__BIT(24)
 
 /* Status Register bits: */
 #define	ETH_SR_IDLE	0x0004U	/* 1 = PHY logic is running		*/
@@ -244,30 +245,36 @@ typedef struct eth_dsc {
 #define	ETH_RDSC_F_USED		0x00000001U
 
 /* frame info bits: */
-#define	ETH_RDSC_I_BCAST	0x80000000U
-#define	ETH_RDSC_I_MULTICAST	0x40000000U
-#define	ETH_RDSC_I_UNICAST	0x20000000U
+#define	ETH_RDSC_I_BCAST	__BIT(31)
+#define	ETH_RDSC_I_MULTICAST	__BIT(30)
+#define	ETH_RDSC_I_UNICAST	__BIT(29)
 #define	ETH_RDSC_I_VLAN		0x10000000U
 #define	ETH_RDSC_I_UNKNOWN_SRC	0x08000000U
 #define	ETH_RDSC_I_MATCH1	0x04000000U
 #define	ETH_RDSC_I_MATCH2	0x02000000U
 #define	ETH_RDSC_I_MATCH3	0x01000000U
 #define	ETH_RDSC_I_MATCH4	0x00800000U
-#define	ETH_RDSC_I_LEN		0x000007FFU
+#define	ETH_RDSC_I_CHKSUM	__BITS(23, 22)
+#define	ETH_RDSC_I_CHKSUM_NONE	__SHIFTIN(0, ETH_RDSC_I_CHKSUM)
+#define	ETH_RDSC_I_CHKSUM_IP	__SHIFTIN(1, ETH_RDSC_I_CHKSUM)
+#define	ETH_RDSC_I_CHKSUM_TCP	__SHIFTIN(2, ETH_RDSC_I_CHKSUM)
+#define	ETH_RDSC_I_CHKSUM_UDP	__SHIFTIN(3, ETH_RDSC_I_CHKSUM)
+#define	ETH_RDSC_I_LEN		__BITS(13, 0)
 
 #define ETH_TDSC_I_USED				__BIT(31)	/* done transmitting */
 #define ETH_TDSC_I_WRAP				__BIT(30)	/* end of descr ring */
 #define ETH_TDSC_I_RETRY_ERR			__BIT(29)
 #define ETH_TDSC_I_AHB_ERR			__BIT(27)
 #define ETH_TDSC_I_LATE_COLL			__BIT(26)
-#define ETH_TDSC_I_CKSUM_GEN_STAT_MASK		__BIT(20)
-#define ETH_TDSC_I_CKSUM_GEN_STAT_VLAN_HDR_ERR	__BIT(20)
-#define ETH_TDSC_I_CKSUM_GEN_STAT_SNAP_HDR_ERR	__BIT(20)
-#define ETH_TDSC_I_CKSUM_GEN_STAT_IP_HDR_ERR	__BIT(20)
-#define ETH_TDSC_I_CKSUM_GEN_STAT_UNKNOWN_TYPE	__BIT(20)
-#define ETH_TDSC_I_CKSUM_GEN_STAT_UNSUPP_FRAG	__BIT(20)
-#define ETH_TDSC_I_CKSUM_GEN_STAT_NOT_TCPUDP	__BIT(20)
-#define ETH_TDSC_I_CKSUM_GEN_STAT_SHORT_PKT	__BIT(20)
+#define	ETH_TDSC_I_CHKSUM			__BITS(22, 20)
+#define ETH_TDSC_I_CHKSUM_GEN_STAT_NO_ERR	__SHIFTIN(0, ETH_TDSC_I_CHKSUM)
+#define ETH_TDSC_I_CHKSUM_GEN_STAT_VLAN_HDR_ERR	__SHIFTIN(1, ETH_TDSC_I_CHKSUM)
+#define ETH_TDSC_I_CHKSUM_GEN_STAT_SNAP_HDR_ERR	__SHIFTIN(2, ETH_TDSC_I_CHKSUM)
+#define ETH_TDSC_I_CHKSUM_GEN_STAT_IP_HDR_ERR	__SHIFTIN(3, ETH_TDSC_I_CHKSUM)
+#define ETH_TDSC_I_CHKSUM_GEN_STAT_UNKNOWN_TYPE	__SHIFTIN(4, ETH_TDSC_I_CHKSUM)
+#define ETH_TDSC_I_CHKSUM_GEN_STAT_UNSUPP_FRAG	__SHIFTIN(5, ETH_TDSC_I_CHKSUM)
+#define ETH_TDSC_I_CHKSUM_GEN_STAT_NOT_TCPUDP	__SHIFTIN(6, ETH_TDSC_I_CHKSUM)
+#define ETH_TDSC_I_CHKSUM_GEN_STAT_SHORT_PKT	__SHIFTIN(7, ETH_TDSC_I_CHKSUM)
 #define ETH_TDSC_I_NO_CRC_APPENDED		__BIT(16)
 #define ETH_TDSC_I_LAST_BUF			__BIT(15)	/* last buf in frame */
 #define ETH_TDSC_I_LEN				__BITS(13, 0)

Index: src/sys/dev/cadence/if_cemac.c
diff -u src/sys/dev/cadence/if_cemac.c:1.6 src/sys/dev/cadence/if_cemac.c:1.7
--- src/sys/dev/cadence/if_cemac.c:1.6	Mon Aug 24 18:40:57 2015
+++ src/sys/dev/cadence/if_cemac.c	Mon Aug 24 18:51:37 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_cemac.c,v 1.6 2015/08/24 18:40:57 rjs Exp $	*/
+/*	$NetBSD: if_cemac.c,v 1.7 2015/08/24 18:51:37 rjs Exp $	*/
 
 /*
  * Copyright (c) 2015  Genetec Corporation.  All rights reserved.
@@ -40,7 +40,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_cemac.c,v 1.6 2015/08/24 18:40:57 rjs Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_cemac.c,v 1.7 2015/08/24 18:51:37 rjs Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -322,7 +322,7 @@ cemac_intr(void *arg)
 		uint32_t nfo;
 		DPRINTFN(2,("#2 RDSC[%i].INFO=0x%08X\n", sc->rxqi % RX_QLEN, sc->RDSC[sc->rxqi % RX_QLEN].Info));
 		while (sc->RDSC[(bi = sc->rxqi % RX_QLEN)].Addr & ETH_RDSC_F_USED) {
-			int fl;
+			int fl, csum;
 			struct mbuf *m;
 
 			nfo = sc->RDSC[bi].Info;
@@ -339,6 +339,23 @@ cemac_intr(void *arg)
 				sc->rxq[bi].m->m_pkthdr.rcvif = ifp;
 				sc->rxq[bi].m->m_pkthdr.len =
 					sc->rxq[bi].m->m_len = fl;
+				switch (nfo & ETH_RDSC_I_CHKSUM) {
+				case ETH_RDSC_I_CHKSUM_IP:
+					csum = M_CSUM_IPv4;
+					break;
+				case ETH_RDSC_I_CHKSUM_UDP:
+					csum = M_CSUM_IPv4 | M_CSUM_UDPv4 |
+					    M_CSUM_UDPv6;
+					break;
+				case ETH_RDSC_I_CHKSUM_TCP:
+					csum = M_CSUM_IPv4 | M_CSUM_TCPv4 |
+					    M_CSUM_TCPv6;
+					break;
+				default:
+					csum = 0;
+					break;
+				}
+				sc->rxq[bi].m->m_pkthdr.csum_flags = csum;
 				bpf_mtap(ifp, sc->rxq[bi].m);
 				DPRINTFN(2,("received %u bytes packet\n", fl));
                                 (*ifp->if_input)(ifp, sc->rxq[bi].m);
@@ -579,6 +596,16 @@ cemac_init(struct cemac_softc *sc)
 	    | ETH_CTL_CSR | ETH_CTL_MPE);
 #endif
 	/*
+	 * We can support hardware checksumming.
+	 */
+	ifp->if_capabilities |=
+	    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;
+
+	/*
 	 * We can support 802.1Q VLAN-sized frames.
 	 */
 	sc->sc_ethercom.ec_capabilities |= ETHERCAP_VLAN_MTU;
@@ -726,10 +753,16 @@ cemac_ifioctl(struct ifnet *ifp, u_long 
 		break;
 	default:
 		error = ether_ioctl(ifp, cmd, data);
-		if (error == ENETRESET) {
-			if (ifp->if_flags & IFF_RUNNING)
-				cemac_setaddr(ifp);
-			error = 0;
+		if (error != ENETRESET)
+			break;
+		error = 0;
+
+		if (cmd == SIOCSIFCAP) {
+			error = (*ifp->if_init)(ifp);
+		} else if (cmd != SIOCADDMULTI && cmd != SIOCDELMULTI)
+			;
+		else if (ifp->if_flags & IFF_RUNNING) {
+			cemac_setaddr(ifp);
 		}
 	}
 	splx(s);
@@ -856,10 +889,31 @@ static int
 cemac_ifinit(struct ifnet *ifp)
 {
 	struct cemac_softc *sc = ifp->if_softc;
+	uint32_t dma, cfg;
 	int s = splnet();
 
 	callout_stop(&sc->cemac_tick_ch);
 
+	if (ISSET(sc->cemac_flags, CEMAC_FLAG_GEM)) {
+
+		if (ifp->if_capenable &
+		    (IFCAP_CSUM_IPv4_Tx |
+			IFCAP_CSUM_TCPv4_Tx | IFCAP_CSUM_UDPv4_Tx |
+			IFCAP_CSUM_TCPv6_Tx | IFCAP_CSUM_UDPv6_Tx)) {
+			dma = CEMAC_READ(GEM_DMA_CFG);
+			dma |= GEM_DMA_CFG_CHKSUM_GEN_OFFLOAD_EN;
+			CEMAC_WRITE(GEM_DMA_CFG, dma);
+		}
+		if (ifp->if_capenable &
+		    (IFCAP_CSUM_IPv4_Rx |
+			IFCAP_CSUM_TCPv4_Rx | IFCAP_CSUM_UDPv4_Rx |
+			IFCAP_CSUM_TCPv6_Rx | IFCAP_CSUM_UDPv6_Rx)) {
+			cfg = CEMAC_READ(ETH_CFG);
+			cfg |= GEM_CFG_RX_CHKSUM_OFFLD_EN;
+			CEMAC_WRITE(ETH_CFG, cfg);
+		}
+	}
+
 	// enable interrupts
 	CEMAC_WRITE(ETH_IDR, -1);
 	CEMAC_WRITE(ETH_IER, ETH_ISR_RCOM | ETH_ISR_TBRE | ETH_ISR_TIDLE

Reply via email to