Index: if_ixl.c =================================================================== RCS file: /cvs/src/sys/dev/pci/if_ixl.c,v retrieving revision 1.76 diff -u -p -r1.76 if_ixl.c --- if_ixl.c 9 Nov 2021 09:26:18 -0000 1.76 +++ if_ixl.c 22 Nov 2021 03:35:58 -0000 @@ -2776,11 +2776,11 @@ ixl_load_mbuf(bus_dma_tag_t dmat, bus_dm BUS_DMA_STREAMING | BUS_DMA_NOWAIT)); } -static void -ixl_tx_setup_offload(struct mbuf *mp, uint64_t *cmd) +static uint64_t +ixl_tx_setup_offload(struct mbuf *mp) { - uint64_t ip_hdr_len; - int ipoff = ETHER_HDR_LEN; + uint64_t iphlen; + int hoff; uint8_t ipproto; struct ip *ip; #ifdef INET6 @@ -2788,55 +2788,74 @@ ixl_tx_setup_offload(struct mbuf *mp, ui #endif struct tcphdr *th; struct mbuf *m; + uint64_t offload = 0; switch (ntohs(mtod(mp, struct ether_header *)->ether_type)) { case ETHERTYPE_IP: if (mp->m_pkthdr.len < ETHER_HDR_LEN + sizeof(*ip)) - return; - m = m_getptr(mp, ETHER_HDR_LEN, &ipoff); - KASSERT(m != NULL && m->m_len - ipoff >= sizeof(*ip)); - ip = (struct ip *)(m->m_data + ipoff); - - if (mp->m_pkthdr.csum_flags & M_IPV4_CSUM_OUT) - *cmd |= IXL_TX_DESC_CMD_IIPT_IPV4_CSUM; - else - *cmd |= IXL_TX_DESC_CMD_IIPT_IPV4; + return (0); + m = m_getptr(mp, ETHER_HDR_LEN, &hoff); + KASSERT(m != NULL && m->m_len - hoff >= sizeof(*ip)); + ip = (struct ip *)(mtod(m, caddr_t) + hoff); + + offload |= ISSET(mp->m_pkthdr.csum_flags, M_IPV4_CSUM_OUT) ? + IXL_TX_DESC_CMD_IIPT_IPV4_CSUM : + IXL_TX_DESC_CMD_IIPT_IPV4; - ip_hdr_len = ip->ip_hl << 2; + iphlen = ip->ip_hl << 2; ipproto = ip->ip_p; break; #ifdef INET6 case ETHERTYPE_IPV6: if (mp->m_pkthdr.len < ETHER_HDR_LEN + sizeof(*ip6)) - return; - m = m_getptr(mp, ETHER_HDR_LEN, &ipoff); - KASSERT(m != NULL && m->m_len - ipoff >= sizeof(*ip6)); - ip6 = (struct ip6_hdr *)(m->m_data + ipoff); + return (0); + + m = m_getptr(mp, ETHER_HDR_LEN, &hoff); + KASSERT(m != NULL && m->m_len - hoff >= sizeof(*ip6)); + ip6 = (struct ip6_hdr *)(mtod(m, caddr_t) + hoff); - *cmd |= IXL_TX_DESC_CMD_IIPT_IPV6; + offload |= IXL_TX_DESC_CMD_IIPT_IPV6; - ip_hdr_len = sizeof(*ip6); + iphlen = sizeof(*ip6); ipproto = ip6->ip6_nxt; break; #endif default: - return; + return (0); } - *cmd |= (ETHER_HDR_LEN >> 1) << IXL_TX_DESC_MACLEN_SHIFT; - *cmd |= (ip_hdr_len >> 2) << IXL_TX_DESC_IPLEN_SHIFT; + offload |= (ETHER_HDR_LEN >> 1) << IXL_TX_DESC_MACLEN_SHIFT; + offload |= (iphlen >> 2) << IXL_TX_DESC_IPLEN_SHIFT; - if (ipproto == IPPROTO_TCP && m->m_pkthdr.csum_flags & M_TCP_CSUM_OUT) { - th = (struct tcphdr *)(m->m_data + ipoff + ip_hdr_len); + switch (ipproto) { + case IPPROTO_TCP: + if (!ISSET(m->m_pkthdr.csum_flags, M_TCP_CSUM_OUT)) + break; + if (mp->m_pkthdr.len < ETHER_HDR_LEN + iphlen + + sizeof(*th)) + break; - *cmd |= IXL_TX_DESC_CMD_L4T_EOFT_TCP; - *cmd |= (uint64_t)th->th_off << IXL_TX_DESC_L4LEN_SHIFT; - } + m = m_getptr(m, hoff + iphlen, &hoff); + KASSERT(m != NULL && m->m_len - hoff >= sizeof(*th)); + th = (struct tcphdr *)(mtod(m, caddr_t) + hoff); - if (ipproto == IPPROTO_UDP && m->m_pkthdr.csum_flags & M_UDP_CSUM_OUT) { - *cmd |= IXL_TX_DESC_CMD_L4T_EOFT_UDP; - *cmd |= (sizeof(struct udphdr) >> 2) << IXL_TX_DESC_L4LEN_SHIFT; + offload |= IXL_TX_DESC_CMD_L4T_EOFT_TCP; + offload |= (uint64_t)th->th_off << IXL_TX_DESC_L4LEN_SHIFT; + break; + case IPPROTO_UDP: + if (!ISSET(m->m_pkthdr.csum_flags, M_UDP_CSUM_OUT)) + break; + if (mp->m_pkthdr.len < ETHER_HDR_LEN + iphlen + + sizeof(struct udphdr)) + break; + + offload |= IXL_TX_DESC_CMD_L4T_EOFT_UDP; + offload |= (sizeof(struct udphdr) >> 2) << + IXL_TX_DESC_L4LEN_SHIFT; + break; } + + return (offload); } static void @@ -2849,7 +2868,7 @@ ixl_start(struct ifqueue *ifq) struct ixl_tx_map *txm; bus_dmamap_t map; struct mbuf *m; - uint64_t cmd, off = 0; + uint64_t cmd, offload; unsigned int prod, free, last, i; unsigned int mask; int post = 0; @@ -2896,7 +2915,7 @@ ixl_start(struct ifqueue *ifq) bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, BUS_DMASYNC_PREWRITE); - ixl_tx_setup_offload(m, &off); + offload = ixl_tx_setup_offload(m); for (i = 0; i < map->dm_nsegs; i++) { txd = &ring[prod]; @@ -2904,7 +2923,7 @@ ixl_start(struct ifqueue *ifq) cmd = (uint64_t)map->dm_segs[i].ds_len << IXL_TX_DESC_BSIZE_SHIFT; cmd |= IXL_TX_DESC_DTYPE_DATA | IXL_TX_DESC_CMD_ICRC; - cmd |= off; + cmd |= offload; htolem64(&txd->addr, map->dm_segs[i].ds_addr); htolem64(&txd->cmd, cmd);