diff options
author | Patrick Wildt <patrick@cvs.openbsd.org> | 2023-07-07 10:23:40 +0000 |
---|---|---|
committer | Patrick Wildt <patrick@cvs.openbsd.org> | 2023-07-07 10:23:40 +0000 |
commit | ca891b6d8eac884b8be8b5dcf4f0fc4e72480a5e (patch) | |
tree | 55c52c3d33d8d462c52458c1545c4fc53fbece24 /sys | |
parent | 8888312e624ecc9bdb18bb3b6833e7687fc08b77 (diff) |
The per-VQ MSI-X interrupt handler needs to sync DMA mappings in the
same way that the shared interrupt handler does. This is one of the
requirements of virtio_dequeue(), as specified in its comment above.
Without the DMA sync, it will not see a new entry on the ring and
return. Since the interrupt is edge-triggered there won't be another
one and we'll get stuck.
ok dv@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/pci/virtio_pci.c | 14 | ||||
-rw-r--r-- | sys/dev/pv/virtio.c | 33 | ||||
-rw-r--r-- | sys/dev/pv/virtiovar.h | 3 |
3 files changed, 31 insertions, 19 deletions
diff --git a/sys/dev/pci/virtio_pci.c b/sys/dev/pci/virtio_pci.c index 28087f1ac9d..398dc960f6d 100644 --- a/sys/dev/pci/virtio_pci.c +++ b/sys/dev/pci/virtio_pci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: virtio_pci.c,v 1.34 2023/07/05 18:11:08 patrick Exp $ */ +/* $OpenBSD: virtio_pci.c,v 1.35 2023/07/07 10:23:39 patrick Exp $ */ /* $NetBSD: virtio.c,v 1.3 2011/11/02 23:05:52 njoly Exp $ */ /* @@ -961,6 +961,13 @@ virtio_pci_setup_msix(struct virtio_pci_softc *sc, struct pci_attach_args *pa, struct virtio_softc *vsc = &sc->sc_sc; int i; + /* Shared needs config + queue */ + if (shared && pci_intr_msix_count(pa) < 1 + 1) + return 1; + /* Per VQ needs config + N * queue */ + if (!shared && pci_intr_msix_count(pa) < 1 + vsc->sc_nvqs) + return 1; + if (virtio_pci_msix_establish(sc, pa, 0, virtio_pci_config_intr, vsc)) return 1; sc->sc_devcfg_offset = VIRTIO_CONFIG_DEVICE_CONFIG_MSI; @@ -1059,10 +1066,9 @@ int virtio_pci_queue_intr(void *arg) { struct virtqueue *vq = arg; + struct virtio_softc *vsc = vq->vq_owner; - if (vq->vq_done) - return (vq->vq_done)(vq); - return 0; + return virtio_check_vq(vsc, vq); } int diff --git a/sys/dev/pv/virtio.c b/sys/dev/pv/virtio.c index d085376d054..e9be61c0bbe 100644 --- a/sys/dev/pv/virtio.c +++ b/sys/dev/pv/virtio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: virtio.c,v 1.22 2023/04/20 19:28:31 jcs Exp $ */ +/* $OpenBSD: virtio.c,v 1.23 2023/07/07 10:23:39 patrick Exp $ */ /* $NetBSD: virtio.c,v 1.3 2011/11/02 23:05:52 njoly Exp $ */ /* @@ -218,26 +218,31 @@ vq_sync_indirect(struct virtio_softc *sc, struct virtqueue *vq, int slot, int virtio_check_vqs(struct virtio_softc *sc) { - struct virtqueue *vq; int i, r = 0; /* going backwards is better for if_vio */ - for (i = sc->sc_nvqs - 1; i >= 0; i--) { - vq = &sc->sc_vqs[i]; - if (vq->vq_queued) { - vq->vq_queued = 0; - vq_sync_aring(sc, vq, BUS_DMASYNC_POSTWRITE); - } - vq_sync_uring(sc, vq, BUS_DMASYNC_POSTREAD); - if (vq->vq_used_idx != vq->vq_used->idx) { - if (vq->vq_done) - r |= (vq->vq_done)(vq); - } - } + for (i = sc->sc_nvqs - 1; i >= 0; i--) + r |= virtio_check_vq(sc, &sc->sc_vqs[i]); return r; } +int +virtio_check_vq(struct virtio_softc *sc, struct virtqueue *vq) +{ + if (vq->vq_queued) { + vq->vq_queued = 0; + vq_sync_aring(sc, vq, BUS_DMASYNC_POSTWRITE); + } + vq_sync_uring(sc, vq, BUS_DMASYNC_POSTREAD); + if (vq->vq_used_idx != vq->vq_used->idx) { + if (vq->vq_done) + return (vq->vq_done)(vq); + } + + return 0; +} + /* * Initialize vq structure. */ diff --git a/sys/dev/pv/virtiovar.h b/sys/dev/pv/virtiovar.h index 9e3e9c9a27b..7f2aea701cd 100644 --- a/sys/dev/pv/virtiovar.h +++ b/sys/dev/pv/virtiovar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: virtiovar.h,v 1.14 2019/05/26 15:22:31 sf Exp $ */ +/* $OpenBSD: virtiovar.h,v 1.15 2023/07/07 10:23:39 patrick Exp $ */ /* $NetBSD: virtiovar.h,v 1.1 2011/10/30 12:12:21 hannken Exp $ */ /* @@ -233,6 +233,7 @@ int virtio_dequeue_commit(struct virtqueue*, int); int virtio_intr(void *arg); int virtio_check_vqs(struct virtio_softc *); +int virtio_check_vq(struct virtio_softc *, struct virtqueue *); void virtio_stop_vq_intr(struct virtio_softc *, struct virtqueue *); int virtio_start_vq_intr(struct virtio_softc *, struct virtqueue *); |