]> xenbits.xensource.com Git - pvdrivers/win/xenvif.git/commitdiff
Move the Receiver and Transmitter event and DPC processing...
authorPaul Durrant <paul.durrant@citrix.com>
Wed, 18 Oct 2017 14:02:52 +0000 (15:02 +0100)
committerPaul Durrant <paul.durrant@citrix.com>
Mon, 23 Oct 2017 15:30:33 +0000 (16:30 +0100)
...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@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..7b600228704dfac9c902a5445c5fed3de402be41 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);
+
+    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);
 }
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