trying to keep a local disabled flag for the interrupt.
If we don't do this we can get into a interrupt storm on
startup.
Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
LONG References;
PXENBUS_RESOURCE Interrupt;
PKINTERRUPT InterruptObject;
+ BOOLEAN Enabled;
PXENBUS_SUSPEND_INTERFACE SuspendInterface;
PXENBUS_SUSPEND_CALLBACK SuspendCallbackEarly;
PXENBUS_DEBUG_INTERFACE DebugInterface;
Context);
}
+static FORCEINLINE VOID
+__EvtchnInterruptEnable(
+ IN PXENBUS_EVTCHN_CONTEXT Context
+ )
+{
+ NTSTATUS status;
+
+ status = HvmSetParam(HVM_PARAM_CALLBACK_IRQ,
+ Context->Interrupt->Raw.u.Interrupt.Vector);
+ ASSERT(NT_SUCCESS(status));
+}
+
+static FORCEINLINE VOID
+__EvtchnInterruptDisable(
+ IN PXENBUS_EVTCHN_CONTEXT Context
+ )
+{
+ NTSTATUS status;
+
+ UNREFERENCED_PARAMETER(Context);
+
+ status = HvmSetParam(HVM_PARAM_CALLBACK_IRQ, 0);
+ ASSERT(NT_SUCCESS(status));
+}
+
static VOID
EvtchnSuspendCallbackEarly(
IN PVOID Argument
{
PXENBUS_EVTCHN_CONTEXT Context = Argument;
PLIST_ENTRY ListEntry;
- NTSTATUS status;
for (ListEntry = Context->List.Flink;
ListEntry != &Context->List;
}
}
- status = HvmSetParam(HVM_PARAM_CALLBACK_IRQ, Context->Interrupt->Raw.u.Interrupt.Vector);
- ASSERT(NT_SUCCESS(status));
+ if (Context->Enabled)
+ __EvtchnInterruptEnable(Context);
}
static VOID
Context->Interrupt = FdoGetResource(Fdo, INTERRUPT_RESOURCE);
Context->InterruptObject = FdoGetInterruptObject(Fdo);
- status = HvmSetParam(HVM_PARAM_CALLBACK_IRQ, Context->Interrupt->Raw.u.Interrupt.Vector);
- ASSERT(NT_SUCCESS(status));
-
Context->SuspendInterface = FdoGetSuspendInterface(Fdo);
SUSPEND(Acquire, Context->SuspendInterface);
return status;
}
+VOID
+EvtchnEnable(
+ IN PXENBUS_EVTCHN_INTERFACE Interface
+ )
+{
+ PXENBUS_EVTCHN_CONTEXT Context = Interface->Context;
+
+ ASSERT(!Context->Enabled);
+
+ __EvtchnInterruptEnable(Context);
+ Context->Enabled = TRUE;
+}
+
+VOID
+EvtchnDisable(
+ IN PXENBUS_EVTCHN_INTERFACE Interface
+ )
+{
+ PXENBUS_EVTCHN_CONTEXT Context = Interface->Context;
+
+ ASSERT(Context->Enabled);
+
+ Context->Enabled = FALSE;
+ __EvtchnInterruptDisable(Context);
+}
+
VOID
EvtchnTeardown(
IN OUT PXENBUS_EVTCHN_INTERFACE Interface
SUSPEND(Release, Context->SuspendInterface);
Context->SuspendInterface = NULL;
- (VOID) HvmSetParam(HVM_PARAM_CALLBACK_IRQ, 0);
Context->InterruptObject = NULL;
Context->Interrupt = NULL;
IN PXENBUS_EVTCHN_INTERFACE Interface
);
+extern VOID
+EvtchnEnable(
+ IN PXENBUS_EVTCHN_INTERFACE Interface
+ );
+
+extern VOID
+EvtchnDisable(
+ IN PXENBUS_EVTCHN_INTERFACE Interface
+ );
+
extern VOID
EvtchnTeardown(
IN OUT PXENBUS_EVTCHN_INTERFACE Interface
XENBUS_RESOURCE Resource[RESOURCE_COUNT];
PKINTERRUPT InterruptObject;
- BOOLEAN InterruptEnabled;
XENBUS_SUSPEND_INTERFACE SuspendInterface;
XENBUS_SHARED_INFO_INTERFACE SharedInfoInterface;
__FreePoolWithTag(Buffer, FDO_TAG);
}
-#pragma warning(push)
-#pragma warning(disable: 28230)
-#pragma warning(disable: 28285)
-
-_IRQL_requires_max_(HIGH_LEVEL) // HIGH_LEVEL is best approximation of DIRQL
-_IRQL_saves_
-_IRQL_raises_(HIGH_LEVEL) // HIGH_LEVEL is best approximation of DIRQL
-static FORCEINLINE KIRQL
-__AcquireInterruptLock(
- _Inout_ PKINTERRUPT Interrupt
- )
-{
- return KeAcquireInterruptSpinLock(Interrupt);
-}
-
-_IRQL_requires_(HIGH_LEVEL) // HIGH_LEVEL is best approximation of DIRQL
-static FORCEINLINE VOID
-__ReleaseInterruptLock(
- _Inout_ PKINTERRUPT Interrupt,
- _In_ _IRQL_restores_ KIRQL Irql
- )
-{
-#pragma prefast(suppress:28121) // The function is not permitted to be called at the current IRQ level
- KeReleaseInterruptSpinLock(Interrupt, Irql);
-}
-
-#pragma warning(pop)
-
static FORCEINLINE VOID
__FdoSetDevicePnpState(
IN PXENBUS_FDO Fdo,
)
{
PXENBUS_FDO Fdo = Context;
+ BOOLEAN DoneSomething;
UNREFERENCED_PARAMETER(InterruptObject);
ASSERT(Fdo != NULL);
- if (!Fdo->InterruptEnabled)
- return FALSE;
+ DoneSomething = EvtchnInterrupt(&Fdo->EvtchnInterface);
- return EvtchnInterrupt(&Fdo->EvtchnInterface);
+ return DoneSomething;
}
static FORCEINLINE VOID
IoDisconnectInterruptEx(&Disconnect);
}
-static FORCEINLINE VOID
-__FdoEnableInterrupt(
- IN PXENBUS_FDO Fdo
- )
-{
- PKINTERRUPT InterruptObject;
- KIRQL Irql;
-
- InterruptObject = __FdoGetInterruptObject(Fdo);
-
- Irql = __AcquireInterruptLock(InterruptObject);
- Fdo->InterruptEnabled = TRUE;
-
- __ReleaseInterruptLock(InterruptObject, Irql);
-}
-
-static FORCEINLINE VOID
-__FdoDisableInterrupt(
- IN PXENBUS_FDO Fdo
- )
-{
- PKINTERRUPT InterruptObject;
- KIRQL Irql;
-
- InterruptObject = __FdoGetInterruptObject(Fdo);
-
- Irql = __AcquireInterruptLock(InterruptObject);
- Fdo->InterruptEnabled = FALSE;
-
- __ReleaseInterruptLock(InterruptObject, Irql);
-}
-
PXENBUS_DEBUG_INTERFACE
FdoGetDebugInterface(
IN PXENBUS_FDO Fdo
__FdoSetSystemPowerState(Fdo, PowerSystemSleeping3);
- __FdoEnableInterrupt(Fdo);
+ EvtchnEnable(&Fdo->EvtchnInterface);
KeLowerIrql(Irql);
ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
ASSERT3U(__FdoGetSystemPowerState(Fdo), ==, PowerSystemSleeping3);
- __FdoDisableInterrupt(Fdo);
+ EvtchnDisable(&Fdo->EvtchnInterface);
__FdoSetSystemPowerState(Fdo, PowerSystemHibernate);