\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
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 */
)
{
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( ¶ms, 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(¶ms);
+
+ 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(¶ms);
+ }
+ 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 */
#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
// "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
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
\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
%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
[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
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;
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 ?
}
#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 */
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;
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
// OS
#include <ntddk.h>
+#include <iointex.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#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
};
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)
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 */
);