commit 3f257538798b48dd727e79c8af6b2a11bd502e5b Author: Bryan Venteicher Date: Tue Feb 4 00:08:52 2014 -0600 Simulate an interrupt if the watchdog drained the Tx complete queue diff --git a/sys/dev/virtio/network/if_vtnet.c b/sys/dev/virtio/network/if_vtnet.c index cc4adeb..93de504 100644 --- a/sys/dev/virtio/network/if_vtnet.c +++ b/sys/dev/virtio/network/if_vtnet.c @@ -149,7 +149,7 @@ static void vtnet_txq_tq_deferred(void *, int); #endif static void vtnet_txq_start(struct vtnet_txq *); static void vtnet_txq_tq_intr(void *, int); -static void vtnet_txq_eof(struct vtnet_txq *); +static int vtnet_txq_eof(struct vtnet_txq *); static void vtnet_tx_vq_intr(void *); static void vtnet_tx_start_all(struct vtnet_softc *); @@ -2385,18 +2385,21 @@ vtnet_txq_tq_intr(void *xtxq, int pending) VTNET_TXQ_UNLOCK(txq); } -static void +static int vtnet_txq_eof(struct vtnet_txq *txq) { struct virtqueue *vq; struct vtnet_tx_header *txhdr; struct mbuf *m; + int deq; vq = txq->vtntx_vq; + deq = 0; VTNET_TXQ_LOCK_ASSERT(txq); while ((txhdr = virtqueue_dequeue(vq, NULL)) != NULL) { m = txhdr->vth_mbuf; + deq++; txq->vtntx_stats.vtxs_opackets++; txq->vtntx_stats.vtxs_obytes += m->m_pkthdr.len; @@ -2409,6 +2412,8 @@ vtnet_txq_eof(struct vtnet_txq *txq) if (virtqueue_empty(vq)) txq->vtntx_watchdog = 0; + + return (deq); } static void @@ -2512,8 +2517,13 @@ vtnet_watchdog(struct vtnet_txq *txq) sc = txq->vtntx_sc; VTNET_TXQ_LOCK(txq); - if (sc->vtnet_flags & VTNET_FLAG_EVENT_IDX) - vtnet_txq_eof(txq); + if (sc->vtnet_flags & VTNET_FLAG_EVENT_IDX) { + if (txq->vtntx_watchdog != 0 && vtnet_txq_eof(txq) != 0) { + taskqueue_enqueue(txq->vtntx_tq, &txq->vtntx_intrtask); + VTNET_TXQ_UNLOCK(txq); + return (0); + } + } if (txq->vtntx_watchdog == 0 || --txq->vtntx_watchdog) { VTNET_TXQ_UNLOCK(txq); return (0);