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_alloc_intr_msix_shared(struct vtpci_softc *sc) { int error; if (vtpci_disable_msix != 0 || sc->vtpci_flags & VTPCI_FLAG_NO_MSIX) return (ENOTSUP); error = vtpci_alloc_msix(sc, 1); if (error) return (error); sc->vtpci_flags |= VTPCI_FLAG_MSIX | VTPCI_FLAG_SHARED_MSIX; return (0); }
static int vtpci_alloc_intr_msix_pervq(struct vtpci_softc *sc) { int i, nvectors, error; if (vtpci_disable_msix != 0 || sc->vtpci_flags & VTPCI_FLAG_NO_MSIX) return (ENOTSUP); for (nvectors = 0, i = 0; i < sc->vtpci_nvqs; i++) { if (sc->vtpci_vqs[i].vtv_no_intr == 0) nvectors++; } error = vtpci_alloc_msix(sc, nvectors); if (error) return (error); sc->vtpci_flags |= VTPCI_FLAG_MSIX; return (0); }