Index: sys/dev/uart/uart_bus.h =================================================================== --- sys/dev/uart/uart_bus.h +++ sys/dev/uart/uart_bus.h @@ -92,6 +92,7 @@ int sc_txbusy:1; /* This UART is transmitting. */ int sc_isquelch:1; /* This UART has input squelched. */ int sc_testintr:1; /* This UART is under int. testing. */ + int sc_msi:1; /* This UART is using MSI */ struct uart_devinfo *sc_sysdev; /* System device (or NULL). */ Index: sys/dev/uart/uart_bus_pci.c =================================================================== --- sys/dev/uart/uart_bus_pci.c +++ sys/dev/uart/uart_bus_pci.c @@ -45,12 +45,14 @@ #define DEFAULT_RCLK 1843200 static int uart_pci_probe(device_t dev); +static int uart_pci_attach(device_t dev); +static int uart_pci_detach(device_t dev); static device_method_t uart_pci_methods[] = { /* Device interface */ DEVMETHOD(device_probe, uart_pci_probe), - DEVMETHOD(device_attach, uart_bus_attach), - DEVMETHOD(device_detach, uart_bus_detach), + DEVMETHOD(device_attach, uart_pci_attach), + DEVMETHOD(device_detach, uart_pci_detach), DEVMETHOD(device_resume, uart_bus_resume), DEVMETHOD_END }; @@ -206,7 +208,52 @@ /* Set/override the device description. */ if (id->desc) device_set_desc(dev, id->desc); + /* Enable MSI if this device has MSI vectors. */ + if (pci_msi_count(dev) > 0) + sc->sc_msi = 1; return (result); } +static int +uart_pci_attach(device_t dev) +{ + device_t parent; + struct uart_softc *sc; + int count; + + parent = device_get_parent(dev); + sc = device_get_softc(dev); + + if (sc->sc_msi) { + count = 1; + if (pci_alloc_msi(dev, &count) == 0) { + if (count == 1) { + sc->sc_irid = 1; + device_printf(dev, "Using %d MSI message\n", + count); + } else { + pci_release_msi(dev); + sc->sc_msi = 0; + } + } + } + + return (uart_bus_attach(dev)); +} + +static int +uart_pci_detach(device_t dev) +{ + device_t parent; + struct uart_softc *sc; + + parent = device_get_parent(dev); + sc = device_get_softc(dev); + + if (sc->sc_msi && sc->sc_irid != 0) + pci_release_msi(dev); + + return (uart_bus_detach(dev)); +} + DRIVER_MODULE(uart, pci, uart_pci_driver, uart_devclass, NULL, NULL); Index: sys/dev/uart/uart_core.c =================================================================== --- sys/dev/uart/uart_core.c +++ sys/dev/uart/uart_core.c @@ -677,9 +677,11 @@ * safest thing to do. */ if (filt != FILTER_SCHEDULE_THREAD && !uart_force_poll) { - sc->sc_irid = 0; + if (!sc->sc_msi) + sc->sc_irid = 0; sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, - &sc->sc_irid, RF_ACTIVE | RF_SHAREABLE); + &sc->sc_irid, + RF_ACTIVE | (sc->sc_irid != 0 ? 0 : RF_SHAREABLE)); } if (sc->sc_ires != NULL) { error = bus_setup_intr(dev, sc->sc_ires, INTR_TYPE_TTY,