Index: sys/dev/nfe/if_nfe.c =================================================================== --- sys/dev/nfe/if_nfe.c (revision 213900) +++ sys/dev/nfe/if_nfe.c (working copy) @@ -40,6 +40,7 @@ #include #include +#include #include #include #include @@ -48,7 +49,11 @@ #include #include -#include +#include +#include +#include +#include +#include #include #include @@ -2333,6 +2338,70 @@ prod = si = sc->txq.cur; map = sc->txq.data[prod].tx_data_map; + m = *m_head; + if ((m->m_pkthdr.csum_flags & NFE_CSUM_FEATURES) != 0) { + struct ether_header *eh; + struct ip *ip; + struct tcphdr *tcp; + uint32_t ip_off, poff; + + if (M_WRITABLE(*m_head) == 0) { + /* Get a writable copy. */ + m = m_dup(*m_head, M_DONTWAIT); + m_freem(*m_head); + if (m == NULL) { + *m_head = NULL; + return (ENOBUFS); + } + *m_head = m; + } + ip_off = sizeof(struct ether_header); + m = m_pullup(*m_head, ip_off); + if (m == NULL) { + *m_head = NULL; + return (ENOBUFS); + } + eh = mtod(m, struct ether_header *); + /* Check the existence of VLAN tag. */ + if (eh->ether_type == htons(ETHERTYPE_VLAN)) { + ip_off = sizeof(struct ether_vlan_header); + m = m_pullup(m, ip_off); + if (m == NULL) { + *m_head = NULL; + return (ENOBUFS); + } + } + m = m_pullup(m, ip_off + sizeof(struct ip)); + if (m == NULL) { + *m_head = NULL; + return (ENOBUFS); + } + ip = (struct ip *)(mtod(m, char *) + ip_off); + poff = ip_off + (ip->ip_hl << 2); + m = m_pullup(m, poff + sizeof(struct tcphdr)); + if (m == NULL) { + *m_head = NULL; + return (ENOBUFS); + } + if ((m->m_pkthdr.csum_flags & CSUM_TCP) != 0) { + tcp = (struct tcphdr *)(mtod(m, char *) + poff); + m = m_pullup(m, poff + sizeof(struct tcphdr) + + (tcp->th_off << 2)); + if (m == NULL) { + *m_head = NULL; + return (ENOBUFS); + } + } else if ((m->m_pkthdr.csum_flags & CSUM_UDP) != 0) { + m = m_pullup(m, poff + sizeof(struct udphdr)); + if (m == NULL) { + *m_head = NULL; + return (ENOBUFS); + } + + } + *m_head = m; + } + error = bus_dmamap_load_mbuf_sg(sc->txq.tx_data_tag, map, *m_head, segs, &nsegs, BUS_DMA_NOWAIT); if (error == EFBIG) {