[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[win-pv-devel] [PATCH 4/7] Remove notifier object



Fold event channels into transmitter/receiver ring objects.
Receiver ring object takes over single event channel case and passes
notifications to transmitter object, tagged with ring index (so that
only the specified ring is executed).
Split notifications are handled independently by each ring object.

Signed-off-by: Owen Smith <owen.smith@xxxxxxxxxx>
---
 src/xenvif/frontend.c        |  75 ++---
 src/xenvif/frontend.h        |   7 -
 src/xenvif/notifier.c        | 684 -------------------------------------------
 src/xenvif/notifier.h        |  99 -------
 src/xenvif/receiver.c        | 376 +++++++++++++++++++++---
 src/xenvif/receiver.h        |  17 +-
 src/xenvif/transmitter.c     | 352 +++++++++++++++++++---
 src/xenvif/transmitter.h     |   5 +-
 vs2012/xenvif/xenvif.vcxproj |   1 -
 vs2013/xenvif/xenvif.vcxproj |   1 -
 10 files changed, 678 insertions(+), 939 deletions(-)
 delete mode 100644 src/xenvif/notifier.c
 delete mode 100644 src/xenvif/notifier.h

diff --git a/src/xenvif/frontend.c b/src/xenvif/frontend.c
index 305faaf..268bab9 100644
--- a/src/xenvif/frontend.c
+++ b/src/xenvif/frontend.c
@@ -44,7 +44,6 @@
 #include "frontend.h"
 #include "names.h"
 #include "granter.h"
-#include "notifier.h"
 #include "mac.h"
 #include "tcpip.h"
 #include "receiver.h"
@@ -66,7 +65,6 @@ struct _XENVIF_FRONTEND {
     USHORT                      BackendDomain;
 
     PXENVIF_GRANTER             Granter;
-    PXENVIF_NOTIFIER            Notifier;
     PXENVIF_MAC                 Mac;
     PXENVIF_RECEIVER            Receiver;
     PXENVIF_TRANSMITTER         Transmitter;
@@ -221,7 +219,6 @@ FrontendGet ## _Function(                               \
 }
 
 DEFINE_FRONTEND_GET_FUNCTION(Granter, PXENVIF_GRANTER)
-DEFINE_FRONTEND_GET_FUNCTION(Notifier, PXENVIF_NOTIFIER)
 DEFINE_FRONTEND_GET_FUNCTION(Mac, PXENVIF_MAC)
 DEFINE_FRONTEND_GET_FUNCTION(Transmitter, PXENVIF_TRANSMITTER)
 DEFINE_FRONTEND_GET_FUNCTION(Receiver, PXENVIF_RECEIVER)
@@ -1318,10 +1315,6 @@ __FrontendConnect(
     if (!NT_SUCCESS(status))
         goto fail6;
 
-    status = NotifierConnect(__FrontendGetNotifier(Frontend));
-    if (!NT_SUCCESS(status))
-        goto fail7;
-
     Attempt = 0;
     do {
         PXENBUS_STORE_TRANSACTION   Transaction;
@@ -1332,11 +1325,6 @@ __FrontendConnect(
         if (!NT_SUCCESS(status))
             break;
 
-        status = NotifierStoreWrite(__FrontendGetNotifier(Frontend),
-                                    Transaction);
-        if (!NT_SUCCESS(status))
-            goto abort;
-
         status = ReceiverStoreWrite(__FrontendGetReceiver(Frontend),
                                     Transaction);
         if (!NT_SUCCESS(status))
@@ -1365,7 +1353,7 @@ abort:
     } while (status == STATUS_RETRY);
 
     if (!NT_SUCCESS(status))
-        goto fail8;
+        goto fail7;
 
     status = XENBUS_STORE(Printf,
                           &Frontend->StoreInterface,
@@ -1375,25 +1363,22 @@ abort:
                           "%u",
                           XenbusStateConnected);
     if (!NT_SUCCESS(status))
-        goto fail9;
+        goto fail8;
 
     State = XenbusStateInitWait;
     status = __FrontendWaitForStateChange(Frontend, Path, &State);
     if (!NT_SUCCESS(status))
-        goto fail10;
+        goto fail9;
 
     status = STATUS_UNSUCCESSFUL;
     if (State != XenbusStateConnected)
-        goto fail11;
+        goto fail10;
 
     ThreadWake(Frontend->MibThread);
 
     Trace("<====\n");
     return STATUS_SUCCESS;
 
-fail11:
-    Error("fail11\n");
-
 fail10:
     Error("fail10\n");
 
@@ -1403,8 +1388,6 @@ fail9:
 fail8:
     Error("fail8\n");
 
-    NotifierDisconnect(__FrontendGetNotifier(Frontend));
-
 fail7:
     Error("fail7\n");
 
@@ -1452,7 +1435,6 @@ __FrontendDisconnect(
 {
     Trace("====>\n");
 
-    NotifierDisconnect(__FrontendGetNotifier(Frontend));
     TransmitterDisconnect(__FrontendGetTransmitter(Frontend));
     ReceiverDisconnect(__FrontendGetReceiver(Frontend));
     MacDisconnect(__FrontendGetMac(Frontend));
@@ -1495,18 +1477,9 @@ __FrontendEnable(
     if (!NT_SUCCESS(status))
         goto fail4;
 
-    status = NotifierEnable(__FrontendGetNotifier(Frontend));
-    if (!NT_SUCCESS(status))
-        goto fail5;
-
     Trace("<====\n");
     return STATUS_SUCCESS;
 
-fail5:
-    Error("fail5\n");
-
-    TransmitterDisable(__FrontendGetTransmitter(Frontend));
-
 fail4:
     Error("fail4\n");
 
@@ -1535,7 +1508,6 @@ __FrontendDisable(
 {
     Trace("====>\n");
 
-    NotifierDisable(__FrontendGetNotifier(Frontend));
     TransmitterDisable(__FrontendGetTransmitter(Frontend));
     ReceiverDisable(__FrontendGetReceiver(Frontend));
     MacDisable(__FrontendGetMac(Frontend));
@@ -1894,64 +1866,54 @@ FrontendInitialize(
     if (!NT_SUCCESS(status))
         goto fail6;
 
-    status = NotifierInitialize(*Frontend, &(*Frontend)->Notifier);
-    if (!NT_SUCCESS(status))
-        goto fail7;
-
     status = MacInitialize(*Frontend, &(*Frontend)->Mac);
     if (!NT_SUCCESS(status))
-        goto fail8;
+        goto fail7;
 
     status = ReceiverInitialize(*Frontend, 1, &(*Frontend)->Receiver);
     if (!NT_SUCCESS(status))
-        goto fail9;
+        goto fail8;
 
     status = TransmitterInitialize(*Frontend, 1, &(*Frontend)->Transmitter);
     if (!NT_SUCCESS(status))
-        goto fail10;
+        goto fail9;
 
     status = ThreadCreate(FrontendEject, *Frontend, &(*Frontend)->EjectThread);
     if (!NT_SUCCESS(status))
-        goto fail11;
+        goto fail10;
 
     status = ThreadCreate(FrontendMib, *Frontend, &(*Frontend)->MibThread);
     if (!NT_SUCCESS(status))
-        goto fail12;
+        goto fail11;
 
     Trace("<====\n");
 
     return STATUS_SUCCESS;
 
-fail12:
-    Error("fail12\n");
+fail11:
+    Error("fail11\n");
 
     ThreadAlert((*Frontend)->EjectThread);
     ThreadJoin((*Frontend)->EjectThread);
     (*Frontend)->EjectThread = NULL;
 
-fail11:
-    Error("fail11\n");
-
-    TransmitterTeardown(__FrontendGetTransmitter(*Frontend));
-    (*Frontend)->Transmitter = NULL;
-
 fail10:
     Error("fail10\n");
 
-    ReceiverTeardown(__FrontendGetReceiver(*Frontend));
-    (*Frontend)->Receiver = NULL;
+    TransmitterTeardown(__FrontendGetTransmitter(*Frontend));
+    (*Frontend)->Transmitter = NULL;
 
 fail9:
     Error("fail9\n");
 
-    MacTeardown(__FrontendGetMac(*Frontend));
-    (*Frontend)->Mac = NULL;
+    ReceiverTeardown(__FrontendGetReceiver(*Frontend));
+    (*Frontend)->Receiver = NULL;
 
 fail8:
     Error("fail8\n");
 
-    NotifierTeardown(__FrontendGetNotifier(*Frontend));
-    (*Frontend)->Notifier = NULL;
+    MacTeardown(__FrontendGetMac(*Frontend));
+    (*Frontend)->Mac = NULL;
 
 fail7:
     Error("fail7\n");
@@ -2043,9 +2005,6 @@ FrontendTeardown(
     MacTeardown(__FrontendGetMac(Frontend));
     Frontend->Mac = NULL;
 
-    NotifierTeardown(__FrontendGetNotifier(Frontend));
-    Frontend->Notifier = NULL;
-
     GranterTeardown(__FrontendGetGranter(Frontend));
     Frontend->Granter = NULL;
 
diff --git a/src/xenvif/frontend.h b/src/xenvif/frontend.h
index 60c085a..67696d6 100644
--- a/src/xenvif/frontend.h
+++ b/src/xenvif/frontend.h
@@ -119,13 +119,6 @@ FrontendGetGranter(
     IN  PXENVIF_FRONTEND    Frontend
     );
 
-#include "notifier.h"
-
-extern PXENVIF_NOTIFIER
-FrontendGetNotifier(
-    IN  PXENVIF_FRONTEND    Frontend
-    );
-
 #include "mac.h"
 
 extern PXENVIF_MAC
diff --git a/src/xenvif/notifier.c b/src/xenvif/notifier.c
deleted file mode 100644
index fc6725a..0000000
--- a/src/xenvif/notifier.c
+++ /dev/null
@@ -1,684 +0,0 @@
-/* Copyright (c) Citrix Systems Inc.
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, 
- * with or without modification, are permitted provided 
- * that the following conditions are met:
- * 
- * *   Redistributions of source code must retain the above 
- *     copyright notice, this list of conditions and the 
- *     following disclaimer.
- * *   Redistributions in binary form must reproduce the above 
- *     copyright notice, this list of conditions and the 
- *     following disclaimer in the documentation and/or other 
- *     materials provided with the distribution.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
- * SUCH DAMAGE.
- */
-
-#include <ntddk.h>
-#include <ntstrsafe.h>
-#include <stdlib.h>
-#include <util.h>
-
-#include "pdo.h"
-#include "frontend.h"
-#include "notifier.h"
-#include "receiver.h"
-#include "transmitter.h"
-#include "dbg_print.h"
-#include "assert.h"
-
-typedef enum _XENVIF_NOTIFIER_EVTCHN {
-    XENVIF_NOTIFIER_EVTCHN_COMBINED = 0,
-    XENVIF_NOTIFIER_EVTCHN_RX,
-    XENVIF_NOTIFIER_EVTCHN_TX,
-    XENVIF_NOTIFIER_EVTCHN_COUNT
-} XENVIF_NOTIFIER_EVTCHN, *PXENVIF_NOTIFIER_EVTCHN;
-
-struct _XENVIF_NOTIFIER {
-    PXENVIF_FRONTEND            Frontend;
-    XENBUS_EVTCHN_INTERFACE     EvtchnInterface;
-    PXENBUS_EVTCHN_CHANNEL      Channel[XENVIF_NOTIFIER_EVTCHN_COUNT];
-    KDPC                        Dpc[XENVIF_NOTIFIER_EVTCHN_COUNT];
-    ULONG                       Dpcs[XENVIF_NOTIFIER_EVTCHN_COUNT];
-    ULONG                       Events[XENVIF_NOTIFIER_EVTCHN_COUNT];
-    BOOLEAN                     Connected;
-    KSPIN_LOCK                  Lock;
-    BOOLEAN                     Split;
-    BOOLEAN                     Enabled;
-    XENBUS_STORE_INTERFACE      StoreInterface;
-    XENBUS_DEBUG_INTERFACE      DebugInterface;
-    PXENBUS_DEBUG_CALLBACK      DebugCallback;
-};
-
-#define XENVIF_NOTIFIER_TAG 'ITON'
-
-static FORCEINLINE PVOID
-__NotifierAllocate(
-    IN  ULONG   Length
-    )
-{
-    return __AllocateNonPagedPoolWithTag(Length, XENVIF_NOTIFIER_TAG);
-}
-
-static FORCEINLINE VOID
-__NotifierFree(
-    IN  PVOID   Buffer
-    )
-{
-    __FreePoolWithTag(Buffer, XENVIF_NOTIFIER_TAG);
-}
-
-static FORCEINLINE BOOLEAN
-__NotifierUnmask(
-    IN  PXENVIF_NOTIFIER        Notifier,
-    IN  XENVIF_NOTIFIER_EVTCHN  Index
-    )
-{
-    PXENVIF_FRONTEND            Frontend;
-    BOOLEAN                     Pending;
-
-    Frontend = Notifier->Frontend;
-
-    KeAcquireSpinLockAtDpcLevel(&Notifier->Lock);
-
-    Pending = (Notifier->Connected) ?
-              XENBUS_EVTCHN(Unmask,
-                            &Notifier->EvtchnInterface,
-                            Notifier->Channel[Index],
-                            FALSE) :
-              FALSE;
-
-    KeReleaseSpinLockFromDpcLevel(&Notifier->Lock);
-
-    return Pending;
-}
-
-__drv_functionClass(KDEFERRED_ROUTINE)
-__drv_maxIRQL(DISPATCH_LEVEL)
-__drv_minIRQL(DISPATCH_LEVEL)
-__drv_requiresIRQL(DISPATCH_LEVEL)
-__drv_sameIRQL
-static VOID
-NotifierDpc(
-    IN  PKDPC               Dpc,
-    IN  PVOID               Context,
-    IN  PVOID               Argument1,
-    IN  PVOID               Argument2
-    )
-{
-    PXENVIF_NOTIFIER        Notifier = Context;
-    XENVIF_NOTIFIER_EVTCHN  Index = (ULONG_PTR)Argument1;
-    PXENVIF_FRONTEND        Frontend;
-    BOOLEAN                 Pending;
-
-    UNREFERENCED_PARAMETER(Dpc);
-    UNREFERENCED_PARAMETER(Argument2);
-
-    ASSERT(Notifier != NULL);
-
-    Frontend = Notifier->Frontend;
-
-    do {
-        if (Notifier->Enabled) {
-            switch (Index) {
-            case XENVIF_NOTIFIER_EVTCHN_TX:
-                TransmitterNotify(FrontendGetTransmitter(Frontend));
-                break;
-
-            case XENVIF_NOTIFIER_EVTCHN_RX:
-                ReceiverNotify(FrontendGetReceiver(Frontend));
-                break;
-
-            case XENVIF_NOTIFIER_EVTCHN_COMBINED:
-                TransmitterNotify(FrontendGetTransmitter(Frontend));
-                ReceiverNotify(FrontendGetReceiver(Frontend));
-                break;
-
-            default:
-                ASSERT(FALSE);
-                break;
-            }
-        }
-
-        Pending = __NotifierUnmask(Notifier, Index);
-    } while (Pending);
-}
-
-static FORCEINLINE BOOLEAN
-__NotifierEvtchnCallback(
-    IN  PXENVIF_NOTIFIER    Notifier,
-    IN  XENVIF_NOTIFIER_EVTCHN     Index
-    )
-{
-    Notifier->Events[Index]++;
-
-    if (KeInsertQueueDpc(&Notifier->Dpc[Index],
-                         (PVOID)(ULONG_PTR)Index,
-                         NULL))
-        Notifier->Dpcs[Index]++;
-
-    return TRUE;
-}
-
-#define DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(_Type)                   \
-                                                                        \
-KSERVICE_ROUTINE    Notifier ## _Type ## EvtchnCallback;                \
-                                                                        \
-BOOLEAN                                                                 \
-Notifier ## _Type ## EvtchnCallback(                                    \
-    IN  PKINTERRUPT         InterruptObject,                            \
-    IN  PVOID               Argument                                    \
-    )                                                                   \
-{                                                                       \
-    PXENVIF_NOTIFIER        Notifier = Argument;                        \
-                                                                        \
-    UNREFERENCED_PARAMETER(InterruptObject);                            \
-                                                                        \
-    ASSERT(Notifier != NULL);                                           \
-    return __NotifierEvtchnCallback(Notifier,                           \
-                                    XENVIF_NOTIFIER_EVTCHN_ ## _Type);  \
-}
-
-DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(COMBINED)
-DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(RX)
-DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(TX)
-
-#undef DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK
-
-#define DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(_Type)   \
-    Notifier ## _Type ## EvtchnCallback,
-
-PKSERVICE_ROUTINE   NotifierEvtchnCallback[] = {
-    DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(COMBINED)
-    DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(RX)
-    DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(TX)
-};
-
-#undef DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK
-
-C_ASSERT(ARRAYSIZE(NotifierEvtchnCallback) == XENVIF_NOTIFIER_EVTCHN_COUNT);
-
-static VOID
-NotifierDebugCallback(
-    IN  PVOID           Argument,
-    IN  BOOLEAN         Crashing
-    )
-{
-    PXENVIF_NOTIFIER    Notifier = Argument;
-    PXENVIF_FRONTEND    Frontend;
-    ULONG               Index;
-
-    UNREFERENCED_PARAMETER(Crashing);
-
-    Frontend = Notifier->Frontend;
-
-    for (Index = 0; Index < XENVIF_NOTIFIER_EVTCHN_COUNT; Index++)
-        XENBUS_DEBUG(Printf,
-                     &Notifier->DebugInterface,
-                     "[%s]: Events = %lu Dpcs = %lu\n",
-                     ((Index == XENVIF_NOTIFIER_EVTCHN_COMBINED) ? "COMBINED" :
-                      ((Index == XENVIF_NOTIFIER_EVTCHN_RX) ? "RX" :
-                       ((Index == XENVIF_NOTIFIER_EVTCHN_TX) ? "TX" :
-                        "UNKNOWN"))),
-                     Notifier->Events[Index],
-                     Notifier->Dpcs[Index]);
-}
-
-NTSTATUS
-NotifierInitialize(
-    IN  PXENVIF_FRONTEND    Frontend,
-    OUT PXENVIF_NOTIFIER    *Notifier
-    )
-{
-    ULONG                   Index;
-    NTSTATUS                status;
-
-    *Notifier = __NotifierAllocate(sizeof (XENVIF_NOTIFIER));
-
-    status = STATUS_NO_MEMORY;
-    if (*Notifier == NULL)
-        goto fail1;
-
-    FdoGetEvtchnInterface(PdoGetFdo(FrontendGetPdo(Frontend)),
-                          &(*Notifier)->EvtchnInterface);
-
-    FdoGetDebugInterface(PdoGetFdo(FrontendGetPdo(Frontend)),
-                         &(*Notifier)->DebugInterface);
-
-    FdoGetStoreInterface(PdoGetFdo(FrontendGetPdo(Frontend)),
-                         &(*Notifier)->StoreInterface);
-
-    (*Notifier)->Frontend = Frontend;
-
-    KeInitializeSpinLock(&(*Notifier)->Lock);
-    for (Index = 0; Index < XENVIF_NOTIFIER_EVTCHN_COUNT; Index++)
-        KeInitializeDpc(&(*Notifier)->Dpc[Index],
-                        NotifierDpc,
-                        *Notifier);
-
-    return STATUS_SUCCESS;
-
-fail1:
-    Error("fail1 (%08x)\n", status);
-
-    return status;
-}
-
-NTSTATUS
-NotifierConnect(
-    IN  PXENVIF_NOTIFIER    Notifier
-    )
-{
-    PXENVIF_FRONTEND        Frontend;
-    LONG                    Index;
-    PCHAR                   Buffer;
-    NTSTATUS                status;
-
-    Frontend = Notifier->Frontend;
-
-    ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
-    KeAcquireSpinLockAtDpcLevel(&Notifier->Lock);
-
-    ASSERT(!Notifier->Connected);
-
-    status = XENBUS_EVTCHN(Acquire, &Notifier->EvtchnInterface);
-    if (!NT_SUCCESS(status))
-        goto fail1;
-
-    status = XENBUS_DEBUG(Acquire, &Notifier->DebugInterface);
-    if (!NT_SUCCESS(status))
-        goto fail2;
-
-    status = XENBUS_STORE(Acquire, &Notifier->StoreInterface);
-    if (!NT_SUCCESS(status))
-        goto fail3;
-
-    for (Index = 0; Index < XENVIF_NOTIFIER_EVTCHN_COUNT; Index++) {
-        PKSERVICE_ROUTINE   Callback = NotifierEvtchnCallback[Index];
-        BOOLEAN             Pending;
-
-        Notifier->Channel[Index] = XENBUS_EVTCHN(Open,
-                                                &Notifier->EvtchnInterface,
-                                                XENBUS_EVTCHN_TYPE_UNBOUND,
-                                                Callback,
-                                                Notifier,
-                                                
FrontendGetBackendDomain(Frontend),
-                                                TRUE);
-
-        status = STATUS_UNSUCCESSFUL;
-        if (Notifier->Channel[Index] == NULL)
-            goto fail4;
-
-        Pending = XENBUS_EVTCHN(Unmask,
-                                &Notifier->EvtchnInterface,
-                                Notifier->Channel[Index],
-                                FALSE);
-        if (Pending)
-            XENBUS_EVTCHN(Trigger,
-                          &Notifier->EvtchnInterface,
-                          Notifier->Channel[Index]);
-    }
-
-    status = XENBUS_DEBUG(Register,
-                          &Notifier->DebugInterface,
-                          __MODULE__ "|NOTIFIER",
-                          NotifierDebugCallback,
-                          Notifier,
-                          &Notifier->DebugCallback);
-    if (!NT_SUCCESS(status))
-        goto fail5;
-
-    status = XENBUS_STORE(Read,
-                          &Notifier->StoreInterface,
-                          NULL,
-                          FrontendGetBackendPath(Frontend),
-                          "feature-split-event-channels",
-                          &Buffer);
-    if (!NT_SUCCESS(status)) {
-        Notifier->Split = FALSE;
-    } else {
-        Notifier->Split = (BOOLEAN)strtol(Buffer, NULL, 2);
-
-        XENBUS_STORE(Free,
-                     &Notifier->StoreInterface,
-                     Buffer);
-    }
-
-    Notifier->Connected = TRUE;
-    KeReleaseSpinLockFromDpcLevel(&Notifier->Lock);
-
-    return STATUS_SUCCESS;
-
-fail5:
-    Error("fail5\n");
-
-    Index = XENVIF_NOTIFIER_EVTCHN_COUNT;
-
-fail4:
-    Error("fail4\n");
-
-    while (--Index >= 0) {
-        XENBUS_EVTCHN(Close,
-                      &Notifier->EvtchnInterface,
-                      Notifier->Channel[Index]);
-        Notifier->Channel[Index] = NULL;
-
-        Notifier->Events[Index] = 0;
-    }
-
-    XENBUS_STORE(Release, &Notifier->StoreInterface);
-
-fail3:
-    Error("fail3\n");
-
-    XENBUS_DEBUG(Release, &Notifier->DebugInterface);
-
-fail2:
-    Error("fail2\n");
-
-    XENBUS_EVTCHN(Release, &Notifier->EvtchnInterface);
-
-fail1:
-    Error("fail1 (%08x)\n", status);
-
-    KeReleaseSpinLockFromDpcLevel(&Notifier->Lock);
-
-    return status;
-}
-
-NTSTATUS
-NotifierStoreWrite(
-    IN  PXENVIF_NOTIFIER            Notifier,
-    IN  PXENBUS_STORE_TRANSACTION   Transaction
-    )
-{
-    PXENVIF_FRONTEND                Frontend = Notifier->Frontend;
-    ULONG                           Index;
-    NTSTATUS                        status;
-
-    for (Index = 0; Index < XENVIF_NOTIFIER_EVTCHN_COUNT; Index++) {
-        PCHAR   Node;
-        ULONG   Port;
-
-        switch (Index) {
-        case XENVIF_NOTIFIER_EVTCHN_COMBINED:
-            if (Notifier->Split)
-                continue;
-
-            Node = "event-channel";
-            break;
-
-        case XENVIF_NOTIFIER_EVTCHN_RX:
-            if (!Notifier->Split)
-                continue;
-
-            Node = "event-channel-rx";
-            break;
-
-        case XENVIF_NOTIFIER_EVTCHN_TX:
-            if (!Notifier->Split)
-                continue;
-
-            Node = "event-channel-tx";
-            break;
-
-        default:
-            ASSERT(FALSE);
-
-            Node = "";
-            break;
-        }
-
-        Port = XENBUS_EVTCHN(GetPort,
-                             &Notifier->EvtchnInterface,
-                             Notifier->Channel[Index]);
-
-        status = XENBUS_STORE(Printf,
-                              &Notifier->StoreInterface,
-                              Transaction,
-                              FrontendGetPath(Frontend),
-                              Node,
-                              "%u",
-                              Port);
-
-        if (!NT_SUCCESS(status))
-            goto fail1;
-    }
-
-    return STATUS_SUCCESS;
-
-fail1:
-    Error("fail1 (%08x)\n", status);
-
-    return status;
-}
-
-NTSTATUS
-NotifierEnable(
-    IN  PXENVIF_NOTIFIER    Notifier
-    )
-{   
-    ULONG                   Index;
-
-    ASSERT(!Notifier->Enabled);
-    Notifier->Enabled = TRUE;
-
-    for (Index = 0; Index < XENVIF_NOTIFIER_EVTCHN_COUNT; Index++) {
-        switch (Index) {
-        case XENVIF_NOTIFIER_EVTCHN_COMBINED:
-            if (Notifier->Split)
-                continue;
-
-            break;
-
-        case XENVIF_NOTIFIER_EVTCHN_RX:
-            if (!Notifier->Split)
-                continue;
-
-            break;
-
-        case XENVIF_NOTIFIER_EVTCHN_TX:
-            if (!Notifier->Split)
-                continue;
-
-            break;
-
-        default:
-            ASSERT(FALSE);
-
-            break;
-        }
-
-        if (KeInsertQueueDpc(&Notifier->Dpc[Index],
-                             (PVOID)(ULONG_PTR)Index,
-                             NULL))
-            Notifier->Dpcs[Index]++;
-    }
-
-    return STATUS_SUCCESS;
-}
-
-VOID
-NotifierDisable(
-    IN  PXENVIF_NOTIFIER    Notifier
-    )
-{
-    ASSERT(Notifier->Enabled);
-    Notifier->Enabled = FALSE;
-}
-
-VOID
-NotifierDisconnect(
-    IN  PXENVIF_NOTIFIER    Notifier
-    )
-{
-    PXENVIF_FRONTEND        Frontend;
-    LONG                    Index;
-
-    Frontend = Notifier->Frontend;
-
-    KeAcquireSpinLockAtDpcLevel(&Notifier->Lock);
-
-    ASSERT(Notifier->Connected);
-    Notifier->Connected = FALSE;
-
-    Notifier->Split = FALSE;
-
-    XENBUS_DEBUG(Deregister,
-                 &Notifier->DebugInterface,
-                 Notifier->DebugCallback);
-    Notifier->DebugCallback = NULL;
-
-    Index = XENVIF_NOTIFIER_EVTCHN_COUNT;
-    while (--Index >= 0) {
-        XENBUS_EVTCHN(Close,
-                      &Notifier->EvtchnInterface,
-                      Notifier->Channel[Index]);
-        Notifier->Channel[Index] = NULL;
-
-        Notifier->Events[Index] = 0;
-    }
-
-    XENBUS_STORE(Release, &Notifier->StoreInterface);
-
-    XENBUS_DEBUG(Release, &Notifier->DebugInterface);
-
-    XENBUS_EVTCHN(Release, &Notifier->EvtchnInterface);
-
-    KeReleaseSpinLockFromDpcLevel(&Notifier->Lock);
-}
-
-VOID
-NotifierTeardown(
-    IN  PXENVIF_NOTIFIER    Notifier
-    )
-{
-    LONG                    Index;
-
-    ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
-    KeFlushQueuedDpcs();
-
-    Index = XENVIF_NOTIFIER_EVTCHN_COUNT;
-    while (--Index >= 0) {
-        Notifier->Dpcs[Index] = 0;
-        RtlZeroMemory(&Notifier->Dpc[Index], sizeof (KDPC));
-    }
-
-    Notifier->Frontend = NULL;
-
-    RtlZeroMemory(&Notifier->StoreInterface,
-                  sizeof (XENBUS_STORE_INTERFACE));
-
-    RtlZeroMemory(&Notifier->DebugInterface,
-                  sizeof (XENBUS_DEBUG_INTERFACE));
-
-    RtlZeroMemory(&Notifier->EvtchnInterface,
-                  sizeof (XENBUS_EVTCHN_INTERFACE));
-
-    RtlZeroMemory(&Notifier->Lock, sizeof (KSPIN_LOCK));
-
-    ASSERT(IsZeroMemory(Notifier, sizeof (XENVIF_NOTIFIER)));
-
-    __NotifierFree(Notifier);
-}
-
-static FORCEINLINE VOID
-__NotifierSend(
-    IN  PXENVIF_NOTIFIER    Notifier,
-    IN  ULONG               Index
-    )
-{
-    PXENVIF_FRONTEND        Frontend;
-    KIRQL                   Irql;
-
-    Frontend = Notifier->Frontend;
-
-    KeAcquireSpinLock(&Notifier->Lock, &Irql);
-
-    if (Notifier->Connected)
-        (VOID) XENBUS_EVTCHN(Send,
-                             &Notifier->EvtchnInterface,
-                             Notifier->Channel[Index]);
-
-    KeReleaseSpinLock(&Notifier->Lock, Irql);
-}
-
-VOID
-NotifierSendTx(
-    IN  PXENVIF_NOTIFIER    Notifier
-    )
-{
-    if (Notifier->Split)
-        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_TX);
-    else
-        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED);
-}
-
-VOID
-NotifierSendRx(
-    IN  PXENVIF_NOTIFIER    Notifier
-    )
-{
-    if (Notifier->Split)
-        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_RX);
-    else
-        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED);
-}
-
-static FORCEINLINE VOID
-__NotifierTrigger(
-    IN  PXENVIF_NOTIFIER    Notifier,
-    IN  ULONG               Index
-    )
-{
-    PXENVIF_FRONTEND        Frontend;
-    KIRQL                   Irql;
-
-    Frontend = Notifier->Frontend;
-
-    KeAcquireSpinLock(&Notifier->Lock, &Irql);
-
-    if (Notifier->Connected)
-        (VOID) XENBUS_EVTCHN(Trigger,
-                             &Notifier->EvtchnInterface,
-                             Notifier->Channel[Index]);
-
-    KeReleaseSpinLock(&Notifier->Lock, Irql);
-}
-
-VOID
-NotifierTriggerTx(
-    IN  PXENVIF_NOTIFIER    Notifier
-    )
-{
-    if (Notifier->Split)
-        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_TX);
-    else
-        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED);
-}
-
-VOID
-NotifierTriggerRx(
-    IN  PXENVIF_NOTIFIER    Notifier
-    )
-{
-    if (Notifier->Split)
-        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_RX);
-    else
-        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED);
-}
diff --git a/src/xenvif/notifier.h b/src/xenvif/notifier.h
deleted file mode 100644
index 2f06a6f..0000000
--- a/src/xenvif/notifier.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/* Copyright (c) Citrix Systems Inc.
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, 
- * with or without modification, are permitted provided 
- * that the following conditions are met:
- * 
- * *   Redistributions of source code must retain the above 
- *     copyright notice, this list of conditions and the 
- *     following disclaimer.
- * *   Redistributions in binary form must reproduce the above 
- *     copyright notice, this list of conditions and the 
- *     following disclaimer in the documentation and/or other 
- *     materials provided with the distribution.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
- * SUCH DAMAGE.
- */
-
-#ifndef _XENVIF_NOTIFIER_H
-#define _XENVIF_NOTIFIER_H
-
-#include <ntddk.h>
-#include <store_interface.h>
-
-#include "frontend.h"
-
-typedef struct _XENVIF_NOTIFIER XENVIF_NOTIFIER, *PXENVIF_NOTIFIER;
-
-extern NTSTATUS
-NotifierInitialize(
-    IN  PXENVIF_FRONTEND    Frontend,
-    OUT PXENVIF_NOTIFIER    *Notifier
-    );
-
-extern NTSTATUS
-NotifierConnect(
-    IN  PXENVIF_NOTIFIER    Notifier
-    );
-
-extern NTSTATUS
-NotifierStoreWrite(
-    IN  PXENVIF_NOTIFIER            Notifier,
-    IN  PXENBUS_STORE_TRANSACTION   Transaction
-    );
-
-extern NTSTATUS
-NotifierEnable(
-    IN  PXENVIF_NOTIFIER    Notifier
-    );
-
-extern VOID
-NotifierDisable(
-    IN  PXENVIF_NOTIFIER    Notifier
-    );
-
-extern VOID
-NotifierDisconnect(
-    IN  PXENVIF_NOTIFIER    Notifier
-    );
-
-extern VOID
-NotifierTeardown(
-    IN  PXENVIF_NOTIFIER    Notifier
-    );
-
-extern VOID
-NotifierSendTx(
-    IN  PXENVIF_NOTIFIER    Notifier
-    );
-
-extern VOID
-NotifierSendRx(
-    IN  PXENVIF_NOTIFIER    Notifier
-    );
-
-extern VOID
-NotifierTriggerTx(
-    IN  PXENVIF_NOTIFIER    Notifier
-    );
-
-extern VOID
-NotifierTriggerRx(
-    IN  PXENVIF_NOTIFIER    Notifier
-    );
-
-#endif  // _XENVIF_NOTIFIER_H
diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c
index 1b81b73..a11d91e 100644
--- a/src/xenvif/receiver.c
+++ b/src/xenvif/receiver.c
@@ -37,6 +37,7 @@
 #include <debug_interface.h>
 #include <store_interface.h>
 #include <cache_interface.h>
+#include <evtchn_interface.h>
 
 // This should be in public/io/netif.h
 #define _NETRXF_gso_prefix     (4)
@@ -50,8 +51,8 @@
 #include "checksum.h"
 #include "parse.h"
 #include "granter.h"
-#include "notifier.h"
 #include "mac.h"
+#include "transmitter.h"
 #include "vif.h"
 #include "receiver.h"
 #include "thread.h"
@@ -82,10 +83,16 @@ typedef struct _XENVIF_RECEIVER_RING {
     netif_rx_front_ring_t       Front;
     netif_rx_sring_t            *Shared;
     XENVIF_GRANTER_HANDLE       Handle;
+    PXENBUS_EVTCHN_CHANNEL      Channel;
+    KDPC                        Dpc;
+    ULONG                       Dpcs;
+    ULONG                       Events;
+    KSPIN_LOCK                  EvtchnLock;
     PXENVIF_RECEIVER_FRAGMENT   Pending[XENVIF_RECEIVER_MAXIMUM_FRAGMENT_ID + 
1];
     ULONG                       RequestsPosted;
     ULONG                       RequestsPushed;
     ULONG                       ResponsesProcessed;
+    BOOLEAN                     Connected;
     BOOLEAN                     Enabled;
     BOOLEAN                     Stopped;
     XENVIF_VIF_OFFLOAD_OPTIONS  OffloadOptions;
@@ -97,7 +104,9 @@ typedef struct _XENVIF_RECEIVER_RING {
 struct _XENVIF_RECEIVER {
     PXENVIF_FRONTEND        Frontend;
     XENBUS_CACHE_INTERFACE  CacheInterface;
+    XENBUS_EVTCHN_INTERFACE EvtchnInterface;
     PXENVIF_RECEIVER_RING   Rings[MAXIMUM_PROCESSORS];
+    BOOLEAN                 Split;
     LONG                    Loaned;
     LONG                    Returned;
     KEVENT                  Event;
@@ -1352,6 +1361,46 @@ __ReceiverRingIsStopped(
 }
 
 static FORCEINLINE VOID
+__ReceiverRingTrigger(
+    IN  PXENVIF_RECEIVER_RING   Ring
+    )
+{
+    KIRQL                       Irql;
+    PXENVIF_RECEIVER            Receiver;
+
+    Receiver = Ring->Receiver;
+
+    KeAcquireSpinLock(&Ring->EvtchnLock, &Irql);
+
+    if (Ring->Connected)
+        (VOID) XENBUS_EVTCHN(Trigger,
+                             &Receiver->EvtchnInterface,
+                             Ring->Channel);
+
+    KeReleaseSpinLock(&Ring->EvtchnLock, Irql);
+}
+
+static FORCEINLINE VOID
+__ReceiverRingSend(
+    IN  PXENVIF_RECEIVER_RING   Ring
+    )
+{
+    KIRQL                       Irql;
+    PXENVIF_RECEIVER            Receiver;
+
+    Receiver = Ring->Receiver;
+
+    KeAcquireSpinLock(&Ring->EvtchnLock, &Irql);
+
+    if (Ring->Connected)
+        (VOID) XENBUS_EVTCHN(Send,
+                             &Receiver->EvtchnInterface,
+                             Ring->Channel);
+
+    KeReleaseSpinLock(&Ring->EvtchnLock, Irql);
+}
+
+static FORCEINLINE VOID
 __ReceiverRingReturnPacket(
     IN  PXENVIF_RECEIVER_RING   Ring,
     IN  PXENVIF_RECEIVER_PACKET Packet,
@@ -1382,15 +1431,8 @@ __ReceiverRingReturnPacket(
             __ReceiverRingAcquireLock(Ring);
 
         if (__ReceiverRingIsStopped(Ring)) {
-            PXENVIF_RECEIVER    Receiver;
-            PXENVIF_FRONTEND    Frontend;
-
             __ReceiverRingStart(Ring);
-
-            Receiver = Ring->Receiver;
-            Frontend = Receiver->Frontend;
-
-            NotifierTriggerRx(FrontendGetNotifier(Frontend));
+            __ReceiverRingTrigger(Ring);
         }
 
         if (!Locked)
@@ -1464,13 +1506,7 @@ __ReceiverRingPushRequests(
 #pragma warning (pop)
 
     if (Notify) {
-        PXENVIF_RECEIVER    Receiver;
-        PXENVIF_FRONTEND    Frontend;
-
-        Receiver = Ring->Receiver;
-        Frontend = Receiver->Frontend;
-
-        NotifierSendRx(FrontendGetNotifier(Frontend));
+        __ReceiverRingSend(Ring);
     }
 
     Ring->RequestsPushed = Ring->RequestsPosted;
@@ -1599,8 +1635,9 @@ ReceiverRingDebugCallback(
 
     XENBUS_DEBUG(Printf,
                  &Receiver->DebugInterface,
-                 "0x%p [%s][%s]\n",
+                 "0x%p [%u] [%s][%s]\n",
                  Ring,
+                 Ring->Index,
                  (Ring->Enabled) ? "ENABLED" : "DISABLED",
                  (__ReceiverRingIsStopped(Ring)) ? "STOPPED" : "RUNNING");
 
@@ -1628,6 +1665,14 @@ ReceiverRingDebugCallback(
                  Ring->RequestsPosted,
                  Ring->RequestsPushed,
                  Ring->ResponsesProcessed);
+
+    // Dump event channel
+    XENBUS_DEBUG(Printf,
+                 &Receiver->DebugInterface,
+                 "[%s]: Events = %lu Dpcs = %lu\n",
+                 Receiver->Split ? "RX" : "COMBINED",
+                 Ring->Events,
+                 Ring->Dpcs);
 }
 
 static DECLSPEC_NOINLINE VOID
@@ -1801,6 +1846,104 @@ ReceiverRingPoll(
 #undef  XENVIF_RECEIVER_BATCH
 }
 
+static FORCEINLINE VOID
+__ReceiverRingNotify(
+    IN  PXENVIF_RECEIVER_RING   Ring
+    )
+{
+    __ReceiverRingAcquireLock(Ring);
+    ReceiverRingPoll(Ring);
+    __ReceiverRingReleaseLock(Ring);
+}
+
+static FORCEINLINE BOOLEAN
+__ReceiverRingUnmask(
+    IN  PXENVIF_RECEIVER_RING   Ring
+    )
+{
+    PXENVIF_RECEIVER            Receiver;
+    BOOLEAN                     Pending;
+
+    Receiver = Ring->Receiver;
+
+    KeAcquireSpinLockAtDpcLevel(&Ring->EvtchnLock);
+
+    Pending = (Ring->Connected) ?
+              XENBUS_EVTCHN(Unmask,
+                            &Receiver->EvtchnInterface,
+                            Ring->Channel,
+                            FALSE) :
+              FALSE;
+
+    KeReleaseSpinLockFromDpcLevel(&Ring->EvtchnLock);
+
+    return Pending;
+}
+
+__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;
+    PXENVIF_RECEIVER        Receiver;
+    PXENVIF_FRONTEND        Frontend;
+    BOOLEAN                 Pending;
+
+    UNREFERENCED_PARAMETER(Dpc);
+    UNREFERENCED_PARAMETER(Argument1);
+    UNREFERENCED_PARAMETER(Argument2);
+
+    ASSERT(Ring != NULL);
+
+    Receiver = Ring->Receiver;
+    Frontend = Receiver->Frontend;
+
+    do {
+        if (Ring->Enabled) {
+            if (Receiver->Split) {
+                __ReceiverRingNotify(Ring);
+            } else {
+                TransmitterRingNotify(FrontendGetTransmitter(Frontend),
+                                      Ring->Index);
+                __ReceiverRingNotify(Ring);
+            }
+        }
+
+        Pending = __ReceiverRingUnmask(Ring);
+    } while (Pending);
+}
+
+KSERVICE_ROUTINE    ReceiverRingEvtchnCallback;
+
+BOOLEAN
+ReceiverRingEvtchnCallback(
+    IN  PKINTERRUPT             InterruptObject,
+    IN  PVOID                   Argument
+    )
+{
+    PXENVIF_RECEIVER_RING       Ring = Argument;
+
+    UNREFERENCED_PARAMETER(InterruptObject);
+
+    ASSERT(Ring != NULL);
+
+    Ring->Events++;
+
+    if (KeInsertQueueDpc(&Ring->Dpc, NULL, NULL))
+        Ring->Dpcs++;
+
+    return TRUE;
+}
+
 #define TIME_US(_us)        ((_us) * 10)
 #define TIME_MS(_ms)        (TIME_US((_ms) * 1000))
 #define TIME_S(_s)          (TIME_MS((_s) * 1000))
@@ -1851,10 +1994,8 @@ 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,
@@ -1862,7 +2003,7 @@ ReceiverRingWatchdog(
 
                 // Try to move things along
                 ReceiverRingPoll(Ring);
-                NotifierSendRx(FrontendGetNotifier(Frontend));
+                __ReceiverRingSend(Ring);
             }
 
             KeMemoryBarrier();
@@ -1905,6 +2046,9 @@ __ReceiverRingInitialize(
     (*Ring)->Index = Index;
 
     InitializeListHead(&(*Ring)->PacketList);
+
+    KeInitializeSpinLock(&(*Ring)->EvtchnLock);
+    KeInitializeDpc(&(*Ring)->Dpc, ReceiverRingDpc, *Ring);
 
     status = RtlStringCbPrintfA(Name,
                                 sizeof (Name),
@@ -1989,6 +2133,9 @@ fail3:
 fail2:
     Error("fail2\n");
 
+    RtlZeroMemory(&(*Ring)->EvtchnLock, sizeof (KSPIN_LOCK));
+    RtlZeroMemory(&(*Ring)->Dpc, sizeof (KDPC));
+
     RtlZeroMemory(&(*Ring)->PacketList, sizeof (LIST_ENTRY));
 
     (*Ring)->Index = 0;
@@ -2014,6 +2161,7 @@ __ReceiverRingConnect(
     PXENVIF_RECEIVER            Receiver;
     PXENVIF_FRONTEND            Frontend;
     PFN_NUMBER                  Pfn;
+    BOOLEAN                     Pending;
     CHAR                        Name[MAXNAMELEN];
     NTSTATUS                    status;
 
@@ -2049,6 +2197,38 @@ __ReceiverRingConnect(
     if (!NT_SUCCESS(status))
         goto fail3;
 
+    ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
+    KeAcquireSpinLockAtDpcLevel(&Ring->EvtchnLock);
+
+    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) {
+        KeReleaseSpinLockFromDpcLevel(&Ring->EvtchnLock);
+        goto fail4;
+    }
+
+    Pending = XENBUS_EVTCHN(Unmask,
+                            &Receiver->EvtchnInterface,
+                            Ring->Channel,
+                            FALSE);
+
+    if (Pending)
+        XENBUS_EVTCHN(Trigger,
+                     &Receiver->EvtchnInterface,
+                     Ring->Channel);
+
+    Ring->Connected = TRUE;
+    KeReleaseSpinLockFromDpcLevel(&Ring->EvtchnLock);
+
     status = XENBUS_DEBUG(Register,
                           &Receiver->DebugInterface,
                           Name,
@@ -2056,10 +2236,22 @@ __ReceiverRingConnect(
                           Ring,
                           &Ring->DebugCallback);
     if (!NT_SUCCESS(status))
-        goto fail4;
+        goto fail5;
 
     return STATUS_SUCCESS;
 
+fail5:
+    Error("fail5\n");
+
+    Ring->Connected = FALSE;
+
+    XENBUS_EVTCHN(Close,
+                  &Receiver->EvtchnInterface,
+                  Ring->Channel);
+    Ring->Channel = NULL;
+
+    Ring->Events = 0;
+
 fail4:
     Error("fail4\n");
 
@@ -2094,6 +2286,7 @@ __ReceiverRingStoreWrite(
 {
     PXENVIF_RECEIVER                Receiver;
     PXENVIF_FRONTEND                Frontend;
+    ULONG                           Port;
     NTSTATUS                        status;
 
     Receiver = Ring->Receiver;
@@ -2111,8 +2304,25 @@ __ReceiverRingStoreWrite(
     if (!NT_SUCCESS(status))
         goto fail1;
 
+    Port = XENBUS_EVTCHN(GetPort,
+                         &Receiver->EvtchnInterface,
+                         Ring->Channel);
+
+    status = XENBUS_STORE(Printf,
+                          &Receiver->StoreInterface,
+                          Transaction,
+                          FrontendGetPath(Frontend),
+                          Receiver->Split ? "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);
 
@@ -2143,6 +2353,9 @@ __ReceiverRingEnable(
 
     Ring->Enabled = TRUE;
 
+    if (KeInsertQueueDpc(&Ring->Dpc, NULL, NULL))
+        Ring->Dpcs++;
+
     __ReceiverRingReleaseLock(Ring);
 
     return STATUS_SUCCESS;
@@ -2183,6 +2396,20 @@ __ReceiverRingDisconnect(
 
     __ReceiverRingEmpty(Ring);
 
+    KeAcquireSpinLockAtDpcLevel(&Ring->EvtchnLock);
+
+    ASSERT(Ring->Connected);
+    Ring->Connected = FALSE;
+
+    XENBUS_EVTCHN(Close,
+                  &Receiver->EvtchnInterface,
+                  Ring->Channel);
+    Ring->Channel = NULL;
+
+    Ring->Events = 0;
+
+    KeReleaseSpinLockFromDpcLevel(&Ring->EvtchnLock);
+
     ASSERT3U(Ring->ResponsesProcessed, ==, Ring->RequestsPushed);
     ASSERT3U(Ring->RequestsPushed, ==, Ring->RequestsPosted);
 
@@ -2216,6 +2443,10 @@ __ReceiverRingTeardown(
 
     Receiver = Ring->Receiver;
 
+    Ring->Dpcs = 0;
+    RtlZeroMemory(&Ring->Dpc, sizeof (KDPC));
+    RtlZeroMemory(&Ring->EvtchnLock, sizeof (KSPIN_LOCK));
+
     Ring->OffloadOptions.Value = 0;
 
     ThreadAlert(Ring->WatchdogThread);
@@ -2245,16 +2476,6 @@ __ReceiverRingTeardown(
 }
 
 static FORCEINLINE VOID
-__ReceiverRingNotify(
-    IN  PXENVIF_RECEIVER_RING   Ring
-    )
-{
-    __ReceiverRingAcquireLock(Ring);
-    ReceiverRingPoll(Ring);
-    __ReceiverRingReleaseLock(Ring);
-}
-
-static FORCEINLINE VOID
 __ReceiverRingSetOffloadOptions(
     IN  PXENVIF_RECEIVER_RING       Ring,
     IN  XENVIF_VIF_OFFLOAD_OPTIONS  Options
@@ -2313,6 +2534,7 @@ ReceiverInitialize(
     (*Receiver)->DisableIpVersion6Gso = 0;
     (*Receiver)->IpAlignOffset = 0;
     (*Receiver)->AlwaysPullup = 0;
+    (*Receiver)->Split = FALSE;
 
     if (ParametersKey != NULL) {
         ULONG   ReceiverCalculateChecksums;
@@ -2370,6 +2592,9 @@ ReceiverInitialize(
     FdoGetCacheInterface(PdoGetFdo(FrontendGetPdo(Frontend)),
                          &(*Receiver)->CacheInterface);
 
+    FdoGetEvtchnInterface(PdoGetFdo(FrontendGetPdo(Frontend)),
+                          &(*Receiver)->EvtchnInterface);
+
     (*Receiver)->Frontend = Frontend;
 
     status = XENBUS_CACHE(Acquire, &(*Receiver)->CacheInterface);
@@ -2411,6 +2636,9 @@ fail2:
 
     (*Receiver)->Frontend = NULL;
 
+    RtlZeroMemory(&(*Receiver)->EvtchnInterface,
+                  sizeof (XENBUS_EVTCHN_INTERFACE));
+
     RtlZeroMemory(&(*Receiver)->CacheInterface,
                   sizeof (XENBUS_CACHE_INTERFACE));
 
@@ -2428,6 +2656,7 @@ fail2:
     (*Receiver)->DisableIpVersion6Gso = 0;
     (*Receiver)->IpAlignOffset = 0;
     (*Receiver)->AlwaysPullup = 0;
+    (*Receiver)->Split = FALSE;
 
     ASSERT(IsZeroMemory(*Receiver, sizeof (XENVIF_RECEIVER)));
     __ReceiverFree(*Receiver);
@@ -2445,6 +2674,7 @@ ReceiverConnect(
 {
     PXENVIF_FRONTEND        Frontend;
     ULONG                   Index;
+    PCHAR                   Buffer;
     NTSTATUS                status;
 
     Frontend = Receiver->Frontend;
@@ -2457,6 +2687,26 @@ ReceiverConnect(
     if (!NT_SUCCESS(status))
         goto fail2;
 
+    status = XENBUS_EVTCHN(Acquire, &Receiver->EvtchnInterface);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
+    status = XENBUS_STORE(Read,
+                          &Receiver->StoreInterface,
+                          NULL,
+                          FrontendGetBackendPath(Frontend),
+                          "feature-split-event-channels",
+                          &Buffer);
+    if (!NT_SUCCESS(status)) {
+        Receiver->Split = FALSE;
+    } else {
+        Receiver->Split = (BOOLEAN)strtol(Buffer, NULL, 2);
+
+        XENBUS_STORE(Free,
+                     &Receiver->StoreInterface,
+                     Buffer);
+    }
+
     for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
@@ -2466,7 +2716,7 @@ ReceiverConnect(
 
         status = __ReceiverRingConnect(Ring);
         if (!NT_SUCCESS(status))
-            goto fail3;
+            goto fail4;
     }    
 
     status = XENBUS_DEBUG(Register,
@@ -2476,16 +2726,16 @@ ReceiverConnect(
                           Receiver,
                           &Receiver->DebugCallback);
     if (!NT_SUCCESS(status))
-        goto fail4;
+        goto fail5;
 
     return STATUS_SUCCESS;
 
+fail5:
+    Error("fail5\n");
+
 fail4:
     Error("fail4\n");
 
-fail3:
-    Error("fail3\n");
-
     for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
@@ -2496,6 +2746,11 @@ fail3:
         __ReceiverRingDisconnect(Ring);
     }
 
+    XENBUS_EVTCHN(Release, &Receiver->EvtchnInterface);
+
+fail3:
+    Error("fail3\n");
+
     XENBUS_STORE(Release, &Receiver->StoreInterface);
 
 fail2:
@@ -2747,6 +3002,8 @@ ReceiverDisconnect(
 
     Frontend = Receiver->Frontend;
 
+    Receiver->Split = FALSE;
+
     XENBUS_DEBUG(Deregister,
                  &Receiver->DebugInterface,
                  Receiver->DebugCallback);
@@ -2765,6 +3022,8 @@ ReceiverDisconnect(
     XENBUS_STORE(Release, &Receiver->StoreInterface);
 
     XENBUS_DEBUG(Release, &Receiver->DebugInterface);
+
+    XENBUS_EVTCHN(Release, &Receiver->EvtchnInterface);
 }
 
 VOID
@@ -2774,6 +3033,9 @@ ReceiverTeardown(
 {
     ULONG                   Index;
 
+    ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
+    KeFlushQueuedDpcs();
+
     ASSERT3U(Receiver->Returned, ==, Receiver->Loaned);
     Receiver->Loaned = 0;
     Receiver->Returned = 0;
@@ -2793,6 +3055,10 @@ ReceiverTeardown(
     XENBUS_CACHE(Release, &Receiver->CacheInterface);
 
     Receiver->Frontend = NULL;
+    Receiver->Split = FALSE;
+
+    RtlZeroMemory(&Receiver->EvtchnInterface,
+                  sizeof (XENBUS_EVTCHN_INTERFACE));
 
     RtlZeroMemory(&Receiver->CacheInterface,
                   sizeof (XENBUS_CACHE_INTERFACE));
@@ -2921,19 +3187,37 @@ ReceiverWaitForPackets(
 }
 
 VOID
-ReceiverNotify(
-    IN  PXENVIF_RECEIVER    Receiver
+ReceiverRingTrigger(
+    IN  PXENVIF_RECEIVER    Receiver,
+    IN  ULONG               Index
     )
 {
-    ULONG                   Index;
+    PXENVIF_RECEIVER_RING   Ring;
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
-        PXENVIF_RECEIVER_RING   Ring;
+    if (Index >= MAXIMUM_PROCESSORS)
+        return;
 
-        Ring = Receiver->Rings[Index];
-        if (Ring == NULL)
-            break;
+    Ring = Receiver->Rings[Index];
+    if (Ring == NULL)
+        return;
 
-        __ReceiverRingNotify(Ring);
-    }    
+    __ReceiverRingTrigger(Ring);
+}
+
+VOID
+ReceiverRingSend(
+    IN  PXENVIF_RECEIVER    Receiver,
+    IN  ULONG               Index
+    )
+{
+    PXENVIF_RECEIVER_RING   Ring;
+
+    if (Index >= MAXIMUM_PROCESSORS)
+        return;
+
+    Ring = Receiver->Rings[Index];
+    if (Ring == NULL)
+        return;
+
+    __ReceiverRingSend(Ring);
 }
diff --git a/src/xenvif/receiver.h b/src/xenvif/receiver.h
index 0497c5b..f926500 100644
--- a/src/xenvif/receiver.h
+++ b/src/xenvif/receiver.h
@@ -79,11 +79,6 @@ ReceiverTeardown(
     );
 
 extern VOID
-ReceiverNotify(
-    IN  PXENVIF_RECEIVER    Receiver
-    );
-
-extern VOID
 ReceiverWaitForPackets(
     IN  PXENVIF_RECEIVER    Receiver
     );
@@ -106,4 +101,16 @@ ReceiverReturnPackets(
     IN  PLIST_ENTRY         List
     );
 
+extern VOID
+ReceiverRingTrigger(
+    IN  PXENVIF_RECEIVER    Receiver,
+    IN  ULONG               Index
+    );
+
+extern VOID
+ReceiverRingSend(
+    IN  PXENVIF_RECEIVER    Receiver,
+    IN  ULONG               Index
+    );
+
 #endif  // _XENVIF_RECEIVER_H
diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
index 645872b..e482392 100644
--- a/src/xenvif/transmitter.c
+++ b/src/xenvif/transmitter.c
@@ -40,6 +40,7 @@
 #include <cache_interface.h>
 #include <gnttab_interface.h>
 #include <range_set_interface.h>
+#include <evtchn_interface.h>
 
 #include "ethernet.h"
 #include "tcpip.h"
@@ -114,6 +115,11 @@ typedef struct _XENVIF_TRANSMITTER_RING {
     netif_tx_front_ring_t           Front;
     netif_tx_sring_t                *Shared;
     XENVIF_GRANTER_HANDLE           Handle;
+    PXENBUS_EVTCHN_CHANNEL          Channel;
+    KDPC                            Dpc;
+    ULONG                           Dpcs;
+    ULONG                           Events;
+    KSPIN_LOCK                      EvtchnLock;
     BOOLEAN                         Connected;
     BOOLEAN                         Enabled;
     BOOLEAN                         Stopped;
@@ -145,8 +151,10 @@ struct _XENVIF_TRANSMITTER {
     PXENVIF_FRONTEND            Frontend;
     XENBUS_CACHE_INTERFACE      CacheInterface;
     XENBUS_RANGE_SET_INTERFACE  RangeSetInterface;
+    XENBUS_EVTCHN_INTERFACE     EvtchnInterface;
     PXENVIF_TRANSMITTER_RING    Rings[MAXIMUM_PROCESSORS];
     LONG_PTR                    Offset[XENVIF_TRANSMITTER_PACKET_OFFSET_COUNT];
+    BOOLEAN                     Split;
     ULONG                       DisableIpVersion4Gso;
     ULONG                       DisableIpVersion6Gso;
     ULONG                       AlwaysCopy;
@@ -2127,6 +2135,72 @@ TransmitterRingPoll(
 }
 
 static FORCEINLINE VOID
+__TransmitterRingTrigger(
+    IN  PXENVIF_TRANSMITTER_RING   Ring
+    )
+{
+    KIRQL                           Irql;
+    PXENVIF_TRANSMITTER             Transmitter;
+
+    Transmitter = Ring->Transmitter;
+
+    KeAcquireSpinLock(&Ring->EvtchnLock, &Irql);
+
+    if (Ring->Connected) {
+        if (Transmitter->Split) {
+            ASSERT(Ring->Channel != NULL);
+
+            (VOID) XENBUS_EVTCHN(Trigger,
+                                 &Transmitter->EvtchnInterface,
+                                 Ring->Channel);
+        } else {
+            PXENVIF_FRONTEND        Frontend;
+
+            ASSERT(Ring->Channel == NULL);
+            Frontend = Transmitter->Frontend;
+
+            ReceiverRingTrigger(FrontendGetReceiver(Frontend),
+                                Ring->Index);
+        }
+    }
+
+    KeReleaseSpinLock(&Ring->EvtchnLock, Irql);
+}
+
+static FORCEINLINE VOID
+__TransmitterRingSend(
+    IN  PXENVIF_TRANSMITTER_RING    Ring
+    )
+{
+    KIRQL                           Irql;
+    PXENVIF_TRANSMITTER             Transmitter;
+
+    Transmitter = Ring->Transmitter;
+
+    KeAcquireSpinLock(&Ring->EvtchnLock, &Irql);
+
+    if (Ring->Connected) {
+        if (Transmitter->Split) {
+            ASSERT(Ring->Channel != NULL);
+
+            (VOID) XENBUS_EVTCHN(Send,
+                                 &Transmitter->EvtchnInterface,
+                                 Ring->Channel);
+        } else {
+            PXENVIF_FRONTEND        Frontend;
+
+            ASSERT(Ring->Channel == NULL);
+            Frontend = Transmitter->Frontend;
+
+            ReceiverRingSend(FrontendGetReceiver(Frontend),
+                             Ring->Index);
+        }
+    }
+
+    KeReleaseSpinLock(&Ring->EvtchnLock, Irql);
+}
+
+static FORCEINLINE VOID
 __TransmitterRingPushRequests(
     IN  PXENVIF_TRANSMITTER_RING    Ring
     )
@@ -2145,13 +2219,7 @@ __TransmitterRingPushRequests(
 #pragma warning (pop)
 
     if (Notify) {
-        PXENVIF_TRANSMITTER Transmitter;
-        PXENVIF_FRONTEND    Frontend;
-
-        Transmitter = Ring->Transmitter;
-        Frontend = Transmitter->Frontend;
-
-        NotifierSendTx(FrontendGetNotifier(Frontend));
+        __TransmitterRingSend(Ring);
     }
 
     Ring->RequestsPushed = Ring->RequestsPosted;
@@ -2475,6 +2543,97 @@ TransmitterRingReleaseLock(
     __TransmitterRingReleaseLock(Ring);
 }
 
+static FORCEINLINE VOID
+__TransmitterRingNotify(
+    IN  PXENVIF_TRANSMITTER_RING    Ring
+    )
+{
+    __TransmitterRingAcquireLock(Ring);
+    TransmitterRingPoll(Ring);
+    __TransmitterRingReleaseLock(Ring);
+}
+
+static FORCEINLINE BOOLEAN
+__TransmitterRingUnmask(
+    IN  PXENVIF_TRANSMITTER_RING    Ring
+    )
+{
+    PXENVIF_TRANSMITTER             Transmitter;
+    BOOLEAN                         Pending;
+
+    Transmitter = Ring->Transmitter;
+
+    KeAcquireSpinLockAtDpcLevel(&Ring->EvtchnLock);
+
+    Pending = (Ring->Connected) ?
+              XENBUS_EVTCHN(Unmask,
+                            &Transmitter->EvtchnInterface,
+                            Ring->Channel,
+                            FALSE) :
+              FALSE;
+
+    KeReleaseSpinLockFromDpcLevel(&Ring->EvtchnLock);
+
+    return Pending;
+}
+
+__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;
+    PXENVIF_TRANSMITTER         Transmitter;
+    BOOLEAN                     Pending;
+
+    UNREFERENCED_PARAMETER(Dpc);
+    UNREFERENCED_PARAMETER(Argument1);
+    UNREFERENCED_PARAMETER(Argument2);
+
+    ASSERT(Ring != NULL);
+
+    Transmitter = Ring->Transmitter;
+
+    do {
+        if (Ring->Enabled) {
+            ASSERT(Transmitter->Split);
+            __TransmitterRingNotify(Ring);
+        }
+
+        Pending = __TransmitterRingUnmask(Ring);
+    } while (Pending);
+}
+
+KSERVICE_ROUTINE    TransmitterRingEvtchnCallback;
+
+BOOLEAN
+TransmitterRingEvtchnCallback(
+    IN  PKINTERRUPT         InterruptObject,
+    IN  PVOID               Argument
+    )
+{
+    PXENVIF_TRANSMITTER_RING    Ring = Argument;
+
+    UNREFERENCED_PARAMETER(InterruptObject);
+
+    ASSERT(Ring != NULL);
+
+    Ring->Events++;
+
+    if (KeInsertQueueDpc(&Ring->Dpc, NULL, NULL))
+        Ring->Dpcs++;
+
+    return TRUE;
+}
+
 #define TIME_US(_us)        ((_us) * 10)
 #define TIME_MS(_ms)        (TIME_US((_ms) * 1000))
 #define TIME_S(_s)          (TIME_MS((_s) * 1000))
@@ -2520,17 +2679,15 @@ 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
-                NotifierSendTx(FrontendGetNotifier(Frontend));
+                __TransmitterRingSend(Ring);
                 TransmitterRingPoll(Ring);
             }
 
@@ -2625,6 +2782,8 @@ __TransmitterRingInitialize(
     (*Ring)->Index = Index;
     (*Ring)->Queued.TailPacket = &(*Ring)->Queued.HeadPacket;
     (*Ring)->Completed.TailPacket = &(*Ring)->Completed.HeadPacket;
+    KeInitializeSpinLock(&(*Ring)->EvtchnLock);
+    KeInitializeDpc(&(*Ring)->Dpc, TransmitterRingDpc, *Ring);
 
     status = RtlStringCbPrintfA(Name,
                                 sizeof (Name),
@@ -2755,6 +2914,9 @@ fail3:
 fail2:
     Error("fail2\n");
 
+    RtlZeroMemory(&(*Ring)->Dpc, sizeof (KDPC));
+    RtlZeroMemory(&(*Ring)->EvtchnLock, sizeof (KSPIN_LOCK));
+
     (*Ring)->Queued.TailPacket = NULL;
     (*Ring)->Completed.TailPacket = NULL;
     (*Ring)->Index = 0;
@@ -2778,6 +2940,7 @@ __TransmitterRingConnect(
     PXENVIF_TRANSMITTER             Transmitter;
     PXENVIF_FRONTEND                Frontend;
     PFN_NUMBER                      Pfn;
+    BOOLEAN                         Pending;
     CHAR                            Name[MAXNAMELEN];
     NTSTATUS                        status;
 
@@ -2815,6 +2978,38 @@ __TransmitterRingConnect(
     if (!NT_SUCCESS(status))
         goto fail3;
 
+    ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
+    KeAcquireSpinLockAtDpcLevel(&Ring->EvtchnLock);
+
+    if (Transmitter->Split) {
+        Ring->Channel = XENBUS_EVTCHN(Open,
+                                      &Transmitter->EvtchnInterface,
+                                      XENBUS_EVTCHN_TYPE_UNBOUND,
+                                      TransmitterRingEvtchnCallback,
+                                      Ring,
+                                      FrontendGetBackendDomain(Frontend),
+                                      TRUE);
+
+        status = STATUS_UNSUCCESSFUL;
+        if (Ring->Channel == NULL) {
+            KeReleaseSpinLockFromDpcLevel(&Ring->EvtchnLock);
+            goto fail4;
+        }
+
+        Pending = XENBUS_EVTCHN(Unmask,
+                                &Transmitter->EvtchnInterface,
+                                Ring->Channel,
+                                FALSE);
+
+        if (Pending)
+            XENBUS_EVTCHN(Trigger,
+                          &Transmitter->EvtchnInterface,
+                          Ring->Channel);
+    }
+
+    KeReleaseSpinLockFromDpcLevel(&Ring->EvtchnLock);
+
+
     status = XENBUS_DEBUG(Register,
                           &Transmitter->DebugInterface,
                           Name,
@@ -2822,12 +3017,22 @@ __TransmitterRingConnect(
                           Ring,
                           &Ring->DebugCallback);
     if (!NT_SUCCESS(status))
-        goto fail4;
+        goto fail5;
 
     Ring->Connected = TRUE;
 
     return STATUS_SUCCESS;
 
+fail5:
+    Error("fail5\n");
+
+    XENBUS_EVTCHN(Close,
+                  &Transmitter->EvtchnInterface,
+                  Ring->Channel);
+    Ring->Channel = NULL;
+
+    Ring->Events = 0;
+
 fail4:
     Error("fail4\n");
 
@@ -2862,6 +3067,7 @@ __TransmitterRingStoreWrite(
 {
     PXENVIF_TRANSMITTER             Transmitter;
     PXENVIF_FRONTEND                Frontend;
+    ULONG                           Port;
     NTSTATUS                        status;
 
     Transmitter = Ring->Transmitter;
@@ -2879,8 +3085,29 @@ __TransmitterRingStoreWrite(
     if (!NT_SUCCESS(status))
         goto fail1;
 
+    if (!Transmitter->Split)
+        goto done;
+
+    Port = XENBUS_EVTCHN(GetPort,
+                         &Transmitter->EvtchnInterface,
+                         Ring->Channel);
+
+    status = XENBUS_STORE(Printf,
+                          &Transmitter->StoreInterface,
+                          Transaction,
+                          FrontendGetPath(Frontend),
+                          "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);
 
@@ -2897,6 +3124,9 @@ __TransmitterRingEnable(
     ASSERT(!Ring->Enabled);
     Ring->Enabled = TRUE;
 
+    if (KeInsertQueueDpc(&Ring->Dpc, NULL, NULL))
+        Ring->Dpcs++;
+
     __TransmitterRingReleaseLock(Ring);
 
     return STATUS_SUCCESS;
@@ -2992,6 +3222,21 @@ __TransmitterRingDisconnect(
     Transmitter = Ring->Transmitter;
     Frontend = Transmitter->Frontend;
 
+    KeAcquireSpinLockAtDpcLevel(&Ring->EvtchnLock);
+
+    Transmitter->Split = FALSE;
+
+    if (Ring->Channel != NULL) {
+        XENBUS_EVTCHN(Close,
+                      &Transmitter->EvtchnInterface,
+                      Ring->Channel);
+        Ring->Channel = NULL;
+
+        Ring->Events = 0;
+    }
+
+    KeReleaseSpinLockFromDpcLevel(&Ring->EvtchnLock);
+
     ASSERT3U(Ring->ResponsesProcessed, ==, Ring->RequestsPushed);
     ASSERT3U(Ring->RequestsPushed, ==, Ring->RequestsPosted);
 
@@ -3028,6 +3273,10 @@ __TransmitterRingTeardown(
     Transmitter = Ring->Transmitter;
     Frontend = Transmitter->Frontend;
 
+    Ring->Dpcs = 0;
+    RtlZeroMemory(&Ring->Dpc, sizeof (KDPC));
+    RtlZeroMemory(&Ring->EvtchnLock, sizeof (KSPIN_LOCK));
+
     ASSERT3U(Ring->PacketsCompleted, ==, Ring->PacketsSent);
     ASSERT3U(Ring->PacketsSent, ==, Ring->PacketsPrepared - 
Ring->PacketsUnprepared);
     ASSERT3U(Ring->PacketsPrepared, ==, Ring->PacketsCopied + 
Ring->PacketsGranted + Ring->PacketsFaked);
@@ -3164,16 +3413,6 @@ __TransmitterRingAbortPackets(
     __TransmitterRingReleaseLock(Ring);
 }
 
-static FORCEINLINE VOID
-__TransmitterRingNotify(
-    IN  PXENVIF_TRANSMITTER_RING    Ring
-    )
-{
-    __TransmitterRingAcquireLock(Ring);
-    TransmitterRingPoll(Ring);
-    __TransmitterRingReleaseLock(Ring);
-}
-
 static VOID
 TransmitterDebugCallback(
     IN  PVOID           Argument,
@@ -3214,6 +3453,7 @@ TransmitterInitialize(
     (*Transmitter)->DisableIpVersion4Gso = 0;
     (*Transmitter)->DisableIpVersion6Gso = 0;
     (*Transmitter)->AlwaysCopy = 0;
+    (*Transmitter)->Split = FALSE;
 
     if (ParametersKey != NULL) {
         ULONG   TransmitterDisableIpVersion4Gso;
@@ -3251,6 +3491,9 @@ TransmitterInitialize(
     FdoGetCacheInterface(PdoGetFdo(FrontendGetPdo(Frontend)),
                          &(*Transmitter)->CacheInterface);
 
+    FdoGetEvtchnInterface(PdoGetFdo(FrontendGetPdo(Frontend)),
+                          &(*Transmitter)->EvtchnInterface);
+
     (*Transmitter)->Frontend = Frontend;
 
     status = XENBUS_RANGE_SET(Acquire, &(*Transmitter)->RangeSetInterface);
@@ -3332,6 +3575,7 @@ TransmitterConnect(
     )
 {
     PXENVIF_FRONTEND            Frontend;
+    PCHAR                       Buffer;
     ULONG                       Index;
     NTSTATUS                    status;
 
@@ -3345,6 +3589,26 @@ TransmitterConnect(
     if (!NT_SUCCESS(status))
         goto fail2;
 
+    status = XENBUS_EVTCHN(Acquire, &Transmitter->EvtchnInterface);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
+    status = XENBUS_STORE(Read,
+                          &Transmitter->StoreInterface,
+                          NULL,
+                          FrontendGetBackendPath(Frontend),
+                          "feature-split-event-channels",
+                          &Buffer);
+    if (!NT_SUCCESS(status)) {
+        Transmitter->Split = FALSE;
+    } else {
+        Transmitter->Split = (BOOLEAN)strtol(Buffer, NULL, 2);
+
+        XENBUS_STORE(Free,
+                     &Transmitter->StoreInterface,
+                     Buffer);
+    }
+
     for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
@@ -3354,7 +3618,7 @@ TransmitterConnect(
 
         status = __TransmitterRingConnect(Ring);
         if (!NT_SUCCESS(status))
-            goto fail3;
+            goto fail4;
     }    
 
     status = XENBUS_DEBUG(Register,
@@ -3364,16 +3628,16 @@ TransmitterConnect(
                           Transmitter,
                           &Transmitter->DebugCallback);
     if (!NT_SUCCESS(status))
-        goto fail4;
+        goto fail5;
 
     return STATUS_SUCCESS;
 
+fail5:
+    Error("fail5\n");
+
 fail4:
     Error("fail4\n");
 
-fail3:
-    Error("fail3\n");
-
     for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
@@ -3384,6 +3648,11 @@ fail3:
         __TransmitterRingDisconnect(Ring);
     }
 
+    XENBUS_EVTCHN(Release, &Transmitter->EvtchnInterface);
+
+fail3:
+    Error("fail3\n");
+
     XENBUS_STORE(Release, &Transmitter->StoreInterface);
 
 fail2:
@@ -3474,6 +3743,8 @@ TransmitterDisconnect(
 
     Frontend = Transmitter->Frontend;
 
+    Transmitter->Split = FALSE;
+
     XENBUS_DEBUG(Deregister,
                  &Transmitter->DebugInterface,
                  Transmitter->DebugCallback);
@@ -3492,6 +3763,8 @@ TransmitterDisconnect(
     XENBUS_STORE(Release, &Transmitter->StoreInterface);
 
     XENBUS_DEBUG(Release, &Transmitter->DebugInterface);
+
+    XENBUS_EVTCHN(Release, &Transmitter->EvtchnInterface);
 }
 
 VOID
@@ -3501,6 +3774,9 @@ TransmitterTeardown(
 {
     ULONG                   Index;
 
+    ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
+    KeFlushQueuedDpcs();
+
     RtlZeroMemory(Transmitter->Offset,
                   sizeof (LONG_PTR) *  
XENVIF_TRANSMITTER_PACKET_OFFSET_COUNT); 
 
@@ -3521,6 +3797,7 @@ TransmitterTeardown(
     XENBUS_RANGE_SET(Release, &Transmitter->RangeSetInterface);
 
     Transmitter->Frontend = NULL;
+    Transmitter->Split = FALSE;
 
     RtlZeroMemory(&Transmitter->CacheInterface,
                   sizeof (XENBUS_CACHE_INTERFACE));
@@ -3534,6 +3811,9 @@ TransmitterTeardown(
     RtlZeroMemory(&Transmitter->DebugInterface,
                   sizeof (XENBUS_DEBUG_INTERFACE));
 
+    RtlZeroMemory(&Transmitter->EvtchnInterface,
+                  sizeof (XENBUS_EVTCHN_INTERFACE));
+
     Transmitter->DisableIpVersion4Gso = 0;
     Transmitter->DisableIpVersion6Gso = 0;
     Transmitter->AlwaysCopy = 0;
@@ -3652,21 +3932,21 @@ TransmitterQueryRingSize(
 }
 
 VOID
-TransmitterNotify(
-    IN  PXENVIF_TRANSMITTER Transmitter
+TransmitterRingNotify(
+    IN  PXENVIF_TRANSMITTER Transmitter,
+    IN  ULONG               Index
     )
 {
-    ULONG                   Index;
+    PXENVIF_TRANSMITTER_RING    Ring;
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
-        PXENVIF_TRANSMITTER_RING    Ring;
+    if (Index >= MAXIMUM_PROCESSORS)
+        return;
 
-        Ring = Transmitter->Rings[Index];
-        if (Ring == NULL)
-            break;
+    Ring = Transmitter->Rings[Index];
+    if (Ring == NULL)
+        return;
 
-        __TransmitterRingNotify(Ring);
-    }    
+    __TransmitterRingNotify(Ring);
 }
 
 VOID
diff --git a/src/xenvif/transmitter.h b/src/xenvif/transmitter.h
index 5ffb590..9c3bfaa 100644
--- a/src/xenvif/transmitter.h
+++ b/src/xenvif/transmitter.h
@@ -79,8 +79,9 @@ TransmitterTeardown(
     );
 
 extern VOID
-TransmitterNotify(
-    IN  PXENVIF_TRANSMITTER Transmitter
+TransmitterRingNotify(
+    IN  PXENVIF_TRANSMITTER Transmitter,
+    IN  ULONG               Index
     );
 
 extern VOID
diff --git a/vs2012/xenvif/xenvif.vcxproj b/vs2012/xenvif/xenvif.vcxproj
index a86acff..edd71ea 100644
--- a/vs2012/xenvif/xenvif.vcxproj
+++ b/vs2012/xenvif/xenvif.vcxproj
@@ -96,7 +96,6 @@
                <ClCompile Include="../../src/xenvif/granter.c" />
                <ClCompile Include="../../src/xenvif/link.c" />
                <ClCompile Include="../../src/xenvif/mac.c" />
-               <ClCompile Include="../../src/xenvif/notifier.c" />
                <ClCompile Include="../../src/xenvif/parse.c" />
                <ClCompile Include="../../src/xenvif/pdo.c" />
                <ClCompile Include="../../src/xenvif/receiver.c" />
diff --git a/vs2013/xenvif/xenvif.vcxproj b/vs2013/xenvif/xenvif.vcxproj
index 69cf86a..32a3033 100644
--- a/vs2013/xenvif/xenvif.vcxproj
+++ b/vs2013/xenvif/xenvif.vcxproj
@@ -127,7 +127,6 @@
     <ClCompile Include="../../src/xenvif/granter.c" />
     <ClCompile Include="../../src/xenvif/link.c" />
     <ClCompile Include="../../src/xenvif/mac.c" />
-    <ClCompile Include="../../src/xenvif/notifier.c" />
     <ClCompile Include="../../src/xenvif/parse.c" />
     <ClCompile Include="../../src/xenvif/pdo.c" />
     <ClCompile Include="../../src/xenvif/receiver.c" />
-- 
1.9.4.msysgit.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@xxxxxxxxxxxxxxxxxxxx
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.