Add hardware checksumming support.

This commit is contained in:
rjs 2015-08-24 18:51:37 +00:00
parent 40b201d5b9
commit eebfc9ef1e
2 changed files with 81 additions and 20 deletions

View File

@ -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)

View File

@ -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);
@ -578,6 +595,16 @@ cemac_init(struct cemac_softc *sc)
CEMAC_WRITE(ETH_CTL, ETH_CTL_TE | ETH_CTL_RE | ETH_CTL_ISR
| 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.
*/
@ -726,10 +753,16 @@ cemac_ifioctl(struct ifnet *ifp, u_long cmd, void *data)
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