summaryrefslogtreecommitdiff
path: root/sys/dev/ic
diff options
context:
space:
mode:
authorBrad Smith <brad@cvs.openbsd.org>2008-08-11 22:42:20 +0000
committerBrad Smith <brad@cvs.openbsd.org>2008-08-11 22:42:20 +0000
commit0f0221b10fcff87d22c7e748f00c4dfb16c27f17 (patch)
treeb62d84c043ebcd805cbd2093133109d45af8e2f3 /sys/dev/ic
parentf061b55d3cc19323d844fb6159a9058dc00c6b4d (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.c58
-rw-r--r--sys/dev/ic/rtl81x9reg.h11
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