1
0
mirror of https://github.com/openbsd/src.git synced 2024-12-22 16:42:56 -08:00

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@
This commit is contained in:
patrick 2023-07-07 10:23:39 +00:00
parent e609121df8
commit 6c89734d1e
3 changed files with 31 additions and 19 deletions

View File

@ -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

View File

@ -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.
*/

View File

@ -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 *);