Index: if_ixl.c =================================================================== RCS file: /cvs/src/sys/dev/pci/if_ixl.c,v diff -u -p -r1.107 if_ixl.c --- if_ixl.c 22 May 2025 06:41:20 -0000 1.107 +++ if_ixl.c 16 Jun 2025 06:07:34 -0000 @@ -2765,10 +2765,8 @@ ixl_load_mbuf(bus_dma_tag_t dmat, bus_dm } static uint64_t -ixl_tx_setup_offload(struct mbuf *m0, struct ixl_tx_ring *txr, - unsigned int prod) +ixl_tx_setup_offload(struct mbuf *m0, struct ether_extracted *ext) { - struct ether_extracted ext; uint64_t hlen; uint64_t offload = 0; @@ -2784,66 +2782,35 @@ ixl_tx_setup_offload(struct mbuf *m0, st M_IPV4_CSUM_OUT|M_TCP_CSUM_OUT|M_UDP_CSUM_OUT|M_TCP_TSO)) return (offload); - ether_extract_headers(m0, &ext); + ether_extract_headers(m0, ext); - if (ext.ip4) { + if (ext->ip4) { offload |= ISSET(m0->m_pkthdr.csum_flags, M_IPV4_CSUM_OUT) ? IXL_TX_DESC_CMD_IIPT_IPV4_CSUM : IXL_TX_DESC_CMD_IIPT_IPV4; #ifdef INET6 - } else if (ext.ip6) { + } else if (ext->ip6) { offload |= IXL_TX_DESC_CMD_IIPT_IPV6; #endif } else { panic("CSUM_OUT set for non-IP packet"); /* NOTREACHED */ } - hlen = ext.iphlen; + hlen = ext->iphlen; offload |= (ETHER_HDR_LEN >> 1) << IXL_TX_DESC_MACLEN_SHIFT; offload |= (hlen >> 2) << IXL_TX_DESC_IPLEN_SHIFT; - if (ext.tcp && ISSET(m0->m_pkthdr.csum_flags, M_TCP_CSUM_OUT)) { + if (ext->tcp && ISSET(m0->m_pkthdr.csum_flags, M_TCP_CSUM_OUT)) { offload |= IXL_TX_DESC_CMD_L4T_EOFT_TCP; - offload |= (uint64_t)(ext.tcphlen >> 2) + offload |= (uint64_t)(ext->tcphlen >> 2) << IXL_TX_DESC_L4LEN_SHIFT; - } else if (ext.udp && ISSET(m0->m_pkthdr.csum_flags, M_UDP_CSUM_OUT)) { + } else if (ext->udp && ISSET(m0->m_pkthdr.csum_flags, M_UDP_CSUM_OUT)) { offload |= IXL_TX_DESC_CMD_L4T_EOFT_UDP; - offload |= (uint64_t)(sizeof(*ext.udp) >> 2) + offload |= (uint64_t)(sizeof(*ext->udp) >> 2) << IXL_TX_DESC_L4LEN_SHIFT; } - if (ISSET(m0->m_pkthdr.csum_flags, M_TCP_TSO)) { - if (ext.tcp && m0->m_pkthdr.ph_mss > 0) { - struct ixl_tx_desc *ring, *txd; - uint64_t cmd = 0, paylen, outlen; - - hlen += ext.tcphlen; - - /* - * The MSS should not be set to a lower value than 64 - * or larger than 9668 bytes. - */ - outlen = MIN(9668, MAX(64, m0->m_pkthdr.ph_mss)); - paylen = m0->m_pkthdr.len - ETHER_HDR_LEN - hlen; - - ring = IXL_DMA_KVA(&txr->txr_mem); - txd = &ring[prod]; - - cmd |= IXL_TX_DESC_DTYPE_CONTEXT; - cmd |= IXL_TX_CTX_DESC_CMD_TSO; - cmd |= paylen << IXL_TX_CTX_DESC_TLEN_SHIFT; - cmd |= outlen << IXL_TX_CTX_DESC_MSS_SHIFT; - - htolem64(&txd->addr, 0); - htolem64(&txd->cmd, cmd); - - tcpstat_add(tcps_outpkttso, - (paylen + outlen - 1) / outlen); - } else - tcpstat_inc(tcps_outbadtso); - } - return (offload); } @@ -2857,11 +2824,9 @@ ixl_start(struct ifqueue *ifq) struct ixl_tx_map *txm; bus_dmamap_t map; struct mbuf *m; - uint64_t cmd; unsigned int prod, free, last, i; unsigned int mask; int post = 0; - uint64_t offload; #if NBPFILTER > 0 caddr_t if_bpf; #endif @@ -2884,6 +2849,12 @@ ixl_start(struct ifqueue *ifq) mask = sc->sc_tx_ring_ndescs - 1; for (;;) { + struct ether_extracted ext; + uint64_t cmd = IXL_TX_DESC_DTYPE_DONE; + uint64_t hdtype = IXL_TX_DESC_DTYPE_DATA; + struct ixl_tx_desc *htxd; + uint64_t offload; + /* We need one extra descriptor for TSO packets. */ if (free <= (IXL_TX_PKT_DESCS + 1)) { ifq_set_oactive(ifq); @@ -2894,21 +2865,58 @@ ixl_start(struct ifqueue *ifq) if (m == NULL) break; - offload = ixl_tx_setup_offload(m, txr, prod); - txm = &txr->txr_maps[prod]; map = txm->txm_map; + if (ixl_load_mbuf(sc->sc_dmat, map, m) != 0) { + ifq->ifq_errors++; + m_freem(m); + continue; + } + + htxd = &ring[prod]; + + offload = ixl_tx_setup_offload(m, &ext); if (ISSET(m->m_pkthdr.csum_flags, M_TCP_TSO)) { + uint64_t paylen, outlen; + uint64_t hlen; + + if (ext.tcp == NULL || m->m_pkthdr.ph_mss == 0) { + tcpstat_inc(tcps_outbadtso); + bus_dmamap_unload(sc->sc_dmat, map); + m_freem(m); + continue; + } + + hlen = ext.iphlen + ext.tcphlen; + + /* + * The MSS should not be set to a lower value than 64 + * or larger than 9668 bytes. + */ + outlen = MIN(9668, MAX(64, m->m_pkthdr.ph_mss)); + paylen = m->m_pkthdr.len - ETHER_HDR_LEN - hlen; + + txd = htxd; + + hdtype = IXL_TX_DESC_DTYPE_CONTEXT; + + /* cmd is IXL_TX_DESC_DTYPE_DONE */ + cmd |= IXL_TX_CTX_DESC_CMD_TSO; + cmd |= paylen << IXL_TX_CTX_DESC_TLEN_SHIFT; + cmd |= outlen << IXL_TX_CTX_DESC_MSS_SHIFT; + + htolem64(&txd->addr, 0); + htolem64(&txd->cmd, cmd); + prod++; prod &= mask; free--; - } - if (ixl_load_mbuf(sc->sc_dmat, map, m) != 0) { - ifq->ifq_errors++; - m_freem(m); - continue; + tcpstat_add(tcps_outpkttso, + (paylen + outlen - 1) / outlen); + + cmd = IXL_TX_DESC_DTYPE_DATA; } bus_dmamap_sync(sc->sc_dmat, map, 0, @@ -2917,10 +2925,9 @@ ixl_start(struct ifqueue *ifq) for (i = 0; i < map->dm_nsegs; i++) { txd = &ring[prod]; - cmd = (uint64_t)map->dm_segs[i].ds_len << + 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 |= offload; + cmd |= IXL_TX_DESC_CMD_ICRC | offload; htolem64(&txd->addr, map->dm_segs[i].ds_addr); htolem64(&txd->cmd, cmd); @@ -2929,6 +2936,8 @@ ixl_start(struct ifqueue *ifq) prod++; prod &= mask; + + cmd = IXL_TX_DESC_DTYPE_DATA; } cmd |= IXL_TX_DESC_CMD_EOP | IXL_TX_DESC_CMD_RS; htolem64(&txd->cmd, cmd); @@ -2943,16 +2952,25 @@ ixl_start(struct ifqueue *ifq) #endif free -= i; + txr->txr_prod = prod; + + bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(&txr->txr_mem), + 0, IXL_DMA_LEN(&txr->txr_mem), + BUS_DMASYNC_PREWRITE|BUS_DMASYNC_POSTWRITE); + + cmd = lemtoh64(&htxd->cmd); + CLR(cmd, IXL_TX_DESC_DTYPE_MASK); + SET(cmd, hdtype); + htolem64(&htxd->cmd, cmd); + post = 1; } bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(&txr->txr_mem), 0, IXL_DMA_LEN(&txr->txr_mem), BUS_DMASYNC_PREWRITE); - if (post) { - txr->txr_prod = prod; + if (post) ixl_wr(sc, txr->txr_tail, prod); - } } static int