Index: sys/dev/virtio/pci/virtio_pci_legacy.c =================================================================== --- sys/dev/virtio/pci/virtio_pci_legacy.c +++ sys/dev/virtio/pci/virtio_pci_legacy.c @@ -60,7 +60,8 @@ device_t vtpci_dev; struct vtpci_common vtpci_common; struct resource *vtpci_res; - struct resource *vtpci_msix_res; + struct resource *vtpci_msix_table_res; + struct resource *vtpci_msix_pba_res; }; static int vtpci_legacy_probe(device_t); @@ -97,6 +98,8 @@ static void vtpci_legacy_read_dev_config(device_t, bus_size_t, void *, int); static void vtpci_legacy_write_dev_config(device_t, bus_size_t, void *, int); +static bool vtpci_legacy_setup_msix(struct vtpci_legacy_softc *sc); +static void vtpci_legacy_cleanup_msix(struct vtpci_legacy_softc *sc); static int vtpci_legacy_alloc_resources(struct vtpci_legacy_softc *); static void vtpci_legacy_free_resources(struct vtpci_legacy_softc *); @@ -539,6 +542,58 @@ } } +static bool +vtpci_legacy_setup_msix(struct vtpci_legacy_softc *sc) +{ + device_t dev; + int rid, table_rid; + + dev = sc->vtpci_dev; + + rid = table_rid = pci_msix_table_bar(dev); + if (rid != PCIR_BAR(0)) { + sc->vtpci_msix_table_res = bus_alloc_resource_any( + dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); + if (sc->vtpci_msix_table_res == NULL) + goto fail; + } + + rid = pci_msix_pba_bar(dev); + if (rid != table_rid && rid != PCIR_BAR(0)) { + sc->vtpci_msix_pba_res = bus_alloc_resource_any( + dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); + if (sc->vtpci_msix_pba_res == NULL) + goto fail; + } + + return (true); + +fail: + vtpci_legacy_cleanup_msix(sc); + return (false); +} + +static void +vtpci_legacy_cleanup_msix(struct vtpci_legacy_softc *sc) +{ + device_t dev; + + dev = sc->vtpci_dev; + + if (sc->vtpci_msix_pba_res != NULL) { + bus_release_resource(dev, SYS_RES_MEMORY, + rman_get_rid(sc->vtpci_msix_pba_res), + sc->vtpci_msix_pba_res); + sc->vtpci_msix_pba_res = NULL; + } + if (sc->vtpci_msix_table_res != NULL) { + bus_release_resource(dev, SYS_RES_MEMORY, + rman_get_rid(sc->vtpci_msix_table_res), + sc->vtpci_msix_table_res); + sc->vtpci_msix_table_res = NULL; + } +} + static int vtpci_legacy_alloc_resources(struct vtpci_legacy_softc *sc) { @@ -552,12 +607,9 @@ &rid, RF_ACTIVE)) == NULL) return (ENXIO); - if (vtpci_is_msix_available(&sc->vtpci_common)) { - rid = PCIR_BAR(1); - if ((sc->vtpci_msix_res = bus_alloc_resource_any(dev, - SYS_RES_MEMORY, &rid, RF_ACTIVE)) == NULL) + if (vtpci_is_msix_available(&sc->vtpci_common) && + !vtpci_legacy_setup_msix(sc)) return (ENXIO); - } return (0); } @@ -569,11 +621,7 @@ dev = sc->vtpci_dev; - if (sc->vtpci_msix_res != NULL) { - bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(1), - sc->vtpci_msix_res); - sc->vtpci_msix_res = NULL; - } + vtpci_legacy_cleanup_msix(sc); if (sc->vtpci_res != NULL) { bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(0),