|
[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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |