On Fri, Jan 18, 2013 at 09:00:25AM +1100, Darren Tucker wrote:
> Thanks to Mark Patruck for noticing that the previous patch didn't
> actually help, due to a bug I introduced in a last minute "obviously
> correct" clean up.
The turd polishing continues unabated. This adds the interrupt disable
bit to descriptors where there's more than one mbuf in a packet.
Index: dev/pci/if_vr.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_vr.c,v
retrieving revision 1.125
diff -u -p -r1.125 if_vr.c
--- dev/pci/if_vr.c 17 Jan 2013 21:49:48 -0000 1.125
+++ dev/pci/if_vr.c 18 Jan 2013 02:04:55 -0000
@@ -724,7 +724,7 @@ vr_list_tx_init(struct vr_softc *sc)
cd = &sc->vr_cdata;
ld = sc->vr_ldata;
- cd->vr_tx_cnt = 0;
+ cd->vr_tx_cnt = cd->vr_tx_pkts = 0;
for (i = 0; i < VR_TX_LIST_CNT; i++) {
cd->vr_tx_chain[i].vr_ptr = &ld->vr_tx_list[i];
@@ -1198,7 +1198,7 @@ vr_encap(struct vr_softc *sc, struct vr_
struct vr_chain *c = *cp;
struct vr_desc *f = NULL;
struct mbuf *m_new = NULL;
- u_int32_t vr_ctl = 0, vr_status = 0;
+ u_int32_t vr_ctl = 0, vr_status = 0, intdisable = 0;
bus_dmamap_t txmap;
int i, runt = 0;
@@ -1259,6 +1259,15 @@ vr_encap(struct vr_softc *sc, struct vr_
}
#endif
+ /*
+ * We only want TX completion interrupts on every Nth packet.
+ * We need to set VR_TXNEXT_INTDISABLE on every descriptor except
+ * for the last discriptor of every Nth packet, where we set
+ * VR_TXCTL_FINT.
+ */
+ if (sc->vr_cdata.vr_tx_pkts++ % 8 != 0)
+ intdisable = VR_TXNEXT_INTDISABLE;
+
if (m_new != NULL) {
m_freem(m_head);
@@ -1276,7 +1285,7 @@ vr_encap(struct vr_softc *sc, struct vr_
f->vr_ctl |= htole32(VR_TXCTL_FIRSTFRAG);
f->vr_status = htole32(vr_status);
f->vr_data = htole32(txmap->dm_segs[i].ds_addr);
- f->vr_next = htole32(c->vr_nextdesc->vr_paddr);
+ f->vr_next = htole32(c->vr_nextdesc->vr_paddr | intdisable);
sc->vr_cdata.vr_tx_cnt++;
}
@@ -1288,12 +1297,15 @@ vr_encap(struct vr_softc *sc, struct vr_
VR_TXCTL_TLINK | vr_ctl);
f->vr_status = htole32(vr_status);
f->vr_data =
htole32(sc->sc_zeromap.vrm_map->dm_segs[0].ds_addr);
- f->vr_next = htole32(c->vr_nextdesc->vr_paddr);
+ f->vr_next = htole32(c->vr_nextdesc->vr_paddr | intdisable);
sc->vr_cdata.vr_tx_cnt++;
}
/* Set EOP on the last descriptor */
- f->vr_ctl |= htole32(VR_TXCTL_LASTFRAG | VR_TXCTL_FINT);
+ f->vr_ctl |= htole32(VR_TXCTL_LASTFRAG);
+
+ if (!intdisable)
+ f->vr_ctl |= htole32(VR_TXCTL_FINT);
return (0);
}
@@ -1582,6 +1594,15 @@ vr_watchdog(struct ifnet *ifp)
struct vr_softc *sc;
sc = ifp->if_softc;
+
+ /*
+ * Because we're only asking for completion interrupts only every
+ * few packets, occasionally the watchdog will fire when we have
+ * some TX descriptors to reclaim, so check for that first.
+ */
+ vr_txeof(sc);
+ if (sc->vr_cdata.vr_tx_cnt == 0);
+ return;
ifp->if_oerrors++;
printf("%s: watchdog timeout\n", sc->sc_dev.dv_xname);
Index: dev/pci/if_vrreg.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_vrreg.h,v
retrieving revision 1.33
diff -u -p -r1.33 if_vrreg.h
--- dev/pci/if_vrreg.h 16 Jan 2013 05:25:57 -0000 1.33
+++ dev/pci/if_vrreg.h 18 Jan 2013 02:04:55 -0000
@@ -429,6 +429,9 @@ struct vr_desc {
#define VR_TXCTL_LASTFRAG 0x00400000
#define VR_TXCTL_FINT 0x00800000
+/* TDES3 aka vr_next */
+#define VR_TXNEXT_INTDISABLE 0x00000001
+
#define VR_MAXFRAGS 8
#define VR_RX_LIST_CNT 128
#define VR_TX_LIST_CNT 128
@@ -467,6 +470,7 @@ struct vr_chain_data {
struct vr_chain *vr_tx_cons;
struct vr_chain *vr_tx_prod;
int vr_tx_cnt;
+ int vr_tx_pkts;
};
struct vr_mii_frame {
--
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.