On Thu, Jan 17, 2013 at 09:34:32PM +1100, Darren Tucker wrote: > OK, here's another diff which does seem to help. It seems that there's > two different bits in the TX descriptor that control interrupts. Quoting > from the VT6105M spec:
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. Index: dev/pci/if_vr.c =================================================================== RCS file: /cvs/src/sys/dev/pci/if_vr.c,v retrieving revision 1.124 diff -u -p -r1.124 if_vr.c --- dev/pci/if_vr.c 16 Jan 2013 06:15:50 -0000 1.124 +++ dev/pci/if_vr.c 17 Jan 2013 21:54:19 -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]; @@ -1292,7 +1292,15 @@ vr_encap(struct vr_softc *sc, struct vr_ } /* Set EOP on the last descriptor */ - f->vr_ctl |= htole32(VR_TXCTL_LASTFRAG | VR_TXCTL_FINT); + f->vr_ctl |= htole32(VR_TXCTL_LASTFRAG); + + /* set the disable-interrupt bit except on every Nth packet */ + if (sc->vr_cdata.vr_tx_pkts++ < 8) + f->vr_next |= htole32(VR_TXNEXT_INTDISABLE); + else { + sc->vr_cdata.vr_tx_pkts = 0; + f->vr_ctl |= htole32(VR_TXCTL_FINT); + } return (0); } @@ -1581,6 +1589,11 @@ vr_watchdog(struct ifnet *ifp) struct vr_softc *sc; sc = ifp->if_softc; + + /* Reclaim first as we don't request an interrupt for every packet. */ + 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); -- 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.