Add hardware checksumming support.
This commit is contained in:
parent
40b201d5b9
commit
eebfc9ef1e
@ -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)
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user