summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorStefan Fritsch <sf@cvs.openbsd.org>2017-05-31 08:57:49 +0000
committerStefan Fritsch <sf@cvs.openbsd.org>2017-05-31 08:57:49 +0000
commitdfc857dd845144a1acbd081477d2124df680e315 (patch)
tree0b7a955ea3d5653dcc510f706df958cce670d957 /sys/dev
parent53aa6b1590faf98db62e08226bfc1c520918625d (diff)
virtio_pci: Support IPL_MPSAFE interrupt handlers
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/pci/virtio_pci.c31
1 files changed, 26 insertions, 5 deletions
diff --git a/sys/dev/pci/virtio_pci.c b/sys/dev/pci/virtio_pci.c
index 33ddbd3a1c0..8434bdb96e1 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.17 2017/01/21 11:29:52 reyk Exp $ */
+/* $OpenBSD: virtio_pci.c,v 1.18 2017/05/31 08:57:48 sf Exp $ */
/* $NetBSD: virtio.c,v 1.3 2011/11/02 23:05:52 njoly Exp $ */
/*
@@ -74,6 +74,7 @@ int virtio_pci_setup_msix(struct virtio_pci_softc *, struct pci_attach_args *,
void virtio_pci_free_irqs(struct virtio_pci_softc *);
int virtio_pci_poll_intr(void *);
int virtio_pci_legacy_intr(void *);
+int virtio_pci_legacy_intr_mpsafe(void *);
int virtio_pci_config_intr(void *);
int virtio_pci_queue_intr(void *);
int virtio_pci_shared_queue_intr(void *);
@@ -254,6 +255,7 @@ virtio_pci_attach(struct device *parent, struct device *self, void *aux)
sc->sc_irq_type = IRQ_MSIX_SHARED;
intrstr = "msix shared";
} else {
+ int (*ih_func)(void *) = virtio_pci_legacy_intr;
if (pci_intr_map_msi(pa, &ih) != 0 && pci_intr_map(pa, &ih) != 0) {
printf("%s: couldn't map interrupt\n", vsc->sc_dev.dv_xname);
goto fail_2;
@@ -263,11 +265,11 @@ virtio_pci_attach(struct device *parent, struct device *self, void *aux)
* We always set the IPL_MPSAFE flag in order to do the relatively
* expensive ISR read without lock, and then grab the kernel lock in
* the interrupt handler.
- * For now, we don't support IPL_MPSAFE vq_done functions.
*/
- KASSERT((vsc->sc_ipl & IPL_MPSAFE) == 0);
+ if (vsc->sc_ipl & IPL_MPSAFE)
+ ih_func = virtio_pci_legacy_intr_mpsafe;
sc->sc_ih[0] = pci_intr_establish(pc, ih, vsc->sc_ipl | IPL_MPSAFE,
- virtio_pci_legacy_intr, sc, vsc->sc_dev.dv_xname);
+ ih_func, sc, vsc->sc_dev.dv_xname);
if (sc->sc_ih[0] == NULL) {
printf("%s: couldn't establish interrupt", vsc->sc_dev.dv_xname);
if (intrstr != NULL)
@@ -551,6 +553,26 @@ virtio_pci_legacy_intr(void *arg)
return r;
}
+int
+virtio_pci_legacy_intr_mpsafe(void *arg)
+{
+ struct virtio_pci_softc *sc = arg;
+ struct virtio_softc *vsc = &sc->sc_sc;
+ int isr, r = 0;
+
+ /* check and ack the interrupt */
+ isr = bus_space_read_1(sc->sc_iot, sc->sc_ioh,
+ VIRTIO_CONFIG_ISR_STATUS);
+ if (isr == 0)
+ return 0;
+ if ((isr & VIRTIO_CONFIG_ISR_CONFIG_CHANGE) &&
+ (vsc->sc_config_change != NULL)) {
+ r = (vsc->sc_config_change)(vsc);
+ }
+ r |= virtio_check_vqs(vsc);
+ return r;
+}
+
/*
* Only used with MSI-X
*/
@@ -604,7 +626,6 @@ virtio_pci_poll_intr(void *arg)
return r;
}
-
void
virtio_pci_kick(struct virtio_softc *vsc, uint16_t idx)
{