[mlx4] Prepare for support in msi for windows 2008
authortzachid <tzachid@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Tue, 26 Aug 2008 13:06:18 +0000 (13:06 +0000)
committertzachid <tzachid@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Tue, 26 Aug 2008 13:06:18 +0000 (13:06 +0000)
git-svn-id: svn://openib.tc.cornell.edu/gen1/trunk@1512 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86

hw/mlx4/kernel/bus/core/SOURCES
hw/mlx4/kernel/bus/core/l2w.c
hw/mlx4/kernel/bus/drv/drv.c
hw/mlx4/kernel/bus/drv/mlx4_bus.inx
hw/mlx4/kernel/bus/net/eq.c
hw/mlx4/kernel/bus/net/main.c
hw/mlx4/kernel/bus/net/mlx4.h
hw/mlx4/kernel/inc/l2w.h
hw/mlx4/kernel/inc/l2w_sync.h

index 2f92107..e0cc75c 100644 (file)
@@ -35,7 +35,8 @@ C_DEFINES=$(C_DEFINES) -DDRIVER -DDEPRECATE_DDK_FUNCTIONS -D__LITTLE_ENDIAN -DUS
 \r
 TARGETLIBS= \\r
     $(DDK_LIB_PATH)\ntstrsafe.lib \\r
-       $(TARGETPATH)\*\complib.lib \r
+       $(TARGETPATH)\*\complib.lib \\r
+       $(DDK_LIB_PATH)\iointex.lib     \r
 \r
 !IFDEF ENABLE_EVENT_TRACING\r
 \r
index f794495..d3a225e 100644 (file)
@@ -265,10 +265,10 @@ uint32_t g_processor_affinity = 0;
 int request_irq(
        IN              struct mlx4_dev *       dev,            
        IN              ULONG                           vector,         /* interrupt or MSI-X vector */
-       IN              PKSERVICE_ROUTINE       isr,            /* ISR */
+       IN              PKSERVICE_ROUTINE       isr,            /* Line ISR */
        IN              PVOID                           isr_ctx,        /* ISR context */
        IN              dpc_t                           dpc,
-       IN              PVOID                           dpc_ctx,        /* ISR context */
+       IN              PVOID                           misr,           /* Message ISR */
        OUT             PKINTERRUPT             *       int_obj         /* interrupt object */
        )
 {
@@ -277,22 +277,113 @@ int request_irq(
        struct mlx4_priv *priv = mlx4_priv(dev);
        struct pci_dev *pdev = dev->pdev;               /* interrupt resources */
 
+       KeInitializeSpinLock( &pdev->isr_lock );
+
 #ifdef CONFIG_PCI_MSI
-       // TODO: for MSI interrupts one needs to use new API
+
 #if (NTDDI_VERSION >= NTDDI_LONGHORN)
-       NTKERNELAPI
-       NTSTATUS
-       IoConnectInterruptEx (
-               __inout PIO_CONNECT_INTERRUPT_PARAMETERS Parameters
-               );
-#endif // NTDDI_VERSION >= NTDDI_LONGHORN
+
+       //
+       // Vista and later platforms build
+       //
+
+       do {
+               IO_CONNECT_INTERRUPT_PARAMETERS params;
+
+               RtlZeroMemory( &params, sizeof(IO_CONNECT_INTERRUPT_PARAMETERS) );
+                       
+               //
+               // try to connect our Interrupt Message Service Rotuine to
+               // all Message-Signaled Interrupts our device has been granted,
+               // with automatic fallback to a single line-based interrupt.
+               //
+               
+               params.Version = CONNECT_MESSAGE_BASED;
+               params.MessageBased.PhysicalDeviceObject = pdev->p_self_do;
+               params.MessageBased.MessageServiceRoutine = misr;
+               params.MessageBased.ServiceContext = isr_ctx;
+               params.MessageBased.SpinLock = &pdev->isr_lock;
+               params.MessageBased.SynchronizeIrql = (KIRQL)pdev->int_info.u.Interrupt.Level;
+               params.MessageBased.FloatingSave = FALSE;
+               // fallback to line-based ISR if there is no MSI support
+               params.MessageBased.FallBackServiceRoutine = isr;
+               
+               status = IoConnectInterruptEx(&params);
+               
+               if ( NT_SUCCESS(status) ) {
+               
+                       //
+                       // It worked, so we're running on Vista or later.
+                       //
+               
+               ... // Code goes here to identify if we were connected
+               ... //                  to a line-based interrupt, or one or more
+               ... //                          Message-Signaled Interrupts
+               
+               
+               } else {
+               
+                       //
+                       // We are on a legacy system and maybe can proceed
+                       //
+
+                       pdev->msi_used = FALSE;  // not using MSI/MSI-X
+
+                       if (params.Version == CONNECT_FULLY_SPECIFIED) {
+               
+                               //
+                               // use IoConnectInterruptEx to connect our ISR to a
+                               // line-based interrupt.
+                               //
+
+                               params.FullySpecified.PhysicalDeviceObject = pdev->p_self_do;
+                               params.FullySpecified.InterruptObject  = int_obj;
+                               params.FullySpecified.ServiceRoutine  = isr;
+                               params.FullySpecified.ServiceContext = isr_ctx;
+                               params.FullySpecified.SpinLock = &pdev->isr_lock;
+                               params.FullySpecified.Vector = vector;
+                               params.FullySpecified.Irql = (KIRQL)pdev->int_info.u.Interrupt.Level;
+                               params.FullySpecified.SynchronizeIrql = (KIRQL)pdev->int_info.u.Interrupt.Level;
+                               params.FullySpecified.ProcessorEnableMask = g_processor_affinity ? 
+                                       g_processor_affinity : (KAFFINITY)pdev->int_info.u.Interrupt.Affinity,  /* interrupt affinity */
+                               params.FullySpecified.InterruptMode = LevelSensitive;
+                               params.FullySpecified.ShareVector = TRUE;
+                               params.FullySpecified.FloatingSave = FALSE;
+
+                               status = IoConnectInterruptEx(&params);
+                       }
+                       else {
+
+                               // Something wrong with IoConnectInterruptEx.
+                               // Lets try the usual way
+                               break;
+                       }
+
+               }
+               
+               if ( !NT_SUCCESS(status) ) {
+                       // Non-recoverable error calling IoConnectInterruptEx
+                       MLX4_PRINT(TRACE_LEVEL_ERROR ,MLX4_DBG_INIT ,("IoConnectInterruptEx  failed status %#x \n",status));
+                       return -EFAULT;         /* failed to connect interrupt */
+               }
+
+               // we should not be here
+               ASSERT(0);
+               return 0;
+       } while (0);
+
+#endif
 
 #else
-       UNUSED_PARAM(dpc_ctx);
+
+       UNUSED_PARAM(misr);
+
 #endif
 
-       KeInitializeSpinLock( &pdev->isr_lock );
-       
+       //
+       // Legacy (before Vista) platform build
+       //
+
        status = IoConnectInterrupt(
                int_obj,                                                                                /* InterruptObject */
                isr,                                                                                    /* ISR */ 
index 35bc591..1f240c5 100644 (file)
@@ -564,6 +564,27 @@ __get_resources(
 #ifdef USE_WDM_INTERRUPTS\r
                        case CmResourceTypeInterrupt:\r
                                pdev->int_info = *desc;\r
+                               if (desc->Flags & CM_RESOURCE_INTERRUPT_MESSAGE) {\r
+                                       MLX4_PRINT(TRACE_LEVEL_WARNING, MLX4_DBG_DRV,\r
+                                               ("EvtPrepareHardware: Desc %d: MsiInterrupt: Share %d, Flags %#x, Level %d, Vector %#x, Affinity %#x\n", \r
+                                               i, desc->ShareDisposition, desc->Flags,\r
+                                               desc->u.MessageInterrupt.Translated.Level, \r
+                                               desc->u.MessageInterrupt.Translated.Vector, \r
+                                               desc->u.MessageInterrupt.Translated.Affinity ));\r
+                                       MLX4_PRINT(TRACE_LEVEL_WARNING, MLX4_DBG_DRV,\r
+                                               ("EvtPrepareHardware: Desc %d: RawMsiInterrupt: Share %d, Flags %#x, MessageCount #hx, Vector %#x, Affinity %#x\n", \r
+                                               i, desc_raw->ShareDisposition, desc_raw->Flags,\r
+                                               desc_raw->u.MessageInterrupt.Raw.MessageCount, \r
+                                               desc_raw->u.MessageInterrupt.Raw.Vector,\r
+                                               desc_raw->u.MessageInterrupt.Raw.Affinity ));\r
+                               }\r
+                               else { // line-based interrupt\r
+                                       MLX4_PRINT(TRACE_LEVEL_WARNING, MLX4_DBG_DRV,\r
+                                               ("EvtPrepareHardware: Desc %d: LineInterrupt: Share %d, Flags %#x, Level %d, Vector %#x, Affinity %#x\n", \r
+                                               i, desc->ShareDisposition, desc->Flags,\r
+                                               desc->u.Interrupt.Level, desc->u.Interrupt.Vector, \r
+                                               desc->u.Interrupt.Affinity ));\r
+                               }\r
                                break;\r
 #endif\r
 \r
@@ -951,7 +972,12 @@ __read_registry(WDFDRIVER *hDriver)
        // "Ports L2 type (ib/eth/auto, entry per port, comma seperated, default ib for all)"\r
        DECLARE_CONST_UNICODE_STRING(PortType, L"PortType");\r
 \r
+       // "MSI is supported"\r
+       DECLARE_CONST_UNICODE_STRING(MsiEnable, L"MsiEnable");\r
 \r
+       // "max number of interrupt vectors, supported"\r
+       DECLARE_CONST_UNICODE_STRING(MsiNumVector, L"MsiNumVector");\r
+       \r
        ULONG value;\r
        WDFKEY hKey = NULL;\r
        NTSTATUS status = STATUS_SUCCESS;\r
@@ -1042,6 +1068,18 @@ __read_registry(WDFDRIVER *hDriver)
                        g.mod_interrupt_from_first = 1;\r
 \r
 \r
+               status = WdfRegistryQueryULong(hKey, &MsiEnable, &value);\r
+               if (NT_SUCCESS (status)) \r
+                       g.mod_msi_enable = value;\r
+               else\r
+                       g.mod_msi_enable = 0;\r
+               \r
+               status = WdfRegistryQueryULong(hKey, &MsiNumVector, &value);\r
+               if (NT_SUCCESS (status)) \r
+                       g.mod_msi_num_vector = value;\r
+               else\r
+                       g.mod_msi_num_vector = 8;\r
+\r
                uvalue.Buffer = uvalue_data;\r
                uvalue.MaximumLength = MAX_UVALUE;\r
                uvalue.Length = 0;\r
@@ -1112,6 +1150,7 @@ Return Value:
 \r
 \r
        // global initializations\r
+       RtlZeroMemory( &g, sizeof(g) );\r
        g_mlx4_dbg_level = g.bwsd.DebugPrintLevel = TRACE_LEVEL_VERBOSE;\r
        g_mlx4_dbg_flags = g.bwsd.DebugPrintFlags = 0xffff;\r
 \r
index bd008fe..1e3010e 100644 (file)
@@ -101,6 +101,40 @@ wdfcoinstaller01007.dll = 1,,
 %MT26458.DeviceDesc%=MLX4BUS.DDInstall, PCI\VEN_15B3&DEV_675A\r
 %MT00401.DeviceDesc%=MLX4BUS.DDInstall, PCI\VEN_15B3&DEV_0191\r
 \r
+[MLX4BUS.DDInstall.ntx86.hw]\r
+AddReg = MLX4BUS.HwReg\r
+\r
+[MLX4BUS.DDInstall.ntamd64.hw]\r
+AddReg = MLX4BUS.HwReg\r
+\r
+[MLX4BUS.DDInstall.ntia64.hw]\r
+AddReg = MLX4BUS.HwReg\r
+\r
+[MLX4BUS.HwReg]\r
+HKR,"Interrupt Management", 0x00000010\r
+HKR,"Interrupt Management\MessageSignaledInterruptProperties",0x00000010\r
+\r
+; MSI/MSI-X support\r
+HKR,"Interrupt Management\MessageSignaledInterruptProperties",MSISupported,0x00010001,0\r
+HKR,"Interrupt Management\MessageSignaledInterruptProperties",MessageNumberLimit,0x00010001,8\r
+HKR,"Interrupt Management\Affinity Policy",0x00000010\r
+\r
+; AssignmentSetOverride - processors KAFFINITY mask  \r
+HKR,"Interrupt Management\Affinity Policy",AssignmentSetOverride,0x00000001,0x0\r
+\r
+; IrqPolicyMachineDefault (0) - use default policy for the computer\r
+; IrqPolicyAllCloseProcessors (1) - connect interrupts to all processors of the near NUMA node\r
+; IrqPolicyOneCloseProcessor (2) - connect interrupts to one processor\r
+; IrqPolicyAllProcessorsInMachine (3) - connect interrupts to all processors in the machine\r
+; IrqPolicySpecifiedProcessors (4) - connects interrupts according to AssignmentSetOverride\r
+HKR,"Interrupt Management\Affinity Policy",DevicePolicy,0x00010001,0x0\r
+\r
+; IrqArbPriorityUndefined (0) - no interrupt priority policy. \r
+; IrqArbPriorityLow (1) - device can tolerate low IRQL\r
+; IrqArbPriorityNormal (2) - device expects normal interrupt latencies\r
+; IrqArbPriorityHigh (3) - device requires the lowest possible interrupt latency\r
+HKR,"Interrupt Management\Affinity Policy",DevicePriority,0x00010001,0x0\r
+\r
 [MLX4BUS.DDInstall.ntx86]\r
 CopyFiles = MLX4BUS.CopyFiles\r
 \r
index bd8741c..0ba17e6 100644 (file)
@@ -589,15 +589,29 @@ int mlx4_init_eq_table(struct mlx4_dev *dev)
                        [MLX4_EQ_ASYNC] = DRV_NAME " (async)"
                };
 
-               for (i = 0; i < MLX4_NUM_EQ; ++i) {
-                       err = request_irq(priv->eq_table.eq[i].irq,
-                                         mlx4_msi_x_interrupt,
-                                         priv->eq_table.eq + i, eq_name[i], );
-                       if (err)
-                               goto err_out_async;
+#ifdef USE_WDM_INTERRUPTS
 
-                       priv->eq_table.eq[i].have_irq = 1;
-               }
+                       for (i = 0; i < MLX4_NUM_EQ; ++i) {
+                               err = request_irq( dev, 
+                                       dev->pdev->int_info.u.Interrupt.Vector,
+                                       mlx4_interrupt, dev, 
+                                       mlx4_dpc, mlx4_msi_x_interrupt,
+                                       &dev->pdev->int_obj );
+                               if (err)
+                                       goto err_out_async;
+
+                               err = request_irq(priv->eq_table.eq[i].irq,
+                                                 mlx4_msi_x_interrupt,
+                                                 priv->eq_table.eq + i, eq_name[i], );
+                               if (err)
+                                       goto err_out_async;
+                       
+                               priv->eq_table.eq[i].have_irq = 1;
+                       }
+
+#else
+                       #error MSI support is not implemented for WDF model
+#endif         
 
        } else 
 #endif
@@ -606,7 +620,7 @@ int mlx4_init_eq_table(struct mlx4_dev *dev)
        err = request_irq( dev, 
                dev->pdev->int_info.u.Interrupt.Vector,
                mlx4_interrupt, dev, 
-               mlx4_dpc, &priv->eq_table.eq[0],
+               mlx4_dpc, NULL,
                &dev->pdev->int_obj );
        if (err)
                goto err_out_async;
@@ -711,7 +725,7 @@ void mlx4_remove_eq(struct mlx4_dev *dev, u8 eq_num)
                err = request_irq( dev, 
                        dev->pdev->int_info.u.Interrupt.Vector,
                        mlx4_interrupt, dev, 
-                       mlx4_dpc, &priv->eq_table.eq[0],
+                       mlx4_dpc, NULL,
                        &dev->pdev->int_obj );
                // BUGBUG: how should the error be propogated ?
        }
index 6ed31cb..a56f95e 100644 (file)
 #include "doorbell.h"
 #include "complib\cl_thread.h"
 
-// TODO: put into Globals
-#ifdef CONFIG_MLX4_DEBUG
-// "Enable debug tracing if > 0"
-int debug_level = 1;
-#endif /* CONFIG_MLX4_DEBUG */
-
-#ifdef CONFIG_PCI_MSI
-
-// "attempt to use MSI-X if nonzero"
-static int msi_x = 1;
-
-#else /* CONFIG_PCI_MSI */
-
-#define msi_x (0)
-
-#endif /* CONFIG_PCI_MSI */
-
 
 static struct mlx4_profile default_profile = {
        1 << 17,        /* num_qp               */
@@ -852,7 +835,7 @@ static void __devinit mlx4_enable_msi_x(struct mlx4_dev *dev)
        int err;
        int i;
 
-       if (msi_x) {
+       if (g.mod_msi_num_vector) {
                for (i = 0; i < MLX4_NUM_EQ; ++i)
                        entries[i].entry = i;
 
index 855bce0..244cc01 100644 (file)
@@ -86,6 +86,8 @@ typedef struct _GLOBALS {
        enum mlx4_port_type mod_port_type[MLX4_MAX_PORTS];
        int mod_interrupt_from_first;
 
+       int mod_msi_enable;
+       int mod_msi_num_vector;
 } GLOBALS;
 #pragma warning(default:4201) // nameless struct/union
 
index a67c670..1c89f17 100644 (file)
@@ -11,6 +11,7 @@
 
 // OS
 #include <ntddk.h>
+#include <iointex.h>
 #include <stdio.h>
 #include <stdarg.h>
 #include <stdlib.h>
@@ -161,6 +162,7 @@ struct pci_dev
 #ifdef USE_WDM_INTERRUPTS
        PKINTERRUPT                                             int_obj;                /* HCA interrupt object */
        KSPIN_LOCK                                              isr_lock;               /* lock for the ISR */
+       int                                                             msi_used;               /* connected to MSI interrupts */
 #endif 
 };
 
@@ -301,7 +303,7 @@ struct mlx4_priv;
 
 static inline int mlx4_is_livefish(struct mlx4_dev *dev)
 {
-       return dev->flags & MLX4_FLAG_LIVEFISH;
+       return !!(dev->flags & MLX4_FLAG_LIVEFISH);
 }
 
 static inline int mlx4_is_barred(struct mlx4_dev *dev)
index 11b06f1..1a32c29 100644 (file)
@@ -147,7 +147,7 @@ int request_irq(
        IN              PKSERVICE_ROUTINE       isr,            /* ISR */
        IN              PVOID                           isr_ctx,        /* ISR context */
        IN              dpc_t                           dpc,
-       IN              PVOID                           dpc_ctx,        /* ISR context */
+       IN              PVOID                           misr,           /* Message ISR */
        OUT             PKINTERRUPT             *       int_obj         /* interrupt object */
        );