Hi all. This patch below reduces the number of interrupts on the transmit side of vr(4). Currently we set the TX competion interrupt bit on each outbound packet. This patch changes it to only set the interrupt bit on the last packet enqueued. (One thing of note is that the interrupt bit is set on the first of potentially several TX descriptors for a packet whereas currently it's the last. I'm not sure if this matters, but if it does I can change it).
On my ALIX, it increase the IP routing throughput from 80Mbit/s to 85Mbit/s while reducing the interrupt CPU usage from 99% to 80%. Testing on any VIA Rhine chips would be appreciated (especially ones that are not 6105M like my ALIX). (Help/suggestions from jsing@ chris@ mikeb@ dlg@...) Thanks. Index: dev/pci/if_vr.c =================================================================== RCS file: /cvs/src/sys/dev/pci/if_vr.c,v retrieving revision 1.121 diff -u -p -r1.121 if_vr.c --- dev/pci/if_vr.c 1 Dec 2012 09:55:03 -0000 1.121 +++ dev/pci/if_vr.c 14 Jan 2013 10:50:58 -0000 @@ -1254,8 +1254,8 @@ vr_encap(struct vr_softc *sc, struct vr_ sc->vr_cdata.vr_tx_cnt++; } - /* Set EOP on the last desciptor */ - f->vr_ctl |= htole32(VR_TXCTL_LASTFRAG | VR_TXCTL_FINT); + /* Set EOP on the last descriptor */ + f->vr_ctl |= htole32(VR_TXCTL_LASTFRAG); return (0); } @@ -1265,6 +1265,13 @@ vr_encap(struct vr_softc *sc, struct vr_ * to the mbuf data regions directly in the transmit lists. We also save a * copy of the pointers since the transmit list fragment pointers are * physical addresses. + * + * Notes: + * We only set ownership bit on first descriptor for a each packet. + * We'll only want an interrupt for a given packet if either vr_encap fails + * (ie the descriptor ring is full) or if the interface input queue is + * empty, and we need to set the interrupt bit before setting the owner bit + * to turn it over to the hardware. */ void @@ -1272,7 +1279,7 @@ vr_start(struct ifnet *ifp) { struct vr_softc *sc; struct mbuf *m_head; - struct vr_chain *cur_tx, *head_tx; + struct vr_chain *cur_tx, *head_tx, *prev_tx = NULL; sc = ifp->if_softc; @@ -1298,9 +1305,9 @@ vr_start(struct ifnet *ifp) IF_PREPEND(&ifp->if_snd, m_head); break; } - - /* Only set ownership bit on first descriptor */ - head_tx->vr_ptr->vr_status |= htole32(VR_TXSTAT_OWN); + /* successfully enqueued new packet, we're done with previous */ + if (prev_tx != NULL) + prev_tx->vr_ptr->vr_status |= htole32(VR_TXSTAT_OWN); #if NBPFILTER > 0 /* @@ -1312,7 +1319,13 @@ vr_start(struct ifnet *ifp) BPF_DIRECTION_OUT); #endif cur_tx = cur_tx->vr_nextdesc; + prev_tx = head_tx; + } + if (prev_tx != NULL) { + prev_tx->vr_ptr->vr_ctl |= htole32(VR_TXCTL_FINT); + prev_tx->vr_ptr->vr_status |= htole32(VR_TXSTAT_OWN); } + if (sc->vr_cdata.vr_tx_cnt != 0) { sc->vr_cdata.vr_tx_prod = cur_tx; -- Darren Tucker (dtucker at zip.com.au) GPG key 8FF4FA69 / D9A3 86E9 7EEE AF4B B2D4 37C9 C982 80C7 8FF4 FA69 Good judgement comes with experience. Unfortunately, the experience usually comes from bad judgement.