Add support for TX/RX checksum offload for newer re(4) chipsets.
authorbrad <brad@openbsd.org>
Mon, 11 Aug 2008 22:42:19 +0000 (22:42 +0000)
committerbrad <brad@openbsd.org>
Mon, 11 Aug 2008 22:42:19 +0000 (22:42 +0000)
Tested by naddy@

From FreeBSD

sys/dev/ic/re.c
sys/dev/ic/rtl81x9reg.h

index ff80af8..b680dfc 100644 (file)
@@ -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))
index b5492f9..8413bad 100644 (file)
@@ -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