[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [win-pv-devel] [PATCH 2/3] Move the Receiver and Transmitter event and DPC processing...
...into the new Poller sub-system. For efficiency it is desirable to have a single DPC handle both Receiver and Transmitter polling, even if there are separate event channels for the shared rings. This patch moves all the basic event and DPC code into the Poller subsystem, which calls back into the Transmitter and Receiver sub-systems (to poll the shared rings) from its single per-CPU DPC. Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx> --- src/xenvif/frontend.c | 48 -- src/xenvif/frontend.h | 10 - src/xenvif/poller.c | 1322 +++++++++++++++++++++++++++++++++++++++++++++- src/xenvif/poller.h | 24 +- src/xenvif/receiver.c | 393 +++----------- src/xenvif/receiver.h | 6 + src/xenvif/transmitter.c | 381 ++----------- src/xenvif/transmitter.h | 6 + 8 files changed, 1449 insertions(+), 741 deletions(-) diff --git a/src/xenvif/frontend.c b/src/xenvif/frontend.c index f715c19..9949357 100644 --- a/src/xenvif/frontend.c +++ b/src/xenvif/frontend.c @@ -81,7 +81,6 @@ struct _XENVIF_FRONTEND { USHORT BackendDomain; ULONG MaxQueues; ULONG NumQueues; - BOOLEAN Split; ULONG DisableToeplitz; PXENVIF_MAC Mac; @@ -1800,50 +1799,6 @@ FrontendGetNumQueues( return __FrontendGetNumQueues(Frontend); } -static VOID -FrontendSetSplit( - IN PXENVIF_FRONTEND Frontend - ) -{ - PCHAR Buffer; - NTSTATUS status; - - status = XENBUS_STORE(Read, - &Frontend->StoreInterface, - NULL, - __FrontendGetBackendPath(Frontend), - "feature-split-event-channels", - &Buffer); - if (NT_SUCCESS(status)) { - Frontend->Split = (BOOLEAN)strtol(Buffer, NULL, 2); - - XENBUS_STORE(Free, - &Frontend->StoreInterface, - Buffer); - } else { - Frontend->Split = FALSE; - } - - Info("%s: %s\n", __FrontendGetPath(Frontend), - (Frontend->Split) ? "TRUE" : "FALSE"); -} - -static FORCEINLINE BOOLEAN -__FrontendIsSplit( - IN PXENVIF_FRONTEND Frontend - ) -{ - return Frontend->Split; -} - -BOOLEAN -FrontendIsSplit( - IN PXENVIF_FRONTEND Frontend - ) -{ - return __FrontendIsSplit(Frontend); -} - static FORCEINLINE NTSTATUS __FrontendUpdateHash( PXENVIF_FRONTEND Frontend, @@ -2208,7 +2163,6 @@ FrontendConnect( goto fail3; FrontendSetNumQueues(Frontend); - FrontendSetSplit(Frontend); status = PollerConnect(__FrontendGetPoller(Frontend)); if (!NT_SUCCESS(status)) @@ -2360,7 +2314,6 @@ fail4: MacDisconnect(__FrontendGetMac(Frontend)); - Frontend->Split = FALSE; Frontend->NumQueues = 0; fail3: @@ -2398,7 +2351,6 @@ FrontendDisconnect( PollerDisconnect(__FrontendGetPoller(Frontend)); MacDisconnect(__FrontendGetMac(Frontend)); - Frontend->Split = FALSE; Frontend->NumQueues = 0; XENBUS_DEBUG(Deregister, diff --git a/src/xenvif/frontend.h b/src/xenvif/frontend.h index 92008d0..7f3b7c5 100644 --- a/src/xenvif/frontend.h +++ b/src/xenvif/frontend.h @@ -123,16 +123,6 @@ FrontendGetNumQueues( IN PXENVIF_FRONTEND Frontend ); -extern BOOLEAN -FrontendIsSplit( - IN PXENVIF_FRONTEND Frontend - ); - -extern BOOLEAN -FrontendIsSplit( - IN PXENVIF_FRONTEND Frontend - ); - extern PCHAR FrontendFormatPath( IN PXENVIF_FRONTEND Frontend, diff --git a/src/xenvif/poller.c b/src/xenvif/poller.c index 4ac358e..7b60022 100644 --- a/src/xenvif/poller.c +++ b/src/xenvif/poller.c @@ -42,6 +42,8 @@ #include "pdo.h" #include "frontend.h" +#include "transmitter.h" +#include "receiver.h" #include "poller.h" #include "vif.h" #include "thread.h" @@ -52,38 +54,1013 @@ #define MAXNAMELEN 128 +typedef struct _XENVIF_POLLER_INSTANCE XENVIF_POLLER_INSTANCE, *PXENVIF_POLLER_INSTANCE; + +typedef enum _XENVIF_POLLER_CHANNEL_TYPE { + XENVIF_POLLER_CHANNEL_RECEIVER, + XENVIF_POLLER_CHANNEL_TRANSMITTER, + XENVIF_POLLER_CHANNEL_COMBINED, + XENVIF_POLLER_CHANNEL_TYPE_COUNT +} XENVIF_POLLER_CHANNEL_TYPE, *PXENVIF_POLLER_CHANNEL_TYPE; + +#define XENVIF_POLLER_CHANNEL_INVALID XENVIF_POLLER_CHANNEL_TYPE_COUNT + +typedef struct _XENVIF_POLLER_CHANNEL { + PXENVIF_POLLER_INSTANCE Instance; + XENVIF_POLLER_CHANNEL_TYPE Type; + const CHAR *Node; + PXENBUS_EVTCHN_CHANNEL Channel; + ULONG Events; +} XENVIF_POLLER_CHANNEL, *PXENVIF_POLLER_CHANNEL; + +struct _XENVIF_POLLER_INSTANCE { + PXENVIF_POLLER Poller; + ULONG Index; + PCHAR Path; + KSPIN_LOCK Lock; + KDPC Dpc; + ULONG Dpcs; + KTIMER Timer; + KDPC TimerDpc; + PXENVIF_POLLER_CHANNEL Channel[XENVIF_POLLER_CHANNEL_TYPE_COUNT]; + BOOLEAN Enabled; + LONG Pending; +}; + struct _XENVIF_POLLER { PXENVIF_FRONTEND Frontend; + PXENVIF_POLLER_INSTANCE *Instance; + BOOLEAN Split; + XENBUS_STORE_INTERFACE StoreInterface; + XENBUS_EVTCHN_INTERFACE EvtchnInterface; XENBUS_DEBUG_INTERFACE DebugInterface; PXENBUS_DEBUG_CALLBACK DebugCallback; }; -#define XENVIF_POLLER_TAG 'LLOP' +#define XENVIF_POLLER_TAG 'LLOP' + +static FORCEINLINE PVOID +__PollerAllocate( + IN ULONG Length + ) +{ + return __AllocatePoolWithTag(NonPagedPool, Length, XENVIF_POLLER_TAG); +} + +static FORCEINLINE VOID +__PollerFree( + IN PVOID Buffer + ) +{ + __FreePoolWithTag(Buffer, XENVIF_POLLER_TAG); +} + +static NTSTATUS +PollerChannelInitialize( + IN PXENVIF_POLLER_INSTANCE Instance, + IN ULONG Type, + OUT PXENVIF_POLLER_CHANNEL *Channel + ) +{ + NTSTATUS status; + + *Channel = __PollerAllocate(sizeof (XENVIF_POLLER_CHANNEL)); + + status = STATUS_NO_MEMORY; + if (*Channel == NULL) + goto fail1; + + (*Channel)->Instance = Instance; + (*Channel)->Type = Type; + + switch (Type) { + case XENVIF_POLLER_CHANNEL_RECEIVER: + (*Channel)->Node = "event-channel-rx"; + break; + + case XENVIF_POLLER_CHANNEL_TRANSMITTER: + (*Channel)->Node = "event-channel-tx"; + break; + + case XENVIF_POLLER_CHANNEL_COMBINED: + (*Channel)->Node = "event-channel"; + break; + + default: + ASSERT(FALSE); + break; + } + + return STATUS_SUCCESS; + +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} + +static VOID +PollerChannelSetPending( + IN PXENVIF_POLLER_CHANNEL Channel + ) +{ + PXENVIF_POLLER_INSTANCE Instance; + + Instance = Channel->Instance; + + switch (Channel->Type) + { + case XENVIF_POLLER_CHANNEL_RECEIVER: + (VOID) InterlockedBitTestAndSet(&Instance->Pending, + XENVIF_POLLER_EVENT_RECEIVE); + break; + + case XENVIF_POLLER_CHANNEL_TRANSMITTER: + (VOID) InterlockedBitTestAndSet(&Instance->Pending, + XENVIF_POLLER_EVENT_TRANSMIT); + break; + + case XENVIF_POLLER_CHANNEL_COMBINED: + (VOID) InterlockedBitTestAndSet(&Instance->Pending, + XENVIF_POLLER_EVENT_RECEIVE); + (VOID) InterlockedBitTestAndSet(&Instance->Pending, + XENVIF_POLLER_EVENT_TRANSMIT); + break; + + default: + ASSERT(FALSE); + break; + } +} + +static FORCEINLINE BOOLEAN +__BitTest( + IN PLONG Mask, + IN LONG Bit + ) +{ + return (*Mask & (1L << Bit)) ? TRUE : FALSE; +} + +static BOOLEAN +PollerChannelTestPending( + IN PXENVIF_POLLER_CHANNEL Channel + ) +{ + PXENVIF_POLLER_INSTANCE Instance; + + Instance = Channel->Instance; + + switch (Channel->Type) + { + case XENVIF_POLLER_CHANNEL_RECEIVER: + if (__BitTest(&Instance->Pending, XENVIF_POLLER_EVENT_RECEIVE)) + return TRUE; + + break; + + case XENVIF_POLLER_CHANNEL_TRANSMITTER: + if (__BitTest(&Instance->Pending, XENVIF_POLLER_EVENT_TRANSMIT)) + return TRUE; + + break; + + case XENVIF_POLLER_CHANNEL_COMBINED: + if (__BitTest(&Instance->Pending, XENVIF_POLLER_EVENT_RECEIVE) || + __BitTest(&Instance->Pending, XENVIF_POLLER_EVENT_TRANSMIT)) + return TRUE; + + break; + + default: + ASSERT(FALSE); + break; + } + + return FALSE; +} + +KSERVICE_ROUTINE PollerChannelEvtchnCallback; + +BOOLEAN +PollerChannelEvtchnCallback( + IN PKINTERRUPT InterruptObject, + IN PVOID Argument + ) +{ + PXENVIF_POLLER_CHANNEL Channel = Argument; + PXENVIF_POLLER_INSTANCE Instance; + + UNREFERENCED_PARAMETER(InterruptObject); + + ASSERT(Channel != NULL); + Instance = Channel->Instance; + + Channel->Events++; + + PollerChannelSetPending(Channel); + + if (KeInsertQueueDpc(&Instance->Dpc, NULL, NULL)) + Instance->Dpcs++; + + return TRUE; +} + +static FORCEINLINE BOOLEAN +__PollerIsSplit( + IN PXENVIF_POLLER Poller + ) +{ + return Poller->Split; +} + +static NTSTATUS +PollerChannelConnect( + IN PXENVIF_POLLER_CHANNEL Channel + ) +{ + PXENVIF_POLLER_INSTANCE Instance; + PXENVIF_POLLER Poller; + PXENVIF_FRONTEND Frontend; + PROCESSOR_NUMBER ProcNumber; + NTSTATUS status; + + Instance = Channel->Instance; + Poller = Instance->Poller; + Frontend = Poller->Frontend; + + switch (Channel->Type) + { + case XENVIF_POLLER_CHANNEL_RECEIVER: + case XENVIF_POLLER_CHANNEL_TRANSMITTER: + if (!__PollerIsSplit(Poller)) + goto done; + + break; + + case XENVIF_POLLER_CHANNEL_COMBINED: + if (__PollerIsSplit(Poller)) + goto done; + + break; + + default: + ASSERT(FALSE); + break; + } + + Channel->Channel = XENBUS_EVTCHN(Open, + &Poller->EvtchnInterface, + XENBUS_EVTCHN_TYPE_UNBOUND, + PollerChannelEvtchnCallback, + Channel, + FrontendGetBackendDomain(Frontend), + TRUE); + + status = STATUS_UNSUCCESSFUL; + if (Channel->Channel == NULL) + goto fail1; + + status = KeGetProcessorNumberFromIndex(Instance->Index, &ProcNumber); + ASSERT(NT_SUCCESS(status)); + + (VOID) XENBUS_EVTCHN(Bind, + &Poller->EvtchnInterface, + Channel->Channel, + ProcNumber.Group, + ProcNumber.Number); + + XENBUS_EVTCHN(Unmask, + &Poller->EvtchnInterface, + Channel->Channel, + FALSE); + +done: + return STATUS_SUCCESS; + +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} + +static NTSTATUS +PollerChannelStoreWrite( + IN PXENVIF_POLLER_CHANNEL Channel, + IN PXENBUS_STORE_TRANSACTION Transaction + ) +{ + PXENVIF_POLLER_INSTANCE Instance; + PXENVIF_POLLER Poller; + ULONG Port; + NTSTATUS status; + + Instance = Channel->Instance; + Poller = Instance->Poller; + + if (Channel->Channel == NULL) + goto done; + + Port = XENBUS_EVTCHN(GetPort, + &Poller->EvtchnInterface, + Channel->Channel); + + status = XENBUS_STORE(Printf, + &Poller->StoreInterface, + Transaction, + Instance->Path, + (PCHAR)Channel->Node, + "%u", + Port); + if (!NT_SUCCESS(status)) + goto fail1; + +done: + return STATUS_SUCCESS; + +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} + +static VOID +PollerChannelUnmask( + IN PXENVIF_POLLER_CHANNEL Channel + ) +{ + PXENVIF_POLLER_INSTANCE Instance; + PXENVIF_POLLER Poller; + + Instance = Channel->Instance; + Poller = Instance->Poller; + + if (Channel->Channel == NULL) + return; + + if (!PollerChannelTestPending(Channel)) + XENBUS_EVTCHN(Unmask, + &Poller->EvtchnInterface, + Channel->Channel, + FALSE); +} + +static VOID +PollerChannelSend( + IN PXENVIF_POLLER_CHANNEL Channel + ) +{ + PXENVIF_POLLER_INSTANCE Instance; + PXENVIF_POLLER Poller; + + Instance = Channel->Instance; + Poller = Instance->Poller; + + XENBUS_EVTCHN(Send, + &Poller->EvtchnInterface, + Channel->Channel); +} + +static VOID +PollerChannelDebugCallback( + IN PXENVIF_POLLER_CHANNEL Channel + ) +{ + PXENVIF_POLLER_INSTANCE Instance; + PXENVIF_POLLER Poller; + + Instance = Channel->Instance; + Poller = Instance->Poller; + + if (Channel->Channel == NULL) + return; + + XENBUS_DEBUG(Printf, + &Poller->DebugInterface, + "[%s]: Events = %lu\n", + Channel->Node, + Channel->Events); +} + +static VOID +PollerChannelDisconnect( + IN PXENVIF_POLLER_CHANNEL Channel + ) +{ + PXENVIF_POLLER_INSTANCE Instance; + PXENVIF_POLLER Poller; + + Instance = Channel->Instance; + Poller = Instance->Poller; + + if (Channel->Channel == NULL) + return; + + Channel->Events = 0; + + XENBUS_EVTCHN(Close, + &Poller->EvtchnInterface, + Channel->Channel); + Channel->Channel = NULL; +} + +static VOID +PollerChannelTeardown( + IN PXENVIF_POLLER_CHANNEL Channel + ) +{ + Channel->Node = NULL; + + Channel->Type = 0; + Channel->Instance = NULL; + + ASSERT(IsZeroMemory(Channel, sizeof (XENVIF_POLLER_CHANNEL))); + __PollerFree(Channel); +} + +__drv_requiresIRQL(DISPATCH_LEVEL) +static VOID +PollerInstanceUnmask( + IN PXENVIF_POLLER_INSTANCE Instance, + IN XENVIF_POLLER_EVENT_TYPE Event + ) +{ + PXENVIF_POLLER Poller; + XENVIF_POLLER_CHANNEL_TYPE Type; + PXENVIF_POLLER_CHANNEL Channel; + + ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL); + + Poller = Instance->Poller; + + KeAcquireSpinLockAtDpcLevel(&Instance->Lock); + + if (!Instance->Enabled) + goto done; + + if (!__PollerIsSplit(Poller)) { + Type = XENVIF_POLLER_CHANNEL_COMBINED; + } else { + switch (Event) { + case XENVIF_POLLER_EVENT_RECEIVE: + Type = XENVIF_POLLER_CHANNEL_RECEIVER; + break; + + case XENVIF_POLLER_EVENT_TRANSMIT: + Type = XENVIF_POLLER_CHANNEL_TRANSMITTER; + break; + + default: + Type = XENVIF_POLLER_CHANNEL_INVALID; + break; + } + } + + ASSERT(Type != XENVIF_POLLER_CHANNEL_INVALID); + + Channel = Instance->Channel[Type]; + + PollerChannelUnmask(Channel); + +done: + KeReleaseSpinLockFromDpcLevel(&Instance->Lock); +} + +#define TIME_US(_us) ((_us) * 10) +#define TIME_MS(_ms) (TIME_US((_ms) * 1000)) +#define TIME_S(_s) (TIME_MS((_s) * 1000)) +#define TIME_RELATIVE(_t) (-(_t)) + +__drv_requiresIRQL(DISPATCH_LEVEL) +static VOID +PollerInstanceDefer( + IN PXENVIF_POLLER_INSTANCE Instance + ) +{ + LARGE_INTEGER Delay; + + ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL); + + KeAcquireSpinLockAtDpcLevel(&Instance->Lock); + + if (!Instance->Enabled) + goto done; + + Delay.QuadPart = TIME_RELATIVE(TIME_US(100)); + KeSetTimer(&Instance->Timer, Delay, &Instance->TimerDpc); + +done: + KeReleaseSpinLockFromDpcLevel(&Instance->Lock); +} + +static FORCEINLINE BOOLEAN +PollerInstanceDpcTimeout( + IN PXENVIF_POLLER_INSTANCE Instance + ) +{ + KDPC_WATCHDOG_INFORMATION Watchdog; + NTSTATUS status; + + UNREFERENCED_PARAMETER(Instance); + + RtlZeroMemory(&Watchdog, sizeof (Watchdog)); + + status = KeQueryDpcWatchdogInformation(&Watchdog); + ASSERT(NT_SUCCESS(status)); + + if (Watchdog.DpcTimeLimit == 0 || + Watchdog.DpcWatchdogLimit == 0) + return FALSE; + + if (Watchdog.DpcTimeCount > (Watchdog.DpcTimeLimit / 2) && + Watchdog.DpcWatchdogCount > (Watchdog.DpcWatchdogLimit / 2)) + return FALSE; + + return TRUE; +} + +__drv_functionClass(KDEFERRED_ROUTINE) +__drv_maxIRQL(DISPATCH_LEVEL) +__drv_minIRQL(DISPATCH_LEVEL) +__drv_requiresIRQL(DISPATCH_LEVEL) +__drv_sameIRQL +static VOID +PollerInstanceDpc( + IN PKDPC Dpc, + IN PVOID Context, + IN PVOID Argument1, + IN PVOID Argument2 + ) +{ + PXENVIF_POLLER_INSTANCE Instance = Context; + PXENVIF_POLLER Poller; + PXENVIF_FRONTEND Frontend; + BOOLEAN NeedReceiverPoll; + BOOLEAN NeedTransmitterPoll; + + UNREFERENCED_PARAMETER(Dpc); + UNREFERENCED_PARAMETER(Argument1); + UNREFERENCED_PARAMETER(Argument2); + + ASSERT(Instance != NULL); + + Poller = Instance->Poller; + Frontend = Poller->Frontend; + + NeedReceiverPoll = FALSE; + NeedTransmitterPoll = FALSE; + + for (;;) { + NeedReceiverPoll |= + (InterlockedBitTestAndReset(&Instance->Pending, + XENVIF_POLLER_EVENT_RECEIVE) != 0) ? + TRUE : + FALSE; + + NeedTransmitterPoll |= + (InterlockedBitTestAndReset(&Instance->Pending, + XENVIF_POLLER_EVENT_TRANSMIT) != 0) ? + TRUE : + FALSE; + + if (!NeedReceiverPoll && !NeedTransmitterPoll) + break; + + if (NeedReceiverPoll) + { + BOOLEAN Retry = ReceiverPoll(FrontendGetReceiver(Frontend), + Instance->Index); + + if (!Retry) { + NeedReceiverPoll = FALSE; + PollerInstanceUnmask(Instance, XENVIF_POLLER_EVENT_RECEIVE); + } + } + if (NeedTransmitterPoll) + { + BOOLEAN Retry = TransmitterPoll(FrontendGetTransmitter(Frontend), + Instance->Index); + + if (!Retry) { + NeedTransmitterPoll = FALSE; + PollerInstanceUnmask(Instance, XENVIF_POLLER_EVENT_TRANSMIT); + } + } + + if (PollerInstanceDpcTimeout(Instance)) { + PollerInstanceDefer(Instance); + break; + } + } +} + +static NTSTATUS +PollerInstanceInitialize( + IN PXENVIF_POLLER Poller, + IN LONG Index, + OUT PXENVIF_POLLER_INSTANCE *Instance + ) +{ + PXENVIF_FRONTEND Frontend; + LONG Type; + NTSTATUS status; + + Frontend = Poller->Frontend; + + *Instance = __PollerAllocate(sizeof (XENVIF_POLLER_INSTANCE)); + + status = STATUS_NO_MEMORY; + if (*Instance == NULL) + goto fail1; + + (*Instance)->Poller = Poller; + (*Instance)->Index = Index; + + for (Type = 0; Type < XENVIF_POLLER_CHANNEL_TYPE_COUNT; Type++) + { + PXENVIF_POLLER_CHANNEL Channel; + + status = PollerChannelInitialize(*Instance, Type, &Channel); + if (!NT_SUCCESS(status)) + goto fail2; + + (*Instance)->Channel[Type] = Channel; + } + + (*Instance)->Path = FrontendFormatPath(Frontend, Index); + if ((*Instance)->Path == NULL) + goto fail3; + + KeInitializeSpinLock(&(*Instance)->Lock); + + KeInitializeDpc(&(*Instance)->Dpc, PollerInstanceDpc, *Instance); + KeInitializeTimer(&(*Instance)->Timer); + KeInitializeDpc(&(*Instance)->TimerDpc, PollerInstanceDpc, *Instance); + + return STATUS_SUCCESS; + +fail3: + Error("fail3\n"); + + Type = XENVIF_POLLER_CHANNEL_TYPE_COUNT; + +fail2: + Error("fail2\n"); + + while (--Type >= 0) + { + PXENVIF_POLLER_CHANNEL Channel = (*Instance)->Channel[Type]; + + (*Instance)->Channel[Type] = NULL; + PollerChannelTeardown(Channel); + } + + (*Instance)->Index = 0; + (*Instance)->Poller = NULL; + + ASSERT(IsZeroMemory(*Instance, sizeof (XENVIF_POLLER_INSTANCE))); + __PollerFree(*Instance); + +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} + +__drv_requiresIRQL(DISPATCH_LEVEL) +static NTSTATUS +PollerInstanceConnect( + IN PXENVIF_POLLER_INSTANCE Instance + ) +{ + PROCESSOR_NUMBER ProcNumber; + LONG Type; + NTSTATUS status; + + ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL); + + status = KeGetProcessorNumberFromIndex(Instance->Index, &ProcNumber); + ASSERT(NT_SUCCESS(status)); + + KeSetTargetProcessorDpcEx(&Instance->Dpc, &ProcNumber); + KeSetTargetProcessorDpcEx(&Instance->TimerDpc, &ProcNumber); + + for (Type = 0; Type < XENVIF_POLLER_CHANNEL_TYPE_COUNT; Type++) + { + PXENVIF_POLLER_CHANNEL Channel = Instance->Channel[Type]; + + status = PollerChannelConnect(Channel); + if (!NT_SUCCESS(status)) + goto fail1; + } + + return STATUS_SUCCESS; + +fail1: + Error("fail1 (%08x)\n", status); + + while (--Type >= 0) + { + PXENVIF_POLLER_CHANNEL Channel = Instance->Channel[Type]; + + PollerChannelDisconnect(Channel); + } + + return status; +} + +static NTSTATUS +PollerInstanceStoreWrite( + IN PXENVIF_POLLER_INSTANCE Instance, + IN PXENBUS_STORE_TRANSACTION Transaction + ) +{ + ULONG Type; + NTSTATUS status; + + for (Type = 0; Type < XENVIF_POLLER_CHANNEL_TYPE_COUNT; Type++) + { + PXENVIF_POLLER_CHANNEL Channel = Instance->Channel[Type]; + + status = PollerChannelStoreWrite(Channel, Transaction); + if (!NT_SUCCESS(status)) + goto fail1; + } + + return STATUS_SUCCESS; + +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} -static FORCEINLINE PVOID -__PollerAllocate( - IN ULONG Length +__drv_requiresIRQL(DISPATCH_LEVEL) +static NTSTATUS +PollerInstanceEnable( + IN PXENVIF_POLLER_INSTANCE Instance ) { - return __AllocatePoolWithTag(NonPagedPool, Length, XENVIF_POLLER_TAG); + ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL); + + (VOID) InterlockedBitTestAndSet(&Instance->Pending, + XENVIF_POLLER_EVENT_RECEIVE); + (VOID) InterlockedBitTestAndSet(&Instance->Pending, + XENVIF_POLLER_EVENT_TRANSMIT); + + KeAcquireSpinLockAtDpcLevel(&Instance->Lock); + Instance->Enabled = TRUE; + KeReleaseSpinLockFromDpcLevel(&Instance->Lock); + + (VOID) KeInsertQueueDpc(&Instance->Dpc, NULL, NULL); + + return STATUS_SUCCESS; } -static FORCEINLINE VOID -__PollerFree( - IN PVOID Buffer +__drv_requiresIRQL(DISPATCH_LEVEL) +static NTSTATUS +PollerInstanceSend( + IN PXENVIF_POLLER_INSTANCE Instance, + IN XENVIF_POLLER_EVENT_TYPE Event ) { - __FreePoolWithTag(Buffer, XENVIF_POLLER_TAG); + PXENVIF_POLLER Poller; + XENVIF_POLLER_CHANNEL_TYPE Type; + PXENVIF_POLLER_CHANNEL Channel; + NTSTATUS status; + + ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL); + + Poller = Instance->Poller; + + KeAcquireSpinLockAtDpcLevel(&Instance->Lock); + + Type = XENVIF_POLLER_CHANNEL_INVALID; + + if (Instance->Enabled) { + if (!__PollerIsSplit(Poller)) { + Type = XENVIF_POLLER_CHANNEL_COMBINED; + } else { + switch (Event) { + case XENVIF_POLLER_EVENT_RECEIVE: + Type = XENVIF_POLLER_CHANNEL_RECEIVER; + break; + + case XENVIF_POLLER_EVENT_TRANSMIT: + Type = XENVIF_POLLER_CHANNEL_TRANSMITTER; + break; + + default: + ASSERT(FALSE); + break; + } + } + } + + KeReleaseSpinLockFromDpcLevel(&Instance->Lock); + + status = STATUS_UNSUCCESSFUL; + if (Type == XENVIF_POLLER_CHANNEL_INVALID) + goto fail1; + + Channel = Instance->Channel[Type]; + + PollerChannelSend(Channel); + + return STATUS_SUCCESS; + +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} + +__drv_requiresIRQL(DISPATCH_LEVEL) +static NTSTATUS +PollerInstanceTrigger( + IN PXENVIF_POLLER_INSTANCE Instance, + IN XENVIF_POLLER_EVENT_TYPE Event + ) +{ + NTSTATUS status; + + status = STATUS_INVALID_PARAMETER; + if (Event >= XENVIF_POLLER_EVENT_TYPE_COUNT) + goto fail1; + + (VOID) InterlockedBitTestAndSet(&Instance->Pending, Event); + + if (KeInsertQueueDpc(&Instance->Dpc, NULL, NULL)) + Instance->Dpcs++; + + return STATUS_SUCCESS; + +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} + +static VOID +PollerInstanceDebugCallback( + IN PXENVIF_POLLER_INSTANCE Instance + ) +{ + PXENVIF_POLLER Poller; + ULONG Type; + + Poller = Instance->Poller; + + XENBUS_DEBUG(Printf, + &Poller->DebugInterface, + "[%d]: Dpcs = %lu\n", + Instance->Index, + Instance->Dpcs); + + for (Type = 0; Type < XENVIF_POLLER_CHANNEL_TYPE_COUNT; Type++) + { + PXENVIF_POLLER_CHANNEL Channel = Instance->Channel[Type]; + + PollerChannelDebugCallback(Channel); + } +} + +__drv_requiresIRQL(DISPATCH_LEVEL) +static VOID +PollerInstanceDisable( + IN PXENVIF_POLLER_INSTANCE Instance + ) +{ + ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL); + + KeAcquireSpinLockAtDpcLevel(&Instance->Lock); + Instance->Enabled = FALSE; + KeReleaseSpinLockFromDpcLevel(&Instance->Lock); + + // + // No new timers can be scheduled once Enabled goes to FALSE. + // Cancel any existing ones. + // + (VOID) KeCancelTimer(&Instance->Timer); +} + +__drv_requiresIRQL(DISPATCH_LEVEL) +static VOID +PollerInstanceDisconnect( + IN PXENVIF_POLLER_INSTANCE Instance + ) +{ + LONG Type; + + ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL); + + Instance->Dpcs = 0; + Instance->Pending = 0; + + Type = XENVIF_POLLER_CHANNEL_TYPE_COUNT; + + while (--Type >= 0) + { + PXENVIF_POLLER_CHANNEL Channel = Instance->Channel[Type]; + + PollerChannelDisconnect(Channel); + } +} + +static VOID +PollerInstanceTeardown( + IN PXENVIF_POLLER_INSTANCE Instance + ) +{ + PXENVIF_POLLER Poller; + PXENVIF_FRONTEND Frontend; + LONG Type; + + ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); + KeFlushQueuedDpcs(); + + Poller = Instance->Poller; + Frontend = Poller->Frontend; + + RtlZeroMemory(&Instance->TimerDpc, sizeof (KDPC)); + RtlZeroMemory(&Instance->Timer, sizeof (KTIMER)); + RtlZeroMemory(&Instance->Dpc, sizeof (KDPC)); + + RtlZeroMemory(&Instance->Lock, sizeof (KSPIN_LOCK)); + + FrontendFreePath(Frontend, Instance->Path); + Instance->Path = NULL; + + Type = XENVIF_POLLER_CHANNEL_TYPE_COUNT; + + while (--Type >= 0) + { + PXENVIF_POLLER_CHANNEL Channel = Instance->Channel[Type]; + + Instance->Channel[Type] = NULL; + PollerChannelTeardown(Channel); + } + + Instance->Index = 0; + Instance->Poller = NULL; + + ASSERT(IsZeroMemory(Instance, sizeof (XENVIF_POLLER_INSTANCE))); + __PollerFree(Instance); } static VOID PollerDebugCallback( - IN PVOID Argument, - IN BOOLEAN Crashing + IN PVOID Argument, + IN BOOLEAN Crashing ) { - UNREFERENCED_PARAMETER(Argument); + PXENVIF_POLLER Poller = Argument; + PXENVIF_FRONTEND Frontend; + ULONG NumQueues; + ULONG Index; + UNREFERENCED_PARAMETER(Crashing); + + Frontend = Poller->Frontend; + + NumQueues = FrontendGetNumQueues(Frontend); + + for (Index = 0; Index < NumQueues; Index++) { + PXENVIF_POLLER_INSTANCE Instance = Poller->Instance[Index]; + + PollerInstanceDebugCallback(Instance); + } +} + +static VOID +PollerSetSplit( + IN PXENVIF_POLLER Poller + ) +{ + PXENVIF_FRONTEND Frontend; + PCHAR Buffer; + NTSTATUS status; + + Frontend = Poller->Frontend; + + status = XENBUS_STORE(Read, + &Poller->StoreInterface, + NULL, + FrontendGetBackendPath(Frontend), + "feature-split-event-channels", + &Buffer); + if (NT_SUCCESS(status)) { + Poller->Split = (BOOLEAN)strtol(Buffer, NULL, 2); + + XENBUS_STORE(Free, + &Poller->StoreInterface, + Buffer); + } else { + Poller->Split = FALSE; + } + + Info("%s: %s\n", FrontendGetPath(Frontend), + (Poller->Split) ? "TRUE" : "FALSE"); } NTSTATUS @@ -92,6 +1069,8 @@ PollerInitialize( OUT PXENVIF_POLLER *Poller ) { + LONG MaxQueues; + LONG Index; NTSTATUS status; *Poller = __PollerAllocate(sizeof (XENVIF_POLLER)); @@ -100,13 +1079,67 @@ PollerInitialize( if (*Poller == NULL) goto fail1; + FdoGetEvtchnInterface(PdoGetFdo(FrontendGetPdo(Frontend)), + &(*Poller)->EvtchnInterface); + + FdoGetStoreInterface(PdoGetFdo(FrontendGetPdo(Frontend)), + &(*Poller)->StoreInterface); + FdoGetDebugInterface(PdoGetFdo(FrontendGetPdo(Frontend)), &(*Poller)->DebugInterface); (*Poller)->Frontend = Frontend; + MaxQueues = FrontendGetMaxQueues(Frontend); + (*Poller)->Instance = __PollerAllocate(sizeof (PXENVIF_POLLER_INSTANCE) * + MaxQueues); + + status = STATUS_NO_MEMORY; + if ((*Poller)->Instance == NULL) + goto fail2; + + for (Index = 0; Index < MaxQueues; Index++) { + PXENVIF_POLLER_INSTANCE Instance; + + status = PollerInstanceInitialize(*Poller, Index, &Instance); + if (!NT_SUCCESS(status)) + goto fail3; + + (*Poller)->Instance[Index] = Instance; + } + return STATUS_SUCCESS; +fail3: + Error("fail3\n"); + + while (--Index >= 0) + { + PXENVIF_POLLER_INSTANCE Instance = (*Poller)->Instance[Index]; + + (*Poller)->Instance[Index] = NULL; + PollerInstanceTeardown(Instance); + } + + ASSERT(IsZeroMemory((*Poller)->Instance, + sizeof (PXENVIF_POLLER_INSTANCE) * MaxQueues)); + __PollerFree((*Poller)->Instance); + (*Poller)->Instance = NULL; + +fail2: + Error("fail2\n"); + + (*Poller)->Frontend = NULL; + + RtlZeroMemory(&(*Poller)->DebugInterface, + sizeof (XENBUS_DEBUG_INTERFACE)); + + RtlZeroMemory(&(*Poller)->StoreInterface, + sizeof (XENBUS_STORE_INTERFACE)); + + RtlZeroMemory(&(*Poller)->EvtchnInterface, + sizeof (XENBUS_EVTCHN_INTERFACE)); + fail1: Error("fail1 (%08x)\n", status); @@ -118,14 +1151,39 @@ PollerConnect( IN PXENVIF_POLLER Poller ) { + PXENVIF_FRONTEND Frontend; + LONG NumQueues; + LONG Index; NTSTATUS status; Trace("====>\n"); - status = XENBUS_DEBUG(Acquire, &Poller->DebugInterface); + Frontend = Poller->Frontend; + + status = XENBUS_EVTCHN(Acquire, &Poller->EvtchnInterface); if (!NT_SUCCESS(status)) goto fail1; + status = XENBUS_STORE(Acquire, &Poller->StoreInterface); + if (!NT_SUCCESS(status)) + goto fail2; + + status = XENBUS_DEBUG(Acquire, &Poller->DebugInterface); + if (!NT_SUCCESS(status)) + goto fail3; + + PollerSetSplit(Poller); + + NumQueues = FrontendGetNumQueues(Frontend); + + for (Index = 0; Index < NumQueues; Index++) { + PXENVIF_POLLER_INSTANCE Instance = Poller->Instance[Index]; + + status = PollerInstanceConnect(Instance); + if (!NT_SUCCESS(status)) + goto fail4; + } + status = XENBUS_DEBUG(Register, &Poller->DebugInterface, __MODULE__ "|POLLER", @@ -133,15 +1191,39 @@ PollerConnect( Poller, &Poller->DebugCallback); if (!NT_SUCCESS(status)) - goto fail2; + goto fail5; Trace("<====\n"); return STATUS_SUCCESS; +fail5: + Error("fail5\n"); + + Index = NumQueues; + +fail4: + Error("fail4\n"); + + while (--Index >= 0) + { + PXENVIF_POLLER_INSTANCE Instance = Poller->Instance[Index]; + + PollerInstanceDisconnect(Instance); + } + + Poller->Split = FALSE; + + XENBUS_DEBUG(Release, &Poller->DebugInterface); + +fail3: + Error("fail3\n"); + + XENBUS_STORE(Release, &Poller->StoreInterface); + fail2: Error("fail2\n"); - XENBUS_DEBUG(Release, &Poller->DebugInterface); + XENBUS_EVTCHN(Release, &Poller->EvtchnInterface); fail1: Error("fail1 (%08x)\n", status); @@ -155,34 +1237,174 @@ PollerStoreWrite( IN PXENBUS_STORE_TRANSACTION Transaction ) { - UNREFERENCED_PARAMETER(Poller); - UNREFERENCED_PARAMETER(Transaction); + PXENVIF_FRONTEND Frontend; + LONG NumQueues; + LONG Index; + NTSTATUS status; + + Trace("====>\n"); + + Frontend = Poller->Frontend; + + NumQueues = FrontendGetNumQueues(Frontend); + + for (Index = 0; Index < NumQueues; Index++) { + PXENVIF_POLLER_INSTANCE Instance = Poller->Instance[Index]; - Trace("<===>\n"); + status = PollerInstanceStoreWrite(Instance, Transaction); + if (!NT_SUCCESS(status)) + goto fail1; + } + + Trace("<====\n"); return STATUS_SUCCESS; + +fail1: + Error("fail1 (%08x)\n", status); + + return status; } NTSTATUS PollerEnable( - IN PXENVIF_POLLER Poller + IN PXENVIF_POLLER Poller + ) +{ + PXENVIF_FRONTEND Frontend; + LONG NumQueues; + LONG Index; + NTSTATUS status; + + Trace("====>\n"); + + Frontend = Poller->Frontend; + + NumQueues = FrontendGetNumQueues(Frontend); + + for (Index = 0; Index < NumQueues; Index++) { + PXENVIF_POLLER_INSTANCE Instance = Poller->Instance[Index]; + + status = PollerInstanceEnable(Instance); + if (!NT_SUCCESS(status)) + goto fail1; + } + + Trace("<====\n"); + + return STATUS_SUCCESS; + +fail1: + Error("fail1 (%08x)\n", status); + + while (--Index >= 0) + { + PXENVIF_POLLER_INSTANCE Instance = Poller->Instance[Index]; + + PollerInstanceDisable(Instance); + } + + return status; +} + +NTSTATUS +PollerSend( + IN PXENVIF_POLLER Poller, + IN ULONG Index, + IN XENVIF_POLLER_EVENT_TYPE Event ) { - UNREFERENCED_PARAMETER(Poller); + PXENVIF_FRONTEND Frontend; + ULONG NumQueues; + PXENVIF_POLLER_INSTANCE Instance; + NTSTATUS status; - Trace("<===>\n"); + Frontend = Poller->Frontend; + + NumQueues = FrontendGetNumQueues(Frontend); + + status = STATUS_INVALID_PARAMETER; + if (Index >= NumQueues) + goto fail1; + + Instance = Poller->Instance[Index]; + + status = PollerInstanceSend(Instance, Event); + if (!NT_SUCCESS(status)) + goto fail2; + + return STATUS_SUCCESS; + +fail2: + Error("fail2\n"); + +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} + +NTSTATUS +PollerTrigger( + IN PXENVIF_POLLER Poller, + IN ULONG Index, + IN XENVIF_POLLER_EVENT_TYPE Event + ) +{ + PXENVIF_FRONTEND Frontend; + ULONG NumQueues; + PXENVIF_POLLER_INSTANCE Instance; + NTSTATUS status; + + Frontend = Poller->Frontend; + + NumQueues = FrontendGetNumQueues(Frontend); + + status = STATUS_INVALID_PARAMETER; + if (Index >= NumQueues) + goto fail1; + + Instance = Poller->Instance[Index]; + + status = PollerInstanceTrigger(Instance, Event); + if (!NT_SUCCESS(status)) + goto fail2; return STATUS_SUCCESS; + +fail2: + Error("fail2\n"); + +fail1: + Error("fail1 (%08x)\n", status); + + return status; } VOID PollerDisable( - IN PXENVIF_POLLER Poller + IN PXENVIF_POLLER Poller ) { - UNREFERENCED_PARAMETER(Poller); + PXENVIF_FRONTEND Frontend; + LONG NumQueues; + LONG Index; - Trace("<===>\n"); + Trace("====>\n"); + + Frontend = Poller->Frontend; + + NumQueues = FrontendGetNumQueues(Frontend); + Index = NumQueues; + + while (--Index >= 0) + { + PXENVIF_POLLER_INSTANCE Instance = Poller->Instance[Index]; + + PollerInstanceDisable(Instance); + } + + Trace("<====\n"); } VOID @@ -190,15 +1412,37 @@ PollerDisconnect( IN PXENVIF_POLLER Poller ) { + PXENVIF_FRONTEND Frontend; + LONG NumQueues; + LONG Index; + Trace("====>\n"); + Frontend = Poller->Frontend; + XENBUS_DEBUG(Deregister, &Poller->DebugInterface, Poller->DebugCallback); Poller->DebugCallback = NULL; + NumQueues = FrontendGetNumQueues(Frontend); + Index = NumQueues; + + while (--Index >= 0) + { + PXENVIF_POLLER_INSTANCE Instance = Poller->Instance[Index]; + + PollerInstanceDisconnect(Instance); + } + + Poller->Split = FALSE; + XENBUS_DEBUG(Release, &Poller->DebugInterface); + XENBUS_STORE(Release, &Poller->StoreInterface); + + XENBUS_EVTCHN(Release, &Poller->EvtchnInterface); + Trace("<====\n"); } @@ -207,11 +1451,41 @@ PollerTeardown( IN PXENVIF_POLLER Poller ) { + PXENVIF_FRONTEND Frontend; + LONG MaxQueues; + LONG Index; + ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); + Frontend = Poller->Frontend; + + MaxQueues = FrontendGetMaxQueues(Frontend); + Index = MaxQueues; + + while (--Index >= 0) + { + PXENVIF_POLLER_INSTANCE Instance = Poller->Instance[Index]; + + Poller->Instance[Index] = NULL; + PollerInstanceTeardown(Instance); + } + + ASSERT(IsZeroMemory(Poller->Instance, + sizeof (PXENVIF_POLLER_INSTANCE) * MaxQueues)); + __PollerFree(Poller->Instance); + Poller->Instance = NULL; + + Poller->Frontend = NULL; + RtlZeroMemory(&Poller->DebugInterface, sizeof (XENBUS_DEBUG_INTERFACE)); + RtlZeroMemory(&Poller->StoreInterface, + sizeof (XENBUS_STORE_INTERFACE)); + + RtlZeroMemory(&Poller->EvtchnInterface, + sizeof (XENBUS_EVTCHN_INTERFACE)); + ASSERT(IsZeroMemory(Poller, sizeof (XENVIF_POLLER))); __PollerFree(Poller); } diff --git a/src/xenvif/poller.h b/src/xenvif/poller.h index 5ba0eaa..a2b32a1 100644 --- a/src/xenvif/poller.h +++ b/src/xenvif/poller.h @@ -40,10 +40,16 @@ typedef struct _XENVIF_POLLER XENVIF_POLLER, *PXENVIF_POLLER; +typedef enum _XENVIF_POLLER_EVENT_TYPE { + XENVIF_POLLER_EVENT_RECEIVE, + XENVIF_POLLER_EVENT_TRANSMIT, + XENVIF_POLLER_EVENT_TYPE_COUNT +} XENVIF_POLLER_EVENT_TYPE, *PXENVIF_POLLER_EVENT_TYPE; + extern NTSTATUS PollerInitialize( IN PXENVIF_FRONTEND Frontend, - OUT PXENVIF_POLLER *Poller + OUT PXENVIF_POLLER *Poller ); extern NTSTATUS @@ -53,7 +59,7 @@ PollerConnect( extern NTSTATUS PollerStoreWrite( - IN PXENVIF_POLLER Poller, + IN PXENVIF_POLLER Poller, IN PXENBUS_STORE_TRANSACTION Transaction ); @@ -62,6 +68,20 @@ PollerEnable( IN PXENVIF_POLLER Poller ); +extern NTSTATUS +PollerSend( + IN PXENVIF_POLLER Poller, + IN ULONG Index, + IN XENVIF_POLLER_EVENT_TYPE Event + ); + +extern NTSTATUS +PollerTrigger( + IN PXENVIF_POLLER Poller, + IN ULONG Index, + IN XENVIF_POLLER_EVENT_TYPE Event + ); + extern VOID PollerDisable( IN PXENVIF_POLLER Poller diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c index d7f3870..e48b678 100644 --- a/src/xenvif/receiver.c +++ b/src/xenvif/receiver.c @@ -41,7 +41,6 @@ #include <store_interface.h> #include <cache_interface.h> #include <gnttab_interface.h> -#include <evtchn_interface.h> #include "pdo.h" #include "registry.h" @@ -88,12 +87,6 @@ typedef struct _XENVIF_RECEIVER_RING { netif_rx_front_ring_t Front; netif_rx_sring_t *Shared; PXENBUS_GNTTAB_ENTRY Entry; - PXENBUS_EVTCHN_CHANNEL Channel; - KDPC Dpc; - ULONG Dpcs; - KTIMER Timer; - KDPC TimerDpc; - ULONG Events; PXENVIF_RECEIVER_FRAGMENT Pending[XENVIF_RECEIVER_MAXIMUM_FRAGMENT_ID + 1]; ULONG RequestsPosted; ULONG RequestsPushed; @@ -128,7 +121,6 @@ struct _XENVIF_RECEIVER { PXENVIF_FRONTEND Frontend; XENBUS_CACHE_INTERFACE CacheInterface; XENBUS_GNTTAB_INTERFACE GnttabInterface; - XENBUS_EVTCHN_INTERFACE EvtchnInterface; PXENVIF_RECEIVER_RING *Ring; LONG Loaned; LONG Returned; @@ -1615,58 +1607,19 @@ __ReceiverRingIsStopped( } static FORCEINLINE VOID -__ReceiverRingTrigger( - IN PXENVIF_RECEIVER_RING Ring, - IN BOOLEAN Locked - ) -{ - PXENVIF_RECEIVER Receiver; - - Receiver = Ring->Receiver; - - if (!Locked) - __ReceiverRingAcquireLock(Ring); - - if (Ring->Connected) - (VOID) XENBUS_EVTCHN(Trigger, - &Receiver->EvtchnInterface, - Ring->Channel); - - if (!Locked) - __ReceiverRingReleaseLock(Ring); -} - -static FORCEINLINE VOID -__ReceiverRingSend( - IN PXENVIF_RECEIVER_RING Ring, - IN BOOLEAN Locked - ) -{ - PXENVIF_RECEIVER Receiver; - - Receiver = Ring->Receiver; - - if (!Locked) - __ReceiverRingAcquireLock(Ring); - - if (Ring->Connected) - (VOID) XENBUS_EVTCHN(Send, - &Receiver->EvtchnInterface, - Ring->Channel); - - if (!Locked) - __ReceiverRingReleaseLock(Ring); -} - -static FORCEINLINE VOID __ReceiverRingReturnPacket( IN PXENVIF_RECEIVER_RING Ring, IN PXENVIF_RECEIVER_PACKET Packet, IN BOOLEAN Locked ) { + PXENVIF_RECEIVER Receiver; + PXENVIF_FRONTEND Frontend; PMDL Mdl; + Receiver = Ring->Receiver; + Frontend = Receiver->Frontend; + Mdl = &Packet->Mdl; while (Mdl != NULL) { @@ -1690,7 +1643,9 @@ __ReceiverRingReturnPacket( if (__ReceiverRingIsStopped(Ring)) { __ReceiverRingStart(Ring); - __ReceiverRingTrigger(Ring, TRUE); + PollerTrigger(FrontendGetPoller(Frontend), + Ring->Index, + XENVIF_POLLER_EVENT_RECEIVE); } if (!Locked) @@ -1770,8 +1725,17 @@ __ReceiverRingPushRequests( #pragma warning (pop) - if (Notify) - __ReceiverRingSend(Ring, TRUE); + if (Notify) { + PXENVIF_RECEIVER Receiver; + PXENVIF_FRONTEND Frontend; + + Receiver = Ring->Receiver; + Frontend = Receiver->Frontend; + + PollerSend(FrontendGetPoller(Frontend), + Ring->Index, + XENVIF_POLLER_EVENT_RECEIVE); + } Ring->RequestsPushed = Ring->RequestsPosted; } @@ -1927,14 +1891,6 @@ ReceiverRingDebugCallback( Ring->RequestsPosted, Ring->RequestsPushed, Ring->ResponsesProcessed); - - // Dump event channel - XENBUS_DEBUG(Printf, - &Receiver->DebugInterface, - "[%s]: Events = %lu Dpcs = %lu\n", - FrontendIsSplit(Frontend) ? "RX" : "COMBINED", - Ring->Events, - Ring->Dpcs); } static DECLSPEC_NOINLINE BOOLEAN @@ -2182,130 +2138,11 @@ done: #undef XENVIF_RECEIVER_BATCH } -static FORCEINLINE VOID -__ReceiverRingUnmask( - IN PXENVIF_RECEIVER_RING Ring - ) -{ - PXENVIF_RECEIVER Receiver; - - if (!Ring->Connected) - return; - - Receiver = Ring->Receiver; - - XENBUS_EVTCHN(Unmask, - &Receiver->EvtchnInterface, - Ring->Channel, - FALSE); -} - -static FORCEINLINE BOOLEAN -__ReceiverRingDpcTimeout( - IN PXENVIF_RECEIVER_RING Ring - ) -{ - KDPC_WATCHDOG_INFORMATION Watchdog; - NTSTATUS status; - - UNREFERENCED_PARAMETER(Ring); - - RtlZeroMemory(&Watchdog, sizeof (Watchdog)); - - status = KeQueryDpcWatchdogInformation(&Watchdog); - ASSERT(NT_SUCCESS(status)); - - if (Watchdog.DpcTimeLimit == 0 || - Watchdog.DpcWatchdogLimit == 0) - return FALSE; - - if (Watchdog.DpcTimeCount > (Watchdog.DpcTimeLimit / 2) && - Watchdog.DpcWatchdogCount > (Watchdog.DpcWatchdogLimit / 2)) - return FALSE; - - return TRUE; -} - #define TIME_US(_us) ((_us) * 10) #define TIME_MS(_ms) (TIME_US((_ms) * 1000)) #define TIME_S(_s) (TIME_MS((_s) * 1000)) #define TIME_RELATIVE(_t) (-(_t)) -__drv_functionClass(KDEFERRED_ROUTINE) -__drv_maxIRQL(DISPATCH_LEVEL) -__drv_minIRQL(DISPATCH_LEVEL) -__drv_requiresIRQL(DISPATCH_LEVEL) -__drv_sameIRQL -static VOID -ReceiverRingDpc( - IN PKDPC Dpc, - IN PVOID Context, - IN PVOID Argument1, - IN PVOID Argument2 - ) -{ - PXENVIF_RECEIVER_RING Ring = Context; - - UNREFERENCED_PARAMETER(Dpc); - UNREFERENCED_PARAMETER(Argument1); - UNREFERENCED_PARAMETER(Argument2); - - ASSERT(Ring != NULL); - - for (;;) { - BOOLEAN Retry; - - __ReceiverRingAcquireLock(Ring); - Retry = ReceiverRingPoll(Ring); - __ReceiverRingReleaseLock(Ring); - - if (!Retry) { - __ReceiverRingUnmask(Ring); - break; - } - - if (__ReceiverRingDpcTimeout(Ring)) { - LARGE_INTEGER Delay; - - Delay.QuadPart = TIME_RELATIVE(TIME_US(100)); - - KeSetTimer(&Ring->Timer, Delay, &Ring->TimerDpc); - break; - } - } -} - -KSERVICE_ROUTINE ReceiverRingEvtchnCallback; - -BOOLEAN -ReceiverRingEvtchnCallback( - IN PKINTERRUPT InterruptObject, - IN PVOID Argument - ) -{ - PXENVIF_RECEIVER_RING Ring = Argument; - PXENVIF_RECEIVER Receiver; - PXENVIF_FRONTEND Frontend; - - UNREFERENCED_PARAMETER(InterruptObject); - - ASSERT(Ring != NULL); - - Ring->Events++; - - if (KeInsertQueueDpc(&Ring->Dpc, NULL, NULL)) - Ring->Dpcs++; - - Receiver = Ring->Receiver; - Frontend = Receiver->Frontend; - - if (!FrontendIsSplit(Frontend)) - TransmitterNotify(FrontendGetTransmitter(Frontend), - Ring->Index); - - return TRUE; -} - #define XENVIF_RECEIVER_WATCHDOG_PERIOD 30 static NTSTATUS @@ -2369,16 +2206,22 @@ ReceiverRingWatchdog( if (Ring->Shared->rsp_prod != rsp_prod && Ring->Front.rsp_cons == rsp_cons) { PXENVIF_RECEIVER Receiver; + PXENVIF_FRONTEND Frontend; Receiver = Ring->Receiver; + Frontend = Receiver->Frontend; XENBUS_DEBUG(Trigger, &Receiver->DebugInterface, Ring->DebugCallback); // Try to move things along - __ReceiverRingTrigger(Ring, TRUE); - __ReceiverRingSend(Ring, TRUE); + PollerTrigger(FrontendGetPoller(Frontend), + Ring->Index, + XENVIF_POLLER_EVENT_RECEIVE); + PollerSend(FrontendGetPoller(Frontend), + Ring->Index, + XENVIF_POLLER_EVENT_RECEIVE); } KeMemoryBarrier(); @@ -2426,10 +2269,6 @@ __ReceiverRingInitialize( InitializeListHead(&(*Ring)->PacketList); - KeInitializeDpc(&(*Ring)->Dpc, ReceiverRingDpc, *Ring); - KeInitializeTimer(&(*Ring)->Timer); - KeInitializeDpc(&(*Ring)->TimerDpc, ReceiverRingDpc, *Ring); - status = RtlStringCbPrintfA(Name, sizeof (Name), "%s_receiver_packet", @@ -2513,10 +2352,6 @@ fail4: fail3: Error("fail3\n"); - RtlZeroMemory(&(*Ring)->TimerDpc, sizeof (KDPC)); - RtlZeroMemory(&(*Ring)->Timer, sizeof (KTIMER)); - RtlZeroMemory(&(*Ring)->Dpc, sizeof (KDPC)); - RtlZeroMemory(&(*Ring)->PacketList, sizeof (LIST_ENTRY)); FrontendFreePath(Frontend, (*Ring)->Path); @@ -2550,7 +2385,6 @@ __ReceiverRingConnect( PFN_NUMBER Pfn; CHAR Name[MAXNAMELEN]; ULONG Index; - PROCESSOR_NUMBER ProcNumber; NTSTATUS status; Receiver = Ring->Receiver; @@ -2614,35 +2448,6 @@ __ReceiverRingConnect( ASSERT(!Ring->Connected); - Ring->Channel = XENBUS_EVTCHN(Open, - &Receiver->EvtchnInterface, - XENBUS_EVTCHN_TYPE_UNBOUND, - ReceiverRingEvtchnCallback, - Ring, - FrontendGetBackendDomain(Frontend), - TRUE); - - status = STATUS_UNSUCCESSFUL; - if (Ring->Channel == NULL) - goto fail6; - - status = KeGetProcessorNumberFromIndex(Ring->Index, &ProcNumber); - ASSERT(NT_SUCCESS(status)); - - KeSetTargetProcessorDpcEx(&Ring->Dpc, &ProcNumber); - KeSetTargetProcessorDpcEx(&Ring->TimerDpc, &ProcNumber); - - (VOID) XENBUS_EVTCHN(Bind, - &Receiver->EvtchnInterface, - Ring->Channel, - ProcNumber.Group, - ProcNumber.Number); - - XENBUS_EVTCHN(Unmask, - &Receiver->EvtchnInterface, - Ring->Channel, - FALSE); - Ring->Connected = TRUE; status = XENBUS_DEBUG(Register, @@ -2652,25 +2457,15 @@ __ReceiverRingConnect( Ring, &Ring->DebugCallback); if (!NT_SUCCESS(status)) - goto fail7; + goto fail6; return STATUS_SUCCESS; -fail7: - Error("fail7\n"); - - Ring->Connected = FALSE; - - XENBUS_EVTCHN(Close, - &Receiver->EvtchnInterface, - Ring->Channel); - Ring->Channel = NULL; - - Ring->Events = 0; - fail6: Error("fail6\n"); + Ring->Connected = FALSE; + fail5: Error("fail5\n"); @@ -2716,7 +2511,6 @@ __ReceiverRingStoreWrite( { PXENVIF_RECEIVER Receiver; PXENVIF_FRONTEND Frontend; - ULONG Port; PCHAR Path; NTSTATUS status; @@ -2739,25 +2533,8 @@ __ReceiverRingStoreWrite( if (!NT_SUCCESS(status)) goto fail1; - Port = XENBUS_EVTCHN(GetPort, - &Receiver->EvtchnInterface, - Ring->Channel); - - status = XENBUS_STORE(Printf, - &Receiver->StoreInterface, - Transaction, - Path, - FrontendIsSplit(Frontend) ? "event-channel-rx" : "event-channel", - "%u", - Port); - if (!NT_SUCCESS(status)) - goto fail2; - return STATUS_SUCCESS; -fail2: - Error("fail2\n"); - fail1: Error("fail1 (%08x)\n", status); @@ -2792,8 +2569,6 @@ __ReceiverRingEnable( Ring->Enabled = TRUE; - (VOID) KeInsertQueueDpc(&Ring->Dpc, NULL, NULL); - __ReceiverRingReleaseLock(Ring); Info("%s[%u]: <====\n", @@ -2834,12 +2609,6 @@ __ReceiverRingDisable( __ReceiverRingReleaseLock(Ring); - // - // No new timers can be scheduled once Enabled goes to FALSE. - // Cancel any existing ones. - // - (VOID) KeCancelTimer(&Ring->Timer); - Info("%s[%u]: <====\n", FrontendGetPath(Frontend), Ring->Index); @@ -2861,14 +2630,6 @@ __ReceiverRingDisconnect( ASSERT(Ring->Connected); Ring->Connected = FALSE; - XENBUS_EVTCHN(Close, - &Receiver->EvtchnInterface, - Ring->Channel); - Ring->Channel = NULL; - - Ring->Events = 0; - Ring->Dpcs = 0; - ASSERT3U(Ring->ResponsesProcessed, ==, Ring->RequestsPushed); ASSERT3U(Ring->RequestsPushed, ==, Ring->RequestsPosted); @@ -2913,9 +2674,6 @@ __ReceiverRingTeardown( Frontend = Receiver->Frontend; RtlZeroMemory(&Ring->Hash, sizeof (XENVIF_RECEIVER_HASH)); - RtlZeroMemory(&Ring->TimerDpc, sizeof (KDPC)); - RtlZeroMemory(&Ring->Timer, sizeof (KTIMER)); - RtlZeroMemory(&Ring->Dpc, sizeof (KDPC)); Ring->BackfillSize = 0; Ring->OffloadOptions.Value = 0; @@ -3085,9 +2843,6 @@ ReceiverInitialize( FdoGetGnttabInterface(PdoGetFdo(FrontendGetPdo(Frontend)), &(*Receiver)->GnttabInterface); - FdoGetEvtchnInterface(PdoGetFdo(FrontendGetPdo(Frontend)), - &(*Receiver)->EvtchnInterface); - (*Receiver)->Frontend = Frontend; status = XENBUS_CACHE(Acquire, &(*Receiver)->CacheInterface); @@ -3140,9 +2895,6 @@ fail2: (*Receiver)->Frontend = NULL; - RtlZeroMemory(&(*Receiver)->EvtchnInterface, - sizeof (XENBUS_EVTCHN_INTERFACE)); - RtlZeroMemory(&(*Receiver)->GnttabInterface, sizeof (XENBUS_GNTTAB_INTERFACE)); @@ -3194,13 +2946,9 @@ ReceiverConnect( if (!NT_SUCCESS(status)) goto fail2; - status = XENBUS_EVTCHN(Acquire, &Receiver->EvtchnInterface); - if (!NT_SUCCESS(status)) - goto fail3; - status = XENBUS_GNTTAB(Acquire, &Receiver->GnttabInterface); if (!NT_SUCCESS(status)) - goto fail4; + goto fail3; Index = 0; while (Index < (LONG)FrontendGetNumQueues(Frontend)) { @@ -3208,7 +2956,7 @@ ReceiverConnect( status = __ReceiverRingConnect(Ring); if (!NT_SUCCESS(status)) - goto fail5; + goto fail4; Index++; } @@ -3220,18 +2968,18 @@ ReceiverConnect( Receiver, &Receiver->DebugCallback); if (!NT_SUCCESS(status)) - goto fail6; + goto fail5; Trace("<====\n"); return STATUS_SUCCESS; -fail6: - Error("fail6\n"); +fail5: + Error("fail5\n"); Index = FrontendGetNumQueues(Frontend); -fail5: - Error("fail5\n"); +fail4: + Error("fail4\n"); while (--Index >= 0) { PXENVIF_RECEIVER_RING Ring = Receiver->Ring[Index]; @@ -3241,11 +2989,6 @@ fail5: XENBUS_GNTTAB(Release, &Receiver->GnttabInterface); -fail4: - Error("fail4\n"); - - XENBUS_EVTCHN(Release, &Receiver->EvtchnInterface); - fail3: Error("fail3\n"); @@ -3485,6 +3228,34 @@ fail1: return status; } +BOOLEAN +ReceiverPoll( + IN PXENVIF_RECEIVER Receiver, + IN ULONG Index + ) +{ + PXENVIF_FRONTEND Frontend; + ULONG NumQueues; + PXENVIF_RECEIVER_RING Ring; + BOOLEAN Retry; + + ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL); + + Frontend = Receiver->Frontend; + + NumQueues = FrontendGetNumQueues(Frontend); + if (Index >= NumQueues) + return FALSE; + + Ring = Receiver->Ring[Index]; + + __ReceiverRingAcquireLock(Ring); + Retry = ReceiverRingPoll(Ring); + __ReceiverRingReleaseLock(Ring); + + return Retry; +} + VOID ReceiverDisable( IN PXENVIF_RECEIVER Receiver @@ -3533,8 +3304,6 @@ ReceiverDisconnect( XENBUS_GNTTAB(Release, &Receiver->GnttabInterface); - XENBUS_EVTCHN(Release, &Receiver->EvtchnInterface); - XENBUS_STORE(Release, &Receiver->StoreInterface); XENBUS_DEBUG(Release, &Receiver->DebugInterface); @@ -3552,9 +3321,6 @@ ReceiverTeardown( Frontend = Receiver->Frontend; - ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); - KeFlushQueuedDpcs(); - ASSERT3U(Receiver->Returned, ==, Receiver->Loaned); Receiver->Loaned = 0; Receiver->Returned = 0; @@ -3574,9 +3340,6 @@ ReceiverTeardown( Receiver->Frontend = NULL; - RtlZeroMemory(&Receiver->EvtchnInterface, - sizeof (XENBUS_EVTCHN_INTERFACE)); - RtlZeroMemory(&Receiver->GnttabInterface, sizeof (XENBUS_GNTTAB_INTERFACE)); @@ -3753,32 +3516,6 @@ ReceiverWaitForPackets( Trace("%s: <====\n", FrontendGetPath(Frontend)); } -VOID -ReceiverTrigger( - IN PXENVIF_RECEIVER Receiver, - IN ULONG Index - ) -{ - PXENVIF_RECEIVER_RING Ring; - - Ring = Receiver->Ring[Index]; - - __ReceiverRingTrigger(Ring, FALSE); -} - -VOID -ReceiverSend( - IN PXENVIF_RECEIVER Receiver, - IN ULONG Index - ) -{ - PXENVIF_RECEIVER_RING Ring; - - Ring = Receiver->Ring[Index]; - - __ReceiverRingSend(Ring, FALSE); -} - NTSTATUS ReceiverSetHashAlgorithm( IN PXENVIF_RECEIVER Receiver, diff --git a/src/xenvif/receiver.h b/src/xenvif/receiver.h index 7846f0b..e1b7a88 100644 --- a/src/xenvif/receiver.h +++ b/src/xenvif/receiver.h @@ -62,6 +62,12 @@ ReceiverEnable( IN PXENVIF_RECEIVER Receiver ); +extern BOOLEAN +ReceiverPoll( + IN PXENVIF_RECEIVER Receiver, + IN ULONG Index + ); + extern VOID ReceiverDisable( IN PXENVIF_RECEIVER Receiver diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c index 3ab3cbd..eed0a0f 100644 --- a/src/xenvif/transmitter.c +++ b/src/xenvif/transmitter.c @@ -43,7 +43,6 @@ #include <cache_interface.h> #include <gnttab_interface.h> #include <range_set_interface.h> -#include <evtchn_interface.h> #include "pdo.h" #include "frontend.h" @@ -179,12 +178,6 @@ typedef struct _XENVIF_TRANSMITTER_RING { netif_tx_front_ring_t Front; netif_tx_sring_t *Shared; PXENBUS_GNTTAB_ENTRY Entry; - PXENBUS_EVTCHN_CHANNEL Channel; - KDPC Dpc; - ULONG Dpcs; - KTIMER Timer; - KDPC TimerDpc; - ULONG Events; BOOLEAN Connected; BOOLEAN Enabled; BOOLEAN Stopped; @@ -215,7 +208,6 @@ struct _XENVIF_TRANSMITTER { XENBUS_CACHE_INTERFACE CacheInterface; XENBUS_GNTTAB_INTERFACE GnttabInterface; XENBUS_RANGE_SET_INTERFACE RangeSetInterface; - XENBUS_EVTCHN_INTERFACE EvtchnInterface; PXENVIF_TRANSMITTER_RING *Ring; BOOLEAN MulticastControl; ULONG DisableIpVersion4Gso; @@ -770,15 +762,6 @@ TransmitterRingDebugCallback( Ring->PacketsUnprepared, Ring->PacketsSent, Ring->PacketsCompleted); - - if (FrontendIsSplit(Frontend)) { - // Dump event channel - XENBUS_DEBUG(Printf, - &Transmitter->DebugInterface, - "Events = %lu Dpcs = %lu\n", - Ring->Events, - Ring->Dpcs); - } } static BOOLEAN @@ -2796,64 +2779,17 @@ done: } static FORCEINLINE VOID -__TransmitterRingTrigger( - IN PXENVIF_TRANSMITTER_RING Ring - ) -{ - PXENVIF_TRANSMITTER Transmitter; - PXENVIF_FRONTEND Frontend; - - Transmitter = Ring->Transmitter; - Frontend = Transmitter->Frontend; - - if (!Ring->Connected) - return; - - if (FrontendIsSplit(Frontend)) { - ASSERT(Ring->Channel != NULL); - - (VOID) XENBUS_EVTCHN(Trigger, - &Transmitter->EvtchnInterface, - Ring->Channel); - } else { - ReceiverTrigger(FrontendGetReceiver(Frontend), - Ring->Index); - } -} - -static FORCEINLINE VOID -__TransmitterRingSend( +__TransmitterRingPushRequests( IN PXENVIF_TRANSMITTER_RING Ring ) { PXENVIF_TRANSMITTER Transmitter; PXENVIF_FRONTEND Frontend; + BOOLEAN Notify; Transmitter = Ring->Transmitter; Frontend = Transmitter->Frontend; - if (!Ring->Connected) - return; - - if (FrontendIsSplit(Frontend)) { - ASSERT(Ring->Channel != NULL); - - (VOID) XENBUS_EVTCHN(Send, - &Transmitter->EvtchnInterface, - Ring->Channel); - } else { - ReceiverSend(FrontendGetReceiver(Frontend), - Ring->Index); - } -} - -static FORCEINLINE VOID -__TransmitterRingPushRequests( - IN PXENVIF_TRANSMITTER_RING Ring - ) -{ - BOOLEAN Notify; - if (Ring->RequestsPosted == Ring->RequestsPushed) return; @@ -2866,7 +2802,9 @@ __TransmitterRingPushRequests( #pragma warning (pop) if (Notify) - __TransmitterRingSend(Ring); + PollerSend(FrontendGetPoller(Frontend), + Ring->Index, + XENVIF_POLLER_EVENT_TRANSMIT); Ring->RequestsPushed = Ring->RequestsPosted; } @@ -3220,130 +3158,11 @@ TransmitterRingReleaseLock( __TransmitterRingReleaseLock(Ring); } -static FORCEINLINE VOID -__TransmitterRingUnmask( - IN PXENVIF_TRANSMITTER_RING Ring - ) -{ - PXENVIF_TRANSMITTER Transmitter; - PXENVIF_FRONTEND Frontend; - - Transmitter = Ring->Transmitter; - Frontend = Transmitter->Frontend; - - if (!Ring->Connected || !FrontendIsSplit(Frontend)) - return; - - XENBUS_EVTCHN(Unmask, - &Transmitter->EvtchnInterface, - Ring->Channel, - FALSE); -} - -static FORCEINLINE BOOLEAN -__TransmitterRingDpcTimeout( - IN PXENVIF_TRANSMITTER_RING Ring - ) -{ - KDPC_WATCHDOG_INFORMATION Watchdog; - NTSTATUS status; - - UNREFERENCED_PARAMETER(Ring); - - RtlZeroMemory(&Watchdog, sizeof (Watchdog)); - - status = KeQueryDpcWatchdogInformation(&Watchdog); - ASSERT(NT_SUCCESS(status)); - - if (Watchdog.DpcTimeLimit == 0 || - Watchdog.DpcWatchdogLimit == 0) - return FALSE; - - if (Watchdog.DpcTimeCount > (Watchdog.DpcTimeLimit / 2) && - Watchdog.DpcWatchdogCount > (Watchdog.DpcWatchdogLimit / 2)) - return FALSE; - - return TRUE; -} - #define TIME_US(_us) ((_us) * 10) #define TIME_MS(_ms) (TIME_US((_ms) * 1000)) #define TIME_S(_s) (TIME_MS((_s) * 1000)) #define TIME_RELATIVE(_t) (-(_t)) -__drv_functionClass(KDEFERRED_ROUTINE) -__drv_maxIRQL(DISPATCH_LEVEL) -__drv_minIRQL(DISPATCH_LEVEL) -__drv_requiresIRQL(DISPATCH_LEVEL) -__drv_sameIRQL -static VOID -TransmitterRingDpc( - IN PKDPC Dpc, - IN PVOID Context, - IN PVOID Argument1, - IN PVOID Argument2 - ) -{ - PXENVIF_TRANSMITTER_RING Ring = Context; - - UNREFERENCED_PARAMETER(Dpc); - UNREFERENCED_PARAMETER(Argument1); - UNREFERENCED_PARAMETER(Argument2); - - ASSERT(Ring != NULL); - - for (;;) { - BOOLEAN Retry; - - __TransmitterRingAcquireLock(Ring); - Retry = TransmitterRingPoll(Ring); - __TransmitterRingReleaseLock(Ring); - - if (!Retry) { - __TransmitterRingUnmask(Ring); - break; - } - - if (__TransmitterRingDpcTimeout(Ring)) { - LARGE_INTEGER Delay; - - Delay.QuadPart = TIME_RELATIVE(TIME_US(100)); - - KeSetTimer(&Ring->Timer, Delay, &Ring->TimerDpc); - break; - } - } -} - -KSERVICE_ROUTINE TransmitterRingEvtchnCallback; - -BOOLEAN -TransmitterRingEvtchnCallback( - IN PKINTERRUPT InterruptObject, - IN PVOID Argument - ) -{ - PXENVIF_TRANSMITTER_RING Ring = Argument; - PXENVIF_TRANSMITTER Transmitter; - PXENVIF_FRONTEND Frontend; - - UNREFERENCED_PARAMETER(InterruptObject); - - ASSERT(Ring != NULL); - - Transmitter = Ring->Transmitter; - Frontend = Transmitter->Frontend; - - ASSERT(FrontendIsSplit(Frontend)); - - Ring->Events++; - - if (KeInsertQueueDpc(&Ring->Dpc, NULL, NULL)) - Ring->Dpcs++; - - return TRUE; -} - #define XENVIF_TRANSMITTER_WATCHDOG_PERIOD 30 static NTSTATUS @@ -3402,16 +3221,22 @@ TransmitterRingWatchdog( if (Ring->PacketsQueued == PacketsQueued && Ring->PacketsCompleted != PacketsQueued) { PXENVIF_TRANSMITTER Transmitter; + PXENVIF_FRONTEND Frontend; Transmitter = Ring->Transmitter; + Frontend = Transmitter->Frontend; XENBUS_DEBUG(Trigger, &Transmitter->DebugInterface, Ring->DebugCallback); // Try to move things along - __TransmitterRingTrigger(Ring); - __TransmitterRingSend(Ring); + PollerTrigger(FrontendGetPoller(Frontend), + Ring->Index, + XENVIF_POLLER_EVENT_TRANSMIT); + PollerSend(FrontendGetPoller(Frontend), + Ring->Index, + XENVIF_POLLER_EVENT_TRANSMIT); } PacketsQueued = Ring->PacketsQueued; @@ -3456,10 +3281,6 @@ __TransmitterRingInitialize( InitializeListHead(&(*Ring)->RequestQueue); InitializeListHead(&(*Ring)->PacketComplete); - KeInitializeDpc(&(*Ring)->Dpc, TransmitterRingDpc, *Ring); - KeInitializeTimer(&(*Ring)->Timer); - KeInitializeDpc(&(*Ring)->TimerDpc, TransmitterRingDpc, *Ring); - status = RtlStringCbPrintfA(Name, sizeof (Name), "%s_transmitter_buffer", @@ -3661,8 +3482,6 @@ fail4: fail3: Error("fail3\n"); - RtlZeroMemory(&(*Ring)->Dpc, sizeof (KDPC)); - RtlZeroMemory(&(*Ring)->PacketComplete, sizeof (LIST_ENTRY)); RtlZeroMemory(&(*Ring)->RequestQueue, sizeof (LIST_ENTRY)); RtlZeroMemory(&(*Ring)->PacketQueue, sizeof (LIST_ENTRY)); @@ -3696,7 +3515,6 @@ __TransmitterRingConnect( PFN_NUMBER Pfn; CHAR Name[MAXNAMELEN]; ULONG Index; - PROCESSOR_NUMBER ProcNumber; NTSTATUS status; ASSERT(!Ring->Connected); @@ -3762,37 +3580,6 @@ __TransmitterRingConnect( ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL); - if (FrontendIsSplit(Frontend)) { - Ring->Channel = XENBUS_EVTCHN(Open, - &Transmitter->EvtchnInterface, - XENBUS_EVTCHN_TYPE_UNBOUND, - TransmitterRingEvtchnCallback, - Ring, - FrontendGetBackendDomain(Frontend), - TRUE); - - status = STATUS_UNSUCCESSFUL; - if (Ring->Channel == NULL) - goto fail6; - - status = KeGetProcessorNumberFromIndex(Ring->Index, &ProcNumber); - ASSERT(NT_SUCCESS(status)); - - KeSetTargetProcessorDpcEx(&Ring->Dpc, &ProcNumber); - KeSetTargetProcessorDpcEx(&Ring->TimerDpc, &ProcNumber); - - (VOID) XENBUS_EVTCHN(Bind, - &Transmitter->EvtchnInterface, - Ring->Channel, - ProcNumber.Group, - ProcNumber.Number); - - XENBUS_EVTCHN(Unmask, - &Transmitter->EvtchnInterface, - Ring->Channel, - FALSE); - } - status = XENBUS_DEBUG(Register, &Transmitter->DebugInterface, Name, @@ -3800,22 +3587,12 @@ __TransmitterRingConnect( Ring, &Ring->DebugCallback); if (!NT_SUCCESS(status)) - goto fail7; + goto fail6; Ring->Connected = TRUE; return STATUS_SUCCESS; -fail7: - Error("fail7\n"); - - XENBUS_EVTCHN(Close, - &Transmitter->EvtchnInterface, - Ring->Channel); - Ring->Channel = NULL; - - Ring->Events = 0; - fail6: Error("fail6\n"); @@ -3864,7 +3641,6 @@ __TransmitterRingStoreWrite( { PXENVIF_TRANSMITTER Transmitter; PXENVIF_FRONTEND Frontend; - ULONG Port; PCHAR Path; NTSTATUS status; @@ -3887,29 +3663,8 @@ __TransmitterRingStoreWrite( if (!NT_SUCCESS(status)) goto fail1; - if (!FrontendIsSplit(Frontend)) - goto done; - - Port = XENBUS_EVTCHN(GetPort, - &Transmitter->EvtchnInterface, - Ring->Channel); - - status = XENBUS_STORE(Printf, - &Transmitter->StoreInterface, - Transaction, - Path, - "event-channel-tx", - "%u", - Port); - if (!NT_SUCCESS(status)) - goto fail2; - -done: return STATUS_SUCCESS; -fail2: - Error("fail2\n"); - fail1: Error("fail1 (%08x)\n", status); @@ -3936,8 +3691,6 @@ __TransmitterRingEnable( ASSERT(!Ring->Enabled); Ring->Enabled = TRUE; - KeInsertQueueDpc(&Ring->Dpc, NULL, NULL); - __TransmitterRingReleaseLock(Ring); Info("%s[%u]: <====\n", @@ -4017,7 +3770,9 @@ __TransmitterRingDisable( ASSERT(Attempt < 100); // Try to move things along - __TransmitterRingSend(Ring); + PollerSend(FrontendGetPoller(Frontend), + Ring->Index, + XENVIF_POLLER_EVENT_TRANSMIT); (VOID) TransmitterRingPoll(Ring); if (State != XenbusStateConnected) @@ -4035,12 +3790,6 @@ __TransmitterRingDisable( __TransmitterRingReleaseLock(Ring); - // - // No new timers can be scheduled once Enabled goes to FALSE. - // Cancel any existing ones. - // - (VOID) KeCancelTimer(&Ring->Timer); - Info("%s[%u]: <====\n", FrontendGetPath(Frontend), Ring->Index); @@ -4060,17 +3809,6 @@ __TransmitterRingDisconnect( Transmitter = Ring->Transmitter; Frontend = Transmitter->Frontend; - if (Ring->Channel != NULL) { - XENBUS_EVTCHN(Close, - &Transmitter->EvtchnInterface, - Ring->Channel); - Ring->Channel = NULL; - - Ring->Events = 0; - } - - Ring->Dpcs = 0; - ASSERT3U(Ring->ResponsesProcessed, ==, Ring->RequestsPushed); ASSERT3U(Ring->RequestsPushed, ==, Ring->RequestsPosted); @@ -4114,12 +3852,6 @@ __TransmitterRingTeardown( Transmitter = Ring->Transmitter; Frontend = Transmitter->Frontend; - Ring->Dpcs = 0; - - RtlZeroMemory(&Ring->TimerDpc, sizeof (KDPC)); - RtlZeroMemory(&Ring->Timer, sizeof (KTIMER)); - RtlZeroMemory(&Ring->Dpc, sizeof (KDPC)); - ASSERT3U(Ring->PacketsCompleted, ==, Ring->PacketsSent); ASSERT3U(Ring->PacketsSent, ==, Ring->PacketsPrepared - Ring->PacketsUnprepared); ASSERT3U(Ring->PacketsPrepared, ==, Ring->PacketsCopied + Ring->PacketsGranted + Ring->PacketsFaked); @@ -4545,9 +4277,6 @@ TransmitterInitialize( FdoGetGnttabInterface(PdoGetFdo(FrontendGetPdo(Frontend)), &(*Transmitter)->GnttabInterface); - FdoGetEvtchnInterface(PdoGetFdo(FrontendGetPdo(Frontend)), - &(*Transmitter)->EvtchnInterface); - (*Transmitter)->Frontend = Frontend; KeInitializeSpinLock(&(*Transmitter)->Lock); @@ -4700,13 +4429,9 @@ TransmitterConnect( if (!NT_SUCCESS(status)) goto fail2; - status = XENBUS_EVTCHN(Acquire, &Transmitter->EvtchnInterface); - if (!NT_SUCCESS(status)) - goto fail3; - status = XENBUS_GNTTAB(Acquire, &Transmitter->GnttabInterface); if (!NT_SUCCESS(status)) - goto fail4; + goto fail3; if (Transmitter->DisableMulticastControl == 0) { status = XENBUS_STORE(Read, @@ -4730,7 +4455,7 @@ TransmitterConnect( status = __TransmitterRingConnect(Ring); if (!NT_SUCCESS(status)) - goto fail5; + goto fail4; Index++; } @@ -4742,18 +4467,18 @@ TransmitterConnect( Transmitter, &Transmitter->DebugCallback); if (!NT_SUCCESS(status)) - goto fail6; + goto fail5; Trace("<====\n"); return STATUS_SUCCESS; -fail6: - Error("fail6\n"); +fail5: + Error("fail5\n"); Index = FrontendGetNumQueues(Frontend); -fail5: - Error("fail5\n"); +fail4: + Error("fail4\n"); while (--Index >= 0) { PXENVIF_TRANSMITTER_RING Ring; @@ -4767,11 +4492,6 @@ fail5: XENBUS_GNTTAB(Release, &Transmitter->GnttabInterface); -fail4: - Error("fail4\n"); - - XENBUS_EVTCHN(Release, &Transmitter->EvtchnInterface); - fail3: Error("fail3\n"); @@ -4908,6 +4628,34 @@ TransmitterEnable( return STATUS_SUCCESS; } +BOOLEAN +TransmitterPoll( + IN PXENVIF_TRANSMITTER Transmitter, + IN ULONG Index + ) +{ + PXENVIF_FRONTEND Frontend; + ULONG NumQueues; + PXENVIF_TRANSMITTER_RING Ring; + BOOLEAN Retry; + + ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL); + + Frontend = Transmitter->Frontend; + + NumQueues = FrontendGetNumQueues(Frontend); + if (Index >= NumQueues) + return FALSE; + + Ring = Transmitter->Ring[Index]; + + __TransmitterRingAcquireLock(Ring); + Retry = TransmitterRingPoll(Ring); + __TransmitterRingReleaseLock(Ring); + + return Retry; +} + VOID TransmitterDisable( IN PXENVIF_TRANSMITTER Transmitter @@ -4958,8 +4706,6 @@ TransmitterDisconnect( XENBUS_GNTTAB(Release, &Transmitter->GnttabInterface); - XENBUS_EVTCHN(Release, &Transmitter->EvtchnInterface); - XENBUS_STORE(Release, &Transmitter->StoreInterface); XENBUS_DEBUG(Release, &Transmitter->DebugInterface); @@ -4978,7 +4724,6 @@ TransmitterTeardown( Frontend = Transmitter->Frontend; ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); - KeFlushQueuedDpcs(); Index = FrontendGetMaxQueues(Frontend); while (--Index >= 0) { @@ -5020,9 +4765,6 @@ TransmitterTeardown( RtlZeroMemory(&Transmitter->DebugInterface, sizeof (XENBUS_DEBUG_INTERFACE)); - RtlZeroMemory(&Transmitter->EvtchnInterface, - sizeof (XENBUS_EVTCHN_INTERFACE)); - Transmitter->DisableIpVersion4Gso = 0; Transmitter->DisableIpVersion6Gso = 0; Transmitter->AlwaysCopy = 0; @@ -5299,25 +5041,6 @@ TransmitterQueryRingSize( } VOID -TransmitterNotify( - IN PXENVIF_TRANSMITTER Transmitter, - IN ULONG Index - ) -{ - PXENVIF_FRONTEND Frontend; - PXENVIF_TRANSMITTER_RING Ring; - - Frontend = Transmitter->Frontend; - - ASSERT(!FrontendIsSplit(Frontend)); - - Ring = Transmitter->Ring[Index]; - - if (KeInsertQueueDpc(&Ring->Dpc, NULL, NULL)) - Ring->Dpcs++; -} - -VOID TransmitterQueryOffloadOptions( IN PXENVIF_TRANSMITTER Transmitter, OUT PXENVIF_VIF_OFFLOAD_OPTIONS Options diff --git a/src/xenvif/transmitter.h b/src/xenvif/transmitter.h index d44f77e..2446220 100644 --- a/src/xenvif/transmitter.h +++ b/src/xenvif/transmitter.h @@ -64,6 +64,12 @@ TransmitterEnable( IN PXENVIF_TRANSMITTER Transmitter ); +extern BOOLEAN +TransmitterPoll( + IN PXENVIF_TRANSMITTER Transmitter, + IN ULONG Index + ); + extern VOID TransmitterDisable( IN PXENVIF_TRANSMITTER Transmitter -- 2.5.3 _______________________________________________ win-pv-devel mailing list win-pv-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |