summaryrefslogtreecommitdiffstats
path: root/sys/dev/et
diff options
context:
space:
mode:
authoryongari <yongari@FreeBSD.org>2011-12-07 19:08:54 +0000
committeryongari <yongari@FreeBSD.org>2011-12-07 19:08:54 +0000
commitfbd2077e9a7438404706cb5778aa2e8f431e759c (patch)
tree07d0e152e6417df47a58da27d745e1ce5ffad332 /sys/dev/et
parentc6a9c8f2c8308b3d82c1704f4976cf05b9d9e55f (diff)
downloadFreeBSD-src-fbd2077e9a7438404706cb5778aa2e8f431e759c.zip
FreeBSD-src-fbd2077e9a7438404706cb5778aa2e8f431e759c.tar.gz
Controller does not require TX start command for every frame. So
send a single TX command after setting up all TX frames. This removes unnecessary register accesses and bus_dmamap_sync(9) calls. et(4) uses TX interrupt moderation so it's possible to have TX buffers that were already transmitted but waiting for TX completion interrupt. If the number of available TX descriptor is less then 1/3 of total TX descriptor, try reclaiming first to get enough free TX descriptors before setting up TX descriptors. After r228325, et_txeof() no longer tries to send frames after reclaiming TX buffers. That change was made to give more chance to transmit frames in main interrupt handler since we can still send frames in interrupt handler with RX interrupt. So right before exiting interrupt hander, after enabling interrupt, try to send more frames. This gives slightly better performance numbers. While I'm here reduce number of spare TX descriptors from 8 to 4. Controller does not require reserved TX descriptors, it was just to reduce TX overhead. After r228325, driver has much lower TX overhead so it does not make sense to reserve 8 TX descriptors.
Diffstat (limited to 'sys/dev/et')
-rw-r--r--sys/dev/et/if_et.c38
-rw-r--r--sys/dev/et/if_etvar.h2
2 files changed, 30 insertions, 10 deletions
diff --git a/sys/dev/et/if_et.c b/sys/dev/et/if_et.c
index 4ea1193..ae88dfa 100644
--- a/sys/dev/et/if_et.c
+++ b/sys/dev/et/if_et.c
@@ -1097,7 +1097,11 @@ et_intr(void *xsc)
if (intrs & ET_INTR_TIMER)
CSR_WRITE_4(sc, ET_TIMER, sc->sc_timer);
back:
- et_enable_intrs(sc, ET_INTRS);
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ et_enable_intrs(sc, ET_INTRS);
+ if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+ et_start_locked(ifp);
+ }
ET_UNLOCK(sc);
}
@@ -1240,7 +1244,9 @@ et_start_locked(struct ifnet *ifp)
{
struct et_softc *sc;
struct mbuf *m_head = NULL;
+ struct et_txdesc_ring *tx_ring;
struct et_txbuf_data *tbd;
+ uint32_t tx_ready_pos;
int enq;
sc = ifp->if_softc;
@@ -1252,7 +1258,18 @@ et_start_locked(struct ifnet *ifp)
if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != IFF_DRV_RUNNING)
return;
+ /*
+ * Driver does not request TX completion interrupt for every
+ * queued frames to prevent generating excessive interrupts.
+ * This means driver may wait for TX completion interrupt even
+ * though some frames were sucessfully transmitted. Reclaiming
+ * transmitted frames will ensure driver see all available
+ * descriptors.
+ */
tbd = &sc->sc_tx_data;
+ if (tbd->tbd_used > (ET_TX_NDESC * 2) / 3)
+ et_txeof(sc);
+
for (enq = 0; !IFQ_DRV_IS_EMPTY(&ifp->if_snd); ) {
if (tbd->tbd_used + ET_NSEG_SPARE >= ET_TX_NDESC) {
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
@@ -1277,8 +1294,17 @@ et_start_locked(struct ifnet *ifp)
ETHER_BPF_MTAP(ifp, m_head);
}
- if (enq > 0)
+ if (enq > 0) {
+ tx_ring = &sc->sc_tx_ring;
+ bus_dmamap_sync(tx_ring->tr_dtag, tx_ring->tr_dmap,
+ BUS_DMASYNC_PREWRITE);
+ tx_ready_pos = tx_ring->tr_ready_index &
+ ET_TX_READY_POS_INDEX_MASK;
+ if (tx_ring->tr_ready_wrap)
+ tx_ready_pos |= ET_TX_READY_POS_WRAP;
+ CSR_WRITE_4(sc, ET_TX_READY_POS, tx_ready_pos);
sc->watchdog_timer = 5;
+ }
}
static void
@@ -2036,7 +2062,7 @@ et_encap(struct et_softc *sc, struct mbuf **m0)
struct mbuf *m;
bus_dma_segment_t segs[ET_NSEG_MAX];
bus_dmamap_t map;
- uint32_t csum_flags, last_td_ctrl2, tx_ready_pos;
+ uint32_t csum_flags, last_td_ctrl2;
int error, i, idx, first_idx, last_idx, nsegs;
tx_ring = &sc->sc_tx_ring;
@@ -2121,12 +2147,6 @@ et_encap(struct et_softc *sc, struct mbuf **m0)
tbd->tbd_used += nsegs;
MPASS(tbd->tbd_used <= ET_TX_NDESC);
- bus_dmamap_sync(tx_ring->tr_dtag, tx_ring->tr_dmap,
- BUS_DMASYNC_PREWRITE);
- tx_ready_pos = tx_ring->tr_ready_index & ET_TX_READY_POS_INDEX_MASK;
- if (tx_ring->tr_ready_wrap)
- tx_ready_pos |= ET_TX_READY_POS_WRAP;
- CSR_WRITE_4(sc, ET_TX_READY_POS, tx_ready_pos);
return (0);
}
diff --git a/sys/dev/et/if_etvar.h b/sys/dev/et/if_etvar.h
index 6ad0e8e..550603d 100644
--- a/sys/dev/et/if_etvar.h
+++ b/sys/dev/et/if_etvar.h
@@ -41,7 +41,7 @@
#define ET_RING_ALIGN 4096
#define ET_STATUS_ALIGN 8
#define ET_NSEG_MAX 32 /* XXX no limit actually */
-#define ET_NSEG_SPARE 8
+#define ET_NSEG_SPARE 4
#define ET_TX_NDESC 512
#define ET_RX_NDESC 512
OpenPOWER on IntegriCloud