Index: sys/dev/virtio/pci/virtio_pci.c =================================================================== --- sys/dev/virtio/pci/virtio_pci.c +++ sys/dev/virtio/pci/virtio_pci.c @@ -68,7 +68,8 @@ struct vtpci_softc { device_t vtpci_dev; struct resource *vtpci_res; - struct resource *vtpci_msix_res; + struct resource *vtpci_msix_table_res; + struct resource *vtpci_msix_pba_res; uint64_t vtpci_features; uint32_t vtpci_flags; #define VTPCI_FLAG_NO_MSI 0x0001 @@ -277,10 +278,12 @@ { struct vtpci_softc *sc; device_t child; + int msix_load; int rid; sc = device_get_softc(dev); sc->vtpci_dev = dev; + msix_load = 0; pci_enable_busmaster(dev); @@ -305,13 +308,36 @@ sc->vtpci_flags |= VTPCI_FLAG_NO_MSI; if (pci_find_cap(dev, PCIY_MSIX, NULL) == 0) { - rid = PCIR_BAR(1); - sc->vtpci_msix_res = bus_alloc_resource_any(dev, - SYS_RES_MEMORY, &rid, RF_ACTIVE); + int table_rid; + + rid = table_rid = pci_msix_table_bar(dev); + if (table_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) + msix_load++; + } else + msix_load++; + + rid = pci_msix_pba_bar(dev); + if (rid != table_rid) { + sc->vtpci_msix_pba_res = bus_alloc_resource_any( + dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); + if (sc->vtpci_msix_pba_res != NULL) + msix_load++; + } else + msix_load++; } - if (sc->vtpci_msix_res == NULL) + if (msix_load != 2) { sc->vtpci_flags |= VTPCI_FLAG_NO_MSIX; + if (sc->vtpci_msix_table_res) { + 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; + } + } vtpci_reset(sc); @@ -349,10 +375,18 @@ vtpci_reset(sc); - 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; + 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; + } + + 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_res != NULL) {