Date: Mon, 26 Apr 2010 18:04:34 +0000 (UTC) From: Pyun YongHyeon <yongari@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org Subject: svn commit: r207237 - in stable/7/sys/dev: age alc ale fxp msk nfe Message-ID: <201004261804.o3QI4Y3W058889@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: yongari Date: Mon Apr 26 18:04:33 2010 New Revision: 207237 URL: http://svn.freebsd.org/changeset/base/207237 Log: MFC r206876: 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: stable/7/sys/dev/age/if_age.c stable/7/sys/dev/alc/if_alc.c stable/7/sys/dev/ale/if_ale.c stable/7/sys/dev/fxp/if_fxp.c stable/7/sys/dev/msk/if_msk.c stable/7/sys/dev/nfe/if_nfe.c Directory Properties: stable/7/sys/ (props changed) stable/7/sys/cddl/contrib/opensolaris/ (props changed) stable/7/sys/contrib/dev/acpica/ (props changed) stable/7/sys/contrib/pf/ (props changed) Modified: stable/7/sys/dev/age/if_age.c ============================================================================== --- stable/7/sys/dev/age/if_age.c Mon Apr 26 18:02:12 2010 (r207236) +++ stable/7/sys/dev/age/if_age.c Mon Apr 26 18:04:33 2010 (r207237) @@ -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: stable/7/sys/dev/alc/if_alc.c ============================================================================== --- stable/7/sys/dev/alc/if_alc.c Mon Apr 26 18:02:12 2010 (r207236) +++ stable/7/sys/dev/alc/if_alc.c Mon Apr 26 18:04:33 2010 (r207237) @@ -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: stable/7/sys/dev/ale/if_ale.c ============================================================================== --- stable/7/sys/dev/ale/if_ale.c Mon Apr 26 18:02:12 2010 (r207236) +++ stable/7/sys/dev/ale/if_ale.c Mon Apr 26 18:04:33 2010 (r207237) @@ -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: stable/7/sys/dev/fxp/if_fxp.c ============================================================================== --- stable/7/sys/dev/fxp/if_fxp.c Mon Apr 26 18:02:12 2010 (r207236) +++ stable/7/sys/dev/fxp/if_fxp.c Mon Apr 26 18:04:33 2010 (r207237) @@ -1418,60 +1418,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 @@ -1540,6 +1486,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: stable/7/sys/dev/msk/if_msk.c ============================================================================== --- stable/7/sys/dev/msk/if_msk.c Mon Apr 26 18:02:12 2010 (r207236) +++ stable/7/sys/dev/msk/if_msk.c Mon Apr 26 18:04:33 2010 (r207237) @@ -2529,23 +2529,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; @@ -2556,15 +2565,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: stable/7/sys/dev/nfe/if_nfe.c ============================================================================== --- stable/7/sys/dev/nfe/if_nfe.c Mon Apr 26 18:02:12 2010 (r207236) +++ stable/7/sys/dev/nfe/if_nfe.c Mon Apr 26 18:04:33 2010 (r207237) @@ -2357,7 +2357,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) @@ -2365,12 +2370,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) {
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201004261804.o3QI4Y3W058889>