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.

Reply via email to