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

[win-pv-devel] [PATCH 5/5] Make XENVIF processor group aware



Processor groups have been around for a long time in Windows and
contnuing to ignore them becomes ever more painful when trying to
pass the HCK multiple processor group device test. This patch, therefore,
modifies all the code that uses the non-group-aware kernel calls to use
the newer group aware calls.

Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx>
---
 include/emulated_interface.h |   5 +-
 include/evtchn_interface.h   |  36 +++++-
 src/xenvif/driver.c          |  42 +------
 src/xenvif/driver.h          |   5 -
 src/xenvif/frontend.c        | 197 +++++++++++++++++++----------
 src/xenvif/frontend.h        |   7 +-
 src/xenvif/mac.c             |   7 ++
 src/xenvif/receiver.c        | 230 ++++++++++++++++-----------------
 src/xenvif/transmitter.c     | 294 +++++++++++++++++++++----------------------
 src/xenvif/transmitter.h     |   2 +-
 vs2012/xenvif/xenvif.vcxproj |   4 +-
 vs2013/xenvif/xenvif.vcxproj |   4 +-
 12 files changed, 430 insertions(+), 403 deletions(-)

diff --git a/include/emulated_interface.h b/include/emulated_interface.h
index 85ed2b8..9361f8d 100644
--- a/include/emulated_interface.h
+++ b/include/emulated_interface.h
@@ -66,7 +66,8 @@ typedef VOID
 
     \param Interface The interface header
     \param DeviceID The DeviceID of the device
-    \param InstanceID The (un-prefixed) InstanceID of the device
+    \param InstanceID The (un-prefixed) InstanceID of the device or
+           NULL to match any device instance
     \return TRUE if the specified device is present in the system or
     FALSE if it is not
 */  
@@ -74,7 +75,7 @@ typedef BOOLEAN
 (*XENFILT_EMULATED_IS_DEVICE_PRESENT)(
     IN  PVOID   Context,
     IN  PCHAR   DeviceID,
-    IN  PCHAR   InstanceID
+    IN  PCHAR   InstanceID OPTIONAL
     );
 
 /*! \typedef XENFILT_EMULATED_IS_DISK_PRESENT
diff --git a/include/evtchn_interface.h b/include/evtchn_interface.h
index 1bc456a..6f8fe42 100644
--- a/include/evtchn_interface.h
+++ b/include/evtchn_interface.h
@@ -112,18 +112,27 @@ typedef PXENBUS_EVTCHN_CHANNEL
     ...
     );
 
+typedef NTSTATUS
+(*XENBUS_EVTCHN_BIND_V2)(
+    IN  PINTERFACE              Interface,
+    IN  PXENBUS_EVTCHN_CHANNEL  Channel,
+    IN  ULONG                   Cpu
+    );
+
 /*! \typedef XENBUS_EVTCHN_BIND
     \brief Bind an event channel to a specific CPU
 
     \param Interface The interface header
     \param Channel The channel handle
-    \param Cpu The CPU that should handle events
+    \param Group The group number of the CPU that should handle events
+    \param Number The relative number of the CPU that should handle events
 */
 typedef NTSTATUS
 (*XENBUS_EVTCHN_BIND)(
     IN  PINTERFACE              Interface,
     IN  PXENBUS_EVTCHN_CHANNEL  Channel,
-    IN  ULONG                   Cpu
+    IN  USHORT                  Group,
+    IN  UCHAR                   Number
     );
 
 typedef BOOLEAN
@@ -225,7 +234,7 @@ struct _XENBUS_EVTCHN_INTERFACE_V2 {
     XENBUS_EVTCHN_ACQUIRE   EvtchnAcquire;
     XENBUS_EVTCHN_RELEASE   EvtchnRelease;
     XENBUS_EVTCHN_OPEN      EvtchnOpen;
-    XENBUS_EVTCHN_BIND      EvtchnBind;
+    XENBUS_EVTCHN_BIND_V2   EvtchnBindVersion2;
     XENBUS_EVTCHN_UNMASK_V1 EvtchnUnmaskVersion1;
     XENBUS_EVTCHN_SEND      EvtchnSend;
     XENBUS_EVTCHN_TRIGGER   EvtchnTrigger;
@@ -242,6 +251,23 @@ struct _XENBUS_EVTCHN_INTERFACE_V3 {
     XENBUS_EVTCHN_ACQUIRE   EvtchnAcquire;
     XENBUS_EVTCHN_RELEASE   EvtchnRelease;
     XENBUS_EVTCHN_OPEN      EvtchnOpen;
+    XENBUS_EVTCHN_BIND_V2   EvtchnBindVersion2;
+    XENBUS_EVTCHN_UNMASK    EvtchnUnmask;
+    XENBUS_EVTCHN_SEND      EvtchnSend;
+    XENBUS_EVTCHN_TRIGGER   EvtchnTrigger;
+    XENBUS_EVTCHN_GET_PORT  EvtchnGetPort;
+    XENBUS_EVTCHN_CLOSE     EvtchnClose;
+};
+
+/*! \struct _XENBUS_EVTCHN_INTERFACE_V4
+    \brief EVTCHN interface version 4
+    \ingroup interfaces
+*/
+struct _XENBUS_EVTCHN_INTERFACE_V4 {
+    INTERFACE               Interface;
+    XENBUS_EVTCHN_ACQUIRE   EvtchnAcquire;
+    XENBUS_EVTCHN_RELEASE   EvtchnRelease;
+    XENBUS_EVTCHN_OPEN      EvtchnOpen;
     XENBUS_EVTCHN_BIND      EvtchnBind;
     XENBUS_EVTCHN_UNMASK    EvtchnUnmask;
     XENBUS_EVTCHN_SEND      EvtchnSend;
@@ -250,7 +276,7 @@ struct _XENBUS_EVTCHN_INTERFACE_V3 {
     XENBUS_EVTCHN_CLOSE     EvtchnClose;
 };
 
-typedef struct _XENBUS_EVTCHN_INTERFACE_V3 XENBUS_EVTCHN_INTERFACE, 
*PXENBUS_EVTCHN_INTERFACE;
+typedef struct _XENBUS_EVTCHN_INTERFACE_V4 XENBUS_EVTCHN_INTERFACE, 
*PXENBUS_EVTCHN_INTERFACE;
 
 /*! \def XENBUS_EVTCHN
     \brief Macro at assist in method invocation
@@ -261,7 +287,7 @@ typedef struct _XENBUS_EVTCHN_INTERFACE_V3 
XENBUS_EVTCHN_INTERFACE, *PXENBUS_EVT
 #endif  // _WINDLL
 
 #define XENBUS_EVTCHN_INTERFACE_VERSION_MIN 1
-#define XENBUS_EVTCHN_INTERFACE_VERSION_MAX 3
+#define XENBUS_EVTCHN_INTERFACE_VERSION_MAX 4
 
 #endif  // _XENBUS_EVTCHN_INTERFACE_H
 
diff --git a/src/xenvif/driver.c b/src/xenvif/driver.c
index 589bee9..8cf843f 100644
--- a/src/xenvif/driver.c
+++ b/src/xenvif/driver.c
@@ -30,6 +30,7 @@
  */
 
 #include <ntddk.h>
+#include <procgrp.h>
 #include <version.h>
 
 #include "registry.h"
@@ -47,7 +48,6 @@ typedef struct _XENVIF_DRIVER {
     PDRIVER_OBJECT      DriverObject;
     HANDLE              ParametersKey;
     HANDLE              AddressesKey;
-    ULONG               MaximumQueues;
 } XENVIF_DRIVER, *PXENVIF_DRIVER;
 
 static XENVIF_DRIVER    Driver;
@@ -124,30 +124,6 @@ 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
@@ -173,8 +149,6 @@ DriverUnload(
     ParametersKey = __DriverGetParametersKey();
     __DriverSetParametersKey(NULL);
 
-    __DriverSetMaximumQueueCount(0);
-
     RegistryCloseKey(ParametersKey);
 
     RegistryTeardown();
@@ -281,13 +255,12 @@ DriverEntry(
     HANDLE              ParametersKey;
     HANDLE              AddressesKey;
     ULONG               Index;
-    ULONG               MaxQueues;
-    ULONG               Processors;
     NTSTATUS            status;
 
     ASSERT3P(__DriverGetDriverObject(), ==, NULL);
 
     ExInitializeDriverRuntime(DrvRtPoolNxOptIn);
+    WdmlibProcgrpInitialize();
 
     __DbgPrintEnable();
 
@@ -335,17 +308,6 @@ 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 bbea23b..cdef7d1 100644
--- a/src/xenvif/driver.h
+++ b/src/xenvif/driver.h
@@ -52,11 +52,6 @@ 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 12b9789..3aed6a2 100644
--- a/src/xenvif/frontend.c
+++ b/src/xenvif/frontend.c
@@ -30,6 +30,7 @@
  */
 
 #include <ntddk.h>
+#include <procgrp.h>
 #include <ntstrsafe.h>
 #include <stdlib.h>
 #include <netioapi.h>
@@ -51,6 +52,10 @@
 #include "assert.h"
 #include "util.h"
 
+typedef struct _XENVIF_FRONTEND_STATISTICS {
+    ULONGLONG   Value[XENVIF_VIF_STATISTIC_COUNT];
+} XENVIF_FRONTEND_STATISTICS, *PXENVIF_FRONTEND_STATISTICS;
+
 struct _XENVIF_FRONTEND {
     PXENVIF_PDO                 Pdo;
     PCHAR                       Path;
@@ -62,7 +67,8 @@ struct _XENVIF_FRONTEND {
 
     PCHAR                       BackendPath;
     USHORT                      BackendDomain;
-    ULONG                       QueueCount;
+    ULONG                       MaxQueues;
+    ULONG                       NumQueues;
 
     PXENVIF_MAC                 Mac;
     PXENVIF_RECEIVER            Receiver;
@@ -76,7 +82,8 @@ struct _XENVIF_FRONTEND {
     PXENBUS_DEBUG_CALLBACK      DebugCallback;
     PXENBUS_STORE_WATCH         Watch;
 
-    ULONGLONG                   
Statistic[XENVIF_VIF_STATISTIC_COUNT][MAXIMUM_PROCESSORS];
+    PXENVIF_FRONTEND_STATISTICS Statistics;
+    ULONG                       StatisticsCount;
 };
 
 static const PCHAR
@@ -201,28 +208,41 @@ FrontendGetBackendDomain(
 }
 
 static FORCEINLINE VOID
-__FrontendSetQueueCount(
-    IN  PXENVIF_FRONTEND    Frontend,
-    IN  ULONG               Count
+__FrontendSetMaxQueues(
+    IN  PXENVIF_FRONTEND    Frontend
     )
 {
-    Frontend->QueueCount = Count;
+    HANDLE                  ParametersKey;
+    ULONG                   FrontendMaxQueues;
+    NTSTATUS                status;
+
+    Frontend->MaxQueues = KeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS);
+
+    ParametersKey = DriverGetParametersKey();
+
+    status = RegistryQueryDwordValue(ParametersKey,
+                                     "FrontendMaxQueues",
+                                     &FrontendMaxQueues);
+    if (NT_SUCCESS(status) && FrontendMaxQueues < Frontend->MaxQueues)
+        Frontend->MaxQueues = FrontendMaxQueues;
+
+    Info("%u\n", Frontend->MaxQueues);
 }
 
 static FORCEINLINE ULONG
-__FrontendGetQueueCount(
+__FrontendGetMaxQueues(
     IN  PXENVIF_FRONTEND    Frontend
     )
 {
-    return Frontend->QueueCount;
+    return Frontend->MaxQueues;
 }
 
 ULONG
-FrontendGetQueueCount(
+FrontendGetMaxQueues(
     IN  PXENVIF_FRONTEND    Frontend
     )
 {
-    return __FrontendGetQueueCount(Frontend);
+    return __FrontendGetMaxQueues(Frontend);
 }
 
 PCHAR
@@ -1233,56 +1253,65 @@ fail1:
 static FORCEINLINE VOID
 __FrontendQueryStatistic(
     IN  PXENVIF_FRONTEND        Frontend,
-    IN  XENVIF_VIF_STATISTIC    Index,
+    IN  XENVIF_VIF_STATISTIC    Name,
     OUT PULONGLONG              Value
     )
 {
-    ULONG                       Cpu;
+    ULONG                       Index;
 
-    ASSERT(Index < XENVIF_VIF_STATISTIC_COUNT);
+    ASSERT(Name < XENVIF_VIF_STATISTIC_COUNT);
 
     *Value = 0;
-    for (Cpu = 0; Cpu < MAXIMUM_PROCESSORS; Cpu++)
-        *Value += Frontend->Statistic[Index][Cpu];
+    for (Index = 0; Index < Frontend->StatisticsCount; Index++) {
+        PXENVIF_FRONTEND_STATISTICS Statistics;
+
+        Statistics = &Frontend->Statistics[Index];
+        *Value += Statistics->Value[Name];
+    }
 }
 
 VOID
 FrontendQueryStatistic(
     IN  PXENVIF_FRONTEND        Frontend,
-    IN  XENVIF_VIF_STATISTIC    Index,
+    IN  XENVIF_VIF_STATISTIC    Name,
     OUT PULONGLONG              Value
     )
 {
-    __FrontendQueryStatistic(Frontend, Index, Value);
+    __FrontendQueryStatistic(Frontend, Name, Value);
 }
 
 VOID
 FrontendIncrementStatistic(
     IN  PXENVIF_FRONTEND        Frontend,
-    IN  XENVIF_VIF_STATISTIC    Index,
+    IN  XENVIF_VIF_STATISTIC    Name,
     IN  ULONGLONG               Delta
     )
 {
-    ULONG                       Cpu;
+    ULONG                       Index;
+    PXENVIF_FRONTEND_STATISTICS Statistics;
 
-    ASSERT(Index < XENVIF_VIF_STATISTIC_COUNT);
+    ASSERT(Name < XENVIF_VIF_STATISTIC_COUNT);
 
     ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
 
-    Cpu = KeGetCurrentProcessorNumber();
-    Frontend->Statistic[Index][Cpu] += Delta;
+    Index = KeGetCurrentProcessorNumberEx(NULL);
+
+    ASSERT3U(Index, <, Frontend->StatisticsCount);
+    Statistics = &Frontend->Statistics[Index];
+
+    Statistics->Value[Name] += Delta;
 }
 
 static FORCEINLINE const CHAR *
 __FrontendStatisticName(
-    IN  XENVIF_VIF_STATISTIC    Index
+    IN  XENVIF_VIF_STATISTIC    Name
     )
 {
-#define _FRONTEND_STATISTIC_NAME(_Index)    \
-    case XENVIF_ ## _Index:                 \
-        return #_Index;
+#define _FRONTEND_STATISTIC_NAME(_Name)     \
+    case XENVIF_ ## _Name:                  \
+        return #_Name;
 
-    switch (Index) {
+    switch (Name) {
     _FRONTEND_STATISTIC_NAME(TRANSMITTER_PACKETS_DROPPED);
     _FRONTEND_STATISTIC_NAME(TRANSMITTER_BACKEND_ERRORS);
     _FRONTEND_STATISTIC_NAME(TRANSMITTER_FRONTEND_ERRORS);
@@ -1317,7 +1346,7 @@ FrontendDebugCallback(
     )
 {
     PXENVIF_FRONTEND        Frontend = Argument;
-    XENVIF_VIF_STATISTIC    Index;
+    XENVIF_VIF_STATISTIC    Name;
 
     UNREFERENCED_PARAMETER(Crashing);
 
@@ -1330,33 +1359,28 @@ FrontendDebugCallback(
                  &Frontend->DebugInterface,
                  "STATISTICS:\n");
 
-    for (Index = 0; Index < XENVIF_VIF_STATISTIC_COUNT; Index++) {
+    for (Name = 0; Name < XENVIF_VIF_STATISTIC_COUNT; Name++) {
         ULONGLONG   Value;
 
-        __FrontendQueryStatistic(Frontend, Index, &Value);
+        __FrontendQueryStatistic(Frontend, Name, &Value);
 
         XENBUS_DEBUG(Printf,
                      &Frontend->DebugInterface,
                      " - %40s %lu\n",
-                     __FrontendStatisticName(Index),
+                     __FrontendStatisticName(Name),
                      Value);
     }
 }
 
 static FORCEINLINE VOID
-__FrontendReadQueueCount(
+__FrontendSetNumQueues(
     IN  PXENVIF_FRONTEND    Frontend
     )
 {
     PCHAR                   Buffer;
-    ULONG                   Value;
+    ULONG                   BackendMaxQueues;
     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,
@@ -1364,19 +1388,34 @@ __FrontendReadQueueCount(
                           "multi-queue-max-queues",
                           &Buffer);
     if (NT_SUCCESS(status)) {
-        Value = (ULONG)strtoul(Buffer, NULL, 10);
+        BackendMaxQueues = (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();
+    } else {
+        BackendMaxQueues = 1;
     }
 
-    __FrontendSetQueueCount(Frontend, Value);
+    Frontend->NumQueues = __min(Frontend->MaxQueues, BackendMaxQueues);
+
+    Info("%u\n", Frontend->NumQueues);
+}
+
+static FORCEINLINE ULONG
+__FrontendGetNumQueues(
+    IN  PXENVIF_FRONTEND    Frontend
+    )
+{
+    return Frontend->NumQueues;
+}
+
+ULONG
+FrontendGetNumQueues(
+    IN  PXENVIF_FRONTEND    Frontend
+    )
+{
+    return __FrontendGetNumQueues(Frontend);
 }
 
 static FORCEINLINE NTSTATUS
@@ -1391,9 +1430,16 @@ __FrontendConnect(
 
     Trace("====>\n");
 
+    Frontend->StatisticsCount = 
KeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS);
+    Frontend->Statistics = __FrontendAllocate(sizeof 
(XENVIF_FRONTEND_STATISTICS) * Frontend->StatisticsCount);
+
+    status = STATUS_NO_MEMORY;
+    if (Frontend->Statistics == NULL)
+        goto fail1;
+
     status = XENBUS_DEBUG(Acquire, &Frontend->DebugInterface);
     if (!NT_SUCCESS(status))
-        goto fail1;
+        goto fail2;
 
     status = XENBUS_DEBUG(Register,
                           &Frontend->DebugInterface,
@@ -1402,20 +1448,21 @@ __FrontendConnect(
                           Frontend,
                           &Frontend->DebugCallback);
     if (!NT_SUCCESS(status))
-        goto fail2;
+        goto fail3;
 
     status = MacConnect(__FrontendGetMac(Frontend));
     if (!NT_SUCCESS(status))
-        goto fail3;
+        goto fail4;
+
+    __FrontendSetNumQueues(Frontend);
 
-    __FrontendReadQueueCount(Frontend);
     status = ReceiverConnect(__FrontendGetReceiver(Frontend));
     if (!NT_SUCCESS(status))
-        goto fail4;
+        goto fail5;
 
     status = TransmitterConnect(__FrontendGetTransmitter(Frontend));
     if (!NT_SUCCESS(status))
-        goto fail5;
+        goto fail6;
 
     Attempt = 0;
     do {
@@ -1443,7 +1490,7 @@ __FrontendConnect(
                               __FrontendGetPath(Frontend),
                               "multi-queue-num-queues",
                               "%u",
-                              __FrontendGetQueueCount(Frontend));
+                              __FrontendGetNumQueues(Frontend));
         if (!NT_SUCCESS(status))
             goto abort;
 
@@ -1465,7 +1512,7 @@ abort:
     } while (status == STATUS_RETRY);
 
     if (!NT_SUCCESS(status))
-        goto fail6;
+        goto fail7;
 
     status = XENBUS_STORE(Printf,
                           &Frontend->StoreInterface,
@@ -1475,22 +1522,25 @@ abort:
                           "%u",
                           XenbusStateConnected);
     if (!NT_SUCCESS(status))
-        goto fail7;
+        goto fail8;
 
     State = XenbusStateInitWait;
     status = __FrontendWaitForStateChange(Frontend, Path, &State);
     if (!NT_SUCCESS(status))
-        goto fail8;
+        goto fail9;
 
     status = STATUS_UNSUCCESSFUL;
     if (State != XenbusStateConnected)
-        goto fail9;
+        goto fail10;
 
     ThreadWake(Frontend->MibThread);
 
     Trace("<====\n");
     return STATUS_SUCCESS;
 
+fail10:
+    Error("fail10\n");
+
 fail9:
     Error("fail9\n");
 
@@ -1500,33 +1550,38 @@ fail8:
 fail7:
     Error("fail7\n");
 
+    TransmitterDisconnect(__FrontendGetTransmitter(Frontend));
+
 fail6:
     Error("fail6\n");
 
-    TransmitterDisconnect(__FrontendGetTransmitter(Frontend));
+    ReceiverDisconnect(__FrontendGetReceiver(Frontend));
 
 fail5:
     Error("fail5\n");
 
-    ReceiverDisconnect(__FrontendGetReceiver(Frontend));
+    MacDisconnect(__FrontendGetMac(Frontend));
+
+    Frontend->NumQueues = 0;
 
 fail4:
     Error("fail4\n");
 
-    MacDisconnect(__FrontendGetMac(Frontend));
-
-fail3:
-    Error("fail3\n");
-
     XENBUS_DEBUG(Deregister,
                  &Frontend->DebugInterface,
                  Frontend->DebugCallback);
     Frontend->DebugCallback = NULL;
 
+fail3:
+    Error("fail3\n");
+
+    XENBUS_DEBUG(Release, &Frontend->DebugInterface);
+
 fail2:
     Error("fail2\n");
 
-    XENBUS_DEBUG(Release, &Frontend->DebugInterface);
+    __FrontendFree(Frontend->Statistics);
+    Frontend->StatisticsCount = 0;   
 
 fail1:
     Error("fail1 (%08x)\n", status);
@@ -1546,6 +1601,8 @@ __FrontendDisconnect(
     ReceiverDisconnect(__FrontendGetReceiver(Frontend));
     MacDisconnect(__FrontendGetMac(Frontend));
 
+    Frontend->NumQueues = 0;
+
     XENBUS_DEBUG(Deregister,
                  &Frontend->DebugInterface,
                  Frontend->DebugCallback);
@@ -1553,7 +1610,8 @@ __FrontendDisconnect(
 
     XENBUS_DEBUG(Release, &Frontend->DebugInterface);
 
-    RtlZeroMemory(&Frontend->Statistic, sizeof (Frontend->Statistic));
+    __FrontendFree(Frontend->Statistics);
+    Frontend->StatisticsCount = 0;
 
     Trace("<====\n");
 }
@@ -1958,6 +2016,8 @@ FrontendInitialize(
     FdoGetSuspendInterface(PdoGetFdo(Pdo), &(*Frontend)->SuspendInterface);
     FdoGetStoreInterface(PdoGetFdo(Pdo), &(*Frontend)->StoreInterface);
 
+    __FrontendSetMaxQueues(*Frontend);
+
     status = MacInitialize(*Frontend, &(*Frontend)->Mac);
     if (!NT_SUCCESS(status))
         goto fail6;
@@ -2010,6 +2070,8 @@ fail7:
 fail6:
     Error("fail6\n");
 
+    (*Frontend)->MaxQueues = 0;
+
     RtlZeroMemory(&(*Frontend)->StoreInterface,
                   sizeof (XENBUS_STORE_INTERFACE));
 
@@ -2020,6 +2082,7 @@ fail6:
                   sizeof (XENBUS_DEBUG_INTERFACE));
 
     (*Frontend)->State = FRONTEND_STATE_INVALID;
+
     RtlZeroMemory(&(*Frontend)->Lock, sizeof (KSPIN_LOCK));
 
     (*Frontend)->BackendDomain = 0;
@@ -2091,6 +2154,8 @@ FrontendTeardown(
     MacTeardown(__FrontendGetMac(Frontend));
     Frontend->Mac = NULL;
 
+    Frontend->MaxQueues = 0;
+
     RtlZeroMemory(&Frontend->StoreInterface,
                   sizeof (XENBUS_STORE_INTERFACE));
 
@@ -2101,10 +2166,10 @@ FrontendTeardown(
                   sizeof (XENBUS_DEBUG_INTERFACE));
 
     Frontend->State = FRONTEND_STATE_INVALID;
+
     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 adcf53c..1673fac 100644
--- a/src/xenvif/frontend.h
+++ b/src/xenvif/frontend.h
@@ -113,7 +113,12 @@ FrontendGetBackendDomain(
     );
 
 extern ULONG
-FrontendGetQueueCount(
+FrontendGetMaxQueues(
+    IN  PXENVIF_FRONTEND    Frontend
+    );
+
+extern ULONG
+FrontendGetNumQueues(
     IN  PXENVIF_FRONTEND    Frontend
     );
 
diff --git a/src/xenvif/mac.c b/src/xenvif/mac.c
index 1d60a1f..b255d58 100644
--- a/src/xenvif/mac.c
+++ b/src/xenvif/mac.c
@@ -349,6 +349,8 @@ MacEnable(
     PXENVIF_THREAD      Thread;
     NTSTATUS            status;
 
+    Trace("====>\n");
+
     Frontend = Mac->Frontend;
 
     ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
@@ -370,6 +372,7 @@ MacEnable(
 
     KeReleaseSpinLockFromDpcLevel(&Mac->Lock);
 
+    Trace("<====\n");
     return STATUS_SUCCESS;
 
 fail1:
@@ -387,6 +390,8 @@ MacDisable(
 {
     PXENVIF_FRONTEND    Frontend;
 
+    Trace("====>\n");
+
     Frontend = Mac->Frontend;
 
     ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
@@ -401,6 +406,8 @@ MacDisable(
     Mac->Watch = NULL;
 
     KeReleaseSpinLockFromDpcLevel(&Mac->Lock);
+
+    Trace("<====\n");
 }
 
 VOID
diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c
index 6f45627..f09b71c 100644
--- a/src/xenvif/receiver.c
+++ b/src/xenvif/receiver.c
@@ -30,6 +30,7 @@
  */
 
 #include <ntddk.h>
+#include <procgrp.h>
 #include <ntstrsafe.h>
 #include <stdlib.h>
 #include <xen.h>
@@ -108,7 +109,9 @@ struct _XENVIF_RECEIVER {
     XENBUS_CACHE_INTERFACE  CacheInterface;
     XENBUS_GNTTAB_INTERFACE GnttabInterface;
     XENBUS_EVTCHN_INTERFACE EvtchnInterface;
-    PXENVIF_RECEIVER_RING   Rings[MAXIMUM_PROCESSORS];
+    PXENVIF_RECEIVER_RING   *Ring;
+    LONG                    MaxQueues;
+    LONG                    NumQueues;
     BOOLEAN                 Split;
     LONG                    Loaned;
     LONG                    Returned;
@@ -1914,13 +1917,10 @@ ReceiverRingDpc(
     Frontend = Receiver->Frontend;
 
     if (Ring->Enabled) {
-        if (Receiver->Split) {
-            __ReceiverRingNotify(Ring);
-        } else {
-            TransmitterRingNotify(FrontendGetTransmitter(Frontend),
-                                  Ring->Index);
-            __ReceiverRingNotify(Ring);
-        }
+        __ReceiverRingNotify(Ring);
+        if (!Receiver->Split)
+            TransmitterNotify(FrontendGetTransmitter(Frontend),
+                              Ring->Index);
     }
 
     __ReceiverRingUnmask(Ring);
@@ -2175,6 +2175,7 @@ __ReceiverRingConnect(
     PFN_NUMBER                  Pfn;
     CHAR                        Name[MAXNAMELEN];
     ULONG                       Index;
+    PROCESSOR_NUMBER            ProcNumber;
     NTSTATUS                    status;
 
     Receiver = Ring->Receiver;
@@ -2249,15 +2250,16 @@ __ReceiverRingConnect(
     if (Ring->Channel == NULL)
         goto fail6;
 
-    if (FrontendGetQueueCount(Frontend) > 1) {
-        (VOID) XENBUS_EVTCHN(Bind,
-                                &Receiver->EvtchnInterface,
-                                Ring->Channel,
-                                Ring->Index);
+    status = KeGetProcessorNumberFromIndex(Ring->Index, &ProcNumber);
+    ASSERT(NT_SUCCESS(status));
 
-        KeSetTargetProcessorDpc(&Ring->Dpc,
-                                (CCHAR)Ring->Index);
-    }
+    KeSetTargetProcessorDpcEx(&Ring->Dpc, &ProcNumber);
+
+    (VOID) XENBUS_EVTCHN(Bind,
+                         &Receiver->EvtchnInterface,
+                         Ring->Channel,
+                         ProcNumber.Group,
+                         ProcNumber.Number);
 
     XENBUS_EVTCHN(Unmask,
                   &Receiver->EvtchnInterface,
@@ -2344,10 +2346,9 @@ __ReceiverRingStoreWrite(
     Receiver = Ring->Receiver;
     Frontend = Receiver->Frontend;
 
-    ASSERT(IMPLY(FrontendGetQueueCount(Frontend) == 1, Ring->Index == 0));
-    Path = (FrontendGetQueueCount(Frontend) == 1) ?
-                    FrontendGetPath(Frontend) :
-                    Ring->Path;
+    Path = (Receiver->NumQueues == 1) ?
+           FrontendGetPath(Frontend) :
+           Ring->Path;
 
     status = XENBUS_STORE(Printf,
                           &Receiver->StoreInterface,
@@ -2581,11 +2582,9 @@ ReceiverInitialize(
     )
 {
     HANDLE                  ParametersKey;
-    ULONG                   Index;
-    ULONG                   Count;
+    LONG                    Index;
     NTSTATUS                status;
 
-    Count = DriverGetMaximumQueueCount();
     *Receiver = __ReceiverAllocate(sizeof (XENVIF_RECEIVER));
 
     status = STATUS_NO_MEMORY;
@@ -2600,7 +2599,6 @@ ReceiverInitialize(
     (*Receiver)->DisableIpVersion6Gso = 0;
     (*Receiver)->IpAlignOffset = 0;
     (*Receiver)->AlwaysPullup = 0;
-    (*Receiver)->Split = FALSE;
 
     if (ParametersKey != NULL) {
         ULONG   ReceiverCalculateChecksums;
@@ -2670,34 +2668,46 @@ ReceiverInitialize(
     if (!NT_SUCCESS(status))
         goto fail2;
 
-    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
-    for (Index = 0; Index < Count; ++Index) {
+    (*Receiver)->MaxQueues = FrontendGetMaxQueues(Frontend);
+    (*Receiver)->Ring = __ReceiverAllocate(sizeof (PXENVIF_RECEIVER_RING) *
+                                           (*Receiver)->MaxQueues);
+
+    status = STATUS_NO_MEMORY;
+    if ((*Receiver)->Ring == NULL)
+        goto fail3;
+
+    Index = 0;
+    while (Index < (*Receiver)->MaxQueues) {
         PXENVIF_RECEIVER_RING   Ring;
 
         status = __ReceiverRingInitialize(*Receiver, Index, &Ring);
         if (!NT_SUCCESS(status))
-            goto fail3;
+            goto fail4;
 
-        (*Receiver)->Rings[Index] = Ring;
+        (*Receiver)->Ring[Index] = Ring;
+        Index++;
     }
 
     return STATUS_SUCCESS;
 
-fail3:
-    Error("fail3\n");
-
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
-        PXENVIF_RECEIVER_RING   Ring;
-
-        Ring = (*Receiver)->Rings[Index];
-        (*Receiver)->Rings[Index] = NULL;
+fail4:
+    Error("fail4\n");
 
-        if (Ring == NULL)
-            continue; // ensure all rings are destroyed
+    while (--Index >= 0) {
+        PXENVIF_RECEIVER_RING   Ring = (*Receiver)->Ring[Index];
 
+        (*Receiver)->Ring[Index] = NULL;
         __ReceiverRingTeardown(Ring);
     }
 
+    __ReceiverFree((*Receiver)->Ring);
+    (*Receiver)->Ring = NULL;
+
+fail3:
+    Error("fail3\n");
+
+    (*Receiver)->MaxQueues = 0;
+
     XENBUS_CACHE(Release, &(*Receiver)->CacheInterface);
 
 fail2:
@@ -2728,7 +2738,6 @@ fail2:
     (*Receiver)->DisableIpVersion6Gso = 0;
     (*Receiver)->IpAlignOffset = 0;
     (*Receiver)->AlwaysPullup = 0;
-    (*Receiver)->Split = FALSE;
 
     ASSERT(IsZeroMemory(*Receiver, sizeof (XENVIF_RECEIVER)));
     __ReceiverFree(*Receiver);
@@ -2745,8 +2754,7 @@ ReceiverConnect(
     )
 {
     PXENVIF_FRONTEND        Frontend;
-    ULONG                   Index;
-    ULONG                   Count;
+    LONG                    Index;
     PCHAR                   Buffer;
     NTSTATUS                status;
 
@@ -2784,19 +2792,18 @@ ReceiverConnect(
                      Buffer);
     }
 
-    Count = FrontendGetQueueCount(Frontend);
-    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
-
-    for (Index = 0; Index < Count; ++Index) {
-        PXENVIF_RECEIVER_RING   Ring;
+    Receiver->NumQueues = FrontendGetNumQueues(Frontend);
+    ASSERT3U(Receiver->NumQueues, <=, Receiver->MaxQueues);
 
-        Ring = Receiver->Rings[Index];
-        if (Ring == NULL)
-            break;
+    Index = 0;
+    while (Index < Receiver->NumQueues) {
+        PXENVIF_RECEIVER_RING   Ring = Receiver->Ring[Index];
 
         status = __ReceiverRingConnect(Ring);
         if (!NT_SUCCESS(status))
             goto fail5;
+
+        Index++;
     }    
 
     status = XENBUS_DEBUG(Register,
@@ -2813,19 +2820,19 @@ ReceiverConnect(
 fail6:
     Error("fail6\n");
 
+    Index = Receiver->NumQueues;
+
 fail5:
     Error("fail5\n");
 
-    for (Index = 0; Index < Count; ++Index) {
-        PXENVIF_RECEIVER_RING   Ring;
-
-        Ring = Receiver->Rings[Index];
-        if (Ring == NULL)
-            break;
+    while (--Index >= 0) {
+        PXENVIF_RECEIVER_RING   Ring = Receiver->Ring[Index];
 
         __ReceiverRingDisconnect(Ring);
     }
 
+    Receiver->NumQueues = 0;
+
     XENBUS_GNTTAB(Release, &Receiver->GnttabInterface);
 
 fail4:
@@ -2940,8 +2947,7 @@ ReceiverStoreWrite(
     )
 {
     PXENVIF_FRONTEND                Frontend;
-    ULONG                           Index;
-    ULONG                           Count;
+    LONG                            Index;
     NTSTATUS                        status;
 
     Frontend = Receiver->Frontend;
@@ -2984,19 +2990,15 @@ ReceiverStoreWrite(
     if (!NT_SUCCESS(status))
         goto fail5;
 
-    Count = FrontendGetQueueCount(Frontend);
-    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
-
-    for (Index = 0; Index < Count; ++Index) {
-        PXENVIF_RECEIVER_RING   Ring;
-
-        Ring = Receiver->Rings[Index];
-        if (Ring == NULL)
-            break;
+    Index = 0;
+    while (Index < Receiver->NumQueues) {
+        PXENVIF_RECEIVER_RING   Ring = Receiver->Ring[Index];
 
         status = __ReceiverRingStoreWrite(Ring, Transaction);
         if (!NT_SUCCESS(status))
             goto fail6;
+
+        Index++;
     }    
 
     return STATUS_SUCCESS;
@@ -3027,37 +3029,32 @@ ReceiverEnable(
     IN  PXENVIF_RECEIVER    Receiver
     )
 {
-    PXENVIF_FRONTEND        Frontend;
-    ULONG                   Index;
-    ULONG                   Count;
+    LONG                    Index;
     NTSTATUS                status;
 
-    Frontend = Receiver->Frontend;
-
-    Count = FrontendGetQueueCount(Frontend);
-    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
-
-    for (Index = 0; Index < Count; ++Index) {
-        PXENVIF_RECEIVER_RING   Ring;
+    Trace("====>\n");
 
-        Ring = Receiver->Rings[Index];
-        if (Ring == NULL)
-            break;
+    Index = 0;
+    while (Index < Receiver->NumQueues) {
+        PXENVIF_RECEIVER_RING   Ring = Receiver->Ring[Index];
 
         status = __ReceiverRingEnable(Ring);
         if (!NT_SUCCESS(status))
             goto fail1;
+
+        Index++;
     }    
 
+    Trace("<====\n");
     return STATUS_SUCCESS;
 
 fail1:
     Error("fail1 (%08x)\n", status);
 
-    for (Index = 0; Index < Count; ++Index) {
+    while (--Index >= 0) {
         PXENVIF_RECEIVER_RING   Ring;
 
-        Ring = Receiver->Rings[Index];
+        Ring = Receiver->Ring[Index];
         if (Ring == NULL)
             break;
 
@@ -3072,21 +3069,18 @@ ReceiverDisable(
     IN  PXENVIF_RECEIVER    Receiver
     )
 {
-    ULONG                   Index;
-    ULONG                   Count;
+    LONG                    Index;
 
-    Count = FrontendGetQueueCount(Receiver->Frontend);
-    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
-
-    for (Index = 0; Index < Count; ++Index) {
-        PXENVIF_RECEIVER_RING   Ring;
+    Trace("====>\n");
 
-        Ring = Receiver->Rings[Index];
-        if (Ring == NULL)
-            break;
+    Index = Receiver->NumQueues;
+    while (--Index >= 0) {
+        PXENVIF_RECEIVER_RING   Ring = Receiver->Ring[Index];
 
         __ReceiverRingDisable(Ring);
     }
+
+    Trace("<====\n");
 }
 
 VOID
@@ -3095,8 +3089,7 @@ ReceiverDisconnect(
     )
 {
     PXENVIF_FRONTEND        Frontend;
-    ULONG                   Index;
-    ULONG                   Count;
+    LONG                    Index;
 
     Frontend = Receiver->Frontend;
 
@@ -3107,19 +3100,15 @@ ReceiverDisconnect(
                  Receiver->DebugCallback);
     Receiver->DebugCallback = NULL;
 
-    Count = FrontendGetQueueCount(Frontend);
-    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
-
-    for (Index = 0; Index < Count; ++Index) {
-        PXENVIF_RECEIVER_RING   Ring;
-
-        Ring = Receiver->Rings[Index];
-        if (Ring == NULL)
-            break;
+    Index = Receiver->NumQueues;
+    while (--Index >= 0) {
+        PXENVIF_RECEIVER_RING   Ring = Receiver->Ring[Index];
 
         __ReceiverRingDisconnect(Ring);
     }
 
+    Receiver->NumQueues = 0;
+
     XENBUS_GNTTAB(Release, &Receiver->GnttabInterface);
 
     XENBUS_EVTCHN(Release, &Receiver->EvtchnInterface);
@@ -3134,7 +3123,7 @@ ReceiverTeardown(
     IN  PXENVIF_RECEIVER    Receiver
     )
 {
-    ULONG                   Index;
+    LONG                    Index;
 
     ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
     KeFlushQueuedDpcs();
@@ -3143,22 +3132,21 @@ ReceiverTeardown(
     Receiver->Loaned = 0;
     Receiver->Returned = 0;
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
-        PXENVIF_RECEIVER_RING   Ring;
-
-        Ring = Receiver->Rings[Index];
-        Receiver->Rings[Index] = NULL;
-
-        if (Ring == NULL)
-            continue; // ensure all rings are destroyed
+    Index = Receiver->MaxQueues;
+    while (--Index >= 0) {
+        PXENVIF_RECEIVER_RING   Ring = Receiver->Ring[Index];
 
+        Receiver->Ring[Index] = NULL;
         __ReceiverRingTeardown(Ring);
     }
 
+    __ReceiverFree(Receiver->Ring);
+    Receiver->Ring = NULL;
+    Receiver->MaxQueues;
+
     XENBUS_CACHE(Release, &Receiver->CacheInterface);
 
     Receiver->Frontend = NULL;
-    Receiver->Split = FALSE;
 
     RtlZeroMemory(&Receiver->EvtchnInterface,
                   sizeof (XENBUS_EVTCHN_INTERFACE));
@@ -3194,8 +3182,7 @@ ReceiverSetOffloadOptions(
     IN  XENVIF_VIF_OFFLOAD_OPTIONS  Options
     )
 {
-    ULONG                           Index;
-    ULONG                           Count;
+    LONG                            Index;
 
     if (Receiver->AllowGsoPackets == 0) {
         Warning("RECEIVER GSO DISALLOWED\n");
@@ -3203,13 +3190,10 @@ ReceiverSetOffloadOptions(
         Options.OffloadIpVersion6LargePacket = 0;
     }
 
-    Count = FrontendGetQueueCount(Receiver->Frontend);
-    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
-
-    for (Index = 0; Index < Count; ++Index) {
+    for (Index = 0; Index < Receiver->MaxQueues; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
-        Ring = Receiver->Rings[Index];
+        Ring = Receiver->Ring[Index];
         if (Ring == NULL)
             break;
 
@@ -3304,12 +3288,8 @@ ReceiverSend(
 {
     PXENVIF_RECEIVER_RING   Ring;
 
-    if (Index >= MAXIMUM_PROCESSORS)
-        return;
-
-    Ring = Receiver->Rings[Index];
-    if (Ring == NULL)
-        return;
+    ASSERT3U(Index, <, (ULONG)Receiver->NumQueues);
+    Ring = Receiver->Ring[Index];
 
     __ReceiverRingSend(Ring, FALSE);
 }
diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
index 9f81ca1..7fe1738 100644
--- a/src/xenvif/transmitter.c
+++ b/src/xenvif/transmitter.c
@@ -30,6 +30,7 @@
  */
 
 #include <ntddk.h>
+#include <procgrp.h>
 #include <ntstrsafe.h>
 #include <stdlib.h>
 #include <netioapi.h>
@@ -149,7 +150,9 @@ struct _XENVIF_TRANSMITTER {
     XENBUS_GNTTAB_INTERFACE     GnttabInterface;
     XENBUS_RANGE_SET_INTERFACE  RangeSetInterface;
     XENBUS_EVTCHN_INTERFACE     EvtchnInterface;
-    PXENVIF_TRANSMITTER_RING    Rings[MAXIMUM_PROCESSORS];
+    PXENVIF_TRANSMITTER_RING    *Ring;
+    LONG                        MaxQueues;
+    LONG                        NumQueues;
     LONG_PTR                    Offset[XENVIF_TRANSMITTER_PACKET_OFFSET_COUNT];
     BOOLEAN                     Split;
     ULONG                       DisableIpVersion4Gso;
@@ -3030,6 +3033,7 @@ __TransmitterRingConnect(
     PFN_NUMBER                      Pfn;
     CHAR                            Name[MAXNAMELEN];
     ULONG                           Index;
+    PROCESSOR_NUMBER                ProcNumber;
     NTSTATUS                        status;
 
     ASSERT(!Ring->Connected);
@@ -3107,15 +3111,16 @@ __TransmitterRingConnect(
         if (Ring->Channel == NULL)
             goto fail6;
 
-        if (FrontendGetQueueCount(Frontend) > 1) {
-            (VOID) XENBUS_EVTCHN(Bind,
-                                 &Transmitter->EvtchnInterface,
-                                 Ring->Channel,
-                                 Ring->Index);
+        status = KeGetProcessorNumberFromIndex(Ring->Index, &ProcNumber);
+        ASSERT(NT_SUCCESS(status));
 
-            KeSetTargetProcessorDpc(&Ring->Dpc,
-                                    (CCHAR)Ring->Index);
-        }
+        KeSetTargetProcessorDpcEx(&Ring->Dpc, &ProcNumber);
+
+        (VOID) XENBUS_EVTCHN(Bind,
+                             &Transmitter->EvtchnInterface,
+                             Ring->Channel,
+                             ProcNumber.Group,
+                             ProcNumber.Number);
 
         XENBUS_EVTCHN(Unmask,
                       &Transmitter->EvtchnInterface,
@@ -3201,10 +3206,9 @@ __TransmitterRingStoreWrite(
     Transmitter = Ring->Transmitter;
     Frontend = Transmitter->Frontend;
 
-    ASSERT(IMPLY(FrontendGetQueueCount(Frontend) == 1, Ring->Index == 0));
-    Path = (FrontendGetQueueCount(Frontend) == 1) ?
-                    FrontendGetPath(Frontend) :
-                    Ring->Path;
+    Path = (Transmitter->NumQueues == 1) ?
+           FrontendGetPath(Frontend) :
+           Ring->Path;
 
     status = XENBUS_STORE(Printf,
                           &Transmitter->StoreInterface,
@@ -3290,9 +3294,8 @@ __TransmitterRingDisable(
     Packet = __TransmitterRingUnpreparePacket(Ring);
 
     // Put any packet back on the head of the queue
-    if (Packet != NULL) {
+    if (Packet != NULL)
         InsertHeadList(&Ring->Queued, &Packet->ListEntry);
-    }
 
     Ring->AddressIndex = 0;
 
@@ -3559,11 +3562,9 @@ TransmitterInitialize(
     )
 {
     HANDLE                  ParametersKey;
-    ULONG                   Index;
-    ULONG                   Count;
+    LONG                    Index;
     NTSTATUS                status;
 
-    Count = DriverGetMaximumQueueCount();
     *Transmitter = __TransmitterAllocate(sizeof (XENVIF_TRANSMITTER));
 
     status = STATUS_NO_MEMORY;
@@ -3575,7 +3576,6 @@ TransmitterInitialize(
     (*Transmitter)->DisableIpVersion4Gso = 0;
     (*Transmitter)->DisableIpVersion6Gso = 0;
     (*Transmitter)->AlwaysCopy = 0;
-    (*Transmitter)->Split = FALSE;
 
     if (ParametersKey != NULL) {
         ULONG   TransmitterDisableIpVersion4Gso;
@@ -3630,34 +3630,46 @@ TransmitterInitialize(
     if (!NT_SUCCESS(status))
         goto fail3;
 
-    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
-    for (Index = 0; Index < Count; ++Index) {
+    (*Transmitter)->MaxQueues = FrontendGetMaxQueues(Frontend);
+    (*Transmitter)->Ring = __TransmitterAllocate(sizeof 
(PXENVIF_TRANSMITTER_RING) *
+                                                 (*Transmitter)->MaxQueues);
+
+    status = STATUS_NO_MEMORY;
+    if ((*Transmitter)->Ring == NULL)
+        goto fail4;
+
+    Index = 0;
+    while (Index < (*Transmitter)->MaxQueues) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
         status = __TransmitterRingInitialize(*Transmitter, Index, &Ring);
         if (!NT_SUCCESS(status))
-            goto fail4;
+            goto fail5;
 
-        (*Transmitter)->Rings[Index] = Ring;
+        (*Transmitter)->Ring[Index] = Ring;
+        Index++;
     }
 
     return STATUS_SUCCESS;
 
-fail4:
-    Error("fail4\n");
-
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
-        PXENVIF_TRANSMITTER_RING    Ring;
-
-        Ring = (*Transmitter)->Rings[Index];
-        (*Transmitter)->Rings[Index] = NULL;
+fail5:
+    Error("fail5\n");
 
-        if (Ring == NULL)
-            continue; // ensure all rings are destroyed
+    while (--Index > 0) {
+        PXENVIF_TRANSMITTER_RING    Ring = (*Transmitter)->Ring[Index];
 
+        (*Transmitter)->Ring[Index] = NULL;
         __TransmitterRingTeardown(Ring);
     }
 
+    __TransmitterFree((*Transmitter)->Ring);
+    (*Transmitter)->Ring = NULL;
+
+fail4:
+    Error("fail4\n");
+
+    (*Transmitter)->MaxQueues = 0;
+
     XENBUS_CACHE(Release, &(*Transmitter)->CacheInterface);
 
 fail3:
@@ -3709,8 +3721,7 @@ TransmitterConnect(
     PXENVIF_FRONTEND            Frontend;
     CHAR                        Name[MAXNAMELEN];
     PCHAR                       Buffer;
-    ULONG                       Index;
-    ULONG                       Count;
+    LONG                        Index;
     NTSTATUS                    status;
 
     Frontend = Transmitter->Frontend;
@@ -3772,19 +3783,18 @@ TransmitterConnect(
                      Buffer);
     }
 
-    Count = FrontendGetQueueCount(Frontend);
-    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
-
-    for (Index = 0; Index < Count; ++Index) {
-        PXENVIF_TRANSMITTER_RING    Ring;
+    Transmitter->NumQueues = FrontendGetNumQueues(Frontend);
+    ASSERT3U(Transmitter->NumQueues, <=, Transmitter->MaxQueues);
 
-        Ring = Transmitter->Rings[Index];
-        if (Ring == NULL)
-            break;
+    Index = 0;
+    while (Index < Transmitter->NumQueues) {
+        PXENVIF_TRANSMITTER_RING    Ring = Transmitter->Ring[Index];
 
         status = __TransmitterRingConnect(Ring);
         if (!NT_SUCCESS(status))
             goto fail7;
+
+        Index++;
     }    
 
     status = XENBUS_DEBUG(Register,
@@ -3801,19 +3811,21 @@ TransmitterConnect(
 fail8:
     Error("fail8\n");
 
+    Index = Transmitter->NumQueues;
+
 fail7:
     Error("fail7\n");
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    while (--Index >= 0) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
-        Ring = Transmitter->Rings[Index];
-        if (Ring == NULL)
-            continue; // ensure all rings are destroyed
+        Ring = Transmitter->Ring[Index];
 
         __TransmitterRingDisconnect(Ring);
     }
 
+    Transmitter->NumQueues = 0;
+
     XENBUS_CACHE(Destroy,
                  &Transmitter->CacheInterface,
                  Transmitter->PacketCache);
@@ -3855,22 +3867,17 @@ TransmitterStoreWrite(
     )
 {
     NTSTATUS                        status;
-    ULONG                           Index;
-    ULONG                           Count;
-
-    Count = FrontendGetQueueCount(Transmitter->Frontend);
-    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
-
-    for (Index = 0; Index < Count; ++Index) {
-        PXENVIF_TRANSMITTER_RING    Ring;
+    LONG                            Index;
 
-        Ring = Transmitter->Rings[Index];
-        if (Ring == NULL)
-            break;
+    Index = 0;
+    while (Index < Transmitter->NumQueues) {
+        PXENVIF_TRANSMITTER_RING    Ring = Transmitter->Ring[Index];
 
         status = __TransmitterRingStoreWrite(Ring, Transaction);
         if (!NT_SUCCESS(status))
             goto fail1;
+
+        Index++;
     }    
 
     return STATUS_SUCCESS;
@@ -3886,22 +3893,19 @@ TransmitterEnable(
     IN  PXENVIF_TRANSMITTER Transmitter
     )
 {
-    ULONG                   Index;
-    ULONG                   Count;
-
-    Count = FrontendGetQueueCount(Transmitter->Frontend);
-    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+    LONG                    Index;
 
-    for (Index = 0; Index < Count; ++Index) {
-        PXENVIF_TRANSMITTER_RING    Ring;
+    Trace("====>\n");
 
-        Ring = Transmitter->Rings[Index];
-        if (Ring == NULL)
-            break;
+    Index = 0;
+    while (Index < Transmitter->NumQueues) {
+        PXENVIF_TRANSMITTER_RING    Ring = Transmitter->Ring[Index];
 
         __TransmitterRingEnable(Ring);
+        Index++;
     }    
 
+    Trace("<====\n");
     return STATUS_SUCCESS;
 }
 
@@ -3910,21 +3914,18 @@ TransmitterDisable(
     IN  PXENVIF_TRANSMITTER Transmitter
     )
 {
-    ULONG                   Index;
-    ULONG                   Count;
-
-    Count = FrontendGetQueueCount(Transmitter->Frontend);
-    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+    LONG                   Index;
 
-    for (Index = 0; Index < Count; ++Index) {
-        PXENVIF_TRANSMITTER_RING    Ring;
+    Trace("====>\n");
 
-        Ring = Transmitter->Rings[Index];
-        if (Ring == NULL)
-            break;
+    Index = Transmitter->NumQueues;
+    while (--Index >= 0) {
+        PXENVIF_TRANSMITTER_RING    Ring = Transmitter->Ring[Index];
 
         __TransmitterRingDisable(Ring);
     }
+
+    Trace("<====\n");
 }
 
 VOID
@@ -3934,7 +3935,6 @@ TransmitterDisconnect(
 {
     PXENVIF_FRONTEND        Frontend;
     ULONG                   Index;
-    ULONG                   Count;
 
     Frontend = Transmitter->Frontend;
 
@@ -3945,19 +3945,15 @@ TransmitterDisconnect(
                  Transmitter->DebugCallback);
     Transmitter->DebugCallback = NULL;
 
-    Count = FrontendGetQueueCount(Frontend);
-    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
-
-    for (Index = 0; Index < Count; ++Index) {
-        PXENVIF_TRANSMITTER_RING    Ring;
-
-        Ring = Transmitter->Rings[Index];
-        if (Ring == NULL)
-            break;
+    Index = Transmitter->NumQueues;
+    while (--Index >- 0) {
+        PXENVIF_TRANSMITTER_RING    Ring = Transmitter->Ring[Index];
 
         __TransmitterRingDisconnect(Ring);
     }
 
+    Transmitter->NumQueues = 0;
+
     XENBUS_CACHE(Destroy,
                  &Transmitter->CacheInterface,
                  Transmitter->PacketCache);
@@ -3985,24 +3981,23 @@ TransmitterTeardown(
     RtlZeroMemory(Transmitter->Offset,
                   sizeof (LONG_PTR) *  
XENVIF_TRANSMITTER_PACKET_OFFSET_COUNT); 
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
-        PXENVIF_TRANSMITTER_RING    Ring;
-
-        Ring = Transmitter->Rings[Index];
-        Transmitter->Rings[Index] = NULL;
-
-        if (Ring == NULL)
-            continue; // ensure all rings are destroyed
+    Index = Transmitter->MaxQueues;
+    while (--Index >- 0) {
+        PXENVIF_TRANSMITTER_RING    Ring = Transmitter->Ring[Index];
 
+        Transmitter->Ring[Index] = NULL;
         __TransmitterRingTeardown(Ring);
     }
 
+    __TransmitterFree(Transmitter->Ring);
+    Transmitter->Ring = NULL;
+    Transmitter->MaxQueues;
+
     XENBUS_CACHE(Release, &Transmitter->CacheInterface);
 
     XENBUS_RANGE_SET(Release, &Transmitter->RangeSetInterface);
 
     Transmitter->Frontend = NULL;
-    Transmitter->Split = FALSE;
 
     RtlZeroMemory(&Transmitter->Lock,
                   sizeof (KSPIN_LOCK));
@@ -4047,7 +4042,7 @@ TransmitterUpdateAddressTable(
     KeRaiseIrql(DISPATCH_LEVEL, &Irql);
 
     // Use the first ring for address advertisment
-    Ring = Transmitter->Rings[0];
+    Ring = Transmitter->Ring[0];
     ASSERT3U(Ring, !=, NULL);
 
     __TransmitterRingUpdateAddressTable(Ring, Table, Count);
@@ -4063,7 +4058,7 @@ TransmitterAdvertiseAddresses(
     PXENVIF_TRANSMITTER_RING    Ring;
 
     // Use the first ring for address advertisment
-    Ring = Transmitter->Rings[0];
+    Ring = Transmitter->Ring[0];
     ASSERT3U(Ring, !=, NULL);
 
     __TransmitterRingAdvertiseAddresses(Ring);
@@ -4248,64 +4243,66 @@ TransmitterQueuePacketsVersion1(
 #undef OFFSET_EXISTS
 }
 
-static FORCEINLINE ULONG
-__GetQueue(
-    IN  ULONG       QueueCount,
-    IN  ULONG       HashValue
-    )
-{
-    return HashValue % QueueCount;
-}
-
 VOID
 TransmitterQueuePackets(
-    IN  PXENVIF_TRANSMITTER Transmitter,
-    IN  PLIST_ENTRY         List
+    IN  PXENVIF_TRANSMITTER     Transmitter,
+    IN  PLIST_ENTRY             List
     )
 {
     PXENVIF_TRANSMITTER_RING    Ring;
     PXENVIF_FRONTEND            Frontend;
-    ULONG                       QueueCount;
 
     Frontend = Transmitter->Frontend;
 
-    QueueCount = FrontendGetQueueCount(Frontend);
-
-    if (QueueCount == 1) {
-        Ring = Transmitter->Rings[0];
-        ASSERT3P(Ring, !=, NULL);
+    if (Transmitter->NumQueues == 1) {
+        Ring = Transmitter->Ring[0];
 
         __TransmitterRingQueuePackets(Ring, List);
     } else {
         while (!IsListEmpty(List)) {
             PXENVIF_TRANSMITTER_PACKET  Packet;
-            PLIST_ENTRY                 ListEntry;
-            LIST_ENTRY                  ListHead;
-            ULONG                       Queue;
+            LIST_ENTRY                  HashList;
+            ULONG                       Index;
 
-            InitializeListHead(&ListHead);
+            InitializeListHead(&HashList);
+            Index = 0;
 
-            ListEntry = List->Flink;
-            Packet = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_PACKET, 
ListEntry);
-            Queue = __GetQueue(QueueCount, Packet->Value);
+            while (!IsListEmpty(List)) {            
+                PLIST_ENTRY ListEntry;
+                ULONG       Hash;
+
+                ListEntry = RemoveHeadList(List);
+                ASSERT3P(ListEntry, !=, List);
 
-            (VOID) RemoveHeadList(List);
-            InsertTailList(&ListHead, ListEntry);
+                RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
 
-            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);
+                Hash = Packet->Value % Transmitter->NumQueues;
+                if (Hash != Index) {
+                    if (!IsListEmpty(&HashList)) {
+                        Ring = Transmitter->Ring[Index];
+                        ASSERT3P(Ring, !=, NULL);
+
+                        __TransmitterRingQueuePackets(Ring, &HashList);
+                        InitializeListHead(&HashList);
+                    }
+
+                    Index = Hash;
+                }
+
+                InsertTailList(&HashList, ListEntry);
             }
 
-            Ring = Transmitter->Rings[Queue];
-            ASSERT3P(Ring, !=, NULL);
+            if (!IsListEmpty(&HashList)) {
+                Ring = Transmitter->Ring[Index];
+                ASSERT3P(Ring, !=, NULL);
+
+                __TransmitterRingQueuePackets(Ring, &HashList);
+                InitializeListHead(&HashList);
+            }
 
-            __TransmitterRingQueuePackets(Ring, &ListHead);
+            ASSERT(IsListEmpty(&HashList));
         }
     }
 }
@@ -4315,21 +4312,14 @@ TransmitterAbortPackets(
     IN  PXENVIF_TRANSMITTER Transmitter
     )
 {
-    ULONG                   Index;
-    ULONG                   Count;
     KIRQL                   Irql;
+    LONG                    Index;
 
     KeRaiseIrql(DISPATCH_LEVEL, &Irql);
 
-    Count = FrontendGetQueueCount(Transmitter->Frontend);
-    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
-
-    for (Index = 0; Index < Count; ++Index) {
-        PXENVIF_TRANSMITTER_RING    Ring;
-
-        Ring = Transmitter->Rings[Index];
-        if (Ring == NULL)
-            break;
+    Index = Transmitter->NumQueues;
+    while (--Index >= 0) {
+        PXENVIF_TRANSMITTER_RING    Ring = Transmitter->Ring[Index];
 
         __TransmitterRingAbortPackets(Ring);
     }    
@@ -4349,19 +4339,15 @@ TransmitterQueryRingSize(
 }
 
 VOID
-TransmitterRingNotify(
-    IN  PXENVIF_TRANSMITTER Transmitter,
-    IN  ULONG               Index
+TransmitterNotify(
+    IN  PXENVIF_TRANSMITTER     Transmitter,
+    IN  ULONG                   Index
     )
 {
     PXENVIF_TRANSMITTER_RING    Ring;
 
-    if (Index >= MAXIMUM_PROCESSORS)
-        return;
-
-    Ring = Transmitter->Rings[Index];
-    if (Ring == NULL)
-        return;
+    ASSERT3U(Index, <, (ULONG)Transmitter->NumQueues);
+    Ring = Transmitter->Ring[Index];
 
     __TransmitterRingNotify(Ring);
 }
diff --git a/src/xenvif/transmitter.h b/src/xenvif/transmitter.h
index 8dc4e3c..fad0762 100644
--- a/src/xenvif/transmitter.h
+++ b/src/xenvif/transmitter.h
@@ -78,7 +78,7 @@ TransmitterTeardown(
     );
 
 extern VOID
-TransmitterRingNotify(
+TransmitterNotify(
     IN  PXENVIF_TRANSMITTER Transmitter,
     IN  ULONG               Index
     );
diff --git a/vs2012/xenvif/xenvif.vcxproj b/vs2012/xenvif/xenvif.vcxproj
index d9deb03..0429bd0 100644
--- a/vs2012/xenvif/xenvif.vcxproj
+++ b/vs2012/xenvif/xenvif.vcxproj
@@ -36,7 +36,7 @@
       <Inputs>..\..\src\xenvif.inf;..\..\include\version.hx</Inputs>
     </CustomBuildStep>
     <ClCompile>
-      
<PreprocessorDefinitions>__MODULE__="XENVIF";POOL_NX_OPTIN=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      
<PreprocessorDefinitions>__MODULE__="XENVIF";POOL_NX_OPTIN=1;NT_PROCESSOR_GROUPS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <WarningLevel>EnableAllWarnings</WarningLevel>
       
<DisableSpecificWarnings>4711;4548;4820;4668;4255;6001;6054;28196;%(DisableSpecificWarnings)</DisableSpecificWarnings>
       <MultiProcessorCompilation>true</MultiProcessorCompilation>
@@ -44,7 +44,7 @@
     </ClCompile>
     <Link>
       <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
-      
<AdditionalDependencies>$(DDK_LIB_PATH)/libcntpr.lib;$(DDK_LIB_PATH)/aux_klib.lib;$(DDK_LIB_PATH)/ksecdd.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      
<AdditionalDependencies>$(DDK_LIB_PATH)/libcntpr.lib;$(DDK_LIB_PATH)/aux_klib.lib;$(DDK_LIB_PATH)/ksecdd.lib;$(DDK_LIB_PATH)/procgrp.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <EnableCOMDATFolding>false</EnableCOMDATFolding>
     </Link>
     <Inf>
diff --git a/vs2013/xenvif/xenvif.vcxproj b/vs2013/xenvif/xenvif.vcxproj
index 8dd18be..e6a0ac4 100644
--- a/vs2013/xenvif/xenvif.vcxproj
+++ b/vs2013/xenvif/xenvif.vcxproj
@@ -36,7 +36,7 @@
     </CustomBuildStep>
     <ClCompile>
       
<AdditionalIncludeDirectories>$(WindowsSdkDir)\include\km;..\..\include;..\..\include\xen;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      
<PreprocessorDefinitions>__MODULE__="XENVIF";POOL_NX_OPTIN=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      
<PreprocessorDefinitions>__MODULE__="XENVIF";POOL_NX_OPTIN=1;NT_PROCESSOR_GROUPS%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <WarningLevel>EnableAllWarnings</WarningLevel>
       
<DisableSpecificWarnings>4711;4548;4820;4668;4255;6001;6054;28196;%(DisableSpecificWarnings)</DisableSpecificWarnings>
       <MultiProcessorCompilation>true</MultiProcessorCompilation>
@@ -47,7 +47,7 @@
     </ResourceCompile>
     <Link>
       <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
-      
<AdditionalDependencies>$(DDK_LIB_PATH)/libcntpr.lib;$(DDK_LIB_PATH)/aux_klib.lib;$(DDK_LIB_PATH)/ksecdd.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      
<AdditionalDependencies>$(DDK_LIB_PATH)/libcntpr.lib;$(DDK_LIB_PATH)/aux_klib.lib;$(DDK_LIB_PATH)/ksecdd.lib;$(DDK_LIB_PATH)/procgrp.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <EnableCOMDATFolding>false</EnableCOMDATFolding>
     </Link>
     <Inf>
-- 
2.1.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®.