From: Stefan Fritsch Subject: vio(4): fix control queue handling during reset To: tech@openbsd.org Date: Thu, 5 Nov 2026 14:47:35 +0100 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;