static int vtpci_alloc_interrupts(struct vtpci_softc *sc, int flags, int nvqs, struct vq_alloc_info *vq_info) { int i, nvectors, error; /* * Only allocate a vector for virtqueues that are actually * expecting an interrupt. */ for (nvectors = 0, i = 0; i < nvqs; i++) if (vq_info[i].vqai_intr != NULL) nvectors++; if (vtpci_disable_msix != 0 || sc->vtpci_flags & VIRTIO_PCI_FLAG_NO_MSIX || flags & VIRTIO_ALLOC_VQS_DISABLE_MSIX || vtpci_alloc_msix(sc, nvectors) != 0) { /* * Use MSI interrupts if available. Otherwise, we fallback * to legacy interrupts. */ if ((sc->vtpci_flags & VIRTIO_PCI_FLAG_NO_MSI) == 0 && vtpci_alloc_msi(sc) == 0) sc->vtpci_flags |= VIRTIO_PCI_FLAG_MSI; sc->vtpci_nintr_res = 1; } error = vtpci_alloc_intr_resources(sc, nvqs, vq_info); return (error); }
static int vtpci_setup_interrupts(struct vtpci_softc *sc, enum intr_type type) { int error; type |= INTR_MPSAFE; KASSERT(sc->vtpci_flags & VTPCI_FLAG_ITYPE_MASK, ("%s: no interrupt type selected %#x", __func__, sc->vtpci_flags)); error = vtpci_alloc_intr_resources(sc); if (error) return (error); if (sc->vtpci_flags & VTPCI_FLAG_LEGACY) error = vtpci_setup_legacy_interrupt(sc, type); else if (sc->vtpci_flags & VTPCI_FLAG_MSI) error = vtpci_setup_msi_interrupt(sc, type); else error = vtpci_setup_msix_interrupts(sc, type); return (error); }