-/* $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 $ */
/*
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 *);
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;
* 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)
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
*/
return r;
}
-
void
virtio_pci_kick(struct virtio_softc *vsc, uint16_t idx)
{