aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBryan Venteicher <bryanv@FreeBSD.org>2021-01-19 04:55:25 +0000
committerBryan Venteicher <bryanv@FreeBSD.org>2021-01-19 04:55:25 +0000
commit4f18e23f84320fb126ce3ccc899aa3f99b7ae925 (patch)
tree4af193d9a059ba2b42a4e959284155820d4240ab
parentc3187190c71f6850a8d8a058d78a671a45e2871c (diff)
downloadsrc-4f18e23f84320fb126ce3ccc899aa3f99b7ae925.tar.gz
src-4f18e23f84320fb126ce3ccc899aa3f99b7ae925.zip
if_vtnet: Schedule Rx task if pending items when enabling interrupt
Prior to V1, the driver would enable interrupts and then notify the host that DRIVER_OK. Since for V1, DRIVER_OK needs to be set before notifying the virtqueues, there may be items in the queues waiting to be processed by the time interrupts are enabled. This fixes a bug where the Rx queue would appear stuck, only being usable after an interface down/up cycle. Reviewed by: grehan (mentor) Differential Revision: https://reviews.freebsd.org/D27922
-rw-r--r--sys/dev/virtio/network/if_vtnet.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/sys/dev/virtio/network/if_vtnet.c b/sys/dev/virtio/network/if_vtnet.c
index e3a42413d5cd..dc232d769fa6 100644
--- a/sys/dev/virtio/network/if_vtnet.c
+++ b/sys/dev/virtio/network/if_vtnet.c
@@ -3120,11 +3120,13 @@ vtnet_stop_rendezvous(struct vtnet_softc *sc)
struct vtnet_txq *txq;
int i;
+ VTNET_CORE_LOCK_ASSERT(sc);
+
/*
* Lock and unlock the per-queue mutex so we known the stop
* state is visible. Doing only the active queues should be
* sufficient, but it does not cost much extra to do all the
- * queues. Note we hold the core mutex here too.
+ * queues.
*/
for (i = 0; i < sc->vtnet_max_vq_pairs; i++) {
rxq = &sc->vtnet_rxqs[i];
@@ -3168,8 +3170,8 @@ vtnet_stop(struct vtnet_softc *sc)
virtio_stop(dev);
vtnet_stop_rendezvous(sc);
- /* Free any mbufs left in the virtqueues. */
vtnet_drain_rxtx_queues(sc);
+ sc->vtnet_act_vq_pairs = 1;
}
static int
@@ -4278,10 +4280,14 @@ vtnet_txq_disable_intr(struct vtnet_txq *txq)
static void
vtnet_enable_rx_interrupts(struct vtnet_softc *sc)
{
+ struct vtnet_rxq *rxq;
int i;
- for (i = 0; i < sc->vtnet_act_vq_pairs; i++)
- vtnet_rxq_enable_intr(&sc->vtnet_rxqs[i]);
+ for (i = 0; i < sc->vtnet_act_vq_pairs; i++) {
+ rxq = &sc->vtnet_rxqs[i];
+ if (vtnet_rxq_enable_intr(rxq) != 0)
+ taskqueue_enqueue(rxq->vtnrx_tq, &rxq->vtnrx_intrtask);
+ }
}
static void