On Mon, Jan 14, 2013 at 10:10:55PM +1100, Darren Tucker wrote:
> 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).
Here's an updated diff where, when a single packet spans multiple TX
descriptors, it'll only sent the interrupt request bit on the final
discriptor (which matches the current behaviour for that case).
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 23:23:57 -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
@@ -1273,6 +1280,7 @@ vr_start(struct ifnet *ifp)
struct vr_softc *sc;
struct mbuf *m_head;
struct vr_chain *cur_tx, *head_tx;
+ struct vr_chain *prev_head_tx = NULL, *prev_tail_tx = NULL;
sc = ifp->if_softc;
@@ -1298,9 +1306,10 @@ 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_head_tx != NULL)
+ prev_head_tx->vr_ptr->vr_status |=
+ htole32(VR_TXSTAT_OWN);
#if NBPFILTER > 0
/*
@@ -1311,9 +1320,22 @@ vr_start(struct ifnet *ifp)
bpf_mtap_ether(ifp->if_bpf, head_tx->vr_mbuf,
BPF_DIRECTION_OUT);
#endif
+ prev_head_tx = head_tx;
+ prev_tail_tx = cur_tx;
cur_tx = cur_tx->vr_nextdesc;
}
if (sc->vr_cdata.vr_tx_cnt != 0) {
+ /*
+ * If we enqueued any packets, we want to set FINT on the last
+ * descriptor for the last packet, but set TXOWN on the first
+ * descriptor of the last packet.
+ */
+ if (prev_tail_tx != NULL)
+ prev_tail_tx->vr_ptr->vr_ctl |= htole32(VR_TXCTL_FINT);
+ if (prev_head_tx != NULL)
+ prev_head_tx->vr_ptr->vr_status |=
+ htole32(VR_TXSTAT_OWN);
+
sc->vr_cdata.vr_tx_prod = cur_tx;
bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap.vrm_map, 0,
--
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.