diff options
author | Brad Smith <brad@cvs.openbsd.org> | 2008-08-11 22:42:20 +0000 |
---|---|---|
committer | Brad Smith <brad@cvs.openbsd.org> | 2008-08-11 22:42:20 +0000 |
commit | 0f0221b10fcff87d22c7e748f00c4dfb16c27f17 (patch) | |
tree | b62d84c043ebcd805cbd2093133109d45af8e2f3 /sys/dev/ic | |
parent | f061b55d3cc19323d844fb6159a9058dc00c6b4d (diff) |
Add support for TX/RX checksum offload for newer re(4) chipsets.
Tested by naddy@
From FreeBSD
Diffstat (limited to 'sys/dev/ic')
-rw-r--r-- | sys/dev/ic/re.c | 58 | ||||
-rw-r--r-- | sys/dev/ic/rtl81x9reg.h | 11 |
2 files changed, 48 insertions, 21 deletions
diff --git a/sys/dev/ic/re.c b/sys/dev/ic/re.c index ff80af8acd7..b680dfc6532 100644 --- a/sys/dev/ic/re.c +++ b/sys/dev/ic/re.c @@ -1,4 +1,4 @@ -/* $OpenBSD: re.c,v 1.85 2008/08/05 01:58:47 brad Exp $ */ +/* $OpenBSD: re.c,v 1.86 2008/08/11 22:42:19 brad Exp $ */ /* $FreeBSD: if_re.c,v 1.31 2004/09/04 07:54:05 ru Exp $ */ /* * Copyright (c) 1997, 1998-2003 @@ -1067,11 +1067,8 @@ re_attach(struct rl_softc *sc, const char *intrstr) IFQ_SET_MAXLEN(&ifp->if_snd, RL_TX_QLEN); IFQ_SET_READY(&ifp->if_snd); - - ifp->if_capabilities = IFCAP_VLAN_MTU; - if ((sc->rl_flags & RL_FLAG_DESCV2) == 0) - ifp->if_capabilities |= IFCAP_CSUM_IPv4 | - IFCAP_CSUM_TCPv4 | IFCAP_CSUM_UDPv4; + ifp->if_capabilities = IFCAP_VLAN_MTU | IFCAP_CSUM_IPv4 | + IFCAP_CSUM_TCPv4 | IFCAP_CSUM_UDPv4; #if NVLAN > 0 ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING; @@ -1292,7 +1289,7 @@ re_rxeof(struct rl_softc *sc) int i, total_len; struct rl_desc *cur_rx; struct rl_rxsoft *rxs; - u_int32_t rxstat; + u_int32_t rxstat, rxvlan; ifp = &sc->sc_arpcom.ac_if; @@ -1301,6 +1298,7 @@ re_rxeof(struct rl_softc *sc) RL_RXDESCSYNC(sc, i, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); rxstat = letoh32(cur_rx->rl_cmdstat); + rxvlan = letoh32(cur_rx->rl_vlanctl); RL_RXDESCSYNC(sc, i, BUS_DMASYNC_PREREAD); if ((rxstat & RL_RDESC_STAT_OWN) != 0) break; @@ -1413,7 +1411,19 @@ re_rxeof(struct rl_softc *sc) /* Do RX checksumming */ if (sc->rl_flags & RL_FLAG_DESCV2) { - /* XXX V2 CSUM */ + /* Check IP header checksum */ + if ((rxstat & RL_RDESC_STAT_PROTOID) && + !(rxstat & RL_RDESC_STAT_IPSUMBAD) && + (rxvlan & RL_RDESC_IPV4)) + m->m_pkthdr.csum_flags |= M_IPV4_CSUM_IN_OK; + + /* Check TCP/UDP checksum */ + if (((rxstat & RL_RDESC_STAT_TCP) && + !(rxstat & RL_RDESC_STAT_TCPSUMBAD)) || + ((rxstat & RL_RDESC_STAT_UDP) && + !(rxstat & RL_RDESC_STAT_UDPSUMBAD))) + m->m_pkthdr.csum_flags |= M_TCP_CSUM_IN_OK | + M_UDP_CSUM_IN_OK; } else { /* Check IP header checksum */ if ((rxstat & RL_RDESC_STAT_PROTOID) && @@ -1600,7 +1610,7 @@ re_encap(struct rl_softc *sc, struct mbuf *m, int *idx) bus_dmamap_t map; int error, seg, nsegs, uidx, startidx, curidx, lastidx, pad; struct rl_desc *d; - u_int32_t cmdstat, vlanctl, rl_flags = 0; + u_int32_t cmdstat, vlanctl = 0, csum_flags = 0; struct rl_txq *txq; #if NVLAN > 0 struct ifvlan *ifv = NULL; @@ -1628,11 +1638,19 @@ re_encap(struct rl_softc *sc, struct mbuf *m, int *idx) if ((m->m_pkthdr.csum_flags & (M_IPV4_CSUM_OUT|M_TCPV4_CSUM_OUT|M_UDPV4_CSUM_OUT)) != 0) { - rl_flags |= RL_TDESC_CMD_IPCSUM; - if (m->m_pkthdr.csum_flags & M_TCPV4_CSUM_OUT) - rl_flags |= RL_TDESC_CMD_TCPCSUM; - if (m->m_pkthdr.csum_flags & M_UDPV4_CSUM_OUT) - rl_flags |= RL_TDESC_CMD_UDPCSUM; + if (sc->rl_flags & RL_FLAG_DESCV2) { + vlanctl |= RL_TDESC_CMD_IPCSUMV2; + if (m->m_pkthdr.csum_flags & M_TCPV4_CSUM_OUT) + vlanctl |= RL_TDESC_CMD_TCPCSUMV2; + if (m->m_pkthdr.csum_flags & M_UDPV4_CSUM_OUT) + vlanctl |= RL_TDESC_CMD_UDPCSUMV2; + } else { + csum_flags |= RL_TDESC_CMD_IPCSUM; + if (m->m_pkthdr.csum_flags & M_TCPV4_CSUM_OUT) + csum_flags |= RL_TDESC_CMD_TCPCSUM; + if (m->m_pkthdr.csum_flags & M_UDPV4_CSUM_OUT) + csum_flags |= RL_TDESC_CMD_UDPCSUM; + } } txq = &sc->rl_ldata.rl_txq[*idx]; @@ -1648,8 +1666,9 @@ re_encap(struct rl_softc *sc, struct mbuf *m, int *idx) nsegs = map->dm_nsegs; pad = 0; - if (m->m_pkthdr.len <= RL_IP4CSUMTX_PADLEN && - (rl_flags & RL_TDESC_CMD_IPCSUM) != 0) { + if ((sc->rl_flags & RL_FLAG_DESCV2) == 0 && + m->m_pkthdr.len <= RL_IP4CSUMTX_PADLEN && + (csum_flags & RL_TDESC_CMD_IPCSUM) != 0) { pad = 1; nsegs++; } @@ -1671,10 +1690,9 @@ re_encap(struct rl_softc *sc, struct mbuf *m, int *idx) * appear in all descriptors of a multi-descriptor * transmission attempt. */ - vlanctl = 0; #if NVLAN > 0 if (ifv != NULL) - vlanctl = swap16(ifv->ifv_tag) | RL_TDESC_VLANCTL_TAG; + vlanctl |= swap16(ifv->ifv_tag) | RL_TDESC_VLANCTL_TAG; #endif /* @@ -1713,7 +1731,7 @@ re_encap(struct rl_softc *sc, struct mbuf *m, int *idx) d->rl_vlanctl = htole32(vlanctl); re_set_bufaddr(d, map->dm_segs[seg].ds_addr); - cmdstat = rl_flags | map->dm_segs[seg].ds_len; + cmdstat = csum_flags | map->dm_segs[seg].ds_len; if (seg == 0) cmdstat |= RL_TDESC_CMD_SOF; else @@ -1735,7 +1753,7 @@ re_encap(struct rl_softc *sc, struct mbuf *m, int *idx) d->rl_vlanctl = htole32(vlanctl); paddaddr = RL_TXPADDADDR(sc); re_set_bufaddr(d, paddaddr); - cmdstat = rl_flags | + cmdstat = csum_flags | RL_TDESC_CMD_OWN | RL_TDESC_CMD_EOF | (RL_IP4CSUMTX_PADLEN + 1 - m->m_pkthdr.len); if (curidx == (RL_TX_DESC_CNT(sc) - 1)) diff --git a/sys/dev/ic/rtl81x9reg.h b/sys/dev/ic/rtl81x9reg.h index b5492f9f2b4..8413bad71d8 100644 --- a/sys/dev/ic/rtl81x9reg.h +++ b/sys/dev/ic/rtl81x9reg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rtl81x9reg.h,v 1.49 2008/07/15 13:21:17 jsg Exp $ */ +/* $OpenBSD: rtl81x9reg.h,v 1.50 2008/08/11 22:42:19 brad Exp $ */ /* * Copyright (c) 1997, 1998 @@ -528,6 +528,10 @@ struct rl_desc { #define RL_TDESC_VLANCTL_TAG 0x00020000 /* Insert VLAN tag */ #define RL_TDESC_VLANCTL_DATA 0x0000FFFF /* TAG data */ +/* RTL8168C/RTL8168CP/RTL8111C/RTL8111CP */ +#define RL_TDESC_CMD_IPCSUMV2 0x20000000 +#define RL_TDESC_CMD_TCPCSUMV2 0x40000000 +#define RL_TDESC_CMD_UDPCSUMV2 0x80000000 /* * Error bits are valid only on the last descriptor of a frame @@ -565,6 +569,8 @@ struct rl_desc { #define RL_RDESC_STAT_RUNT 0x00080000 /* runt packet received */ #define RL_RDESC_STAT_CRCERR 0x00040000 /* CRC error */ #define RL_RDESC_STAT_PROTOID 0x00030000 /* Protocol type */ +#define RL_RDESC_STAT_UDP 0x00020000 /* UDP, 8168C/CP, 8111C/CP */ +#define RL_RDESC_STAT_TCP 0x00010000 /* TCP, 8168C/CP, 8111C/CP */ #define RL_RDESC_STAT_IPSUMBAD 0x00008000 /* IP header checksum bad */ #define RL_RDESC_STAT_UDPSUMBAD 0x00004000 /* UDP checksum bad */ #define RL_RDESC_STAT_TCPSUMBAD 0x00002000 /* TCP checksum bad */ @@ -576,6 +582,9 @@ struct rl_desc { #define RL_RDESC_VLANCTL_TAG 0x00010000 /* VLAN tag available (rl_vlandata valid)*/ #define RL_RDESC_VLANCTL_DATA 0x0000FFFF /* TAG data */ +/* RTL8168C/RTL8168CP/RTL8111C/RTL8111CP */ +#define RL_RDESC_IPV6 0x80000000 +#define RL_RDESC_IPV4 0x40000000 #define RL_PROTOID_NONIP 0x00000000 #define RL_PROTOID_TCPIP 0x00010000 |