Index: if_rge.c =================================================================== RCS file: /cvs/src/sys/dev/pci/if_rge.c,v diff -u -p -r1.29 if_rge.c --- if_rge.c 12 Aug 2024 06:47:11 -0000 1.29 +++ if_rge.c 12 Aug 2024 07:27:26 -0000 @@ -65,7 +65,6 @@ int rge_match(struct device *, void *, void rge_attach(struct device *, struct device *, void *); int rge_activate(struct device *, int); int rge_intr(void *); -int rge_encap(struct rge_queues *, struct mbuf *, int); int rge_ioctl(struct ifnet *, u_long, caddr_t); void rge_start(struct ifqueue *); void rge_watchdog(struct ifnet *); @@ -413,29 +412,15 @@ rge_intr(void *arg) return (claimed); } -int -rge_encap(struct rge_queues *q, struct mbuf *m, int idx) +static int +rge_encap(struct ifnet *ifp, struct rge_queues *q, struct mbuf *m, int idx) { struct rge_softc *sc = q->q_sc; struct rge_tx_desc *d = NULL; struct rge_txq *txq; bus_dmamap_t txmap; uint32_t cmdsts, cflags = 0; - int cur, error, i, last, nsegs; - - /* - * Set RGE_TDEXTSTS_IPCSUM if any checksum offloading is requested. - * Otherwise, RGE_TDEXTSTS_TCPCSUM / RGE_TDEXTSTS_UDPCSUM does not - * take affect. - */ - if ((m->m_pkthdr.csum_flags & - (M_IPV4_CSUM_OUT | M_TCP_CSUM_OUT | M_UDP_CSUM_OUT)) != 0) { - cflags |= RGE_TDEXTSTS_IPCSUM; - if (m->m_pkthdr.csum_flags & M_TCP_CSUM_OUT) - cflags |= RGE_TDEXTSTS_TCPCSUM; - if (m->m_pkthdr.csum_flags & M_UDP_CSUM_OUT) - cflags |= RGE_TDEXTSTS_UDPCSUM; - } + int cur, error, i, last; txq = &q->q_tx.rge_txq[idx]; txmap = txq->txq_dmamap; @@ -458,7 +443,19 @@ rge_encap(struct rge_queues *q, struct m bus_dmamap_sync(sc->sc_dmat, txmap, 0, txmap->dm_mapsize, BUS_DMASYNC_PREWRITE); - nsegs = txmap->dm_nsegs; + /* + * Set RGE_TDEXTSTS_IPCSUM if any checksum offloading is requested. + * Otherwise, RGE_TDEXTSTS_TCPCSUM / RGE_TDEXTSTS_UDPCSUM does not + * take affect. + */ + if ((m->m_pkthdr.csum_flags & + (M_IPV4_CSUM_OUT | M_TCP_CSUM_OUT | M_UDP_CSUM_OUT)) != 0) { + cflags |= RGE_TDEXTSTS_IPCSUM; + if (m->m_pkthdr.csum_flags & M_TCP_CSUM_OUT) + cflags |= RGE_TDEXTSTS_TCPCSUM; + if (m->m_pkthdr.csum_flags & M_UDP_CSUM_OUT) + cflags |= RGE_TDEXTSTS_UDPCSUM; + } /* Set up hardware VLAN tagging. */ #if NVLAN > 0 @@ -470,12 +467,6 @@ rge_encap(struct rge_queues *q, struct m cmdsts = RGE_TDCMDSTS_SOF; for (i = 0; i < txmap->dm_nsegs; i++) { - d = &q->q_tx.rge_tx_list[cur]; - - d->rge_extsts = htole32(cflags); - d->rge_addrlo = htole32(RGE_ADDR_LO(txmap->dm_segs[i].ds_addr)); - d->rge_addrhi = htole32(RGE_ADDR_HI(txmap->dm_segs[i].ds_addr)); - cmdsts |= txmap->dm_segs[i].ds_len; if (cur == RGE_TX_LIST_CNT - 1) @@ -483,31 +474,27 @@ rge_encap(struct rge_queues *q, struct m if (i == (txmap->dm_nsegs - 1)) cmdsts |= RGE_TDCMDSTS_EOF; + d = &q->q_tx.rge_tx_list[cur]; d->rge_cmdsts = htole32(cmdsts); - - bus_dmamap_sync(sc->sc_dmat, q->q_tx.rge_tx_list_map, - cur * sizeof(struct rge_tx_desc), sizeof(struct rge_tx_desc), - BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + d->rge_extsts = htole32(cflags); + d->rge_addrlo = htole32(RGE_ADDR_LO(txmap->dm_segs[i].ds_addr)); + d->rge_addrhi = htole32(RGE_ADDR_HI(txmap->dm_segs[i].ds_addr)); last = cur; cmdsts = RGE_TDCMDSTS_OWN; cur = RGE_NEXT_TX_DESC(cur); } - /* Transfer ownership of packet to the chip. */ - d = &q->q_tx.rge_tx_list[idx]; - - d->rge_cmdsts |= htole32(RGE_TDCMDSTS_OWN); - - bus_dmamap_sync(sc->sc_dmat, q->q_tx.rge_tx_list_map, - idx * sizeof(struct rge_tx_desc), sizeof(struct rge_tx_desc), - BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); - /* Update info of TX queue and descriptors. */ txq->txq_mbuf = m; txq->txq_descidx = last; - return (nsegs); + /* Transfer ownership of packet to the chip. */ + d = &q->q_tx.rge_tx_list[idx]; + membar_producer(); + d->rge_cmdsts |= htole32(RGE_TDCMDSTS_OWN); + + return (i); } int @@ -580,6 +567,10 @@ rge_start(struct ifqueue *ifq) free += RGE_TX_LIST_CNT; free -= idx; + bus_dmamap_sync(sc->sc_dmat, q->q_tx.rge_tx_list_map, + 0, sizeof(struct rge_tx_desc) * RGE_TX_LIST_CNT, + BUS_DMASYNC_POSTWRITE); + for (;;) { if (free < RGE_TX_NSEGS + 2) { ifq_set_oactive(&ifp->if_snd); @@ -590,20 +581,15 @@ rge_start(struct ifqueue *ifq) if (m == NULL) break; - used = rge_encap(q, m, idx); + used = rge_encap(ifp, q, m, idx); if (used == 0) { m_freem(m); continue; } - KASSERT(used <= free); + KASSERT(used < free); free -= used; -#if NBPFILTER > 0 - if (ifp->if_bpf) - bpf_mtap_ether(ifp->if_bpf, m, BPF_DIRECTION_OUT); -#endif - idx += used; if (idx >= RGE_TX_LIST_CNT) idx -= RGE_TX_LIST_CNT; @@ -611,6 +597,10 @@ rge_start(struct ifqueue *ifq) queued++; } + bus_dmamap_sync(sc->sc_dmat, q->q_tx.rge_tx_list_map, + 0, sizeof(struct rge_tx_desc) * RGE_TX_LIST_CNT, + BUS_DMASYNC_PREWRITE); + if (queued == 0) return; @@ -1363,17 +1353,15 @@ rge_txeof(struct rge_queues *q) prod = q->q_tx.rge_txq_prodidx; cons = q->q_tx.rge_txq_considx; + bus_dmamap_sync(sc->sc_dmat, q->q_tx.rge_tx_list_map, + 0, sizeof(struct rge_tx_desc) * RGE_TX_LIST_CNT, + BUS_DMASYNC_POSTREAD); + while (prod != cons) { txq = &q->q_tx.rge_txq[cons]; idx = txq->txq_descidx; - bus_dmamap_sync(sc->sc_dmat, q->q_tx.rge_tx_list_map, - idx * sizeof(struct rge_tx_desc), - sizeof(struct rge_tx_desc), - BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); - txstat = letoh32(q->q_tx.rge_tx_list[idx].rge_cmdsts); - if (txstat & RGE_TDCMDSTS_OWN) { free = 2; break; @@ -1390,14 +1378,13 @@ rge_txeof(struct rge_queues *q) if (txstat & RGE_TDCMDSTS_TXERR) ifp->if_oerrors++; - bus_dmamap_sync(sc->sc_dmat, q->q_tx.rge_tx_list_map, - idx * sizeof(struct rge_tx_desc), - sizeof(struct rge_tx_desc), - BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); - cons = RGE_NEXT_TX_DESC(idx); free = 1; } + + bus_dmamap_sync(sc->sc_dmat, q->q_tx.rge_tx_list_map, + 0, sizeof(struct rge_tx_desc) * RGE_TX_LIST_CNT, + BUS_DMASYNC_PREREAD); if (free == 0) return (0);