Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/cadence Add hardware checksumming support.



details:   https://anonhg.NetBSD.org/src/rev/eca020924f16
branches:  trunk
changeset: 340148:eca020924f16
user:      rjs <rjs%NetBSD.org@localhost>
date:      Mon Aug 24 18:51:37 2015 +0000

description:
Add hardware checksumming support.

diffstat:

 sys/dev/cadence/cemacreg.h |  33 +++++++++++++--------
 sys/dev/cadence/if_cemac.c |  68 +++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 81 insertions(+), 20 deletions(-)

diffs (187 lines):

diff -r a8db5825ff27 -r eca020924f16 sys/dev/cadence/cemacreg.h
--- a/sys/dev/cadence/cemacreg.h        Mon Aug 24 18:40:57 2015 +0000
+++ b/sys/dev/cadence/cemacreg.h        Mon Aug 24 18:51:37 2015 +0000
@@ -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 @@
 #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)
diff -r a8db5825ff27 -r eca020924f16 sys/dev/cadence/if_cemac.c
--- a/sys/dev/cadence/if_cemac.c        Mon Aug 24 18:40:57 2015 +0000
+++ b/sys/dev/cadence/if_cemac.c        Mon Aug 24 18:51:37 2015 +0000
@@ -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 @@
                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 @@
                                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 @@
            | 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 @@
                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 @@
 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



Home | Main Index | Thread Index | Old Index