From: Stefan Fritsch Subject: vio: allow longer tx chains with tso To: tech@openbsd.org Date: Tue, 17 Sep 2024 11:12:07 +0200 Hi, most of the rest of my vio multi-queue work will wait until after the release. But there are a few small parts that are not really related to multi-queue that I would like to go into 7.6. When TCP segmentation offload is supported, we may get larger packets with more dma segments. Allocate more segments in the busdma_map in this case, so that we need to defragment less often. ok? Cheers, Stefan diff --git a/sys/dev/pv/if_vio.c b/sys/dev/pv/if_vio.c index fc7f330c0ee..25f0316a36b 100644 --- a/sys/dev/pv/if_vio.c +++ b/sys/dev/pv/if_vio.c @@ -269,7 +269,6 @@ struct vio_softc { #define VIO_HAVE_MRG_RXBUF(sc) \ ((sc)->sc_hdr_size == sizeof(struct virtio_net_hdr)) -#define VIRTIO_NET_TX_MAXNSEGS 16 /* for larger chains, defrag */ #define VIRTIO_NET_CTRL_MAC_MC_ENTRIES 64 /* for more entries, use ALLMULTI */ #define VIRTIO_NET_CTRL_MAC_UC_ENTRIES 1 /* one entry for own unicast addr */ #define VIRTIO_NET_CTRL_TIMEOUT (5*1000*1000*1000ULL) /* 5 seconds */ @@ -321,7 +320,7 @@ int vio_ctrl_start(struct vio_softc *, uint8_t, uint8_t, int, int *); int vio_ctrl_submit(struct vio_softc *, int); void vio_ctrl_finish(struct vio_softc *); void vio_ctrl_wakeup(struct vio_softc *, enum vio_ctrl_state); -int vio_alloc_mem(struct vio_softc *); +int vio_alloc_mem(struct vio_softc *, int); int vio_alloc_dmamem(struct vio_softc *); void vio_free_dmamem(struct vio_softc *); @@ -416,7 +415,7 @@ vio_free_dmamem(struct vio_softc *sc) * viq_txmbufs[slot]: mbuf pointer array for sent frames */ int -vio_alloc_mem(struct vio_softc *sc) +vio_alloc_mem(struct vio_softc *sc, int tx_max_segments) { struct virtio_softc *vsc = sc->sc_virtio; struct ifnet *ifp = &sc->sc_ac.ac_if; @@ -503,7 +502,7 @@ vio_alloc_mem(struct vio_softc *sc) for (i = 0; i < txqsize; i++) { r = bus_dmamap_create(vsc->sc_dmat, txsize, - VIRTIO_NET_TX_MAXNSEGS, txsize, 0, + tx_max_segments, txsize, 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &vioq->viq_txdmamaps[i]); if (r != 0) @@ -586,7 +585,7 @@ vio_attach(struct device *parent, struct device *self, void *aux) { struct vio_softc *sc = (struct vio_softc *)self; struct virtio_softc *vsc = (struct virtio_softc *)parent; - int i; + int i, tx_max_segments; struct ifnet *ifp = &sc->sc_ac.ac_if; if (vsc->sc_child != NULL) { @@ -650,6 +649,17 @@ vio_attach(struct device *parent, struct device *self, void *aux) else ifp->if_hardmtu = MCLBYTES - sc->sc_hdr_size - ETHER_HDR_LEN; + /* defrag for longer mbuf chains */ + tx_max_segments = 16; + if (virtio_has_feature(vsc, VIRTIO_NET_F_HOST_TSO4) || + virtio_has_feature(vsc, VIRTIO_NET_F_HOST_TSO6)) { + /* + * With TSO, we may get 64K packets and want to be able to + * send longer chains without defragmenting + */ + tx_max_segments = 32; + } + for (i = 0; i < sc->sc_nqueues; i++) { int vqidx = 2 * i; struct vio_queue *vioq = &sc->sc_q[i]; @@ -664,7 +674,7 @@ vio_attach(struct device *parent, struct device *self, void *aux) vqidx++; vioq->viq_txvq = &vsc->sc_vqs[vqidx]; if (virtio_alloc_vq(vsc, vioq->viq_txvq, vqidx, - VIRTIO_NET_TX_MAXNSEGS + 1, "tx") != 0) { + tx_max_segments + 1, "tx") != 0) { goto err; } vioq->viq_txvq->vq_done = vio_tx_intr; @@ -684,7 +694,7 @@ vio_attach(struct device *parent, struct device *self, void *aux) virtio_start_vq_intr(vsc, sc->sc_ctl_vq); } - if (vio_alloc_mem(sc) < 0) + if (vio_alloc_mem(sc, tx_max_segments) < 0) goto err; strlcpy(ifp->if_xname, self->dv_xname, IFNAMSIZ);