Author: bms
Date: Thu Jan 12 16:30:27 2017
New Revision: 311987
URL: https://svnweb.freebsd.org/changeset/base/311987

Log:
  Allow uart(4) to use MSI interrupts on single-port PCI instances.
  
  Do this here as puc(4) disallows single-port instances; at least
  one multi-port PCIe UART chip (in this case, the ASIX MCS9922)
  present separate PCI configuration space (functions) for each UART.
  
  Tested using lrzsz and a null-modem cable. The ExpressCard/34
  variants containing the MCS9922 should also use MSI with this change.
  
  Reviewed by:          jhb, imp, rpokala
  MFC after:            2 weeks
  Differential Revision:        https://reviews.freebsd.org/D9123

Modified:
  head/sys/dev/uart/uart_bus_pci.c
  head/sys/dev/uart/uart_core.c

Modified: head/sys/dev/uart/uart_bus_pci.c
==============================================================================
--- head/sys/dev/uart/uart_bus_pci.c    Thu Jan 12 16:24:10 2017        
(r311986)
+++ head/sys/dev/uart/uart_bus_pci.c    Thu Jan 12 16:30:27 2017        
(r311987)
@@ -45,12 +45,14 @@ __FBSDID("$FreeBSD$");
 #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
 };
@@ -209,4 +211,40 @@ uart_pci_probe(device_t dev)
        return (result);
 }
 
+static int
+uart_pci_attach(device_t dev)
+{
+       struct uart_softc *sc;
+       int count;
+
+       sc = device_get_softc(dev);
+
+       /*
+        * Use MSI in preference to legacy IRQ if available.
+        * Whilst some PCIe UARTs support >1 MSI vector, use only the first.
+        */
+       if (pci_msi_count(dev) > 0) {
+               count = 1;
+               if (pci_alloc_msi(dev, &count) == 0) {
+                       sc->sc_irid = 1;
+                       device_printf(dev, "Using %d MSI message\n", count);
+               }
+       }
+
+       return (uart_bus_attach(dev));
+}
+
+static int
+uart_pci_detach(device_t dev)
+{
+       struct uart_softc *sc;
+
+       sc = device_get_softc(dev);
+
+       if (sc->sc_irid != 0)
+               pci_release_msi(dev);
+
+       return (uart_bus_detach(dev));
+}
+
 DRIVER_MODULE(uart, pci, uart_pci_driver, uart_devclass, NULL, NULL);

Modified: head/sys/dev/uart/uart_core.c
==============================================================================
--- head/sys/dev/uart/uart_core.c       Thu Jan 12 16:24:10 2017        
(r311986)
+++ head/sys/dev/uart/uart_core.c       Thu Jan 12 16:30:27 2017        
(r311987)
@@ -677,7 +677,6 @@ uart_bus_attach(device_t dev)
         * safest thing to do.
         */
        if (filt != FILTER_SCHEDULE_THREAD && !uart_force_poll) {
-               sc->sc_irid = 0;
                sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ,
                    &sc->sc_irid, RF_ACTIVE | RF_SHAREABLE);
        }
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to