twa(4): Add MSI support.
authorSascha Wildner <saw@online.de>
Sun, 8 Jul 2012 21:33:20 +0000 (23:33 +0200)
committerSascha Wildner <saw@online.de>
Sun, 8 Jul 2012 21:33:20 +0000 (23:33 +0200)
It's off by default, set hw.twa.msi.enable to 1 in /boot/loader.conf to
try it out.

It works here with a 3ware 9650SE-2LP.

share/man/man4/twa.4
sys/dev/raid/twa/tw_osl.h
sys/dev/raid/twa/tw_osl_freebsd.c

index 61dd0c7..52847eb 100644 (file)
@@ -25,7 +25,7 @@
 .\"
 .\" $FreeBSD: src/share/man/man4/twa.4,v 1.9 2010/05/13 12:07:55 uqs Exp $
 .\"
-.Dd August 1, 2010
+.Dd July 8, 2012
 .Dt TWA 4
 .Os
 .Sh NAME
@@ -66,6 +66,12 @@ via the device nodes,
 where
 .Ar Y
 is the logical unit number.
+.Sh LOADER TUNABLES
+.Bl -tag -width indent
+.It Va hw.twa.msi.enable
+To use MSI (if supported), set this tunable to 1.
+The default is 0.
+.El
 .Sh HARDWARE
 The
 .Nm
index 28a9144..235f723 100644 (file)
@@ -174,6 +174,7 @@ struct twa_softc {
        bus_dmamap_t            ioctl_map; /* DMA map for ioctl data buffers */
        struct resource         *irq_res;       /* interrupt resource */
        TW_INT32                irq_res_id;     /* register resource id */
+       TW_INT32                irq_type;       /* interrupt type */
        TW_VOID                 *intr_handle;   /* interrupt handle */
 
        struct sysctl_ctx_list  sysctl_ctxt;    /* sysctl context */
index 0acf4ee..422c21b 100644 (file)
@@ -70,6 +70,9 @@ static struct dev_ops twa_ops = {
 
 static devclass_t      twa_devclass;
 
+static int             twa_msi_enable = 0;
+TUNABLE_INT("hw.twa.msi.enable", &twa_msi_enable);
+
 
 /*
  * Function name:      twa_open
@@ -296,6 +299,7 @@ twa_attach(device_t dev)
        TW_INT32                bar_num;
        TW_INT32                bar0_offset;
        TW_INT32                bar_size;
+       TW_INT32                irq_flags;
        TW_INT32                error;
 
        tw_osli_dbg_dprintf(3, sc, "entered");
@@ -378,9 +382,11 @@ twa_attach(device_t dev)
 
        /* Allocate and register our interrupt. */
        sc->irq_res_id = 0;
+       sc->irq_type = pci_alloc_1intr(sc->bus_dev, twa_msi_enable,
+           &sc->irq_res_id, &irq_flags);
        if ((sc->irq_res = bus_alloc_resource(sc->bus_dev, SYS_RES_IRQ,
                                &(sc->irq_res_id), 0, ~0, 1,
-                               RF_SHAREABLE | RF_ACTIVE)) == NULL) {
+                               irq_flags)) == NULL) {
                tw_osli_printf(sc, "error = %d",
                        TW_CL_SEVERITY_ERROR_STRING,
                        TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
@@ -802,6 +808,8 @@ tw_osli_free_resources(struct twa_softc *sc)
                        tw_osli_dbg_dprintf(1, sc,
                                "release_resource(irq) returned %d", error);
 
+       if (sc->irq_type == PCI_INTR_TYPE_MSI)
+               pci_release_msi(sc->bus_dev);
 
        /* Release the register window mapping. */
        if (sc->reg_res != NULL)