Index | Thread | Search

From:
Stefan Fritsch <sf@sfritsch.de>
Subject:
vio(4): fix control queue handling during reset
To:
tech@openbsd.org
Date:
Thu, 5 Nov 2026 14:47:35 +0100

Download raw body.

Thread
  • Stefan Fritsch:

    vio(4): fix control queue handling during reset

Hi,
    
at virtio_reset(), the features are reset, so we need to check for control 
queue availability in a different way than virtio_has_feature().
    
After reset, we first need to re-enable the control-queue before we can 
use it for configuring multiqueue. Due to the bug above, this has not been 
a problem before.

ok?

Cheers,
Stefan

diff --git a/sys/dev/pv/if_vio.c b/sys/dev/pv/if_vio.c
index 8942b02857a..5a37f4b18f6 100644
--- a/sys/dev/pv/if_vio.c
+++ b/sys/dev/pv/if_vio.c
@@ -1097,38 +1097,42 @@ vio_stop(struct ifnet *ifp, int disable)
 	timeout_del(&sc->sc_rxtick);
 	/* only way to stop I/O and DMA is resetting... */
 	virtio_reset(vsc);
 	virtio_intr_barrier(vsc);
 	for (i = 0; i < sc->sc_nqueues; i++) {
 		mtx_enter(&sc->sc_q[i].viq_rxmtx);
 		vio_rxeof(&sc->sc_q[i]);
 		mtx_leave(&sc->sc_q[i].viq_rxmtx);
 	}
 
-	if (virtio_has_feature(vsc, VIRTIO_NET_F_CTRL_VQ))
+	/*
+	 * We cannot use virtio_has_feature() between virtio_reset and
+	 * virtio_reinit_start()
+	 */
+	if (sc->sc_ctl_vq != NULL)
 		vio_ctrl_wakeup(sc, RESET);
 	vio_tx_drain(sc);
 	if (disable)
 		vio_rx_drain(sc);
 
 	virtio_reinit_start(vsc);
 	for (i = 0; i < sc->sc_nqueues; i++) {
 		virtio_start_vq_intr(vsc, sc->sc_q[i].viq_rxvq);
 		virtio_stop_vq_intr(vsc, sc->sc_q[i].viq_txvq);
 	}
 	if (virtio_has_feature(vsc, VIRTIO_NET_F_CTRL_VQ))
 		virtio_start_vq_intr(vsc, sc->sc_ctl_vq);
 	virtio_reinit_end(vsc);
-	if (virtio_has_feature(vsc, VIRTIO_NET_F_MQ))
-		vio_ctrl_mq(sc);
 	if (virtio_has_feature(vsc, VIRTIO_NET_F_CTRL_VQ))
 		vio_ctrl_wakeup(sc, FREE);
+	if (virtio_has_feature(vsc, VIRTIO_NET_F_MQ))
+		vio_ctrl_mq(sc);
 }
 
 static inline uint16_t
 vio_cksum_update(uint32_t cksum, uint16_t paylen)
 {
 	/* Add payload length */
 	cksum += paylen;
 
 	/* Fold back to 16 bit */
 	cksum += cksum >> 16;