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

[win-pv-devel] [PATCH 05/10] Split notifier into a list of queues.



Move event channel registration to a list item, with 1 item per
max-queue.

Signed-off-by: Owen Smith <owen.smith@xxxxxxxxxx>
---
 src/xenvif/notifier.c    | 686 +++++++++++++++++++++++++++++++++--------------
 src/xenvif/notifier.h    |  12 +-
 src/xenvif/receiver.c    |  11 +-
 src/xenvif/receiver.h    |   3 +-
 src/xenvif/transmitter.c |   9 +-
 src/xenvif/transmitter.h |   3 +-
 6 files changed, 512 insertions(+), 212 deletions(-)

diff --git a/src/xenvif/notifier.c b/src/xenvif/notifier.c
index fc6725a..02a11d8 100644
--- a/src/xenvif/notifier.c
+++ b/src/xenvif/notifier.c
@@ -52,19 +52,26 @@ typedef enum _XENVIF_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;
+    LIST_ENTRY                  List;
     XENBUS_STORE_INTERFACE      StoreInterface;
     XENBUS_DEBUG_INTERFACE      DebugInterface;
     PXENBUS_DEBUG_CALLBACK      DebugCallback;
 };
 
+typedef struct _XENVIF_NOTIFIER_QUEUE {
+    PXENVIF_NOTIFIER            Notifier;
+    LIST_ENTRY                  ListEntry;
+    ULONG                       Index;
+    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];
+} XENVIF_NOTIFIER_QUEUE, *PXENVIF_NOTIFIER_QUEUE;
+
 #define XENVIF_NOTIFIER_TAG 'ITON'
 
 static FORCEINLINE PVOID
@@ -84,22 +91,24 @@ __NotifierFree(
 }
 
 static FORCEINLINE BOOLEAN
-__NotifierUnmask(
-    IN  PXENVIF_NOTIFIER        Notifier,
+__NotifierQueueUnmask(
+    IN  PXENVIF_NOTIFIER_QUEUE  Queue,
     IN  XENVIF_NOTIFIER_EVTCHN  Index
     )
 {
+    PXENVIF_NOTIFIER            Notifier;
     PXENVIF_FRONTEND            Frontend;
     BOOLEAN                     Pending;
 
+    Notifier = Queue->Notifier;
     Frontend = Notifier->Frontend;
 
     KeAcquireSpinLockAtDpcLevel(&Notifier->Lock);
 
-    Pending = (Notifier->Connected) ?
+    Pending = (Notifier->Connected && Queue->Channel[Index]) ?
               XENBUS_EVTCHN(Unmask,
                             &Notifier->EvtchnInterface,
-                            Notifier->Channel[Index],
+                            Queue->Channel[Index],
                             FALSE) :
               FALSE;
 
@@ -114,14 +123,15 @@ __drv_minIRQL(DISPATCH_LEVEL)
 __drv_requiresIRQL(DISPATCH_LEVEL)
 __drv_sameIRQL
 static VOID
-NotifierDpc(
+NotifierQueueDpc(
     IN  PKDPC               Dpc,
     IN  PVOID               Context,
     IN  PVOID               Argument1,
     IN  PVOID               Argument2
     )
 {
-    PXENVIF_NOTIFIER        Notifier = Context;
+    PXENVIF_NOTIFIER_QUEUE  Queue = Context;
+    PXENVIF_NOTIFIER        Notifier;
     XENVIF_NOTIFIER_EVTCHN  Index = (ULONG_PTR)Argument1;
     PXENVIF_FRONTEND        Frontend;
     BOOLEAN                 Pending;
@@ -129,24 +139,25 @@ NotifierDpc(
     UNREFERENCED_PARAMETER(Dpc);
     UNREFERENCED_PARAMETER(Argument2);
 
-    ASSERT(Notifier != NULL);
+    ASSERT(Queue != NULL);
 
+    Notifier = Queue->Notifier;
     Frontend = Notifier->Frontend;
 
     do {
         if (Notifier->Enabled) {
             switch (Index) {
             case XENVIF_NOTIFIER_EVTCHN_TX:
-                TransmitterNotify(FrontendGetTransmitter(Frontend));
+                TransmitterNotify(FrontendGetTransmitter(Frontend), 
Queue->Index);
                 break;
 
             case XENVIF_NOTIFIER_EVTCHN_RX:
-                ReceiverNotify(FrontendGetReceiver(Frontend));
+                ReceiverNotify(FrontendGetReceiver(Frontend), Queue->Index);
                 break;
 
             case XENVIF_NOTIFIER_EVTCHN_COMBINED:
-                TransmitterNotify(FrontendGetTransmitter(Frontend));
-                ReceiverNotify(FrontendGetReceiver(Frontend));
+                TransmitterNotify(FrontendGetTransmitter(Frontend), 
Queue->Index);
+                ReceiverNotify(FrontendGetReceiver(Frontend), Queue->Index);
                 break;
 
             default:
@@ -155,88 +166,345 @@ NotifierDpc(
             }
         }
 
-        Pending = __NotifierUnmask(Notifier, Index);
+        Pending = __NotifierQueueUnmask(Queue, Index);
     } while (Pending);
 }
 
 static FORCEINLINE BOOLEAN
-__NotifierEvtchnCallback(
-    IN  PXENVIF_NOTIFIER    Notifier,
-    IN  XENVIF_NOTIFIER_EVTCHN     Index
+__NotifierQueueEvtchnCallback(
+    IN  PXENVIF_NOTIFIER_QUEUE      Queue,
+    IN  XENVIF_NOTIFIER_EVTCHN      Index
     )
 {
-    Notifier->Events[Index]++;
+    Queue->Events[Index]++;
 
-    if (KeInsertQueueDpc(&Notifier->Dpc[Index],
+    if (KeInsertQueueDpc(&Queue->Dpc[Index],
                          (PVOID)(ULONG_PTR)Index,
                          NULL))
-        Notifier->Dpcs[Index]++;
+        Queue->Dpcs[Index]++;
 
     return TRUE;
 }
 
-#define DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(_Type)                   \
+#define DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK(_Type)             \
                                                                         \
-KSERVICE_ROUTINE    Notifier ## _Type ## EvtchnCallback;                \
+KSERVICE_ROUTINE    NotifierQueue ## _Type ## EvtchnCallback;           \
                                                                         \
 BOOLEAN                                                                 \
-Notifier ## _Type ## EvtchnCallback(                                    \
+NotifierQueue ## _Type ## EvtchnCallback(                               \
     IN  PKINTERRUPT         InterruptObject,                            \
     IN  PVOID               Argument                                    \
     )                                                                   \
 {                                                                       \
-    PXENVIF_NOTIFIER        Notifier = Argument;                        \
+    PXENVIF_NOTIFIER_QUEUE  Queue = Argument;                           \
                                                                         \
     UNREFERENCED_PARAMETER(InterruptObject);                            \
                                                                         \
-    ASSERT(Notifier != NULL);                                           \
-    return __NotifierEvtchnCallback(Notifier,                           \
+    ASSERT(Queue != NULL);                                              \
+    return __NotifierQueueEvtchnCallback(Queue,                         \
                                     XENVIF_NOTIFIER_EVTCHN_ ## _Type);  \
 }
 
-DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(COMBINED)
-DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(RX)
-DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(TX)
+DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK(COMBINED)
+DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK(RX)
+DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK(TX)
 
-#undef DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK
+#undef DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK
 
-#define DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(_Type)   \
-    Notifier ## _Type ## EvtchnCallback,
+#define DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK(_Type)   \
+    NotifierQueue ## _Type ## EvtchnCallback,
 
-PKSERVICE_ROUTINE   NotifierEvtchnCallback[] = {
-    DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(COMBINED)
-    DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(RX)
-    DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(TX)
+PKSERVICE_ROUTINE   NotifierQueueEvtchnCallback[] = {
+    DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK(COMBINED)
+    DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK(RX)
+    DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK(TX)
 };
 
-#undef DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK
+#undef DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK
 
-C_ASSERT(ARRAYSIZE(NotifierEvtchnCallback) == XENVIF_NOTIFIER_EVTCHN_COUNT);
+C_ASSERT(ARRAYSIZE(NotifierQueueEvtchnCallback) == 
XENVIF_NOTIFIER_EVTCHN_COUNT);
 
 static VOID
-NotifierDebugCallback(
-    IN  PVOID           Argument,
-    IN  BOOLEAN         Crashing
+NotifierQueueDebugCallback(
+    IN  PXENVIF_NOTIFIER_QUEUE  Queue
     )
 {
-    PXENVIF_NOTIFIER    Notifier = Argument;
-    PXENVIF_FRONTEND    Frontend;
+    PXENVIF_NOTIFIER    Notifier = Queue->Notifier;
     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",
+                     "[%u][%s]: Events = %lu Dpcs = %lu\n",
+                     Queue->Index,
                      ((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]);
+                     Queue->Events[Index],
+                     Queue->Dpcs[Index]);
+}
+
+static NTSTATUS
+NotifierQueueInitialize(
+    IN  PXENVIF_NOTIFIER        Notifier,
+    IN  ULONG                   QueueIndex,
+    OUT PXENVIF_NOTIFIER_QUEUE  *Queue
+    )
+{
+    ULONG       Index;
+    NTSTATUS    status;
+
+    *Queue = __NotifierAllocate(sizeof (XENVIF_NOTIFIER_QUEUE));
+
+    status = STATUS_NO_MEMORY;
+    if (*Queue == NULL)
+        goto fail1;
+
+    (*Queue)->Notifier = Notifier;
+    (*Queue)->Index = QueueIndex;
+
+    for (Index = 0; Index < XENVIF_NOTIFIER_EVTCHN_COUNT; Index++)
+        KeInitializeDpc(&(*Queue)->Dpc[Index],
+                        NotifierQueueDpc,
+                        *Queue);
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+    return status;
+}
+
+static NTSTATUS
+NotifierQueueConnect(
+    IN  PXENVIF_NOTIFIER_QUEUE  Queue
+    )
+{
+    PXENVIF_NOTIFIER        Notifier;
+    PXENVIF_FRONTEND        Frontend;
+    LONG                    Index;
+    NTSTATUS                status;
+
+    Notifier = Queue->Notifier;
+    Frontend = Notifier->Frontend;
+
+    for (Index = 0; Index < XENVIF_NOTIFIER_EVTCHN_COUNT; Index++) {
+        PKSERVICE_ROUTINE   Callback = NotifierQueueEvtchnCallback[Index];
+        BOOLEAN             Pending;
+
+        Queue->Channel[Index] = XENBUS_EVTCHN(Open,
+                                              &Notifier->EvtchnInterface,
+                                              XENBUS_EVTCHN_TYPE_UNBOUND,
+                                              Callback,
+                                              Queue,
+                                              
FrontendGetBackendDomain(Frontend),
+                                              TRUE);
+
+        status = STATUS_UNSUCCESSFUL;
+        if (Queue->Channel[Index] == NULL)
+            goto fail1;
+
+        Pending = XENBUS_EVTCHN(Unmask,
+                                &Notifier->EvtchnInterface,
+                                Queue->Channel[Index],
+                                FALSE);
+        if (Pending)
+            XENBUS_EVTCHN(Trigger,
+                          &Notifier->EvtchnInterface,
+                          Queue->Channel[Index]);
+    }
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    while (--Index >= 0) {
+        XENBUS_EVTCHN(Close,
+                      &Notifier->EvtchnInterface,
+                      Queue->Channel[Index]);
+        Queue->Channel[Index] = NULL;
+
+        Queue->Events[Index] = 0;
+    }
+
+    return status;
+}
+
+static NTSTATUS
+NotifierQueueStoreWrite(
+    IN  PXENVIF_NOTIFIER_QUEUE      Queue,
+    IN  PXENBUS_STORE_TRANSACTION   Transaction
+    )
+{
+    PXENVIF_NOTIFIER                Notifier = Queue->Notifier;
+    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,
+                             Queue->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;
+}
+
+static NTSTATUS
+NotifierQueueEnable(
+    IN  PXENVIF_NOTIFIER_QUEUE  Queue
+    )
+{
+    PXENVIF_NOTIFIER    Notifier = Queue->Notifier;
+    ULONG               Index;
+
+    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(&Queue->Dpc[Index],
+                             (PVOID)(ULONG_PTR)Index,
+                             NULL))
+            Queue->Dpcs[Index]++;
+    }
+
+    return STATUS_SUCCESS;
+}
+
+static VOID
+NotifierQueueDisconnect(
+    IN  PXENVIF_NOTIFIER_QUEUE  Queue
+    )
+{
+    PXENVIF_NOTIFIER    Notifier = Queue->Notifier;
+    LONG                Index;
+
+    Index = XENVIF_NOTIFIER_EVTCHN_COUNT;
+    while (--Index >= 0) {
+        if (Queue->Channel[Index] == NULL)
+            continue;
+
+        XENBUS_EVTCHN(Close,
+                      &Notifier->EvtchnInterface,
+                      Queue->Channel[Index]);
+        Queue->Channel[Index] = NULL;
+
+        Queue->Events[Index] = 0;
+    }
+}
+
+static VOID
+NotifierQueueTeardown(
+    IN  PXENVIF_NOTIFIER_QUEUE  Queue
+    )
+{
+    LONG        Index;
+
+    Index = XENVIF_NOTIFIER_EVTCHN_COUNT;
+    while (--Index >= 0) {
+        Queue->Dpcs[Index] = 0;
+        RtlZeroMemory(&Queue->Dpc[Index], sizeof (KDPC));
+    }
+
+    Queue->Notifier = NULL;
+    Queue->Index = 0;
+
+    ASSERT(IsZeroMemory(Queue, sizeof (XENVIF_NOTIFIER_QUEUE)));
+
+    __NotifierFree(Queue);
+}
+
+static VOID
+NotifierDebugCallback(
+    IN  PVOID           Argument,
+    IN  BOOLEAN         Crashing
+    )
+{
+    PXENVIF_NOTIFIER    Notifier = Argument;
+    PLIST_ENTRY         ListEntry;
+
+    UNREFERENCED_PARAMETER(Crashing);
+
+    for (ListEntry = Notifier->List.Flink;
+         ListEntry != &Notifier->List;
+         ListEntry = ListEntry->Flink) {
+        PXENVIF_NOTIFIER_QUEUE  Queue;
+
+        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE, ListEntry);
+        NotifierQueueDebugCallback(Queue);
+    }
 }
 
 NTSTATUS
@@ -266,13 +534,41 @@ NotifierInitialize(
     (*Notifier)->Frontend = Frontend;
 
     KeInitializeSpinLock(&(*Notifier)->Lock);
-    for (Index = 0; Index < XENVIF_NOTIFIER_EVTCHN_COUNT; Index++)
-        KeInitializeDpc(&(*Notifier)->Dpc[Index],
-                        NotifierDpc,
-                        *Notifier);
+    InitializeListHead(&(*Notifier)->List);
+
+    Index = 0;
+    while (Index < DriverGetQueueMax()) {
+        PXENVIF_NOTIFIER_QUEUE  Queue;
+
+        status = NotifierQueueInitialize(*Notifier, Index, &Queue);
+        if (!NT_SUCCESS(status))
+            goto fail2;
+
+        InsertTailList(&(*Notifier)->List, &Queue->ListEntry);
+        Index++;
+    }
 
     return STATUS_SUCCESS;
 
+fail2:
+    Error("fail2\n");
+
+    while (!IsListEmpty(&(*Notifier)->List)) {
+        PLIST_ENTRY             ListEntry;
+        PXENVIF_NOTIFIER_QUEUE  Queue;
+
+        ListEntry = RemoveTailList(&(*Notifier)->List);
+        ASSERT3P(ListEntry, !=, &(*Notifier)->List);
+
+        RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
+
+        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE, ListEntry);
+
+        NotifierQueueTeardown(Queue);
+        --Index;
+    }
+    ASSERT3U(Index, ==, 0);
+
 fail1:
     Error("fail1 (%08x)\n", status);
 
@@ -285,7 +581,7 @@ NotifierConnect(
     )
 {
     PXENVIF_FRONTEND        Frontend;
-    LONG                    Index;
+    PLIST_ENTRY             ListEntry;
     PCHAR                   Buffer;
     NTSTATUS                status;
 
@@ -308,32 +604,6 @@ NotifierConnect(
     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",
@@ -341,7 +611,7 @@ NotifierConnect(
                           Notifier,
                           &Notifier->DebugCallback);
     if (!NT_SUCCESS(status))
-        goto fail5;
+        goto fail4;
 
     status = XENBUS_STORE(Read,
                           &Notifier->StoreInterface,
@@ -359,6 +629,20 @@ NotifierConnect(
                      Buffer);
     }
 
+    for (ListEntry = Notifier->List.Flink;
+         ListEntry != &Notifier->List;
+         ListEntry = ListEntry->Flink) {
+        PXENVIF_NOTIFIER_QUEUE  Queue;
+
+        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE, ListEntry);
+        if (Queue->Index >= FrontendGetQueueCount(Frontend))
+            continue;
+
+        status = NotifierQueueConnect(Queue);
+        if (!NT_SUCCESS(status))
+            goto fail5;
+    }
+
     Notifier->Connected = TRUE;
     KeReleaseSpinLockFromDpcLevel(&Notifier->Lock);
 
@@ -367,20 +651,19 @@ NotifierConnect(
 fail5:
     Error("fail5\n");
 
-    Index = XENVIF_NOTIFIER_EVTCHN_COUNT;
+    for (ListEntry = Notifier->List.Flink;
+         ListEntry != &Notifier->List;
+         ListEntry = ListEntry->Flink) {
+        PXENVIF_NOTIFIER_QUEUE  Queue;
 
-fail4:
-    Error("fail4\n");
-
-    while (--Index >= 0) {
-        XENBUS_EVTCHN(Close,
-                      &Notifier->EvtchnInterface,
-                      Notifier->Channel[Index]);
-        Notifier->Channel[Index] = NULL;
+        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE, ListEntry);
 
-        Notifier->Events[Index] = 0;
+        NotifierQueueDisconnect(Queue);
     }
 
+fail4:
+    Error("fail4\n");
+
     XENBUS_STORE(Release, &Notifier->StoreInterface);
 
 fail3:
@@ -408,54 +691,20 @@ NotifierStoreWrite(
     )
 {
     PXENVIF_FRONTEND                Frontend = Notifier->Frontend;
-    ULONG                           Index;
+    PLIST_ENTRY                     ListEntry;
     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);
+    for (ListEntry = Notifier->List.Flink;
+         ListEntry != &Notifier->List;
+         ListEntry = ListEntry->Flink) {
+        PXENVIF_NOTIFIER_QUEUE  Queue;
 
-            Node = "";
-            break;
-        }
-
-        Port = XENBUS_EVTCHN(GetPort,
-                             &Notifier->EvtchnInterface,
-                             Notifier->Channel[Index]);
-
-        status = XENBUS_STORE(Printf,
-                              &Notifier->StoreInterface,
-                              Transaction,
-                              FrontendGetPath(Frontend),
-                              Node,
-                              "%u",
-                              Port);
+        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE, ListEntry);
+        if (Queue->Index > FrontendGetQueueCount(Frontend))
+            continue;
 
+        status = NotifierQueueStoreWrite(Queue,
+                                         Transaction);
         if (!NT_SUCCESS(status))
             goto fail1;
     }
@@ -473,44 +722,34 @@ NotifierEnable(
     IN  PXENVIF_NOTIFIER    Notifier
     )
 {   
-    ULONG                   Index;
+    PLIST_ENTRY             ListEntry;
+    PXENVIF_FRONTEND        Frontend;
+    NTSTATUS                status;
+
+    Frontend = Notifier->Frontend;
 
     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);
+    for (ListEntry = Notifier->List.Flink;
+         ListEntry != &Notifier->List;
+         ListEntry = ListEntry->Flink) {
+        PXENVIF_NOTIFIER_QUEUE  Queue;
 
-            break;
-        }
+        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE, ListEntry);
+        if (Queue->Index > FrontendGetQueueCount(Frontend))
+            continue;
 
-        if (KeInsertQueueDpc(&Notifier->Dpc[Index],
-                             (PVOID)(ULONG_PTR)Index,
-                             NULL))
-            Notifier->Dpcs[Index]++;
+        status = NotifierQueueEnable(Queue);
+        if (!NT_SUCCESS(status))
+            goto fail1;
     }
 
     return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+    return status;
 }
 
 VOID
@@ -528,7 +767,7 @@ NotifierDisconnect(
     )
 {
     PXENVIF_FRONTEND        Frontend;
-    LONG                    Index;
+    PLIST_ENTRY             ListEntry;
 
     Frontend = Notifier->Frontend;
 
@@ -544,14 +783,16 @@ NotifierDisconnect(
                  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;
+    for (ListEntry = Notifier->List.Flink;
+         ListEntry != &Notifier->List;
+         ListEntry = ListEntry->Flink) {
+        PXENVIF_NOTIFIER_QUEUE  Queue;
 
-        Notifier->Events[Index] = 0;
+        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE, ListEntry);
+        if (Queue->Index >= FrontendGetQueueCount(Frontend))
+            continue;
+
+        NotifierQueueDisconnect(Queue);
     }
 
     XENBUS_STORE(Release, &Notifier->StoreInterface);
@@ -568,15 +809,21 @@ 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));
+    while (!IsListEmpty(&Notifier->List)) {
+        PLIST_ENTRY             ListEntry;
+        PXENVIF_NOTIFIER_QUEUE  Queue;
+
+        ListEntry = RemoveTailList(&Notifier->List);
+        ASSERT3P(ListEntry, !=, &Notifier->List);
+
+        RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
+
+        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE, ListEntry);
+
+        NotifierQueueTeardown(Queue);
     }
 
     Notifier->Frontend = NULL;
@@ -590,6 +837,7 @@ NotifierTeardown(
     RtlZeroMemory(&Notifier->EvtchnInterface,
                   sizeof (XENBUS_EVTCHN_INTERFACE));
 
+    RtlZeroMemory(&Notifier->List, sizeof(LIST_ENTRY));
     RtlZeroMemory(&Notifier->Lock, sizeof (KSPIN_LOCK));
 
     ASSERT(IsZeroMemory(Notifier, sizeof (XENVIF_NOTIFIER)));
@@ -600,85 +848,125 @@ NotifierTeardown(
 static FORCEINLINE VOID
 __NotifierSend(
     IN  PXENVIF_NOTIFIER    Notifier,
-    IN  ULONG               Index
+    IN  ULONG               Index,
+    IN  ULONG               QueueIndex
     )
 {
     PXENVIF_FRONTEND        Frontend;
+    PLIST_ENTRY             ListEntry;
     KIRQL                   Irql;
 
     Frontend = Notifier->Frontend;
 
     KeAcquireSpinLock(&Notifier->Lock, &Irql);
 
-    if (Notifier->Connected)
+    if (!Notifier->Connected)
+        goto done;
+
+    for (ListEntry = Notifier->List.Flink;
+         ListEntry != &Notifier->List;
+         ListEntry = ListEntry->Flink) {
+        PXENVIF_NOTIFIER_QUEUE  Queue;
+
+        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE, ListEntry);
+        if (Queue->Index >= FrontendGetQueueCount(Frontend))
+            continue;
+        if (Queue->Index != QueueIndex)
+            continue;
+
         (VOID) XENBUS_EVTCHN(Send,
                              &Notifier->EvtchnInterface,
-                             Notifier->Channel[Index]);
+                             Queue->Channel[Index]);
+        break;
+    }
 
+done:
     KeReleaseSpinLock(&Notifier->Lock, Irql);
 }
 
 VOID
 NotifierSendTx(
-    IN  PXENVIF_NOTIFIER    Notifier
+    IN  PXENVIF_NOTIFIER    Notifier,
+    IN  ULONG               Queue
     )
 {
     if (Notifier->Split)
-        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_TX);
+        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_TX, Queue);
     else
-        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED);
+        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED, Queue);
 }
 
 VOID
 NotifierSendRx(
-    IN  PXENVIF_NOTIFIER    Notifier
+    IN  PXENVIF_NOTIFIER    Notifier,
+    IN  ULONG               Queue
     )
 {
     if (Notifier->Split)
-        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_RX);
+        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_RX, Queue);
     else
-        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED);
+        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED, Queue);
 }
 
 static FORCEINLINE VOID
 __NotifierTrigger(
     IN  PXENVIF_NOTIFIER    Notifier,
-    IN  ULONG               Index
+    IN  ULONG               Index,
+    IN  ULONG               QueueIndex
     )
 {
     PXENVIF_FRONTEND        Frontend;
+    PLIST_ENTRY             ListEntry;
     KIRQL                   Irql;
 
     Frontend = Notifier->Frontend;
 
     KeAcquireSpinLock(&Notifier->Lock, &Irql);
 
-    if (Notifier->Connected)
+    if (!Notifier->Connected)
+        goto done;
+
+    for (ListEntry = Notifier->List.Flink;
+         ListEntry != &Notifier->List;
+         ListEntry = ListEntry->Flink) {
+        PXENVIF_NOTIFIER_QUEUE  Queue;
+
+        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE, ListEntry);
+        if (Queue->Index >= FrontendGetQueueCount(Frontend))
+            continue;
+        if (Queue->Index != QueueIndex)
+            continue;
+
         (VOID) XENBUS_EVTCHN(Trigger,
                              &Notifier->EvtchnInterface,
-                             Notifier->Channel[Index]);
+                             Queue->Channel[Index]);
+        break;
+    }
 
+done:
     KeReleaseSpinLock(&Notifier->Lock, Irql);
 }
 
 VOID
 NotifierTriggerTx(
-    IN  PXENVIF_NOTIFIER    Notifier
+    IN  PXENVIF_NOTIFIER    Notifier,
+    IN  ULONG               Queue
     )
 {
     if (Notifier->Split)
-        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_TX);
+        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_TX, Queue);
     else
-        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED);
+        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED, Queue);
 }
 
 VOID
 NotifierTriggerRx(
-    IN  PXENVIF_NOTIFIER    Notifier
+    IN  PXENVIF_NOTIFIER    Notifier,
+    IN  ULONG               Queue
     )
 {
     if (Notifier->Split)
-        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_RX);
+        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_RX, Queue);
     else
-        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED);
+        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED, Queue);
 }
diff --git a/src/xenvif/notifier.h b/src/xenvif/notifier.h
index 2f06a6f..fd28060 100644
--- a/src/xenvif/notifier.h
+++ b/src/xenvif/notifier.h
@@ -78,22 +78,26 @@ NotifierTeardown(
 
 extern VOID
 NotifierSendTx(
-    IN  PXENVIF_NOTIFIER    Notifier
+    IN  PXENVIF_NOTIFIER    Notifier,
+    IN  ULONG               Queue
     );
 
 extern VOID
 NotifierSendRx(
-    IN  PXENVIF_NOTIFIER    Notifier
+    IN  PXENVIF_NOTIFIER    Notifier,
+    IN  ULONG               Queue
     );
 
 extern VOID
 NotifierTriggerTx(
-    IN  PXENVIF_NOTIFIER    Notifier
+    IN  PXENVIF_NOTIFIER    Notifier,
+    IN  ULONG               Queue
     );
 
 extern VOID
 NotifierTriggerRx(
-    IN  PXENVIF_NOTIFIER    Notifier
+    IN  PXENVIF_NOTIFIER    Notifier,
+    IN  ULONG               Queue
     );
 
 #endif  // _XENVIF_NOTIFIER_H
diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c
index 626feed..85ebcf9 100644
--- a/src/xenvif/receiver.c
+++ b/src/xenvif/receiver.c
@@ -1397,7 +1397,7 @@ __ReceiverRingReturnPacket(
             Receiver = Ring->Receiver;
             Frontend = Receiver->Frontend;
 
-            NotifierTriggerRx(FrontendGetNotifier(Frontend));
+            NotifierTriggerRx(FrontendGetNotifier(Frontend), Ring->Index);
         }
 
         if (!Locked)
@@ -1477,7 +1477,7 @@ __ReceiverRingPushRequests(
         Receiver = Ring->Receiver;
         Frontend = Receiver->Frontend;
 
-        NotifierSendRx(FrontendGetNotifier(Frontend));
+        NotifierSendRx(FrontendGetNotifier(Frontend), Ring->Index);
     }
 
     Ring->RequestsPushed = Ring->RequestsPosted;
@@ -1869,7 +1869,7 @@ ReceiverRingWatchdog(
 
                 // Try to move things along
                 ReceiverRingPoll(Ring);
-                NotifierSendRx(FrontendGetNotifier(Frontend));
+                NotifierSendRx(FrontendGetNotifier(Frontend), Ring->Index);
             }
 
             KeMemoryBarrier();
@@ -2941,7 +2941,8 @@ ReceiverWaitForPackets(
 
 VOID
 ReceiverNotify(
-    IN  PXENVIF_RECEIVER    Receiver
+    IN  PXENVIF_RECEIVER    Receiver,
+    IN  ULONG               Index
     )
 {
     PLIST_ENTRY             ListEntry;
@@ -2952,6 +2953,8 @@ ReceiverNotify(
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        if (Ring->Index != Index)
+            continue;
 
         __ReceiverRingNotify(Ring);
     }    
diff --git a/src/xenvif/receiver.h b/src/xenvif/receiver.h
index 8009858..1505887 100644
--- a/src/xenvif/receiver.h
+++ b/src/xenvif/receiver.h
@@ -79,7 +79,8 @@ ReceiverTeardown(
 
 extern VOID
 ReceiverNotify(
-    IN  PXENVIF_RECEIVER    Receiver
+    IN  PXENVIF_RECEIVER    Receiver,
+    IN  ULONG               Index
     );
 
 extern VOID
diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
index bea46f1..477fecc 100644
--- a/src/xenvif/transmitter.c
+++ b/src/xenvif/transmitter.c
@@ -2195,7 +2195,7 @@ __TransmitterRingPushRequests(
         Transmitter = Ring->Transmitter;
         Frontend = Transmitter->Frontend;
 
-        NotifierSendTx(FrontendGetNotifier(Frontend));
+        NotifierSendTx(FrontendGetNotifier(Frontend), Ring->Index);
     }
 
     Ring->RequestsPushed = Ring->RequestsPosted;
@@ -2624,7 +2624,7 @@ TransmitterRingWatchdog(
                              Ring->DebugCallback);
 
                 // Try to move things along
-                NotifierSendTx(FrontendGetNotifier(Frontend));
+                NotifierSendTx(FrontendGetNotifier(Frontend), Ring->Index);
                 TransmitterRingPoll(Ring);
             }
 
@@ -3972,7 +3972,8 @@ TransmitterQueryRingSize(
 
 VOID
 TransmitterNotify(
-    IN  PXENVIF_TRANSMITTER Transmitter
+    IN  PXENVIF_TRANSMITTER Transmitter,
+    IN  ULONG               Index
     )
 {
     PLIST_ENTRY             ListEntry;
@@ -3983,6 +3984,8 @@ TransmitterNotify(
         PXENVIF_TRANSMITTER_RING    Ring;
 
         Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, 
ListEntry);
+        if (Ring->Index != Index)
+            continue;
 
         __TransmitterRingNotify(Ring);
     }    
diff --git a/src/xenvif/transmitter.h b/src/xenvif/transmitter.h
index 7e10603..3e56b34 100644
--- a/src/xenvif/transmitter.h
+++ b/src/xenvif/transmitter.h
@@ -79,7 +79,8 @@ TransmitterTeardown(
 
 extern VOID
 TransmitterNotify(
-    IN  PXENVIF_TRANSMITTER Transmitter
+    IN  PXENVIF_TRANSMITTER Transmitter,
+    IN  ULONG               Index
     );
 
 extern VOID
-- 
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®.