Author: yongari
Date: Mon Apr 19 22:10:40 2010
New Revision: 206876
URL: http://svn.freebsd.org/changeset/base/206876

Log:
  With r206844, CSUM_TCP is also set for CSUM_TSO case. Modify
  drivers to take into account for the change. Basically CSUM_TSO
  should be checked before checking CSUM_TCP.

Modified:
  head/sys/dev/age/if_age.c
  head/sys/dev/alc/if_alc.c
  head/sys/dev/ale/if_ale.c
  head/sys/dev/fxp/if_fxp.c
  head/sys/dev/msk/if_msk.c
  head/sys/dev/nfe/if_nfe.c

Modified: head/sys/dev/age/if_age.c
==============================================================================
--- head/sys/dev/age/if_age.c   Mon Apr 19 22:01:59 2010        (r206875)
+++ head/sys/dev/age/if_age.c   Mon Apr 19 22:10:40 2010        (r206876)
@@ -1629,22 +1629,8 @@ age_encap(struct age_softc *sc, struct m
        }
 
        m = *m_head;
-       /* Configure Tx IP/TCP/UDP checksum offload. */
-       if ((m->m_pkthdr.csum_flags & AGE_CSUM_FEATURES) != 0) {
-               cflags |= AGE_TD_CSUM;
-               if ((m->m_pkthdr.csum_flags & CSUM_TCP) != 0)
-                       cflags |= AGE_TD_TCPCSUM;
-               if ((m->m_pkthdr.csum_flags & CSUM_UDP) != 0)
-                       cflags |= AGE_TD_UDPCSUM;
-               /* Set checksum start offset. */
-               cflags |= (poff << AGE_TD_CSUM_PLOADOFFSET_SHIFT);
-               /* Set checksum insertion position of TCP/UDP. */
-               cflags |= ((poff + m->m_pkthdr.csum_data) <<
-                   AGE_TD_CSUM_XSUMOFFSET_SHIFT);
-       }
-
-       /* Configure TSO. */
        if ((m->m_pkthdr.csum_flags & CSUM_TSO) != 0) {
+               /* Configure TSO. */
                if (poff + (tcp->th_off << 2) == m->m_pkthdr.len) {
                        /* Not TSO but IP/TCP checksum offload. */
                        cflags |= AGE_TD_IPCSUM | AGE_TD_TCPCSUM;
@@ -1660,6 +1646,18 @@ age_encap(struct age_softc *sc, struct m
                /* Set IP/TCP header size. */
                cflags |= ip->ip_hl << AGE_TD_IPHDR_LEN_SHIFT;
                cflags |= tcp->th_off << AGE_TD_TSO_TCPHDR_LEN_SHIFT;
+       } else if ((m->m_pkthdr.csum_flags & AGE_CSUM_FEATURES) != 0) {
+               /* Configure Tx IP/TCP/UDP checksum offload. */
+               cflags |= AGE_TD_CSUM;
+               if ((m->m_pkthdr.csum_flags & CSUM_TCP) != 0)
+                       cflags |= AGE_TD_TCPCSUM;
+               if ((m->m_pkthdr.csum_flags & CSUM_UDP) != 0)
+                       cflags |= AGE_TD_UDPCSUM;
+               /* Set checksum start offset. */
+               cflags |= (poff << AGE_TD_CSUM_PLOADOFFSET_SHIFT);
+               /* Set checksum insertion position of TCP/UDP. */
+               cflags |= ((poff + m->m_pkthdr.csum_data) <<
+                   AGE_TD_CSUM_XSUMOFFSET_SHIFT);
        }
 
        /* Configure VLAN hardware tag insertion. */

Modified: head/sys/dev/alc/if_alc.c
==============================================================================
--- head/sys/dev/alc/if_alc.c   Mon Apr 19 22:01:59 2010        (r206875)
+++ head/sys/dev/alc/if_alc.c   Mon Apr 19 22:10:40 2010        (r206876)
@@ -1908,28 +1908,7 @@ alc_encap(struct alc_softc *sc, struct m
                vtag = (vtag << TD_VLAN_SHIFT) & TD_VLAN_MASK;
                cflags |= TD_INS_VLAN_TAG;
        }
-       /* Configure Tx checksum offload. */
-       if ((m->m_pkthdr.csum_flags & ALC_CSUM_FEATURES) != 0) {
-#ifdef ALC_USE_CUSTOM_CSUM
-               cflags |= TD_CUSTOM_CSUM;
-               /* Set checksum start offset. */
-               cflags |= ((poff >> 1) << TD_PLOAD_OFFSET_SHIFT) &
-                   TD_PLOAD_OFFSET_MASK;
-               /* Set checksum insertion position of TCP/UDP. */
-               cflags |= (((poff + m->m_pkthdr.csum_data) >> 1) <<
-                   TD_CUSTOM_CSUM_OFFSET_SHIFT) & TD_CUSTOM_CSUM_OFFSET_MASK;
-#else
-               if ((m->m_pkthdr.csum_flags & CSUM_IP) != 0)
-                       cflags |= TD_IPCSUM;
-               if ((m->m_pkthdr.csum_flags & CSUM_TCP) != 0)
-                       cflags |= TD_TCPCSUM;
-               if ((m->m_pkthdr.csum_flags & CSUM_UDP) != 0)
-                       cflags |= TD_UDPCSUM;
-               /* Set TCP/UDP header offset. */
-               cflags |= (poff << TD_L4HDR_OFFSET_SHIFT) &
-                   TD_L4HDR_OFFSET_MASK;
-#endif
-       } else if ((m->m_pkthdr.csum_flags & CSUM_TSO) != 0) {
+       if ((m->m_pkthdr.csum_flags & CSUM_TSO) != 0) {
                /* Request TSO and set MSS. */
                cflags |= TD_TSO | TD_TSO_DESCV1;
                cflags |= ((uint32_t)m->m_pkthdr.tso_segsz << TD_MSS_SHIFT) &
@@ -1961,6 +1940,27 @@ alc_encap(struct alc_softc *sc, struct m
                }
                /* Handle remaining fragments. */
                idx = 1;
+       } else if ((m->m_pkthdr.csum_flags & ALC_CSUM_FEATURES) != 0) {
+               /* Configure Tx checksum offload. */
+#ifdef ALC_USE_CUSTOM_CSUM
+               cflags |= TD_CUSTOM_CSUM;
+               /* Set checksum start offset. */
+               cflags |= ((poff >> 1) << TD_PLOAD_OFFSET_SHIFT) &
+                   TD_PLOAD_OFFSET_MASK;
+               /* Set checksum insertion position of TCP/UDP. */
+               cflags |= (((poff + m->m_pkthdr.csum_data) >> 1) <<
+                   TD_CUSTOM_CSUM_OFFSET_SHIFT) & TD_CUSTOM_CSUM_OFFSET_MASK;
+#else
+               if ((m->m_pkthdr.csum_flags & CSUM_IP) != 0)
+                       cflags |= TD_IPCSUM;
+               if ((m->m_pkthdr.csum_flags & CSUM_TCP) != 0)
+                       cflags |= TD_TCPCSUM;
+               if ((m->m_pkthdr.csum_flags & CSUM_UDP) != 0)
+                       cflags |= TD_UDPCSUM;
+               /* Set TCP/UDP header offset. */
+               cflags |= (poff << TD_L4HDR_OFFSET_SHIFT) &
+                   TD_L4HDR_OFFSET_MASK;
+#endif
        }
        for (; idx < nsegs; idx++) {
                desc = &sc->alc_rdata.alc_tx_ring[prod];

Modified: head/sys/dev/ale/if_ale.c
==============================================================================
--- head/sys/dev/ale/if_ale.c   Mon Apr 19 22:01:59 2010        (r206875)
+++ head/sys/dev/ale/if_ale.c   Mon Apr 19 22:10:40 2010        (r206876)
@@ -1737,8 +1737,14 @@ ale_encap(struct ale_softc *sc, struct m
        bus_dmamap_sync(sc->ale_cdata.ale_tx_tag, map, BUS_DMASYNC_PREWRITE);
 
        m = *m_head;
-       /* Configure Tx checksum offload. */
-       if ((m->m_pkthdr.csum_flags & ALE_CSUM_FEATURES) != 0) {
+       if ((m->m_pkthdr.csum_flags & CSUM_TSO) != 0) {
+               /* Request TSO and set MSS. */
+               cflags |= ALE_TD_TSO;
+               cflags |= ((uint32_t)m->m_pkthdr.tso_segsz << ALE_TD_MSS_SHIFT);
+               /* Set IP/TCP header size. */
+               cflags |= ip->ip_hl << ALE_TD_IPHDR_LEN_SHIFT;
+               cflags |= tcp->th_off << ALE_TD_TCPHDR_LEN_SHIFT;
+       } else if ((m->m_pkthdr.csum_flags & ALE_CSUM_FEATURES) != 0) {
                /*
                 * AR81xx supports Tx custom checksum offload feature
                 * that offloads single 16bit checksum computation.
@@ -1769,15 +1775,6 @@ ale_encap(struct ale_softc *sc, struct m
                    ALE_TD_CSUM_XSUMOFFSET_SHIFT);
        }
 
-       if ((m->m_pkthdr.csum_flags & CSUM_TSO) != 0) {
-               /* Request TSO and set MSS. */
-               cflags |= ALE_TD_TSO;
-               cflags |= ((uint32_t)m->m_pkthdr.tso_segsz << ALE_TD_MSS_SHIFT);
-               /* Set IP/TCP header size. */
-               cflags |= ip->ip_hl << ALE_TD_IPHDR_LEN_SHIFT;
-               cflags |= tcp->th_off << ALE_TD_TCPHDR_LEN_SHIFT;
-       }
-
        /* Configure VLAN hardware tag insertion. */
        if ((m->m_flags & M_VLANTAG) != 0) {
                vtag = ALE_TX_VLAN_TAG(m->m_pkthdr.ether_vtag);

Modified: head/sys/dev/fxp/if_fxp.c
==============================================================================
--- head/sys/dev/fxp/if_fxp.c   Mon Apr 19 22:01:59 2010        (r206875)
+++ head/sys/dev/fxp/if_fxp.c   Mon Apr 19 22:10:40 2010        (r206876)
@@ -1417,60 +1417,6 @@ fxp_encap(struct fxp_softc *sc, struct m
                    FXP_IPCB_HARDWAREPARSING_ENABLE;
 
        m = *m_head;
-       /*
-        * Deal with TCP/IP checksum offload. Note that
-        * in order for TCP checksum offload to work,
-        * the pseudo header checksum must have already
-        * been computed and stored in the checksum field
-        * in the TCP header. The stack should have
-        * already done this for us.
-        */
-       if (m->m_pkthdr.csum_flags & FXP_CSUM_FEATURES) {
-               txp->tx_cb->ipcb_ip_schedule = FXP_IPCB_TCPUDP_CHECKSUM_ENABLE;
-               if (m->m_pkthdr.csum_flags & CSUM_TCP)
-                       txp->tx_cb->ipcb_ip_schedule |= FXP_IPCB_TCP_PACKET;
-
-#ifdef FXP_IP_CSUM_WAR
-               /*
-                * XXX The 82550 chip appears to have trouble
-                * dealing with IP header checksums in very small
-                * datagrams, namely fragments from 1 to 3 bytes
-                * in size. For example, say you want to transmit
-                * a UDP packet of 1473 bytes. The packet will be
-                * fragmented over two IP datagrams, the latter
-                * containing only one byte of data. The 82550 will
-                * botch the header checksum on the 1-byte fragment.
-                * As long as the datagram contains 4 or more bytes
-                * of data, you're ok.
-                *
-                 * The following code attempts to work around this
-                * problem: if the datagram is less than 38 bytes
-                * in size (14 bytes ether header, 20 bytes IP header,
-                * plus 4 bytes of data), we punt and compute the IP
-                * header checksum by hand. This workaround doesn't
-                * work very well, however, since it can be fooled
-                * by things like VLAN tags and IP options that make
-                * the header sizes/offsets vary.
-                */
-
-               if (m->m_pkthdr.csum_flags & CSUM_IP) {
-                       if (m->m_pkthdr.len < 38) {
-                               struct ip *ip;
-                               m->m_data += ETHER_HDR_LEN;
-                               ip = mtod(m, struct ip *);
-                               ip->ip_sum = in_cksum(m, ip->ip_hl << 2);
-                               m->m_data -= ETHER_HDR_LEN;
-                               m->m_pkthdr.csum_flags &= ~CSUM_IP;
-                       } else {
-                               txp->tx_cb->ipcb_ip_activation_high =
-                                   FXP_IPCB_HARDWAREPARSING_ENABLE;
-                               txp->tx_cb->ipcb_ip_schedule |=
-                                   FXP_IPCB_IP_CHECKSUM_ENABLE;
-                       }
-               }
-#endif
-       }
-
        if (m->m_pkthdr.csum_flags & CSUM_TSO) {
                /*
                 * 82550/82551 requires ethernet/IP/TCP headers must be
@@ -1539,6 +1485,58 @@ fxp_encap(struct fxp_softc *sc, struct m
                tcp_payload = m->m_pkthdr.len - ip_off - (ip->ip_hl << 2);
                tcp_payload -= tcp->th_off << 2;
                *m_head = m;
+       } else if (m->m_pkthdr.csum_flags & FXP_CSUM_FEATURES) {
+               /*
+                * Deal with TCP/IP checksum offload. Note that
+                * in order for TCP checksum offload to work,
+                * the pseudo header checksum must have already
+                * been computed and stored in the checksum field
+                * in the TCP header. The stack should have
+                * already done this for us.
+                */
+               txp->tx_cb->ipcb_ip_schedule = FXP_IPCB_TCPUDP_CHECKSUM_ENABLE;
+               if (m->m_pkthdr.csum_flags & CSUM_TCP)
+                       txp->tx_cb->ipcb_ip_schedule |= FXP_IPCB_TCP_PACKET;
+
+#ifdef FXP_IP_CSUM_WAR
+               /*
+                * XXX The 82550 chip appears to have trouble
+                * dealing with IP header checksums in very small
+                * datagrams, namely fragments from 1 to 3 bytes
+                * in size. For example, say you want to transmit
+                * a UDP packet of 1473 bytes. The packet will be
+                * fragmented over two IP datagrams, the latter
+                * containing only one byte of data. The 82550 will
+                * botch the header checksum on the 1-byte fragment.
+                * As long as the datagram contains 4 or more bytes
+                * of data, you're ok.
+                *
+                 * The following code attempts to work around this
+                * problem: if the datagram is less than 38 bytes
+                * in size (14 bytes ether header, 20 bytes IP header,
+                * plus 4 bytes of data), we punt and compute the IP
+                * header checksum by hand. This workaround doesn't
+                * work very well, however, since it can be fooled
+                * by things like VLAN tags and IP options that make
+                * the header sizes/offsets vary.
+                */
+
+               if (m->m_pkthdr.csum_flags & CSUM_IP) {
+                       if (m->m_pkthdr.len < 38) {
+                               struct ip *ip;
+                               m->m_data += ETHER_HDR_LEN;
+                               ip = mtod(m, struct ip *);
+                               ip->ip_sum = in_cksum(m, ip->ip_hl << 2);
+                               m->m_data -= ETHER_HDR_LEN;
+                               m->m_pkthdr.csum_flags &= ~CSUM_IP;
+                       } else {
+                               txp->tx_cb->ipcb_ip_activation_high =
+                                   FXP_IPCB_HARDWAREPARSING_ENABLE;
+                               txp->tx_cb->ipcb_ip_schedule |=
+                                   FXP_IPCB_IP_CHECKSUM_ENABLE;
+                       }
+               }
+#endif
        }
 
        error = bus_dmamap_load_mbuf_sg(sc->fxp_txmtag, txp->tx_map, *m_head,

Modified: head/sys/dev/msk/if_msk.c
==============================================================================
--- head/sys/dev/msk/if_msk.c   Mon Apr 19 22:01:59 2010        (r206875)
+++ head/sys/dev/msk/if_msk.c   Mon Apr 19 22:10:40 2010        (r206876)
@@ -2605,23 +2605,32 @@ msk_encap(struct msk_if_softc *sc_if, st
                ip = (struct ip *)(mtod(m, char *) + offset);
                offset += (ip->ip_hl << 2);
                tcp_offset = offset;
-               /*
-                * It seems that Yukon II has Tx checksum offload bug for
-                * small TCP packets that's less than 60 bytes in size
-                * (e.g. TCP window probe packet, pure ACK packet).
-                * Common work around like padding with zeros to make the
-                * frame minimum ethernet frame size didn't work at all.
-                * Instead of disabling checksum offload completely we
-                * resort to S/W checksum routine when we encounter short
-                * TCP frames.
-                * Short UDP packets appear to be handled correctly by
-                * Yukon II. Also I assume this bug does not happen on
-                * controllers that use newer descriptor format or
-                * automatic Tx checksum calaulcation.
-                */
-               if ((sc_if->msk_flags & MSK_FLAG_AUTOTX_CSUM) == 0 &&
+               if ((m->m_pkthdr.csum_flags & CSUM_TSO) != 0) {
+                       m = m_pullup(m, offset + sizeof(struct tcphdr));
+                       if (m == NULL) {
+                               *m_head = NULL;
+                               return (ENOBUFS);
+                       }
+                       tcp = (struct tcphdr *)(mtod(m, char *) + offset);
+                       offset += (tcp->th_off << 2);
+               } else if ((sc_if->msk_flags & MSK_FLAG_AUTOTX_CSUM) == 0 &&
                    (m->m_pkthdr.len < MSK_MIN_FRAMELEN) &&
                    (m->m_pkthdr.csum_flags & CSUM_TCP) != 0) {
+                       /*
+                        * It seems that Yukon II has Tx checksum offload bug
+                        * for small TCP packets that's less than 60 bytes in
+                        * size (e.g. TCP window probe packet, pure ACK packet).
+                        * Common work around like padding with zeros to make
+                        * the frame minimum ethernet frame size didn't work at
+                        * all.
+                        * Instead of disabling checksum offload completely we
+                        * resort to S/W checksum routine when we encounter
+                        * short TCP frames.
+                        * Short UDP packets appear to be handled correctly by
+                        * Yukon II. Also I assume this bug does not happen on
+                        * controllers that use newer descriptor format or
+                        * automatic Tx checksum calaulcation.
+                        */
                        m = m_pullup(m, offset + sizeof(struct tcphdr));
                        if (m == NULL) {
                                *m_head = NULL;
@@ -2632,15 +2641,6 @@ msk_encap(struct msk_if_softc *sc_if, st
                            m->m_pkthdr.len, offset);
                        m->m_pkthdr.csum_flags &= ~CSUM_TCP;
                }
-               if ((m->m_pkthdr.csum_flags & CSUM_TSO) != 0) {
-                       m = m_pullup(m, offset + sizeof(struct tcphdr));
-                       if (m == NULL) {
-                               *m_head = NULL;
-                               return (ENOBUFS);
-                       }
-                       tcp = (struct tcphdr *)(mtod(m, char *) + offset);
-                       offset += (tcp->th_off << 2);
-               }
                *m_head = m;
        }
 

Modified: head/sys/dev/nfe/if_nfe.c
==============================================================================
--- head/sys/dev/nfe/if_nfe.c   Mon Apr 19 22:01:59 2010        (r206875)
+++ head/sys/dev/nfe/if_nfe.c   Mon Apr 19 22:10:40 2010        (r206876)
@@ -2366,7 +2366,12 @@ nfe_encap(struct nfe_softc *sc, struct m
        m = *m_head;
        cflags = flags = 0;
        tso_segsz = 0;
-       if ((m->m_pkthdr.csum_flags & NFE_CSUM_FEATURES) != 0) {
+       if ((m->m_pkthdr.csum_flags & CSUM_TSO) != 0) {
+               tso_segsz = (uint32_t)m->m_pkthdr.tso_segsz <<
+                   NFE_TX_TSO_SHIFT;
+               cflags &= ~(NFE_TX_IP_CSUM | NFE_TX_TCP_UDP_CSUM);
+               cflags |= NFE_TX_TSO;
+       } else if ((m->m_pkthdr.csum_flags & NFE_CSUM_FEATURES) != 0) {
                if ((m->m_pkthdr.csum_flags & CSUM_IP) != 0)
                        cflags |= NFE_TX_IP_CSUM;
                if ((m->m_pkthdr.csum_flags & CSUM_TCP) != 0)
@@ -2374,12 +2379,6 @@ nfe_encap(struct nfe_softc *sc, struct m
                if ((m->m_pkthdr.csum_flags & CSUM_UDP) != 0)
                        cflags |= NFE_TX_TCP_UDP_CSUM;
        }
-       if ((m->m_pkthdr.csum_flags & CSUM_TSO) != 0) {
-               tso_segsz = (uint32_t)m->m_pkthdr.tso_segsz <<
-                   NFE_TX_TSO_SHIFT;
-               cflags &= ~(NFE_TX_IP_CSUM | NFE_TX_TCP_UDP_CSUM);
-               cflags |= NFE_TX_TSO;
-       }
 
        for (i = 0; i < nsegs; i++) {
                if (sc->nfe_flags & NFE_40BIT_ADDR) {
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to