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

[win-pv-devel] [PATCH 7/7] Implement multiple queues



Signed-off-by: Owen Smith <owen.smith@xxxxxxxxxx>
---
 src/xenvif/driver.c      |  42 ++++++++++
 src/xenvif/driver.h      |   5 ++
 src/xenvif/frontend.c    | 114 ++++++++++++++++++++++++++-
 src/xenvif/frontend.h    |  11 +++
 src/xenvif/receiver.c    | 117 +++++++++++++++++++++-------
 src/xenvif/receiver.h    |   1 -
 src/xenvif/transmitter.c | 198 ++++++++++++++++++++++++++++++++++++-----------
 src/xenvif/transmitter.h |   1 -
 8 files changed, 409 insertions(+), 80 deletions(-)

diff --git a/src/xenvif/driver.c b/src/xenvif/driver.c
index 6f81620..083fa19 100644
--- a/src/xenvif/driver.c
+++ b/src/xenvif/driver.c
@@ -47,6 +47,7 @@ typedef struct _XENVIF_DRIVER {
     PDRIVER_OBJECT      DriverObject;
     HANDLE              ParametersKey;
     HANDLE              AddressesKey;
+    ULONG               MaximumQueues;
 } XENVIF_DRIVER, *PXENVIF_DRIVER;
 
 static XENVIF_DRIVER    Driver;
@@ -123,6 +124,30 @@ DriverGetAddressesKey(
     return __DriverGetAddressesKey();
 }
 
+static FORCEINLINE VOID
+__DriverSetMaximumQueueCount(
+    IN  ULONG   Count
+    )
+{
+    Driver.MaximumQueues = Count;
+}
+
+static FORCEINLINE ULONG
+__DriverGetMaximumQueueCount(
+    VOID
+    )
+{
+    return Driver.MaximumQueues;
+}
+
+ULONG
+DriverGetMaximumQueueCount(
+    VOID
+    )
+{
+    return __DriverGetMaximumQueueCount();
+}
+
 DRIVER_UNLOAD       DriverUnload;
 
 VOID
@@ -148,6 +173,8 @@ DriverUnload(
     ParametersKey = __DriverGetParametersKey();
     __DriverSetParametersKey(NULL);
 
+    __DriverSetMaximumQueueCount(0);
+
     RegistryCloseKey(ParametersKey);
 
     RegistryTeardown();
@@ -254,6 +281,8 @@ DriverEntry(
     HANDLE              ParametersKey;
     HANDLE              AddressesKey;
     ULONG               Index;
+    ULONG               MaxQueues;
+    ULONG               Processors;
     NTSTATUS            status;
 
     ASSERT3P(__DriverGetDriverObject(), ==, NULL);
@@ -295,6 +324,8 @@ DriverEntry(
     if (!NT_SUCCESS(status))
         goto fail3;
 
+    __DriverSetParametersKey(ParametersKey);
+
     status = RegistryCreateSubKey(ServiceKey, 
                                   "Addresses", 
                                   REG_OPTION_VOLATILE, 
@@ -304,6 +335,17 @@ DriverEntry(
 
     __DriverSetAddressesKey(AddressesKey);
 
+    status = RegistryQueryDwordValue(ParametersKey,
+                                     "MultiQueueMaxQueues",
+                                     &MaxQueues);
+    if (!NT_SUCCESS(status))
+        MaxQueues = MAXIMUM_PROCESSORS;
+
+    Processors = KeQueryActiveProcessorCount(NULL);
+    __DriverSetMaximumQueueCount(MaxQueues > Processors ?
+                                        Processors :
+                                        MaxQueues);
+
     RegistryCloseKey(ServiceKey);
 
     DriverObject->DriverExtension->AddDevice = AddDevice;
diff --git a/src/xenvif/driver.h b/src/xenvif/driver.h
index cdef7d1..bbea23b 100644
--- a/src/xenvif/driver.h
+++ b/src/xenvif/driver.h
@@ -52,6 +52,11 @@ DriverGetAliasesKey(
     VOID
     );
 
+extern ULONG
+DriverGetMaximumQueueCount(
+    VOID
+    );
+
 typedef struct _XENVIF_PDO  XENVIF_PDO, *PXENVIF_PDO;
 typedef struct _XENVIF_FDO  XENVIF_FDO, *PXENVIF_FDO;
 
diff --git a/src/xenvif/frontend.c b/src/xenvif/frontend.c
index 268bab9..cfe6220 100644
--- a/src/xenvif/frontend.c
+++ b/src/xenvif/frontend.c
@@ -63,6 +63,7 @@ struct _XENVIF_FRONTEND {
 
     PCHAR                       BackendPath;
     USHORT                      BackendDomain;
+    ULONG                       QueueCount;
 
     PXENVIF_GRANTER             Granter;
     PXENVIF_MAC                 Mac;
@@ -201,6 +202,67 @@ FrontendGetBackendDomain(
     return __FrontendGetBackendDomain(Frontend);
 }
 
+static FORCEINLINE VOID
+__FrontendSetQueueCount(
+    IN  PXENVIF_FRONTEND    Frontend,
+    IN  ULONG               Count
+    )
+{
+    Frontend->QueueCount = Count;
+}
+
+static FORCEINLINE ULONG
+__FrontendGetQueueCount(
+    IN  PXENVIF_FRONTEND    Frontend
+    )
+{
+    return Frontend->QueueCount;
+}
+
+ULONG
+FrontendGetQueueCount(
+    IN  PXENVIF_FRONTEND    Frontend
+    )
+{
+    return __FrontendGetQueueCount(Frontend);
+}
+
+PCHAR
+FrontendFormatPath(
+    IN  PXENVIF_FRONTEND    Frontend,
+    IN  ULONG               Index
+    )
+{
+    ULONG                   Length;
+    PCHAR                   Path;
+    NTSTATUS                status;
+
+    Length = (ULONG)strlen(FrontendGetPath(Frontend)) +
+             (ULONG)strlen("/queue-00") +
+             1;
+
+    Path = ExAllocatePoolWithTag(NonPagedPool,
+                                 Length * sizeof(CHAR),
+                                 'HTAP');
+    if (Path == NULL)
+        goto fail1;
+
+    status = RtlStringCchPrintfA(Path,
+                                 Length,
+                                 "%s/queue-%u",
+                                 FrontendGetPath(Frontend),
+                                 Index);
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
+    return Path;
+
+fail2:
+    ExFreePoolWithTag(Path, 'HTAP');
+fail1:
+    return NULL;
+}
+
 #define DEFINE_FRONTEND_GET_FUNCTION(_Function, _Type)  \
 static FORCEINLINE _Type                                \
 __FrontendGet ## _Function(                             \
@@ -1274,6 +1336,42 @@ FrontendDebugCallback(
     }
 }
 
+static FORCEINLINE VOID
+__FrontendReadQueueCount(
+    IN  PXENVIF_FRONTEND    Frontend
+    )
+{
+    PCHAR                   Buffer;
+    ULONG                   Value;
+    NTSTATUS                status;
+
+    // default to 1 queue.
+    // backend must advertise "multi-queue-max-queues" to enable
+    // multi-queue support.
+    Value = 1;
+
+    status = XENBUS_STORE(Read,
+                          &Frontend->StoreInterface,
+                          NULL,
+                          __FrontendGetBackendPath(Frontend),
+                          "multi-queue-max-queues",
+                          &Buffer);
+    if (NT_SUCCESS(status)) {
+        Value = (ULONG)strtoul(Buffer, NULL, 10);
+
+        XENBUS_STORE(Free,
+                     &Frontend->StoreInterface,
+                     Buffer);
+
+        // set value to minimum of what frontend supports (vCPUs) and
+        // what backend supports (Dom0 vCPUs)
+        if (Value > DriverGetMaximumQueueCount())
+            Value = DriverGetMaximumQueueCount();
+    }
+
+    __FrontendSetQueueCount(Frontend, Value);
+}
+
 static FORCEINLINE NTSTATUS
 __FrontendConnect(
     IN  PXENVIF_FRONTEND    Frontend
@@ -1307,6 +1405,7 @@ __FrontendConnect(
     if (!NT_SUCCESS(status))
         goto fail4;
 
+    __FrontendReadQueueCount(Frontend);
     status = ReceiverConnect(__FrontendGetReceiver(Frontend));
     if (!NT_SUCCESS(status))
         goto fail5;
@@ -1335,6 +1434,16 @@ __FrontendConnect(
         if (!NT_SUCCESS(status))
             goto abort;
 
+        status = XENBUS_STORE(Printf,
+                              &Frontend->StoreInterface,
+                              Transaction,
+                              __FrontendGetPath(Frontend),
+                              "multi-queue-num-queues",
+                              "%u",
+                              __FrontendGetQueueCount(Frontend));
+        if (!NT_SUCCESS(status))
+            goto abort;
+
         status = XENBUS_STORE(TransactionEnd,
                               &Frontend->StoreInterface,
                               Transaction,
@@ -1870,11 +1979,11 @@ FrontendInitialize(
     if (!NT_SUCCESS(status))
         goto fail7;
 
-    status = ReceiverInitialize(*Frontend, 1, &(*Frontend)->Receiver);
+    status = ReceiverInitialize(*Frontend, &(*Frontend)->Receiver);
     if (!NT_SUCCESS(status))
         goto fail8;
 
-    status = TransmitterInitialize(*Frontend, 1, &(*Frontend)->Transmitter);
+    status = TransmitterInitialize(*Frontend, &(*Frontend)->Transmitter);
     if (!NT_SUCCESS(status))
         goto fail9;
 
@@ -2021,6 +2130,7 @@ FrontendTeardown(
     RtlZeroMemory(&Frontend->Lock, sizeof (KSPIN_LOCK));
 
     Frontend->BackendDomain = 0;
+    __FrontendSetQueueCount(Frontend, 0);
 
     __FrontendFree(Frontend->Prefix);
     Frontend->Prefix = NULL;
diff --git a/src/xenvif/frontend.h b/src/xenvif/frontend.h
index 67696d6..5d2905d 100644
--- a/src/xenvif/frontend.h
+++ b/src/xenvif/frontend.h
@@ -112,6 +112,17 @@ FrontendGetBackendDomain(
     IN  PXENVIF_FRONTEND    Frontend
     );
 
+extern ULONG
+FrontendGetQueueCount(
+    IN  PXENVIF_FRONTEND    Frontend
+    );
+
+extern PCHAR
+FrontendFormatPath(
+    IN  PXENVIF_FRONTEND    Frontend,
+    IN  ULONG               Index
+    );
+
 #include "granter.h"
 
 extern PXENVIF_GRANTER
diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c
index a11d91e..aad88e2 100644
--- a/src/xenvif/receiver.c
+++ b/src/xenvif/receiver.c
@@ -76,6 +76,7 @@ typedef struct _XENVIF_RECEIVER_FRAGMENT {
 typedef struct _XENVIF_RECEIVER_RING {
     PXENVIF_RECEIVER            Receiver;
     ULONG                       Index;
+    PCHAR                       FrontendPath;
     KSPIN_LOCK                  Lock;
     PXENBUS_CACHE               PacketCache;
     PXENBUS_CACHE               FragmentCache;
@@ -2045,6 +2046,11 @@ __ReceiverRingInitialize(
     (*Ring)->Receiver = Receiver;
     (*Ring)->Index = Index;
 
+    (*Ring)->FrontendPath = FrontendFormatPath(Frontend,
+                                               Index);
+    if ((*Ring)->FrontendPath == NULL)
+        goto fail2;
+
     InitializeListHead(&(*Ring)->PacketList);
     
     KeInitializeSpinLock(&(*Ring)->EvtchnLock);
@@ -2052,10 +2058,11 @@ __ReceiverRingInitialize(
 
     status = RtlStringCbPrintfA(Name,
                                 sizeof (Name),
-                                "%s_receiver_packet",
-                                FrontendGetPath(Frontend));
+                                "%s_%u_receiver_packet",
+                                FrontendGetPath(Frontend),
+                                (*Ring)->Index);
     if (!NT_SUCCESS(status))
-        goto fail2;
+        goto fail3;
 
     for (Index = 0; Name[Index] != '\0'; Index++)
         if (Name[Index] == '/')
@@ -2073,14 +2080,15 @@ __ReceiverRingInitialize(
                           *Ring,
                           &(*Ring)->PacketCache);
     if (!NT_SUCCESS(status))
-        goto fail3;
+        goto fail4;
 
     status = RtlStringCbPrintfA(Name,
                                 sizeof (Name),
-                                "%s_receiver_fragment",
-                                FrontendGetPath(Frontend));
+                                "%s_%u_receiver_fragment",
+                                FrontendGetPath(Frontend),
+                                (*Ring)->Index);
     if (!NT_SUCCESS(status))
-        goto fail4;
+        goto fail5;
 
     for (Index = 0; Name[Index] != '\0'; Index++)
         if (Name[Index] == '/')
@@ -2098,46 +2106,52 @@ __ReceiverRingInitialize(
                           *Ring,
                           &(*Ring)->FragmentCache);
     if (!NT_SUCCESS(status))
-        goto fail5;
+        goto fail6;
 
     status = ThreadCreate(ReceiverRingWatchdog,
                           *Ring,
                           &(*Ring)->WatchdogThread);
     if (!NT_SUCCESS(status))
-        goto fail6;
+        goto fail7;
 
     return STATUS_SUCCESS;
 
-fail6:
-    Error("fail6\n");
+fail7:
+    Error("fail7\n");
 
     XENBUS_CACHE(Destroy,
                  &Receiver->CacheInterface,
                  (*Ring)->FragmentCache);
     (*Ring)->FragmentCache = NULL;
 
+fail6:
+    Error("fail6\n");
+
 fail5:
     Error("fail5\n");
-    
-fail4:
-    Error("fail4\n");
 
     XENBUS_CACHE(Destroy,
                  &Receiver->CacheInterface,
                  (*Ring)->PacketCache);
     (*Ring)->PacketCache = NULL;
 
+fail4:
+    Error("fail4\n");
+
 fail3:
     Error("fail3\n");
-    
-fail2:
-    Error("fail2\n");
 
     RtlZeroMemory(&(*Ring)->EvtchnLock, sizeof (KSPIN_LOCK));
     RtlZeroMemory(&(*Ring)->Dpc, sizeof (KDPC));
 
     RtlZeroMemory(&(*Ring)->PacketList, sizeof (LIST_ENTRY));
 
+    ExFreePool((*Ring)->FrontendPath); // 'HTAP'
+    (*Ring)->FrontendPath = NULL;
+
+fail2:
+    Error("fail2\n");
+
     (*Ring)->Index = 0;
     (*Ring)->Receiver = NULL;
 
@@ -2216,6 +2230,16 @@ __ReceiverRingConnect(
         goto fail4;
     }
 
+    if (FrontendGetQueueCount(Frontend) > 1) {
+        (VOID) XENBUS_EVTCHN(Bind,
+                                &Receiver->EvtchnInterface,
+                                Ring->Channel,
+                                Ring->Index);
+
+        KeSetTargetProcessorDpc(&Ring->Dpc,
+                                (CCHAR)Ring->Index);
+    }
+
     Pending = XENBUS_EVTCHN(Unmask,
                             &Receiver->EvtchnInterface,
                             Ring->Channel,
@@ -2287,15 +2311,20 @@ __ReceiverRingStoreWrite(
     PXENVIF_RECEIVER                Receiver;
     PXENVIF_FRONTEND                Frontend;
     ULONG                           Port;
+    PCHAR                           Path;
     NTSTATUS                        status;
 
     Receiver = Ring->Receiver;
     Frontend = Receiver->Frontend;
 
+    Path = (FrontendGetQueueCount(Frontend) == 1) ?
+                    FrontendGetPath(Frontend) :
+                    Ring->FrontendPath;
+
     status = XENBUS_STORE(Printf,
                           &Receiver->StoreInterface,
                           Transaction,
-                          FrontendGetPath(Frontend),
+                          Path,
                           "rx-ring-ref",
                           "%u",
                           GranterGetReference(FrontendGetGranter(Frontend),
@@ -2311,7 +2340,7 @@ __ReceiverRingStoreWrite(
     status = XENBUS_STORE(Printf,
                           &Receiver->StoreInterface,
                           Transaction,
-                          FrontendGetPath(Frontend),
+                          Path,
                           Receiver->Split ? "event-channel-rx" : 
"event-channel",
                           "%u",
                           Port);
@@ -2466,6 +2495,9 @@ __ReceiverRingTeardown(
     ASSERT(IsListEmpty(&Ring->PacketList));
     RtlZeroMemory(&Ring->PacketList, sizeof (LIST_ENTRY));
 
+    ExFreePool(Ring->FrontendPath); // 'HTAP'
+    Ring->FrontendPath = NULL;
+
     Ring->Index = 0;
     Ring->Receiver = NULL;
 
@@ -2512,14 +2544,15 @@ ReceiverDebugCallback(
 NTSTATUS
 ReceiverInitialize(
     IN  PXENVIF_FRONTEND    Frontend,
-    IN  ULONG               Count,
     OUT PXENVIF_RECEIVER    *Receiver
     )
 {
     HANDLE                  ParametersKey;
     ULONG                   Index;
+    ULONG                   Count;
     NTSTATUS                status;
 
+    Count = DriverGetMaximumQueueCount();
     *Receiver = __ReceiverAllocate(sizeof (XENVIF_RECEIVER));
 
     status = STATUS_NO_MEMORY;
@@ -2624,7 +2657,7 @@ fail3:
         (*Receiver)->Rings[Index] = NULL;
 
         if (Ring == NULL)
-            continue;
+            continue; // ensure all rings are destroyed
 
         __ReceiverRingTeardown(Ring);
     }
@@ -2674,6 +2707,7 @@ ReceiverConnect(
 {
     PXENVIF_FRONTEND        Frontend;
     ULONG                   Index;
+    ULONG                   Count;
     PCHAR                   Buffer;
     NTSTATUS                status;
 
@@ -2707,7 +2741,10 @@ ReceiverConnect(
                      Buffer);
     }
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    Count = FrontendGetQueueCount(Frontend);
+    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = Receiver->Rings[Index];
@@ -2736,7 +2773,7 @@ fail5:
 fail4:
     Error("fail4\n");
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = Receiver->Rings[Index];
@@ -2856,6 +2893,7 @@ ReceiverStoreWrite(
 {
     PXENVIF_FRONTEND                Frontend;
     ULONG                           Index;
+    ULONG                           Count;
     NTSTATUS                        status;
 
     Frontend = Receiver->Frontend;
@@ -2898,7 +2936,10 @@ ReceiverStoreWrite(
     if (!NT_SUCCESS(status))
         goto fail5;
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    Count = FrontendGetQueueCount(Frontend);
+    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = Receiver->Rings[Index];
@@ -2940,11 +2981,15 @@ ReceiverEnable(
 {
     PXENVIF_FRONTEND        Frontend;
     ULONG                   Index;
+    ULONG                   Count;
     NTSTATUS                status;
 
     Frontend = Receiver->Frontend;
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    Count = FrontendGetQueueCount(Frontend);
+    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = Receiver->Rings[Index];
@@ -2961,7 +3006,7 @@ ReceiverEnable(
 fail1:
     Error("fail1 (%08x)\n", status);
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = Receiver->Rings[Index];
@@ -2980,8 +3025,12 @@ ReceiverDisable(
     )
 {
     ULONG                   Index;
+    ULONG                   Count;
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    Count = FrontendGetQueueCount(Receiver->Frontend);
+    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = Receiver->Rings[Index];
@@ -2999,6 +3048,7 @@ ReceiverDisconnect(
 {
     PXENVIF_FRONTEND        Frontend;
     ULONG                   Index;
+    ULONG                   Count;
 
     Frontend = Receiver->Frontend;
 
@@ -3009,7 +3059,10 @@ ReceiverDisconnect(
                  Receiver->DebugCallback);
     Receiver->DebugCallback = NULL;
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    Count = FrontendGetQueueCount(Frontend);
+    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = Receiver->Rings[Index];
@@ -3047,7 +3100,7 @@ ReceiverTeardown(
         Receiver->Rings[Index] = NULL;
 
         if (Ring == NULL)
-            break;
+            continue; // ensure all rings are destroyed
 
         __ReceiverRingTeardown(Ring);
     }
@@ -3089,6 +3142,7 @@ ReceiverSetOffloadOptions(
     )
 {
     ULONG                           Index;
+    ULONG                           Count;
 
     if (Receiver->AllowGsoPackets == 0) {
         Warning("RECEIVER GSO DISALLOWED\n");
@@ -3096,7 +3150,10 @@ ReceiverSetOffloadOptions(
         Options.OffloadIpVersion6LargePacket = 0;
     }
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    Count = FrontendGetQueueCount(Receiver->Frontend);
+    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = Receiver->Rings[Index];
diff --git a/src/xenvif/receiver.h b/src/xenvif/receiver.h
index f926500..1990ac1 100644
--- a/src/xenvif/receiver.h
+++ b/src/xenvif/receiver.h
@@ -43,7 +43,6 @@ typedef struct _XENVIF_RECEIVER XENVIF_RECEIVER, 
*PXENVIF_RECEIVER;
 extern NTSTATUS
 ReceiverInitialize(
     IN  PXENVIF_FRONTEND    Frontend,
-    IN  ULONG               Count,
     OUT PXENVIF_RECEIVER    *Receiver
     );
 
diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
index 914e544..445fa8b 100644
--- a/src/xenvif/transmitter.c
+++ b/src/xenvif/transmitter.c
@@ -103,6 +103,7 @@ typedef struct _XENVIF_TRANSMITTER_STATE {
 typedef struct _XENVIF_TRANSMITTER_RING {
     PXENVIF_TRANSMITTER             Transmitter;
     ULONG                           Index;
+    PCHAR                           FrontendPath;
     PXENBUS_CACHE                   BufferCache;
     PXENBUS_CACHE                   FragmentCache;
     PXENBUS_RANGE_SET               RangeSet;
@@ -2861,6 +2862,12 @@ __TransmitterRingInitialize(
 
     (*Ring)->Transmitter = Transmitter;
     (*Ring)->Index = Index;
+
+    (*Ring)->FrontendPath = FrontendFormatPath(Frontend,
+                                               Index);
+    if ((*Ring)->FrontendPath == NULL)
+        goto fail2;
+
     InitializeListHead(&(*Ring)->Queued);
     InitializeListHead(&(*Ring)->Completed);
     KeInitializeSpinLock(&(*Ring)->EvtchnLock);
@@ -2868,10 +2875,11 @@ __TransmitterRingInitialize(
 
     status = RtlStringCbPrintfA(Name,
                                 sizeof (Name),
-                                "%s_transmitter_buffer",
-                                FrontendGetPath(Frontend));
+                                "%s_%u_transmitter_buffer",
+                                FrontendGetPath(Frontend),
+                                (*Ring)->Index);
     if (!NT_SUCCESS(status))
-        goto fail2;
+        goto fail3;
 
     for (Index = 0; Name[Index] != '\0'; Index++)
         if (Name[Index] == '/')
@@ -2889,14 +2897,15 @@ __TransmitterRingInitialize(
                           *Ring,
                           &(*Ring)->BufferCache);
     if (!NT_SUCCESS(status))
-        goto fail3;
+        goto fail4;
 
     status = RtlStringCbPrintfA(Name,
                                 sizeof (Name),
-                                "%s_transmitter_req_id",
-                                FrontendGetPath(Frontend));
+                                "%s_%u_transmitter_req_id",
+                                FrontendGetPath(Frontend),
+                                (*Ring)->Index);
     if (!NT_SUCCESS(status))
-        goto fail4;
+        goto fail5;
 
     for (Index = 0; Name[Index] != '\0'; Index++)
         if (Name[Index] == '/')
@@ -2907,7 +2916,7 @@ __TransmitterRingInitialize(
                               Name,
                               &(*Ring)->RangeSet);
     if (!NT_SUCCESS(status))
-        goto fail5;
+        goto fail6;
 
     status = XENBUS_RANGE_SET(Put,
                               &Transmitter->RangeSetInterface,
@@ -2915,14 +2924,15 @@ __TransmitterRingInitialize(
                               1,
                               XENVIF_TRANSMITTER_MAXIMUM_FRAGMENT_ID);
     if (!NT_SUCCESS(status))
-        goto fail6;
+        goto fail7;
 
     status = RtlStringCbPrintfA(Name,
                                 sizeof (Name),
-                                "%s_transmitter_fragment",
-                                FrontendGetPath(Frontend));
+                                "%s_%u_transmitter_fragment",
+                                FrontendGetPath(Frontend),
+                                (*Ring)->Index);
     if (!NT_SUCCESS(status))
-        goto fail7;
+        goto fail8;
 
     for (Index = 0; Name[Index] != '\0'; Index++)
         if (Name[Index] == '/')
@@ -2940,66 +2950,73 @@ __TransmitterRingInitialize(
                           (*Ring),
                           &(*Ring)->FragmentCache);
     if (!NT_SUCCESS(status))
-        goto fail8;
+        goto fail9;
 
     status = ThreadCreate(TransmitterRingWatchdog,
                           *Ring,
                           &(*Ring)->WatchdogThread);
     if (!NT_SUCCESS(status))
-        goto fail9;
+        goto fail10;
 
     return STATUS_SUCCESS;
 
-fail9:
-    Error("fail9\n");
+fail10:
+    Error("fail10\n");
 
     XENBUS_CACHE(Destroy,
                  &Transmitter->CacheInterface,
                  (*Ring)->FragmentCache);
     (*Ring)->FragmentCache = NULL;
 
+fail9:
+    Error("fail9\n");
+
 fail8:
     Error("fail8\n");
 
-fail7:
-    Error("fail7\n");
-
     (VOID) XENBUS_RANGE_SET(Get,
                             &Transmitter->RangeSetInterface,
                             (*Ring)->RangeSet,
                             1,
                             XENVIF_TRANSMITTER_MAXIMUM_FRAGMENT_ID);
 
-fail6:
-    Error("fail6\n");
+fail7:
+    Error("fail7\n");
 
     XENBUS_RANGE_SET(Destroy,
                      &Transmitter->RangeSetInterface,
                      (*Ring)->RangeSet);
     (*Ring)->RangeSet = NULL;
 
+fail6:
+    Error("fail6\n");
+
 fail5:
     Error("fail5\n");
 
-fail4:
-    Error("fail4\n");
-
     XENBUS_CACHE(Destroy,
                  &Transmitter->CacheInterface,
                  (*Ring)->BufferCache);
     (*Ring)->BufferCache = NULL;
 
+fail4:
+    Error("fail4\n");
+
 fail3:
     Error("fail3\n");
 
-fail2:
-    Error("fail2\n");
-
     RtlZeroMemory(&(*Ring)->Dpc, sizeof (KDPC));
     RtlZeroMemory(&(*Ring)->EvtchnLock, sizeof (KSPIN_LOCK));
 
     RtlZeroMemory(&(*Ring)->Queued, sizeof (LIST_ENTRY));
     RtlZeroMemory(&(*Ring)->Completed, sizeof (LIST_ENTRY));
+
+    ExFreePool((*Ring)->FrontendPath); // 'HTAP'
+    (*Ring)->FrontendPath = NULL;
+
+fail2:
+    Error("fail2\n");
+
     (*Ring)->Index = 0;
     (*Ring)->Transmitter = NULL;
 
@@ -3077,6 +3094,16 @@ __TransmitterRingConnect(
             goto fail4;
         }
 
+        if (FrontendGetQueueCount(Frontend) > 1) {
+            (VOID) XENBUS_EVTCHN(Bind,
+                                 &Transmitter->EvtchnInterface,
+                                 Ring->Channel,
+                                 Ring->Index);
+
+            KeSetTargetProcessorDpc(&Ring->Dpc,
+                                    (CCHAR)Ring->Index);
+        }
+
         Pending = XENBUS_EVTCHN(Unmask,
                                 &Transmitter->EvtchnInterface,
                                 Ring->Channel,
@@ -3149,15 +3176,20 @@ __TransmitterRingStoreWrite(
     PXENVIF_TRANSMITTER             Transmitter;
     PXENVIF_FRONTEND                Frontend;
     ULONG                           Port;
+    PCHAR                           Path;
     NTSTATUS                        status;
 
     Transmitter = Ring->Transmitter;
     Frontend = Transmitter->Frontend;
 
+    Path = (FrontendGetQueueCount(Frontend) == 1) ?
+                    FrontendGetPath(Frontend) :
+                    Ring->FrontendPath;
+
     status = XENBUS_STORE(Printf,
                           &Transmitter->StoreInterface,
                           Transaction,
-                          FrontendGetPath(Frontend),
+                          Path,
                           "tx-ring-ref",
                           "%u",
                           GranterGetReference(FrontendGetGranter(Frontend),
@@ -3176,7 +3208,7 @@ __TransmitterRingStoreWrite(
     status = XENBUS_STORE(Printf,
                           &Transmitter->StoreInterface,
                           Transaction,
-                          FrontendGetPath(Frontend),
+                          Path,
                           "event-channel-tx",
                           "%u",
                           Port);
@@ -3404,6 +3436,9 @@ __TransmitterRingTeardown(
     ASSERT(IsListEmpty(&Ring->Completed));
     RtlZeroMemory(&Ring->Completed, sizeof (LIST_ENTRY));
 
+    ExFreePool(Ring->FrontendPath); // 'HTAP'
+    Ring->FrontendPath = NULL;
+
     Ring->Index = 0;
     Ring->Transmitter = NULL;
 
@@ -3498,14 +3533,15 @@ TransmitterDebugCallback(
 NTSTATUS
 TransmitterInitialize(
     IN  PXENVIF_FRONTEND    Frontend,
-    IN  ULONG               Count,
     OUT PXENVIF_TRANSMITTER *Transmitter
     )
 {
     HANDLE                  ParametersKey;
     ULONG                   Index;
+    ULONG                   Count;
     NTSTATUS                status;
 
+    Count = DriverGetMaximumQueueCount();
     *Transmitter = __TransmitterAllocate(sizeof (XENVIF_TRANSMITTER));
 
     status = STATUS_NO_MEMORY;
@@ -3592,7 +3628,7 @@ fail4:
         (*Transmitter)->Rings[Index] = NULL;
 
         if (Ring == NULL)
-            continue;
+            continue; // ensure all rings are destroyed
 
         __TransmitterRingTeardown(Ring);
     }
@@ -3645,6 +3681,7 @@ TransmitterConnect(
     PXENVIF_FRONTEND            Frontend;
     PCHAR                       Buffer;
     ULONG                       Index;
+    ULONG                       Count;
     NTSTATUS                    status;
 
     Frontend = Transmitter->Frontend;
@@ -3691,7 +3728,10 @@ TransmitterConnect(
                      Buffer);
     }
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    Count = FrontendGetQueueCount(Frontend);
+    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
         Ring = Transmitter->Rings[Index];
@@ -3725,7 +3765,7 @@ fail5:
 
         Ring = Transmitter->Rings[Index];
         if (Ring == NULL)
-            continue;
+            continue; // ensure all rings are destroyed
 
         __TransmitterRingDisconnect(Ring);
     }
@@ -3763,9 +3803,13 @@ TransmitterStoreWrite(
     )
 {
     NTSTATUS                        status;
-    ULONG                   Index;
+    ULONG                           Index;
+    ULONG                           Count;
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    Count = FrontendGetQueueCount(Transmitter->Frontend);
+    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
         Ring = Transmitter->Rings[Index];
@@ -3791,8 +3835,12 @@ TransmitterEnable(
     )
 {
     ULONG                   Index;
+    ULONG                   Count;
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    Count = FrontendGetQueueCount(Transmitter->Frontend);
+    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
         Ring = Transmitter->Rings[Index];
@@ -3811,8 +3859,12 @@ TransmitterDisable(
     )
 {
     ULONG                   Index;
+    ULONG                   Count;
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    Count = FrontendGetQueueCount(Transmitter->Frontend);
+    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
         Ring = Transmitter->Rings[Index];
@@ -3830,6 +3882,7 @@ TransmitterDisconnect(
 {
     PXENVIF_FRONTEND        Frontend;
     ULONG                   Index;
+    ULONG                   Count;
 
     Frontend = Transmitter->Frontend;
 
@@ -3840,7 +3893,10 @@ TransmitterDisconnect(
                  Transmitter->DebugCallback);
     Transmitter->DebugCallback = NULL;
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    Count = FrontendGetQueueCount(Frontend);
+    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
         Ring = Transmitter->Rings[Index];
@@ -3882,7 +3938,7 @@ TransmitterTeardown(
         Transmitter->Rings[Index] = NULL;
 
         if (Ring == NULL)
-            continue;
+            continue; // ensure all rings are destroyed
 
         __TransmitterRingTeardown(Ring);
     }
@@ -4132,20 +4188,66 @@ TransmitterQueuePacketsV1(
 #undef OFFSET_EXISTS
 }
 
+static FORCEINLINE ULONG
+__GetQueue(
+    IN  ULONG       QueueCount,
+    IN  ULONG       HashValue
+    )
+{
+    return HashValue % QueueCount;
+}
+
 VOID
 TransmitterQueuePacketsV2(
     IN  PXENVIF_TRANSMITTER Transmitter,
     IN  PLIST_ENTRY         List
     )
 {
-    PXENVIF_TRANSMITTER_RING        Ring;
+    PXENVIF_TRANSMITTER_RING    Ring;
+    PXENVIF_FRONTEND            Frontend;
+    ULONG                       QueueCount;
 
-    // We need to hash for a ring eventually. Since there is only a
-    // single ring for now, we just use that.
-    Ring = Transmitter->Rings[0];
-    ASSERT3P(Ring, !=, NULL);
+    Frontend = Transmitter->Frontend;
+
+    QueueCount = FrontendGetQueueCount(Frontend);
+
+    if (QueueCount == 1) {
+        Ring = Transmitter->Rings[0];
+        ASSERT3P(Ring, !=, NULL);
 
-    __TransmitterRingQueuePackets(Ring, List);
+        __TransmitterRingQueuePackets(Ring, List);
+    } else {
+        while (!IsListEmpty(List)) {
+            PXENVIF_TRANSMITTER_PACKET  Packet;
+            PLIST_ENTRY                 ListEntry;
+            LIST_ENTRY                  ListHead;
+            ULONG                       Queue;
+
+            InitializeListHead(&ListHead);
+
+            ListEntry = List->Flink;
+            Packet = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_PACKET, 
ListEntry);
+            Queue = __GetQueue(QueueCount, Packet->Value);
+
+            (VOID) RemoveHeadList(List);
+            InsertTailList(&ListHead, ListEntry);
+
+            while (!IsListEmpty(List)) {
+                ListEntry = List->Flink;
+                Packet = CONTAINING_RECORD(ListEntry, 
XENVIF_TRANSMITTER_PACKET, ListEntry);
+                if (Queue != __GetQueue(QueueCount, Packet->Value))
+                    break;
+
+                (VOID) RemoveHeadList(List);
+                InsertTailList(&ListHead, ListEntry);
+            }
+
+            Ring = Transmitter->Rings[Queue];
+            ASSERT3P(Ring, !=, NULL);
+
+            __TransmitterRingQueuePackets(Ring, &ListHead);
+        }
+    }
 }
 
 VOID
@@ -4154,11 +4256,15 @@ TransmitterAbortPackets(
     )
 {
     ULONG                   Index;
+    ULONG                   Count;
     KIRQL                   Irql;
 
     KeRaiseIrql(DISPATCH_LEVEL, &Irql);
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    Count = FrontendGetQueueCount(Transmitter->Frontend);
+    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
         Ring = Transmitter->Rings[Index];
diff --git a/src/xenvif/transmitter.h b/src/xenvif/transmitter.h
index 2ed2786..666f049 100644
--- a/src/xenvif/transmitter.h
+++ b/src/xenvif/transmitter.h
@@ -43,7 +43,6 @@ typedef struct _XENVIF_TRANSMITTER XENVIF_TRANSMITTER, 
*PXENVIF_TRANSMITTER;
 extern NTSTATUS
 TransmitterInitialize(
     IN  PXENVIF_FRONTEND    Frontend,
-    IN  ULONG               Count,
     OUT PXENVIF_TRANSMITTER *Transmitter
     );
 
-- 
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®.