]> xenbits.xensource.com Git - people/pauldu/xenvif.git/commitdiff
Stuff
authorPaul Durrant <paul.durrant@citrix.com>
Wed, 18 Oct 2017 14:02:52 +0000 (15:02 +0100)
committerPaul Durrant <paul.durrant@citrix.com>
Fri, 20 Oct 2017 17:01:46 +0000 (18:01 +0100)
Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
src/xenvif/frontend.c
src/xenvif/frontend.h
src/xenvif/poller.c
src/xenvif/poller.h
src/xenvif/receiver.c
src/xenvif/receiver.h
src/xenvif/transmitter.c
src/xenvif/transmitter.h

index f715c198fc9e4583183b3b6481aeabe35daf273a..994935760b3a8715b0f8afc9980685c9c220b00e 100644 (file)
@@ -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,
index 92008d00ab5af415b60e94bb7043f9d391626b1d..7f3b7c53ff3b09ecd3af2e1a71d2468cf59dac4b 100644 (file)
@@ -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,
index 4ac358eee11e6babf7fd0f7ff46d6d26bd3cf563..b57a6a4773c543f37e04e0b1855a13eebaf9675c 100644 (file)
@@ -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"
 
 #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);
+
+    Instance = Channel->Instance;
+
+    ASSERT(Channel != NULL);
+    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
+    )
+{
+    ULONG                       Type;
+
+    ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
+
+    KeAcquireSpinLockAtDpcLevel(&Instance->Lock);
+
+    if (!Instance->Enabled)
+        goto done;
+
+    for (Type = 0; Type < XENVIF_POLLER_CHANNEL_TYPE_COUNT; Type++)
+    {
+        PXENVIF_POLLER_CHANNEL 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 (;;) {
+        if (InterlockedBitTestAndReset(&Instance->Pending,
+                                       XENVIF_POLLER_EVENT_RECEIVE) != 0)
+            NeedReceiverPoll = TRUE;
+
+        if (InterlockedBitTestAndReset(&Instance->Pending,
+                                       XENVIF_POLLER_EVENT_TRANSMIT) != 0)
+            NeedTransmitterPoll = TRUE;
+
+        if (!NeedReceiverPoll && !NeedTransmitterPoll)
+            break;
+
+        if (NeedReceiverPoll)
+        {
+            BOOLEAN Retry = ReceiverPoll(FrontendGetReceiver(Frontend),
+                                         Instance->Index);
+
+            if (!Retry) {
+                NeedReceiverPoll = FALSE;
+                PollerInstanceUnmask(Instance);
+            }
+        }
+
+        if (NeedTransmitterPoll)
+        {
+            BOOLEAN Retry = TransmitterPoll(FrontendGetTransmitter(Frontend),
+                                            Instance->Index);
+
+            if (!Retry) {
+                NeedTransmitterPoll = FALSE;
+                PollerInstanceUnmask(Instance);
+            }
+        }
+
+        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;
+
+    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 +1043,8 @@ PollerInitialize(
     OUT PXENVIF_POLLER      *Poller
     )
 {
+    LONG                    MaxQueues;
+    LONG                    Index;
     NTSTATUS                status;
 
     *Poller = __PollerAllocate(sizeof (XENVIF_POLLER));
@@ -100,13 +1053,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 +1125,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 +1165,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 +1211,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 +1386,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 +1425,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);
 }
index 5ba0eaa2f7e4c84deadf41de04390fb2e10470f1..a2b32a1d5faa59ab9dfd467e9b921e9ef9d77b44 100644 (file)
 
 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
index d7f3870485238dec6b80262676912894dac53fdc..e48b6781669ade426235d1cfd2b7d4ce0f833995 100644 (file)
@@ -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;
@@ -1614,50 +1606,6 @@ __ReceiverRingIsStopped(
     return Ring->Stopped;
 }
 
-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,
@@ -1665,8 +1613,13 @@ __ReceiverRingReturnPacket(
     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,
index 7846f0bf9d0584242f94e8ddd4197af671b4d6a1..e1b7a883bd7201c4bec2c4a57176d5929125f3fa 100644 (file)
@@ -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
index 3ab3cbd92499e840bcb55e5ef7b6bcac6d515003..eed0a0ff169211e47268808026445a755c73c49f 100644 (file)
@@ -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;
@@ -5298,25 +5040,6 @@ TransmitterQueryRingSize(
     *Size = XENVIF_TRANSMITTER_RING_SIZE;
 }
 
-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,
index d44f77ea7151e6d63045e9afd492428d25db04e3..24462208821628259c72ff629f4bea7d3b76e842 100644 (file)
@@ -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