Discussion:
[win-pv-devel] [PATCH xenvif 7/8] Don't force event channel unmasking
Paul Durrant
2018-11-02 16:54:28 UTC
Permalink
The effect of efbe65aa "Make use of possible XENBUS_EVTCHN Unmask failure"
was lost when the poller subsystem was reverted. This patch re-instates
equivalent functionality.

Signed-off-by: Paul Durrant <***@citrix.com>
---
src/xenvif/receiver.c | 38 +++++++++++++++++++++++++-------------
src/xenvif/transmitter.c | 40 ++++++++++++++++++++++++++--------------
2 files changed, 51 insertions(+), 27 deletions(-)

diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c
index 5353294..9c69b77 100644
--- a/src/xenvif/receiver.c
+++ b/src/xenvif/receiver.c
@@ -1975,19 +1975,22 @@ __ReceiverRingQueuePacket(
} while (InterlockedCompareExchangePointer(&Ring->PacketQueue, (PVOID)New, (PVOID)Old) != Old);
}

-static DECLSPEC_NOINLINE VOID
+static DECLSPEC_NOINLINE ULONG
ReceiverRingPoll(
IN PXENVIF_RECEIVER_RING Ring
)
{
PXENVIF_RECEIVER Receiver;
PXENVIF_FRONTEND Frontend;
+ ULONG Count;

Receiver = Ring->Receiver;
Frontend = Receiver->Frontend;

+ Count = 0;
+
if (!Ring->Enabled)
- return;
+ goto done;

for (;;) {
BOOLEAN Error;
@@ -2044,6 +2047,7 @@ ReceiverRingPoll(

rsp_cons++;
Ring->ResponsesProcessed++;
+ Count++;

ASSERT3U(id, <=, XENVIF_RECEIVER_MAXIMUM_FRAGMENT_ID);
Fragment = Ring->Pending[id];
@@ -2216,25 +2220,29 @@ ReceiverRingPoll(
if (Ring->PacketQueue != NULL &&
KeInsertQueueDpc(&Ring->QueueDpc, NULL, NULL))
Ring->QueueDpcs++;
+
+done:
+ return Count;
}

-static FORCEINLINE VOID
+static FORCEINLINE BOOLEAN
__ReceiverRingUnmask(
- IN PXENVIF_RECEIVER_RING Ring
+ IN PXENVIF_RECEIVER_RING Ring,
+ IN BOOLEAN Force
)
{
PXENVIF_RECEIVER Receiver;

if (!Ring->Connected)
- return;
+ return TRUE;

Receiver = Ring->Receiver;

- XENBUS_EVTCHN(Unmask,
- &Receiver->EvtchnInterface,
- Ring->Channel,
- FALSE,
- TRUE);
+ return !XENBUS_EVTCHN(Unmask,
+ &Receiver->EvtchnInterface,
+ Ring->Channel,
+ FALSE,
+ Force);
}

__drv_functionClass(KDEFERRED_ROUTINE)
@@ -2251,6 +2259,7 @@ ReceiverRingPollDpc(
)
{
PXENVIF_RECEIVER_RING Ring = Context;
+ ULONG Count;

UNREFERENCED_PARAMETER(Dpc);
UNREFERENCED_PARAMETER(Argument1);
@@ -2258,13 +2267,16 @@ ReceiverRingPollDpc(

ASSERT(Ring != NULL);

+ Count = 0;
+
for (;;) {
__ReceiverRingAcquireLock(Ring);
- ReceiverRingPoll(Ring);
+ Count += ReceiverRingPoll(Ring);
__ReceiverRingReleaseLock(Ring);

- __ReceiverRingUnmask(Ring);
- break;
+ if (__ReceiverRingUnmask(Ring,
+ (Count > XENVIF_RECEIVER_RING_SIZE)))
+ break;
}
}

diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
index 5e53f9a..34028e7 100644
--- a/src/xenvif/transmitter.c
+++ b/src/xenvif/transmitter.c
@@ -2614,19 +2614,22 @@ done:
Ring->PacketsCompleted++;
}

-static DECLSPEC_NOINLINE VOID
+static DECLSPEC_NOINLINE ULONG
TransmitterRingPoll(
IN PXENVIF_TRANSMITTER_RING Ring
)
{
PXENVIF_TRANSMITTER Transmitter;
PXENVIF_FRONTEND Frontend;
+ ULONG Count;

Transmitter = Ring->Transmitter;
Frontend = Transmitter->Frontend;

+ Count = 0;
+
if (!Ring->Enabled)
- return;
+ goto done;

for (;;) {
RING_IDX rsp_prod;
@@ -2660,6 +2663,7 @@ TransmitterRingPoll(
rsp = RING_GET_RESPONSE(&Ring->Front, rsp_cons);
rsp_cons++;
Ring->ResponsesProcessed++;
+ Count++;

Ring->Stopped = FALSE;

@@ -2785,6 +2789,9 @@ TransmitterRingPoll(

Ring->Front.rsp_cons = rsp_cons;
}
+
+done:
+ return Count;
}

static FORCEINLINE VOID
@@ -2941,7 +2948,7 @@ TransmitterRingSchedule(

if (Ring->Stopped) {
if (!Polled) {
- (VOID) TransmitterRingPoll(Ring);
+ TransmitterRingPoll(Ring);
Polled = TRUE;
}

@@ -3212,9 +3219,10 @@ TransmitterRingReleaseLock(
__TransmitterRingReleaseLock(Ring);
}

-static FORCEINLINE VOID
+static FORCEINLINE BOOLEAN
__TransmitterRingUnmask(
- IN PXENVIF_TRANSMITTER_RING Ring
+ IN PXENVIF_TRANSMITTER_RING Ring,
+ IN BOOLEAN Force
)
{
PXENVIF_TRANSMITTER Transmitter;
@@ -3224,13 +3232,13 @@ __TransmitterRingUnmask(
Frontend = Transmitter->Frontend;

if (!Ring->Connected || !FrontendIsSplit(Frontend))
- return;
+ return TRUE;

- XENBUS_EVTCHN(Unmask,
- &Transmitter->EvtchnInterface,
- Ring->Channel,
- FALSE,
- TRUE);
+ return !XENBUS_EVTCHN(Unmask,
+ &Transmitter->EvtchnInterface,
+ Ring->Channel,
+ FALSE,
+ Force);
}

__drv_functionClass(KDEFERRED_ROUTINE)
@@ -3247,6 +3255,7 @@ TransmitterRingPollDpc(
)
{
PXENVIF_TRANSMITTER_RING Ring = Context;
+ ULONG Count;

UNREFERENCED_PARAMETER(Dpc);
UNREFERENCED_PARAMETER(Argument1);
@@ -3254,13 +3263,16 @@ TransmitterRingPollDpc(

ASSERT(Ring != NULL);

+ Count = 0;
+
for (;;) {
__TransmitterRingAcquireLock(Ring);
- TransmitterRingPoll(Ring);
+ Count += TransmitterRingPoll(Ring);
__TransmitterRingReleaseLock(Ring);

- __TransmitterRingUnmask(Ring);
- break;
+ if (__TransmitterRingUnmask(Ring,
+ (Count > XENVIF_TRANSMITTER_RING_SIZE)))
+ break;
}
}
--
2.5.3
Paul Durrant
2018-11-02 16:54:23 UTC
Permalink
This reverts commit 4f85d004. This patch was put in place to work around
a bug in Windows but seems to have a serious negative effect on
performance. The bug in Windows has since been fixed so the patch can now
be reverted to recover performance.

Signed-off-by: Paul Durrant <***@citrix.com>
---
src/xenvif/controller.c | 12 ++------
src/xenvif/receiver.c | 56 +++++++++--------------------------
src/xenvif/transmitter.c | 24 ++++-----------
src/xenvif/util.h | 76 ++----------------------------------------------
4 files changed, 25 insertions(+), 143 deletions(-)

diff --git a/src/xenvif/controller.c b/src/xenvif/controller.c
index cb9d30e..35901a2 100644
--- a/src/xenvif/controller.c
+++ b/src/xenvif/controller.c
@@ -469,9 +469,7 @@ ControllerConnect(
if (Controller->Mdl == NULL)
goto fail7;

- ASSERT(Controller->Mdl->MdlFlags
- & (MDL_MAPPED_TO_SYSTEM_VA
- | MDL_SOURCE_IS_NONPAGED_POOL));
+ ASSERT(Controller->Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA);
Controller->Shared = Controller->Mdl->MappedSystemVa;
ASSERT(Controller->Shared != NULL);

@@ -906,9 +904,7 @@ ControllerSetHashKey(
if (Mdl == NULL)
goto fail1;

- ASSERT(Mdl->MdlFlags
- & (MDL_MAPPED_TO_SYSTEM_VA
- | MDL_SOURCE_IS_NONPAGED_POOL));
+ ASSERT(Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA);
Buffer = Mdl->MappedSystemVa;
ASSERT(Buffer != NULL);

@@ -1087,9 +1083,7 @@ ControllerSetHashMapping(
if (Mdl == NULL)
goto fail2;

- ASSERT(Mdl->MdlFlags
- & (MDL_MAPPED_TO_SYSTEM_VA
- | MDL_SOURCE_IS_NONPAGED_POOL));
+ ASSERT(Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA);
Buffer = Mdl->MappedSystemVa;
ASSERT(Buffer != NULL);

diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c
index f5d572b..4e8046b 100644
--- a/src/xenvif/receiver.c
+++ b/src/xenvif/receiver.c
@@ -172,9 +172,7 @@ __ReceiverPacketMdlInit(
Packet->Mdl.Size = sizeof (MDL) + sizeof (PFN_NUMBER);
Packet->Mdl.MdlFlags = Mdl->MdlFlags;

- ASSERT(Mdl->MdlFlags &
- (MDL_MAPPED_TO_SYSTEM_VA |
- MDL_SOURCE_IS_NONPAGED_POOL));
+ ASSERT(Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA);
Packet->Mdl.StartVa = Mdl->StartVa;
Packet->Mdl.MappedSystemVa = Mdl->MappedSystemVa;

@@ -411,9 +409,7 @@ ReceiverRingProcessTag(

PayloadLength = Packet->Length - Info->Length;

- ASSERT(Packet->Mdl.MdlFlags &
- (MDL_MAPPED_TO_SYSTEM_VA |
- MDL_SOURCE_IS_NONPAGED_POOL));
+ ASSERT(Packet->Mdl.MdlFlags & MDL_MAPPED_TO_SYSTEM_VA);
BaseVa = Packet->Mdl.MappedSystemVa;
ASSERT(BaseVa != NULL);

@@ -504,9 +500,7 @@ ReceiverRingProcessChecksum(
if (Info->IpHeader.Length == 0)
return;

- ASSERT(Packet->Mdl.MdlFlags &
- (MDL_MAPPED_TO_SYSTEM_VA |
- MDL_SOURCE_IS_NONPAGED_POOL));
+ ASSERT(Packet->Mdl.MdlFlags & MDL_MAPPED_TO_SYSTEM_VA);
BaseVa = Packet->Mdl.MappedSystemVa;
ASSERT(BaseVa != NULL);

@@ -663,9 +657,7 @@ ReceiverRingPullup(
PUCHAR SourceVa;
ULONG CopyLength;

- ASSERT(Mdl->MdlFlags &
- (MDL_MAPPED_TO_SYSTEM_VA |
- MDL_SOURCE_IS_NONPAGED_POOL));
+ ASSERT(Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA);
SourceVa = Mdl->MappedSystemVa;
ASSERT(SourceVa != NULL);

@@ -711,9 +703,7 @@ __ReceiverRingPullupPacket(
XENVIF_PACKET_PAYLOAD Payload;
ULONG Length;

- ASSERT(Packet->Mdl.MdlFlags
- & (MDL_MAPPED_TO_SYSTEM_VA
- | MDL_SOURCE_IS_NONPAGED_POOL));
+ ASSERT(Packet->Mdl.MdlFlags & MDL_MAPPED_TO_SYSTEM_VA);
BaseVa = Packet->Mdl.MappedSystemVa;
ASSERT(BaseVa != NULL);

@@ -757,9 +747,7 @@ __ReceiverRingBuildSegment(

Info = &Packet->Info;

- ASSERT(Packet->Mdl.MdlFlags &
- (MDL_MAPPED_TO_SYSTEM_VA |
- MDL_SOURCE_IS_NONPAGED_POOL));
+ ASSERT(Packet->Mdl.MdlFlags & MDL_MAPPED_TO_SYSTEM_VA);
InfoVa = Packet->Mdl.MappedSystemVa;
ASSERT(InfoVa != NULL);

@@ -782,9 +770,7 @@ __ReceiverRingBuildSegment(

Mdl = &Segment->Mdl;

- ASSERT(Mdl->MdlFlags &
- (MDL_MAPPED_TO_SYSTEM_VA |
- MDL_SOURCE_IS_NONPAGED_POOL));
+ ASSERT(Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA);
BaseVa = Mdl->MappedSystemVa;
ASSERT(BaseVa != NULL);

@@ -866,9 +852,7 @@ __ReceiverRingBuildSegment(

Mdl = Mdl->Next;

- ASSERT(Mdl->MdlFlags &
- (MDL_MAPPED_TO_SYSTEM_VA |
- MDL_SOURCE_IS_NONPAGED_POOL));
+ ASSERT(Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA);
BaseVa = Mdl->MappedSystemVa;
ASSERT(BaseVa != NULL);

@@ -970,9 +954,7 @@ ReceiverRingProcessLargePacket(

Packet->Mdl.Next = NULL;

- ASSERT(Packet->Mdl.MdlFlags &
- (MDL_MAPPED_TO_SYSTEM_VA |
- MDL_SOURCE_IS_NONPAGED_POOL));
+ ASSERT(Packet->Mdl.MdlFlags & MDL_MAPPED_TO_SYSTEM_VA);
InfoVa = Packet->Mdl.MappedSystemVa;
ASSERT(InfoVa != NULL);

@@ -1164,9 +1146,7 @@ ReceiverRingProcessStandardPacket(
if (Mdl == NULL)
goto fail2;

- ASSERT(Mdl->MdlFlags &
- (MDL_MAPPED_TO_SYSTEM_VA |
- MDL_SOURCE_IS_NONPAGED_POOL));
+ ASSERT(Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA);
BaseVa = Mdl->MappedSystemVa;
ASSERT(BaseVa != NULL);

@@ -1269,9 +1249,7 @@ ReceiverRingProcessPacket(
// Override offset to align
Packet->Offset = Receiver->IpAlignOffset;

- ASSERT(Packet->Mdl.MdlFlags &
- (MDL_MAPPED_TO_SYSTEM_VA |
- MDL_SOURCE_IS_NONPAGED_POOL));
+ ASSERT(Packet->Mdl.MdlFlags & MDL_MAPPED_TO_SYSTEM_VA);
BaseVa = Packet->Mdl.MappedSystemVa;
ASSERT(BaseVa != NULL);

@@ -1406,9 +1384,7 @@ __ReceiverRingSwizzle(
XENVIF_RECEIVER_PACKET,
ListEntry);

- ASSERT(Packet->Mdl.MdlFlags &
- (MDL_MAPPED_TO_SYSTEM_VA |
- MDL_SOURCE_IS_NONPAGED_POOL));
+ ASSERT(Packet->Mdl.MdlFlags & MDL_MAPPED_TO_SYSTEM_VA);
BaseVa = Packet->Mdl.MappedSystemVa;
ASSERT(BaseVa != NULL);

@@ -2105,9 +2081,7 @@ ReceiverRingPoll(

ASSERT3U(rsp->id, ==, id);

- ASSERT(Mdl->MdlFlags &
- (MDL_MAPPED_TO_SYSTEM_VA |
- MDL_SOURCE_IS_NONPAGED_POOL));
+ ASSERT(Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA);
BaseVa = Mdl->MappedSystemVa;
ASSERT(BaseVa != NULL);

@@ -2498,9 +2472,7 @@ __ReceiverRingConnect(
if (Ring->Mdl == NULL)
goto fail3;

- ASSERT(Ring->Mdl->MdlFlags &
- (MDL_MAPPED_TO_SYSTEM_VA |
- MDL_SOURCE_IS_NONPAGED_POOL));
+ ASSERT(Ring->Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA);
Ring->Shared = Ring->Mdl->MappedSystemVa;
ASSERT(Ring->Shared != NULL);

diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
index b1d9250..eed0a0f 100644
--- a/src/xenvif/transmitter.c
+++ b/src/xenvif/transmitter.c
@@ -866,9 +866,7 @@ __TransmitterRingCopyPayload(

Length = __min(Payload.Length, PAGE_SIZE);

- ASSERT(Mdl->MdlFlags &
- (MDL_MAPPED_TO_SYSTEM_VA |
- MDL_SOURCE_IS_NONPAGED_POOL));
+ ASSERT(Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA);
BaseVa = Mdl->MappedSystemVa;
ASSERT(BaseVa != NULL);

@@ -1188,9 +1186,7 @@ __TransmitterRingPrepareHeader(

Mdl = Buffer->Mdl;

- ASSERT(Mdl->MdlFlags &
- (MDL_MAPPED_TO_SYSTEM_VA |
- MDL_SOURCE_IS_NONPAGED_POOL));
+ ASSERT(Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA);
BaseVa = Mdl->MappedSystemVa;
ASSERT(BaseVa != NULL);

@@ -1687,9 +1683,7 @@ __TransmitterRingPreparePacket(

ASSERT3U(Mdl->ByteCount, <=, PAGE_SIZE - Trailer);

- ASSERT(Mdl->MdlFlags &
- (MDL_MAPPED_TO_SYSTEM_VA |
- MDL_SOURCE_IS_NONPAGED_POOL));
+ ASSERT(Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA);
BaseVa = Mdl->MappedSystemVa;
ASSERT(BaseVa != NULL);

@@ -1788,9 +1782,7 @@ __TransmitterRingPrepareArp(

Mdl = Buffer->Mdl;

- ASSERT(Mdl->MdlFlags &
- (MDL_MAPPED_TO_SYSTEM_VA |
- MDL_SOURCE_IS_NONPAGED_POOL));
+ ASSERT(Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA);
BaseVa = Mdl->MappedSystemVa;
ASSERT(BaseVa != NULL);

@@ -1931,9 +1923,7 @@ __TransmitterRingPrepareNeighbourAdvertisement(

Mdl = Buffer->Mdl;

- ASSERT(Mdl->MdlFlags &
- (MDL_MAPPED_TO_SYSTEM_VA |
- MDL_SOURCE_IS_NONPAGED_POOL));
+ ASSERT(Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA);
BaseVa = Mdl->MappedSystemVa;
ASSERT(BaseVa != NULL);

@@ -3560,9 +3550,7 @@ __TransmitterRingConnect(
if (Ring->Mdl == NULL)
goto fail3;

- ASSERT(Ring->Mdl->MdlFlags &
- (MDL_MAPPED_TO_SYSTEM_VA |
- MDL_SOURCE_IS_NONPAGED_POOL));
+ ASSERT(Ring->Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA);
Ring->Shared = Ring->Mdl->MappedSystemVa;
ASSERT(Ring->Shared != NULL);

diff --git a/src/xenvif/util.h b/src/xenvif/util.h
index 52faa1e..30322d8 100644
--- a/src/xenvif/util.h
+++ b/src/xenvif/util.h
@@ -244,63 +244,7 @@ fail1:
return NULL;
}

-
-static FORCEINLINE PMDL
-__AllocatePage()
-{
- PHYSICAL_ADDRESS LowAddress;
- PHYSICAL_ADDRESS HighAddress;
- PHYSICAL_ADDRESS Align;
- SIZE_T TotalBytes;
- PMDL Mdl;
- PUCHAR MdlMappedSystemVa;
- NTSTATUS status;
-
- ASSERT3U(KeGetCurrentIrql(), <=, DISPATCH_LEVEL);
-
- LowAddress.QuadPart = 0ull;
- HighAddress.QuadPart = ~0ull;
- Align.QuadPart = PAGE_SIZE;
- TotalBytes = (SIZE_T)PAGE_SIZE;
-
- MdlMappedSystemVa = MmAllocateContiguousMemorySpecifyCache(
- TotalBytes,
- LowAddress,
- HighAddress,
- Align,
- MmCached);
-
- status = STATUS_NO_MEMORY;
- if (MdlMappedSystemVa == NULL)
- goto fail1;
-
- Mdl = IoAllocateMdl(MdlMappedSystemVa,
- (ULONG)TotalBytes,
- FALSE,
- FALSE,
- NULL);
- if (Mdl == NULL)
- goto fail2;
-
- MmBuildMdlForNonPagedPool(Mdl);
-
- ASSERT3U(Mdl->ByteOffset, ==, 0);
- ASSERT3P(Mdl->StartVa, ==, MdlMappedSystemVa);
- ASSERT3P(Mdl->MappedSystemVa, ==, MdlMappedSystemVa);
-
- RtlZeroMemory(MdlMappedSystemVa, Mdl->ByteCount);
-
- return Mdl;
-
-fail2:
- Error("fail2\n");
-
- MmFreeContiguousMemory(MdlMappedSystemVa);
-fail1:
- Error("fail1 (%08x)\n", status);
-
- return NULL;
-}
+#define __AllocatePage() __AllocatePages(1)

static FORCEINLINE VOID
__FreePages(
@@ -318,23 +262,7 @@ __FreePages(
ExFreePool(Mdl);
}

-static FORCEINLINE VOID
-__FreePage(
- IN PMDL Mdl
- )
-{
- PUCHAR MdlMappedSystemVa;
-
- ASSERT(Mdl->MdlFlags &
- (MDL_MAPPED_TO_SYSTEM_VA |
- MDL_SOURCE_IS_NONPAGED_POOL));
-
- MdlMappedSystemVa = Mdl->MappedSystemVa;
-
- IoFreeMdl(Mdl);
-
- MmFreeContiguousMemory(MdlMappedSystemVa);
-}
+#define __FreePage(_Mdl) __FreePages(_Mdl)

static FORCEINLINE PCHAR
__strtok_r(
--
2.5.3
Paul Durrant
2018-11-02 16:54:22 UTC
Permalink
... MPE_Ethernet test failures""

This reverts commit 0f91d01d as it is very detrimental to performance. It
appears that deferring transmit completion events roughly halves TCP
throughput.

Signed-off-by: Paul Durrant <***@citrix.com>
---
src/xenvif/transmitter.c | 94 +-----------------------------------------------
1 file changed, 1 insertion(+), 93 deletions(-)

diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
index bf6004a..b1d9250 100644
--- a/src/xenvif/transmitter.c
+++ b/src/xenvif/transmitter.c
@@ -201,7 +201,6 @@ typedef struct _XENVIF_TRANSMITTER_RING {
ULONG PacketsCompleted;
PXENBUS_DEBUG_CALLBACK DebugCallback;
PXENVIF_THREAD WatchdogThread;
- PXENVIF_THREAD CompletionThread;
} XENVIF_TRANSMITTER_RING, *PXENVIF_TRANSMITTER_RING;

struct _XENVIF_TRANSMITTER {
@@ -2780,6 +2779,7 @@ TransmitterRingPoll(
KeMemoryBarrier();

Ring->Front.rsp_cons = rsp_cons;
+ Ring->Shared->rsp_event = rsp_cons + 1;
}

done:
@@ -2806,8 +2806,6 @@ __TransmitterRingPushRequests(
#pragma warning (push)
#pragma warning (disable:4244)

- Ring->Shared->rsp_event = Ring->Front.req_prod_pvt;
-
// Make the requests visible to the backend
RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&Ring->Front, Notify);

@@ -3263,79 +3261,6 @@ TransmitterRingWatchdog(
return STATUS_SUCCESS;
}

-#define XENVIF_TRANSMITTER_COMPLETION_PERIOD 5
-
-static NTSTATUS
-TransmitterRingCompletion(
- IN PXENVIF_THREAD Self,
- IN PVOID Context
- )
-{
- PXENVIF_TRANSMITTER_RING Ring = Context;
- PROCESSOR_NUMBER ProcNumber;
- GROUP_AFFINITY Affinity;
- LARGE_INTEGER Timeout;
- NTSTATUS status;
-
- Trace("====>\n");
-
- if (RtlIsNtDdiVersionAvailable(NTDDI_WIN7) ) {
- //
- // Affinitize this thread to the same CPU as the event channel
- // and DPC.
- //
- // The following functions don't work before Windows 7
- //
- status = KeGetProcessorNumberFromIndex(Ring->Index, &ProcNumber);
- ASSERT(NT_SUCCESS(status));
-
- Affinity.Group = ProcNumber.Group;
- Affinity.Mask = (KAFFINITY)1 << ProcNumber.Number;
- KeSetSystemGroupAffinityThread(&Affinity, NULL);
- }
-
- Timeout.QuadPart = TIME_RELATIVE(TIME_S(XENVIF_TRANSMITTER_COMPLETION_PERIOD));
-
- for (;;) {
- PKEVENT Event;
- KIRQL Irql;
-
- Event = ThreadGetEvent(Self);
-
- (VOID) KeWaitForSingleObject(Event,
- Executive,
- KernelMode,
- FALSE,
- &Timeout);
- KeClearEvent(Event);
-
- if (ThreadIsAlerted(Self))
- break;
-
- KeRaiseIrql(DISPATCH_LEVEL, &Irql);
- __TransmitterRingAcquireLock(Ring);
-
- if (Ring->Enabled) {
- PXENVIF_TRANSMITTER Transmitter;
- PXENVIF_FRONTEND Frontend;
-
- Transmitter = Ring->Transmitter;
- Frontend = Transmitter->Frontend;
-
- PollerTrigger(FrontendGetPoller(Frontend),
- Ring->Index,
- XENVIF_POLLER_EVENT_TRANSMIT);
- }
-
- __TransmitterRingReleaseLock(Ring);
- KeLowerIrql(Irql);
- }
-
- Trace("<====\n");
-
- return STATUS_SUCCESS;
-}
-
static FORCEINLINE NTSTATUS
__TransmitterRingInitialize(
IN PXENVIF_TRANSMITTER Transmitter,
@@ -3498,21 +3423,8 @@ __TransmitterRingInitialize(
if (!NT_SUCCESS(status))
goto fail14;

- status = ThreadCreate(TransmitterRingCompletion,
- *Ring,
- &(*Ring)->CompletionThread);
- if (!NT_SUCCESS(status))
- goto fail15;
-
return STATUS_SUCCESS;

-fail15:
- Error("fail15\n");
-
- ThreadAlert((*Ring)->WatchdogThread);
- ThreadJoin((*Ring)->WatchdogThread);
- (*Ring)->WatchdogThread = NULL;
-
fail14:
Error("fail14\n");

@@ -3966,10 +3878,6 @@ __TransmitterRingTeardown(
Ring->PacketsPrepared = 0;
Ring->PacketsQueued = 0;

- ThreadAlert(Ring->CompletionThread);
- ThreadJoin(Ring->CompletionThread);
- Ring->CompletionThread = NULL;
-
ThreadAlert(Ring->WatchdogThread);
ThreadJoin(Ring->WatchdogThread);
Ring->WatchdogThread = NULL;
--
2.5.3
Paul Durrant
2018-11-02 16:54:29 UTC
Permalink
There is no need to hold the ring lock to update the packet transmit
completion information, or update the frontend statistics. This patch
creates a new __TransmitterSetCompletionInfo() function and calls this
just before returning each packet to XENNET, after the ring lock has been
dropped.

Signed-off-by: Paul Durrant <***@citrix.com>
---
src/xenvif/transmitter.c | 333 ++++++++++++++++++++++++-----------------------
1 file changed, 169 insertions(+), 164 deletions(-)

diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
index 34028e7..a5e2e72 100644
--- a/src/xenvif/transmitter.c
+++ b/src/xenvif/transmitter.c
@@ -2448,168 +2448,6 @@ __TransmitterRingCompletePacket(
IN PXENVIF_TRANSMITTER_PACKET Packet
)
{
- PXENVIF_TRANSMITTER Transmitter;
- PXENVIF_FRONTEND Frontend;
- PXENVIF_PACKET_PAYLOAD Payload;
- PXENVIF_PACKET_INFO Info;
- PUCHAR BaseVa;
- PETHERNET_HEADER EthernetHeader;
- PETHERNET_ADDRESS DestinationAddress;
- ETHERNET_ADDRESS_TYPE Type;
-
- Transmitter = Ring->Transmitter;
- Frontend = Transmitter->Frontend;
-
- ASSERT(Packet->Completion.Status != 0);
-
- if (Packet->Completion.Status != XENVIF_TRANSMITTER_PACKET_OK) {
- FrontendIncrementStatistic(Frontend,
- XENVIF_TRANSMITTER_PACKETS_DROPPED,
- 1);
-
- if (Packet->Completion.Status == XENVIF_TRANSMITTER_PACKET_ERROR)
- FrontendIncrementStatistic(Frontend,
- XENVIF_TRANSMITTER_BACKEND_ERRORS,
- 1);
-
- goto done;
- }
-
- BaseVa = Packet->Header;
- Info = &Packet->Info;
- Payload = &Packet->Payload;
-
- ASSERT(Info->EthernetHeader.Length != 0);
- EthernetHeader = (PETHERNET_HEADER)(BaseVa + Info->EthernetHeader.Offset);
-
- DestinationAddress = &EthernetHeader->DestinationAddress;
-
- Type = GET_ETHERNET_ADDRESS_TYPE(DestinationAddress);
-
- switch (Type) {
- case ETHERNET_ADDRESS_UNICAST:
- FrontendIncrementStatistic(Frontend,
- XENVIF_TRANSMITTER_UNICAST_PACKETS,
- 1);
- FrontendIncrementStatistic(Frontend,
- XENVIF_TRANSMITTER_UNICAST_OCTETS,
- Packet->Length);
- break;
-
- case ETHERNET_ADDRESS_MULTICAST:
- FrontendIncrementStatistic(Frontend,
- XENVIF_TRANSMITTER_MULTICAST_PACKETS,
- 1);
- FrontendIncrementStatistic(Frontend,
- XENVIF_TRANSMITTER_MULTICAST_OCTETS,
- Packet->Length);
- break;
-
- case ETHERNET_ADDRESS_BROADCAST:
- FrontendIncrementStatistic(Frontend,
- XENVIF_TRANSMITTER_BROADCAST_PACKETS,
- 1);
- FrontendIncrementStatistic(Frontend,
- XENVIF_TRANSMITTER_BROADCAST_OCTETS,
- Packet->Length);
- break;
-
- default:
- ASSERT(FALSE);
- break;
- }
-
- if (ETHERNET_HEADER_IS_TAGGED(EthernetHeader))
- FrontendIncrementStatistic(Frontend,
- XENVIF_TRANSMITTER_TAGGED_PACKETS,
- 1);
-
- if (Info->LLCSnapHeader.Length != 0)
- FrontendIncrementStatistic(Frontend,
- XENVIF_TRANSMITTER_LLC_SNAP_PACKETS,
- 1);
-
- if (Info->IpHeader.Length != 0) {
- PIP_HEADER IpHeader = (PIP_HEADER)(BaseVa + Info->IpHeader.Offset);
-
- if (IpHeader->Version == 4) {
- FrontendIncrementStatistic(Frontend,
- XENVIF_TRANSMITTER_IPV4_PACKETS,
- 1);
- } else {
- ASSERT3U(IpHeader->Version, ==, 6);
-
- FrontendIncrementStatistic(Frontend,
- XENVIF_TRANSMITTER_IPV6_PACKETS,
- 1);
- }
- }
-
- if (Info->TcpHeader.Length != 0)
- FrontendIncrementStatistic(Frontend,
- XENVIF_TRANSMITTER_TCP_PACKETS,
- 1);
-
- if (Info->UdpHeader.Length != 0)
- FrontendIncrementStatistic(Frontend,
- XENVIF_TRANSMITTER_UDP_PACKETS,
- 1);
-
- if (Packet->MaximumSegmentSize != 0)
- FrontendIncrementStatistic(Frontend,
- XENVIF_TRANSMITTER_GSO_PACKETS,
- 1);
-
- if (Packet->Flags.IpChecksumSucceeded != 0)
- FrontendIncrementStatistic(Frontend,
- XENVIF_TRANSMITTER_IPV4_CHECKSUM_SUCCEEDED,
- 1);
-
- if (Packet->Flags.IpChecksumFailed != 0)
- FrontendIncrementStatistic(Frontend,
- XENVIF_TRANSMITTER_IPV4_CHECKSUM_FAILED,
- 1);
-
- if (Packet->Flags.IpChecksumNotValidated != 0)
- FrontendIncrementStatistic(Frontend,
- XENVIF_TRANSMITTER_IPV4_CHECKSUM_NOT_VALIDATED,
- 1);
-
- if (Packet->Flags.TcpChecksumSucceeded != 0)
- FrontendIncrementStatistic(Frontend,
- XENVIF_TRANSMITTER_TCP_CHECKSUM_SUCCEEDED,
- 1);
-
- if (Packet->Flags.TcpChecksumFailed != 0)
- FrontendIncrementStatistic(Frontend,
- XENVIF_TRANSMITTER_TCP_CHECKSUM_FAILED,
- 1);
-
- if (Packet->Flags.TcpChecksumNotValidated != 0)
- FrontendIncrementStatistic(Frontend,
- XENVIF_TRANSMITTER_TCP_CHECKSUM_NOT_VALIDATED,
- 1);
-
- if (Packet->Flags.UdpChecksumSucceeded != 0)
- FrontendIncrementStatistic(Frontend,
- XENVIF_TRANSMITTER_UDP_CHECKSUM_SUCCEEDED,
- 1);
-
- if (Packet->Flags.UdpChecksumFailed != 0)
- FrontendIncrementStatistic(Frontend,
- XENVIF_TRANSMITTER_UDP_CHECKSUM_FAILED,
- 1);
-
- if (Packet->Flags.UdpChecksumNotValidated != 0)
- FrontendIncrementStatistic(Frontend,
- XENVIF_TRANSMITTER_UDP_CHECKSUM_NOT_VALIDATED,
- 1);
-
- Packet->Completion.Type = Type;
- Packet->Completion.PacketLength = (USHORT)Packet->Length;
- Packet->Completion.PayloadLength = (USHORT)Payload->Length;
-
-done:
InsertTailList(&Ring->PacketComplete, &Packet->ListEntry);
Ring->PacketsCompleted++;
}
@@ -3048,6 +2886,172 @@ TransmitterRingSchedule(
}

static FORCEINLINE VOID
+__TransmitterSetCompletionInfo(
+ IN PXENVIF_TRANSMITTER Transmitter,
+ IN PXENVIF_TRANSMITTER_PACKET Packet
+ )
+{
+ PXENVIF_FRONTEND Frontend;
+ PXENVIF_PACKET_PAYLOAD Payload;
+ PXENVIF_PACKET_INFO Info;
+ PUCHAR BaseVa;
+ PETHERNET_HEADER EthernetHeader;
+ PETHERNET_ADDRESS DestinationAddress;
+ ETHERNET_ADDRESS_TYPE Type;
+
+ Frontend = Transmitter->Frontend;
+
+ ASSERT(Packet->Completion.Status != 0);
+
+ if (Packet->Completion.Status != XENVIF_TRANSMITTER_PACKET_OK) {
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_TRANSMITTER_PACKETS_DROPPED,
+ 1);
+
+ if (Packet->Completion.Status == XENVIF_TRANSMITTER_PACKET_ERROR)
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_TRANSMITTER_BACKEND_ERRORS,
+ 1);
+
+ return;
+ }
+
+ BaseVa = Packet->Header;
+ Info = &Packet->Info;
+ Payload = &Packet->Payload;
+
+ ASSERT(Info->EthernetHeader.Length != 0);
+ EthernetHeader = (PETHERNET_HEADER)(BaseVa + Info->EthernetHeader.Offset);
+
+ DestinationAddress = &EthernetHeader->DestinationAddress;
+
+ Type = GET_ETHERNET_ADDRESS_TYPE(DestinationAddress);
+
+ switch (Type) {
+ case ETHERNET_ADDRESS_UNICAST:
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_TRANSMITTER_UNICAST_PACKETS,
+ 1);
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_TRANSMITTER_UNICAST_OCTETS,
+ Packet->Length);
+ break;
+
+ case ETHERNET_ADDRESS_MULTICAST:
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_TRANSMITTER_MULTICAST_PACKETS,
+ 1);
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_TRANSMITTER_MULTICAST_OCTETS,
+ Packet->Length);
+ break;
+
+ case ETHERNET_ADDRESS_BROADCAST:
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_TRANSMITTER_BROADCAST_PACKETS,
+ 1);
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_TRANSMITTER_BROADCAST_OCTETS,
+ Packet->Length);
+ break;
+
+ default:
+ ASSERT(FALSE);
+ break;
+ }
+
+ if (ETHERNET_HEADER_IS_TAGGED(EthernetHeader))
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_TRANSMITTER_TAGGED_PACKETS,
+ 1);
+
+ if (Info->LLCSnapHeader.Length != 0)
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_TRANSMITTER_LLC_SNAP_PACKETS,
+ 1);
+
+ if (Info->IpHeader.Length != 0) {
+ PIP_HEADER IpHeader = (PIP_HEADER)(BaseVa + Info->IpHeader.Offset);
+
+ if (IpHeader->Version == 4) {
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_TRANSMITTER_IPV4_PACKETS,
+ 1);
+ } else {
+ ASSERT3U(IpHeader->Version, ==, 6);
+
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_TRANSMITTER_IPV6_PACKETS,
+ 1);
+ }
+ }
+
+ if (Info->TcpHeader.Length != 0)
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_TRANSMITTER_TCP_PACKETS,
+ 1);
+
+ if (Info->UdpHeader.Length != 0)
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_TRANSMITTER_UDP_PACKETS,
+ 1);
+
+ if (Packet->MaximumSegmentSize != 0)
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_TRANSMITTER_GSO_PACKETS,
+ 1);
+
+ if (Packet->Flags.IpChecksumSucceeded != 0)
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_TRANSMITTER_IPV4_CHECKSUM_SUCCEEDED,
+ 1);
+
+ if (Packet->Flags.IpChecksumFailed != 0)
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_TRANSMITTER_IPV4_CHECKSUM_FAILED,
+ 1);
+
+ if (Packet->Flags.IpChecksumNotValidated != 0)
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_TRANSMITTER_IPV4_CHECKSUM_NOT_VALIDATED,
+ 1);
+
+ if (Packet->Flags.TcpChecksumSucceeded != 0)
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_TRANSMITTER_TCP_CHECKSUM_SUCCEEDED,
+ 1);
+
+ if (Packet->Flags.TcpChecksumFailed != 0)
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_TRANSMITTER_TCP_CHECKSUM_FAILED,
+ 1);
+
+ if (Packet->Flags.TcpChecksumNotValidated != 0)
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_TRANSMITTER_TCP_CHECKSUM_NOT_VALIDATED,
+ 1);
+
+ if (Packet->Flags.UdpChecksumSucceeded != 0)
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_TRANSMITTER_UDP_CHECKSUM_SUCCEEDED,
+ 1);
+
+ if (Packet->Flags.UdpChecksumFailed != 0)
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_TRANSMITTER_UDP_CHECKSUM_FAILED,
+ 1);
+
+ if (Packet->Flags.UdpChecksumNotValidated != 0)
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_TRANSMITTER_UDP_CHECKSUM_NOT_VALIDATED,
+ 1);
+
+ Packet->Completion.Type = Type;
+ Packet->Completion.PacketLength = (USHORT)Packet->Length;
+ Packet->Completion.PayloadLength = (USHORT)Payload->Length;
+}
+
+static FORCEINLINE VOID
__TransmitterReturnPackets(
IN PXENVIF_TRANSMITTER Transmitter,
IN PLIST_ENTRY List
@@ -3072,6 +3076,8 @@ __TransmitterReturnPackets(
XENVIF_TRANSMITTER_PACKET,
ListEntry);

+ __TransmitterSetCompletionInfo(Transmitter, Packet);
+
VifTransmitterReturnPacket(Context,
Packet->Cookie,
&Packet->Completion);
@@ -3206,8 +3212,7 @@ __TransmitterRingReleaseLock(

Transmitter = Ring->Transmitter;

- __TransmitterReturnPackets(Transmitter,
- &List);
+ __TransmitterReturnPackets(Transmitter, &List);
}
}
--
2.5.3
Paul Durrant
2018-11-02 16:54:25 UTC
Permalink
Even though the poller subsystem has been reverted, these still need to
go away as they do not adequately serve the purpose for which they were
added: DPC watchdog avoidance.

A subsequent patch will re-instate the threaded DPC in the receiver to
avoid the DPC watchdog.

Signed-off-by: Paul Durrant <***@citrix.com>
---
src/xenvif/receiver.c | 60 ++++--------------------------------------------
src/xenvif/transmitter.c | 58 ++++------------------------------------------
2 files changed, 10 insertions(+), 108 deletions(-)

diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c
index 3ed5ee8..63f0e0e 100644
--- a/src/xenvif/receiver.c
+++ b/src/xenvif/receiver.c
@@ -91,8 +91,6 @@ typedef struct _XENVIF_RECEIVER_RING {
PXENBUS_EVTCHN_CHANNEL Channel;
KDPC Dpc;
ULONG Dpcs;
- KTIMER Timer;
- KDPC TimerDpc;
ULONG Events;
PXENVIF_RECEIVER_FRAGMENT Pending[XENVIF_RECEIVER_MAXIMUM_FRAGMENT_ID + 1];
ULONG RequestsPosted;
@@ -2211,37 +2209,6 @@ __ReceiverRingUnmask(
TRUE);
}

-static FORCEINLINE BOOLEAN
-__ReceiverRingDpcTimeout(
- IN PXENVIF_RECEIVER_RING Ring
- )
-{
- KDPC_WATCHDOG_INFORMATION Watchdog;
- NTSTATUS status;
-
- UNREFERENCED_PARAMETER(Ring);
-
- RtlZeroMemory(&Watchdog, sizeof (Watchdog));
-
- status = KeQueryDpcWatchdogInformation(&Watchdog);
- ASSERT(NT_SUCCESS(status));
-
- if (Watchdog.DpcTimeLimit == 0 ||
- Watchdog.DpcWatchdogLimit == 0)
- return FALSE;
-
- if (Watchdog.DpcTimeCount > (Watchdog.DpcTimeLimit / 2) &&
- Watchdog.DpcWatchdogCount > (Watchdog.DpcWatchdogLimit / 2))
- return FALSE;
-
- return TRUE;
-}
-
-#define TIME_US(_us) ((_us) * 10)
-#define TIME_MS(_ms) (TIME_US((_ms) * 1000))
-#define TIME_S(_s) (TIME_MS((_s) * 1000))
-#define TIME_RELATIVE(_t) (-(_t))
-
__drv_functionClass(KDEFERRED_ROUTINE)
__drv_maxIRQL(DISPATCH_LEVEL)
__drv_minIRQL(DISPATCH_LEVEL)
@@ -2274,15 +2241,6 @@ ReceiverRingDpc(
__ReceiverRingUnmask(Ring);
break;
}
-
- if (__ReceiverRingDpcTimeout(Ring)) {
- LARGE_INTEGER Delay;
-
- Delay.QuadPart = TIME_RELATIVE(TIME_US(100));
-
- KeSetTimer(&Ring->Timer, Delay, &Ring->TimerDpc);
- break;
- }
}
}

@@ -2317,6 +2275,11 @@ ReceiverRingEvtchnCallback(
return TRUE;
}

+#define TIME_US(_us) ((_us) * 10)
+#define TIME_MS(_ms) (TIME_US((_ms) * 1000))
+#define TIME_S(_s) (TIME_MS((_s) * 1000))
+#define TIME_RELATIVE(_t) (-(_t))
+
#define XENVIF_RECEIVER_WATCHDOG_PERIOD 30

static NTSTATUS
@@ -2438,8 +2401,6 @@ __ReceiverRingInitialize(
InitializeListHead(&(*Ring)->PacketList);

KeInitializeDpc(&(*Ring)->Dpc, ReceiverRingDpc, *Ring);
- KeInitializeTimer(&(*Ring)->Timer);
- KeInitializeDpc(&(*Ring)->TimerDpc, ReceiverRingDpc, *Ring);

status = RtlStringCbPrintfA(Name,
sizeof (Name),
@@ -2524,8 +2485,6 @@ fail4:
fail3:
Error("fail3\n");

- RtlZeroMemory(&(*Ring)->TimerDpc, sizeof (KDPC));
- RtlZeroMemory(&(*Ring)->Timer, sizeof (KTIMER));
RtlZeroMemory(&(*Ring)->Dpc, sizeof (KDPC));

RtlZeroMemory(&(*Ring)->PacketList, sizeof (LIST_ENTRY));
@@ -2641,7 +2600,6 @@ __ReceiverRingConnect(
ASSERT(NT_SUCCESS(status));

KeSetTargetProcessorDpcEx(&Ring->Dpc, &ProcNumber);
- KeSetTargetProcessorDpcEx(&Ring->TimerDpc, &ProcNumber);

(VOID) XENBUS_EVTCHN(Bind,
&Receiver->EvtchnInterface,
@@ -2846,12 +2804,6 @@ __ReceiverRingDisable(

__ReceiverRingReleaseLock(Ring);

- //
- // No new timers can be scheduled once Enabled goes to FALSE.
- // Cancel any existing ones.
- //
- (VOID) KeCancelTimer(&Ring->Timer);
-
Info("%s[%u]: <====\n",
FrontendGetPath(Frontend),
Ring->Index);
@@ -2925,8 +2877,6 @@ __ReceiverRingTeardown(
Frontend = Receiver->Frontend;

RtlZeroMemory(&Ring->Hash, sizeof (XENVIF_RECEIVER_HASH));
- RtlZeroMemory(&Ring->TimerDpc, sizeof (KDPC));
- RtlZeroMemory(&Ring->Timer, sizeof (KTIMER));
RtlZeroMemory(&Ring->Dpc, sizeof (KDPC));

Ring->BackfillSize = 0;
diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
index 770aca9..02c0d3e 100644
--- a/src/xenvif/transmitter.c
+++ b/src/xenvif/transmitter.c
@@ -182,8 +182,6 @@ typedef struct _XENVIF_TRANSMITTER_RING {
PXENBUS_EVTCHN_CHANNEL Channel;
KDPC Dpc;
ULONG Dpcs;
- KTIMER Timer;
- KDPC TimerDpc;
ULONG Events;
BOOLEAN Connected;
BOOLEAN Enabled;
@@ -3250,37 +3248,6 @@ __TransmitterRingUnmask(
TRUE);
}

-static FORCEINLINE BOOLEAN
-__TransmitterRingDpcTimeout(
- IN PXENVIF_TRANSMITTER_RING Ring
- )
-{
- KDPC_WATCHDOG_INFORMATION Watchdog;
- NTSTATUS status;
-
- UNREFERENCED_PARAMETER(Ring);
-
- RtlZeroMemory(&Watchdog, sizeof (Watchdog));
-
- status = KeQueryDpcWatchdogInformation(&Watchdog);
- ASSERT(NT_SUCCESS(status));
-
- if (Watchdog.DpcTimeLimit == 0 ||
- Watchdog.DpcWatchdogLimit == 0)
- return FALSE;
-
- if (Watchdog.DpcTimeCount > (Watchdog.DpcTimeLimit / 2) &&
- Watchdog.DpcWatchdogCount > (Watchdog.DpcWatchdogLimit / 2))
- return FALSE;
-
- return TRUE;
-}
-
-#define TIME_US(_us) ((_us) * 10)
-#define TIME_MS(_ms) (TIME_US((_ms) * 1000))
-#define TIME_S(_s) (TIME_MS((_s) * 1000))
-#define TIME_RELATIVE(_t) (-(_t))
-
__drv_functionClass(KDEFERRED_ROUTINE)
__drv_maxIRQL(DISPATCH_LEVEL)
__drv_minIRQL(DISPATCH_LEVEL)
@@ -3313,15 +3280,6 @@ TransmitterRingDpc(
__TransmitterRingUnmask(Ring);
break;
}
-
- if (__TransmitterRingDpcTimeout(Ring)) {
- LARGE_INTEGER Delay;
-
- Delay.QuadPart = TIME_RELATIVE(TIME_US(100));
-
- KeSetTimer(&Ring->Timer, Delay, &Ring->TimerDpc);
- break;
- }
}
}

@@ -3354,6 +3312,11 @@ TransmitterRingEvtchnCallback(
return TRUE;
}

+#define TIME_US(_us) ((_us) * 10)
+#define TIME_MS(_ms) (TIME_US((_ms) * 1000))
+#define TIME_S(_s) (TIME_MS((_s) * 1000))
+#define TIME_RELATIVE(_t) (-(_t))
+
#define XENVIF_TRANSMITTER_WATCHDOG_PERIOD 30

static NTSTATUS
@@ -3467,8 +3430,6 @@ __TransmitterRingInitialize(
InitializeListHead(&(*Ring)->PacketComplete);

KeInitializeDpc(&(*Ring)->Dpc, TransmitterRingDpc, *Ring);
- KeInitializeTimer(&(*Ring)->Timer);
- KeInitializeDpc(&(*Ring)->TimerDpc, TransmitterRingDpc, *Ring);

status = RtlStringCbPrintfA(Name,
sizeof (Name),
@@ -3789,7 +3750,6 @@ __TransmitterRingConnect(
ASSERT(NT_SUCCESS(status));

KeSetTargetProcessorDpcEx(&Ring->Dpc, &ProcNumber);
- KeSetTargetProcessorDpcEx(&Ring->TimerDpc, &ProcNumber);

(VOID) XENBUS_EVTCHN(Bind,
&Transmitter->EvtchnInterface,
@@ -4046,12 +4006,6 @@ __TransmitterRingDisable(

__TransmitterRingReleaseLock(Ring);

- //
- // No new timers can be scheduled once Enabled goes to FALSE.
- // Cancel any existing ones.
- //
- (VOID) KeCancelTimer(&Ring->Timer);
-
Info("%s[%u]: <====\n",
FrontendGetPath(Frontend),
Ring->Index);
@@ -4127,8 +4081,6 @@ __TransmitterRingTeardown(

Ring->Dpcs = 0;

- RtlZeroMemory(&Ring->TimerDpc, sizeof (KDPC));
- RtlZeroMemory(&Ring->Timer, sizeof (KTIMER));
RtlZeroMemory(&Ring->Dpc, sizeof (KDPC));

ASSERT3U(Ring->PacketsCompleted, ==, Ring->PacketsSent);
--
2.5.3
Paul Durrant
2018-11-02 16:54:26 UTC
Permalink
This patch re-works 264bde12 such that it apply (after reversion of the
poller subsystem), including re-naming the unqualified 'Dpc' and 'Dpcs'
fields in the receiver and transmitter ring structures to 'PollDpc' and
'PollDpcs' to disambiguate them from the new threaded 'QueueDpc' and
associated 'QueueDpcs' counter.

Signed-off-by: Paul Durrant <***@citrix.com>
---
src/xenvif/receiver.c | 383 +++++++++++++++++++++++++++--------------------
src/xenvif/transmitter.c | 32 ++--
src/xenvif/vif.c | 7 +
3 files changed, 242 insertions(+), 180 deletions(-)

diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c
index 63f0e0e..ed362ff 100644
--- a/src/xenvif/receiver.c
+++ b/src/xenvif/receiver.c
@@ -89,8 +89,8 @@ typedef struct _XENVIF_RECEIVER_RING {
netif_rx_sring_t *Shared;
PXENBUS_GNTTAB_ENTRY Entry;
PXENBUS_EVTCHN_CHANNEL Channel;
- KDPC Dpc;
- ULONG Dpcs;
+ KDPC PollDpc;
+ ULONG PollDpcs;
ULONG Events;
PXENVIF_RECEIVER_FRAGMENT Pending[XENVIF_RECEIVER_MAXIMUM_FRAGMENT_ID + 1];
ULONG RequestsPosted;
@@ -103,7 +103,10 @@ typedef struct _XENVIF_RECEIVER_RING {
ULONG BackfillSize;
PXENBUS_DEBUG_CALLBACK DebugCallback;
PXENVIF_THREAD WatchdogThread;
- LIST_ENTRY PacketList;
+ PLIST_ENTRY PacketQueue;
+ KDPC QueueDpc;
+ ULONG QueueDpcs;
+ LIST_ENTRY PacketComplete;
XENVIF_RECEIVER_HASH Hash;
} XENVIF_RECEIVER_RING, *PXENVIF_RECEIVER_RING;

@@ -911,10 +914,22 @@ fail1:
}

static VOID
+ReceiverRingCompletePacket(
+ IN PXENVIF_RECEIVER_RING Ring,
+ IN PXENVIF_RECEIVER_PACKET Packet
+ )
+{
+ ReceiverRingProcessTag(Ring, Packet);
+ ReceiverRingProcessChecksum(Ring, Packet);
+
+ ASSERT(IsZeroMemory(&Packet->ListEntry, sizeof (LIST_ENTRY)));
+ InsertTailList(&Ring->PacketComplete, &Packet->ListEntry);
+}
+
+static VOID
ReceiverRingProcessLargePacket(
IN PXENVIF_RECEIVER_RING Ring,
- IN PXENVIF_RECEIVER_PACKET Packet,
- OUT PLIST_ENTRY List
+ IN PXENVIF_RECEIVER_PACKET Packet
)
{
PXENVIF_RECEIVER Receiver;
@@ -1002,8 +1017,7 @@ ReceiverRingProcessLargePacket(
ASSERT3U(Length, >=, SegmentSize);
Length -= SegmentSize;

- ASSERT(IsZeroMemory(&Segment->ListEntry, sizeof (LIST_ENTRY)));
- InsertTailList(List, &Segment->ListEntry);
+ ReceiverRingCompletePacket(Ring, Segment);

if (Offload) {
ASSERT(Ring->OffloadOptions.NeedLargePacketSplit != 0);
@@ -1052,8 +1066,7 @@ ReceiverRingProcessLargePacket(
if (Receiver->AlwaysPullup != 0)
__ReceiverRingPullupPacket(Ring, Packet);

- ASSERT(IsZeroMemory(&Packet->ListEntry, sizeof (LIST_ENTRY)));
- InsertTailList(List, &Packet->ListEntry);
+ ReceiverRingCompletePacket(Ring, Packet);
} else {
__ReceiverRingPutPacket(Ring, Packet, TRUE);
}
@@ -1090,8 +1103,7 @@ fail1:
static VOID
ReceiverRingProcessStandardPacket(
IN PXENVIF_RECEIVER_RING Ring,
- IN PXENVIF_RECEIVER_PACKET Packet,
- OUT PLIST_ENTRY List
+ IN PXENVIF_RECEIVER_PACKET Packet
)
{
PXENVIF_RECEIVER Receiver;
@@ -1161,9 +1173,7 @@ ReceiverRingProcessStandardPacket(
Packet->Mdl.Next = Mdl;
}

- ASSERT(IsZeroMemory(&Packet->ListEntry, sizeof (LIST_ENTRY)));
- InsertTailList(List, &Packet->ListEntry);
-
+ ReceiverRingCompletePacket(Ring, Packet);
return;

fail2:
@@ -1196,8 +1206,7 @@ fail1:
static VOID
ReceiverRingProcessPacket(
IN PXENVIF_RECEIVER_RING Ring,
- IN PXENVIF_RECEIVER_PACKET Packet,
- OUT PLIST_ENTRY List
+ IN PXENVIF_RECEIVER_PACKET Packet
)
{
PXENVIF_RECEIVER Receiver;
@@ -1283,9 +1292,9 @@ ReceiverRingProcessPacket(
goto fail3;

if (Packet->MaximumSegmentSize != 0)
- ReceiverRingProcessLargePacket(Ring, Packet, List);
+ ReceiverRingProcessLargePacket(Ring, Packet);
else
- ReceiverRingProcessStandardPacket(Ring, Packet, List);
+ ReceiverRingProcessStandardPacket(Ring, Packet);

return;

@@ -1318,63 +1327,8 @@ fail1:
1);
}

-static VOID
-ReceiverRingProcessPackets(
- IN PXENVIF_RECEIVER_RING Ring,
- OUT PLIST_ENTRY List,
- OUT PULONG Count
- )
-{
- PLIST_ENTRY ListEntry;
-
- while (!IsListEmpty(&Ring->PacketList)) {
- PXENVIF_RECEIVER_PACKET Packet;
-
- ListEntry = RemoveHeadList(&Ring->PacketList);
- ASSERT3P(ListEntry, !=, &Ring->PacketList);
-
- RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
-
- Packet = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_PACKET, ListEntry);
- ReceiverRingProcessPacket(Ring, Packet, List);
- }
-
- for (ListEntry = List->Flink;
- ListEntry != List;
- ListEntry = ListEntry->Flink) {
- PXENVIF_RECEIVER_PACKET Packet;
-
- Packet = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_PACKET, ListEntry);
-
- ReceiverRingProcessTag(Ring, Packet);
- ReceiverRingProcessChecksum(Ring, Packet);
-
- (*Count)++;
- }
-}
-
static FORCEINLINE VOID
-__drv_requiresIRQL(DISPATCH_LEVEL)
-__ReceiverRingAcquireLock(
- IN PXENVIF_RECEIVER_RING Ring
- )
-{
- ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
-
- KeAcquireSpinLockAtDpcLevel(&Ring->Lock);
-}
-
-static DECLSPEC_NOINLINE VOID
-ReceiverRingAcquireLock(
- IN PXENVIF_RECEIVER_RING Ring
- )
-{
- __ReceiverRingAcquireLock(Ring);
-}
-
-static FORCEINLINE VOID
-__drv_requiresIRQL(DISPATCH_LEVEL)
-__ReceiverRingReleaseLock(
+__ReceiverRingSwizzle(
IN PXENVIF_RECEIVER_RING Ring
)
{
@@ -1382,33 +1336,44 @@ __ReceiverRingReleaseLock(
PXENVIF_FRONTEND Frontend;
PXENVIF_VIF_CONTEXT Context;
LIST_ENTRY List;
- ULONG Count;
- BOOLEAN More;
-
- ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
+ PLIST_ENTRY ListEntry;

Receiver = Ring->Receiver;
Frontend = Receiver->Frontend;
Context = PdoGetVifContext(FrontendGetPdo(Frontend));

InitializeListHead(&List);
- Count = 0;

- ReceiverRingProcessPackets(Ring, &List, &Count);
- ASSERT(EQUIV(IsListEmpty(&List), Count == 0));
- ASSERT(IsListEmpty(&Ring->PacketList));
+ ListEntry = InterlockedExchangePointer(&Ring->PacketQueue, NULL);

- // We need to bump Loaned before dropping the lock to avoid VifDisable()
- // returning prematurely.
- __InterlockedAdd(&Receiver->Loaned, Count);
+ // Packets are held in the queue in reverse order so that the most
+ // recent is always head of the list. This is necessary to allow
+ // addition to the list to be done atomically.

-#pragma prefast(disable:26110)
- KeReleaseSpinLockFromDpcLevel(&Ring->Lock);
+ while (ListEntry != NULL) {
+ PLIST_ENTRY NextEntry;
+
+ NextEntry = ListEntry->Blink;
+ ListEntry->Flink = ListEntry->Blink = ListEntry;

- More = !IsListEmpty(&List) ? TRUE : FALSE;
+ InsertHeadList(&List, ListEntry);

- while (More) {
- PLIST_ENTRY ListEntry;
+ ListEntry = NextEntry;
+ }
+
+ while (!IsListEmpty(&List)) {
+ PXENVIF_RECEIVER_PACKET Packet;
+
+ ListEntry = RemoveHeadList(&List);
+ ASSERT3P(ListEntry, !=, &List);
+
+ RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
+
+ Packet = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_PACKET, ListEntry);
+ ReceiverRingProcessPacket(Ring, Packet);
+ }
+
+ while (!IsListEmpty(&Ring->PacketComplete)) {
PXENVIF_RECEIVER_PACKET Packet;
PXENVIF_PACKET_INFO Info;
PUCHAR BaseVa;
@@ -1416,14 +1381,11 @@ __ReceiverRingReleaseLock(
PETHERNET_ADDRESS DestinationAddress;
ETHERNET_ADDRESS_TYPE Type;

- ListEntry = RemoveHeadList(&List);
- ASSERT3P(ListEntry, !=, &List);
+ ListEntry = RemoveHeadList(&Ring->PacketComplete);
+ ASSERT3P(ListEntry, !=, &Ring->PacketComplete);

RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));

- ASSERT(More);
- More = !IsListEmpty(&List) ? TRUE : FALSE;
-
Packet = CONTAINING_RECORD(ListEntry,
XENVIF_RECEIVER_PACKET,
ListEntry);
@@ -1512,55 +1474,57 @@ __ReceiverRingReleaseLock(
XENVIF_RECEIVER_UDP_PACKETS,
1);

- if (Packet->MaximumSegmentSize != 0)
+ if (Packet->MaximumSegmentSize != 0)
FrontendIncrementStatistic(Frontend,
XENVIF_RECEIVER_GSO_PACKETS,
1);

- if (Packet->Flags.IpChecksumSucceeded != 0)
- FrontendIncrementStatistic(Frontend,
- XENVIF_RECEIVER_IPV4_CHECKSUM_SUCCEEDED,
- 1);
-
- if (Packet->Flags.IpChecksumFailed != 0)
- FrontendIncrementStatistic(Frontend,
- XENVIF_RECEIVER_IPV4_CHECKSUM_FAILED,
- 1);
-
- if (Packet->Flags.IpChecksumNotValidated != 0)
- FrontendIncrementStatistic(Frontend,
- XENVIF_RECEIVER_IPV4_CHECKSUM_NOT_VALIDATED,
- 1);
-
- if (Packet->Flags.TcpChecksumSucceeded != 0)
- FrontendIncrementStatistic(Frontend,
- XENVIF_RECEIVER_TCP_CHECKSUM_SUCCEEDED,
- 1);
-
- if (Packet->Flags.TcpChecksumFailed != 0)
- FrontendIncrementStatistic(Frontend,
- XENVIF_RECEIVER_TCP_CHECKSUM_FAILED,
- 1);
-
- if (Packet->Flags.TcpChecksumNotValidated != 0)
- FrontendIncrementStatistic(Frontend,
- XENVIF_RECEIVER_TCP_CHECKSUM_NOT_VALIDATED,
- 1);
-
- if (Packet->Flags.UdpChecksumSucceeded != 0)
- FrontendIncrementStatistic(Frontend,
- XENVIF_RECEIVER_UDP_CHECKSUM_SUCCEEDED,
- 1);
-
- if (Packet->Flags.UdpChecksumFailed != 0)
- FrontendIncrementStatistic(Frontend,
- XENVIF_RECEIVER_UDP_CHECKSUM_FAILED,
- 1);
-
- if (Packet->Flags.UdpChecksumNotValidated != 0)
- FrontendIncrementStatistic(Frontend,
- XENVIF_RECEIVER_UDP_CHECKSUM_NOT_VALIDATED,
- 1);
+ if (Packet->Flags.IpChecksumSucceeded != 0)
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_RECEIVER_IPV4_CHECKSUM_SUCCEEDED,
+ 1);
+
+ if (Packet->Flags.IpChecksumFailed != 0)
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_RECEIVER_IPV4_CHECKSUM_FAILED,
+ 1);
+
+ if (Packet->Flags.IpChecksumNotValidated != 0)
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_RECEIVER_IPV4_CHECKSUM_NOT_VALIDATED,
+ 1);
+
+ if (Packet->Flags.TcpChecksumSucceeded != 0)
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_RECEIVER_TCP_CHECKSUM_SUCCEEDED,
+ 1);
+
+ if (Packet->Flags.TcpChecksumFailed != 0)
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_RECEIVER_TCP_CHECKSUM_FAILED,
+ 1);
+
+ if (Packet->Flags.TcpChecksumNotValidated != 0)
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_RECEIVER_TCP_CHECKSUM_NOT_VALIDATED,
+ 1);
+
+ if (Packet->Flags.UdpChecksumSucceeded != 0)
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_RECEIVER_UDP_CHECKSUM_SUCCEEDED,
+ 1);
+
+ if (Packet->Flags.UdpChecksumFailed != 0)
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_RECEIVER_UDP_CHECKSUM_FAILED,
+ 1);
+
+ if (Packet->Flags.UdpChecksumNotValidated != 0)
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_RECEIVER_UDP_CHECKSUM_NOT_VALIDATED,
+ 1);
+
+ (VOID) InterlockedIncrement(&Receiver->Loaned);

VifReceiverQueuePacket(Context,
Ring->Index,
@@ -1572,13 +1536,40 @@ __ReceiverRingReleaseLock(
Packet->TagControlInformation,
&Packet->Info,
&Packet->Hash,
- More,
+ !IsListEmpty(&Ring->PacketComplete) ? TRUE : FALSE,
Packet);
-
- --Count;
}
+}
+
+static FORCEINLINE VOID
+__drv_requiresIRQL(DISPATCH_LEVEL)
+__ReceiverRingAcquireLock(
+ IN PXENVIF_RECEIVER_RING Ring
+ )
+{
+ ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
+
+ KeAcquireSpinLockAtDpcLevel(&Ring->Lock);
+}

- ASSERT3U(Count, ==, 0);
+static DECLSPEC_NOINLINE VOID
+ReceiverRingAcquireLock(
+ IN PXENVIF_RECEIVER_RING Ring
+ )
+{
+ __ReceiverRingAcquireLock(Ring);
+}
+
+static FORCEINLINE VOID
+__drv_requiresIRQL(DISPATCH_LEVEL)
+__ReceiverRingReleaseLock(
+ IN PXENVIF_RECEIVER_RING Ring
+ )
+{
+ ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
+
+#pragma prefast(disable:26110)
+ KeReleaseSpinLockFromDpcLevel(&Ring->Lock);
}

static DECLSPEC_NOINLINE VOID
@@ -1589,6 +1580,29 @@ ReceiverRingReleaseLock(
__ReceiverRingReleaseLock(Ring);
}

+__drv_functionClass(KDEFERRED_ROUTINE)
+__drv_maxIRQL(DISPATCH_LEVEL)
+__drv_minIRQL(PASSIVE_LEVEL)
+__drv_sameIRQL
+static VOID
+ReceiverRingQueueDpc(
+ IN PKDPC Dpc,
+ IN PVOID Context,
+ IN PVOID Argument1,
+ IN PVOID Argument2
+ )
+{
+ PXENVIF_RECEIVER_RING Ring = Context;
+
+ UNREFERENCED_PARAMETER(Dpc);
+ UNREFERENCED_PARAMETER(Argument1);
+ UNREFERENCED_PARAMETER(Argument2);
+
+ ASSERT(Ring != NULL);
+
+ __ReceiverRingSwizzle(Ring);
+}
+
static FORCEINLINE VOID
__ReceiverRingStop(
IN PXENVIF_RECEIVER_RING Ring
@@ -1902,6 +1916,11 @@ ReceiverRingDebugCallback(
(Ring->Enabled) ? "ENABLED" : "DISABLED",
(__ReceiverRingIsStopped(Ring)) ? "STOPPED" : "RUNNING");

+ XENBUS_DEBUG(Printf,
+ &Receiver->DebugInterface,
+ "QueueDpcs = %lu\n",
+ Ring->QueueDpcs);
+
// Dump front ring
XENBUS_DEBUG(Printf,
&Receiver->DebugInterface,
@@ -1930,10 +1949,30 @@ ReceiverRingDebugCallback(
// Dump event channel
XENBUS_DEBUG(Printf,
&Receiver->DebugInterface,
- "[%s]: Events = %lu Dpcs = %lu\n",
+ "[%s]: Events = %lu PollDpcs = %lu\n",
FrontendIsSplit(Frontend) ? "RX" : "COMBINED",
Ring->Events,
- Ring->Dpcs);
+ Ring->PollDpcs);
+}
+
+static FORCEINLINE VOID
+__ReceiverRingQueuePacket(
+ IN PXENVIF_RECEIVER_RING Ring,
+ IN PXENVIF_RECEIVER_PACKET Packet
+ )
+{
+ PLIST_ENTRY ListEntry;
+ PLIST_ENTRY Old;
+ PLIST_ENTRY New;
+
+ ListEntry = &Packet->ListEntry;
+
+ do {
+ Old = Ring->PacketQueue;
+
+ ListEntry->Blink = Ring->PacketQueue;
+ New = ListEntry;
+ } while (InterlockedCompareExchangePointer(&Ring->PacketQueue, (PVOID)New, (PVOID)Old) != Old);
}

static DECLSPEC_NOINLINE BOOLEAN
@@ -2151,7 +2190,7 @@ ReceiverRingPoll(
Packet->Flags.Value = flags;

ASSERT(IsZeroMemory(&Packet->ListEntry, sizeof (LIST_ENTRY)));
- InsertTailList(&Ring->PacketList, &Packet->ListEntry);
+ __ReceiverRingQueuePacket(Ring, Packet);
}

if (rsp_cons - Ring->Front.rsp_cons > XENVIF_RECEIVER_BATCH(Ring))
@@ -2184,6 +2223,10 @@ ReceiverRingPoll(
if (!__ReceiverRingIsStopped(Ring))
ReceiverRingFill(Ring);

+ if (Ring->PacketQueue != NULL &&
+ KeInsertQueueDpc(&Ring->QueueDpc, NULL, NULL))
+ Ring->QueueDpcs++;
+
done:
return Retry;

@@ -2215,7 +2258,7 @@ __drv_minIRQL(DISPATCH_LEVEL)
__drv_requiresIRQL(DISPATCH_LEVEL)
__drv_sameIRQL
static VOID
-ReceiverRingDpc(
+ReceiverRingPollDpc(
IN PKDPC Dpc,
IN PVOID Context,
IN PVOID Argument1,
@@ -2262,8 +2305,8 @@ ReceiverRingEvtchnCallback(

Ring->Events++;

- if (KeInsertQueueDpc(&Ring->Dpc, NULL, NULL))
- Ring->Dpcs++;
+ if (KeInsertQueueDpc(&Ring->PollDpc, NULL, NULL))
+ Ring->PollDpcs++;

Receiver = Ring->Receiver;
Frontend = Receiver->Frontend;
@@ -2398,9 +2441,9 @@ __ReceiverRingInitialize(
if ((*Ring)->Path == NULL)
goto fail2;

- InitializeListHead(&(*Ring)->PacketList);
+ InitializeListHead(&(*Ring)->PacketComplete);

- KeInitializeDpc(&(*Ring)->Dpc, ReceiverRingDpc, *Ring);
+ KeInitializeDpc(&(*Ring)->PollDpc, ReceiverRingPollDpc, *Ring);

status = RtlStringCbPrintfA(Name,
sizeof (Name),
@@ -2458,6 +2501,8 @@ __ReceiverRingInitialize(
if (!NT_SUCCESS(status))
goto fail7;

+ KeInitializeThreadedDpc(&(*Ring)->QueueDpc, ReceiverRingQueueDpc, *Ring);
+
return STATUS_SUCCESS;

fail7:
@@ -2485,9 +2530,9 @@ fail4:
fail3:
Error("fail3\n");

- RtlZeroMemory(&(*Ring)->Dpc, sizeof (KDPC));
+ RtlZeroMemory(&(*Ring)->PollDpc, sizeof (KDPC));

- RtlZeroMemory(&(*Ring)->PacketList, sizeof (LIST_ENTRY));
+ RtlZeroMemory(&(*Ring)->PacketComplete, sizeof (LIST_ENTRY));

FrontendFreePath(Frontend, (*Ring)->Path);
(*Ring)->Path = NULL;
@@ -2599,7 +2644,7 @@ __ReceiverRingConnect(
status = KeGetProcessorNumberFromIndex(Ring->Index, &ProcNumber);
ASSERT(NT_SUCCESS(status));

- KeSetTargetProcessorDpcEx(&Ring->Dpc, &ProcNumber);
+ KeSetTargetProcessorDpcEx(&Ring->PollDpc, &ProcNumber);

(VOID) XENBUS_EVTCHN(Bind,
&Receiver->EvtchnInterface,
@@ -2624,6 +2669,11 @@ __ReceiverRingConnect(
if (!NT_SUCCESS(status))
goto fail7;

+ status = KeGetProcessorNumberFromIndex(Ring->Index, &ProcNumber);
+ ASSERT(NT_SUCCESS(status));
+
+ KeSetTargetProcessorDpcEx(&Ring->QueueDpc, &ProcNumber);
+
return STATUS_SUCCESS;

fail7:
@@ -2762,7 +2812,7 @@ __ReceiverRingEnable(

Ring->Enabled = TRUE;

- (VOID) KeInsertQueueDpc(&Ring->Dpc, NULL, NULL);
+ (VOID) KeInsertQueueDpc(&Ring->PollDpc, NULL, NULL);

__ReceiverRingReleaseLock(Ring);

@@ -2802,6 +2852,9 @@ __ReceiverRingDisable(
Ring->Enabled = FALSE;
Ring->Stopped = FALSE;

+ if (KeInsertQueueDpc(&Ring->QueueDpc, NULL, NULL))
+ Ring->QueueDpcs++;
+
__ReceiverRingReleaseLock(Ring);

Info("%s[%u]: <====\n",
@@ -2820,6 +2873,8 @@ __ReceiverRingDisconnect(
Receiver = Ring->Receiver;
Frontend = Receiver->Frontend;

+ Ring->QueueDpcs = 0;
+
__ReceiverRingEmpty(Ring);

ASSERT(Ring->Connected);
@@ -2831,7 +2886,7 @@ __ReceiverRingDisconnect(
Ring->Channel = NULL;

Ring->Events = 0;
- Ring->Dpcs = 0;
+ Ring->PollDpcs = 0;

ASSERT3U(Ring->ResponsesProcessed, ==, Ring->RequestsPushed);
ASSERT3U(Ring->RequestsPushed, ==, Ring->RequestsPosted);
@@ -2877,11 +2932,14 @@ __ReceiverRingTeardown(
Frontend = Receiver->Frontend;

RtlZeroMemory(&Ring->Hash, sizeof (XENVIF_RECEIVER_HASH));
- RtlZeroMemory(&Ring->Dpc, sizeof (KDPC));
+ RtlZeroMemory(&Ring->PollDpc, sizeof (KDPC));

Ring->BackfillSize = 0;
Ring->OffloadOptions.Value = 0;

+ KeFlushQueuedDpcs();
+ RtlZeroMemory(&Ring->QueueDpc, sizeof (KDPC));
+
ThreadAlert(Ring->WatchdogThread);
ThreadJoin(Ring->WatchdogThread);
Ring->WatchdogThread = NULL;
@@ -2896,8 +2954,8 @@ __ReceiverRingTeardown(
Ring->PacketCache);
Ring->PacketCache = NULL;

- ASSERT(IsListEmpty(&Ring->PacketList));
- RtlZeroMemory(&Ring->PacketList, sizeof (LIST_ENTRY));
+ ASSERT(IsListEmpty(&Ring->PacketComplete));
+ RtlZeroMemory(&Ring->PacketComplete, sizeof (LIST_ENTRY));

FrontendFreePath(Frontend, Ring->Path);
Ring->Path = NULL;
@@ -3673,16 +3731,13 @@ ReceiverWaitForPackets(
LARGE_INTEGER Timeout;

ASSERT3U(KeGetCurrentIrql(), <, DISPATCH_LEVEL);
+ KeFlushQueuedDpcs();

Frontend = Receiver->Frontend;

Trace("%s: ====>\n", FrontendGetPath(Frontend));

Returned = Receiver->Returned;
-
- // Make sure Loaned is not sampled before Returned
- KeMemoryBarrier();
-
Loaned = Receiver->Loaned;
ASSERT3S(Loaned - Returned, >=, 0);

diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
index 02c0d3e..6895f2c 100644
--- a/src/xenvif/transmitter.c
+++ b/src/xenvif/transmitter.c
@@ -180,8 +180,8 @@ typedef struct _XENVIF_TRANSMITTER_RING {
netif_tx_sring_t *Shared;
PXENBUS_GNTTAB_ENTRY Entry;
PXENBUS_EVTCHN_CHANNEL Channel;
- KDPC Dpc;
- ULONG Dpcs;
+ KDPC PollDpc;
+ ULONG PollDpcs;
ULONG Events;
BOOLEAN Connected;
BOOLEAN Enabled;
@@ -773,9 +773,9 @@ TransmitterRingDebugCallback(
// Dump event channel
XENBUS_DEBUG(Printf,
&Transmitter->DebugInterface,
- "Events = %lu Dpcs = %lu\n",
+ "Events = %lu PollDpcs = %lu\n",
Ring->Events,
- Ring->Dpcs);
+ Ring->PollDpcs);
}
}

@@ -3254,7 +3254,7 @@ __drv_minIRQL(DISPATCH_LEVEL)
__drv_requiresIRQL(DISPATCH_LEVEL)
__drv_sameIRQL
static VOID
-TransmitterRingDpc(
+TransmitterRingPollDpc(
IN PKDPC Dpc,
IN PVOID Context,
IN PVOID Argument1,
@@ -3306,8 +3306,8 @@ TransmitterRingEvtchnCallback(

Ring->Events++;

- if (KeInsertQueueDpc(&Ring->Dpc, NULL, NULL))
- Ring->Dpcs++;
+ if (KeInsertQueueDpc(&Ring->PollDpc, NULL, NULL))
+ Ring->PollDpcs++;

return TRUE;
}
@@ -3429,7 +3429,7 @@ __TransmitterRingInitialize(
InitializeListHead(&(*Ring)->RequestQueue);
InitializeListHead(&(*Ring)->PacketComplete);

- KeInitializeDpc(&(*Ring)->Dpc, TransmitterRingDpc, *Ring);
+ KeInitializeDpc(&(*Ring)->PollDpc, TransmitterRingPollDpc, *Ring);

status = RtlStringCbPrintfA(Name,
sizeof (Name),
@@ -3632,7 +3632,7 @@ fail4:
fail3:
Error("fail3\n");

- RtlZeroMemory(&(*Ring)->Dpc, sizeof (KDPC));
+ RtlZeroMemory(&(*Ring)->PollDpc, sizeof (KDPC));

RtlZeroMemory(&(*Ring)->PacketComplete, sizeof (LIST_ENTRY));
RtlZeroMemory(&(*Ring)->RequestQueue, sizeof (LIST_ENTRY));
@@ -3749,7 +3749,7 @@ __TransmitterRingConnect(
status = KeGetProcessorNumberFromIndex(Ring->Index, &ProcNumber);
ASSERT(NT_SUCCESS(status));

- KeSetTargetProcessorDpcEx(&Ring->Dpc, &ProcNumber);
+ KeSetTargetProcessorDpcEx(&Ring->PollDpc, &ProcNumber);

(VOID) XENBUS_EVTCHN(Bind,
&Transmitter->EvtchnInterface,
@@ -3907,7 +3907,7 @@ __TransmitterRingEnable(
ASSERT(!Ring->Enabled);
Ring->Enabled = TRUE;

- KeInsertQueueDpc(&Ring->Dpc, NULL, NULL);
+ KeInsertQueueDpc(&Ring->PollDpc, NULL, NULL);

__TransmitterRingReleaseLock(Ring);

@@ -4034,7 +4034,7 @@ __TransmitterRingDisconnect(
Ring->Events = 0;
}

- Ring->Dpcs = 0;
+ Ring->PollDpcs = 0;

ASSERT3U(Ring->ResponsesProcessed, ==, Ring->RequestsPushed);
ASSERT3U(Ring->RequestsPushed, ==, Ring->RequestsPosted);
@@ -4079,9 +4079,9 @@ __TransmitterRingTeardown(
Transmitter = Ring->Transmitter;
Frontend = Transmitter->Frontend;

- Ring->Dpcs = 0;
+ Ring->PollDpcs = 0;

- RtlZeroMemory(&Ring->Dpc, sizeof (KDPC));
+ RtlZeroMemory(&Ring->PollDpc, sizeof (KDPC));

ASSERT3U(Ring->PacketsCompleted, ==, Ring->PacketsSent);
ASSERT3U(Ring->PacketsSent, ==, Ring->PacketsPrepared - Ring->PacketsUnprepared);
@@ -5276,8 +5276,8 @@ TransmitterNotify(

Ring = Transmitter->Ring[Index];

- if (KeInsertQueueDpc(&Ring->Dpc, NULL, NULL))
- Ring->Dpcs++;
+ if (KeInsertQueueDpc(&Ring->PollDpc, NULL, NULL))
+ Ring->PollDpcs++;
}

VOID
diff --git a/src/xenvif/vif.c b/src/xenvif/vif.c
index ffdec50..69ced78 100644
--- a/src/xenvif/vif.c
+++ b/src/xenvif/vif.c
@@ -1161,6 +1161,7 @@ __VifReceiverQueuePacket(
Hash,
More,
Cookie);
+
}

VOID
@@ -1179,6 +1180,10 @@ VifReceiverQueuePacket(
IN PVOID Cookie
)
{
+ KIRQL Irql;
+
+ KeRaiseIrql(DISPATCH_LEVEL, &Irql);
+
switch (Context->Version) {
case 6:
__VifReceiverQueuePacketVersion6(Context,
@@ -1229,6 +1234,8 @@ VifReceiverQueuePacket(
ASSERT(FALSE);
break;
}
+
+ KeLowerIrql(Irql);
}

VOID
--
2.5.3
Paul Durrant
2018-11-02 16:54:24 UTC
Permalink
It seems to have a bad effect on performance that various attempts at
improvement just don't seem to be able fix, so this patch just gets rid
of the whole thing.

This patch reverts the following commits:

264bde12 "Introduce a threaded DPC into the receiver code"
129ad516 "Stop using a threaded DPC in the poller"
5932938b "Don't bump the receiver event counter if the poller is going to retry"
16002b8f "poller: fix event channels when backends do not support multi-queue"
bc722edd "Don't use KTIMERs in receive path"
dfaa68cc "Don't affinitize timer DPC"
eac9a95a "Move the Receiver and Transmitter event and DPC processing..."
40be5c12 "Add the boilerplate for a new Poller sub-system"

Signed-off-by: Paul Durrant <***@citrix.com>
---
src/xenvif/frontend.c | 133 ++--
src/xenvif/frontend.h | 17 +-
src/xenvif/poller.c | 1454 ------------------------------------------
src/xenvif/poller.h | 100 ---
src/xenvif/receiver.c | 749 ++++++++++++++--------
src/xenvif/receiver.h | 6 -
src/xenvif/transmitter.c | 396 ++++++++++--
src/xenvif/transmitter.h | 6 -
src/xenvif/vif.c | 7 -
vs2015/xenvif/xenvif.vcxproj | 1 -
vs2017/xenvif/xenvif.vcxproj | 1 -
11 files changed, 903 insertions(+), 1967 deletions(-)
delete mode 100644 src/xenvif/poller.c
delete mode 100644 src/xenvif/poller.h

diff --git a/src/xenvif/frontend.c b/src/xenvif/frontend.c
index 5810947..3e31654 100644
--- a/src/xenvif/frontend.c
+++ b/src/xenvif/frontend.c
@@ -47,7 +47,6 @@
#include "tcpip.h"
#include "receiver.h"
#include "transmitter.h"
-#include "poller.h"
#include "link.h"
#include "dbg_print.h"
#include "assert.h"
@@ -81,12 +80,12 @@ struct _XENVIF_FRONTEND {
USHORT BackendDomain;
ULONG MaxQueues;
ULONG NumQueues;
+ BOOLEAN Split;
ULONG DisableToeplitz;

PXENVIF_MAC Mac;
PXENVIF_RECEIVER Receiver;
PXENVIF_TRANSMITTER Transmitter;
- PXENVIF_POLLER Poller;
PXENVIF_CONTROLLER Controller;

XENBUS_DEBUG_INTERFACE DebugInterface;
@@ -339,7 +338,6 @@ FrontendGet ## _Function( \
DEFINE_FRONTEND_GET_FUNCTION(Mac, PXENVIF_MAC)
DEFINE_FRONTEND_GET_FUNCTION(Receiver, PXENVIF_RECEIVER)
DEFINE_FRONTEND_GET_FUNCTION(Transmitter, PXENVIF_TRANSMITTER)
-DEFINE_FRONTEND_GET_FUNCTION(Poller, PXENVIF_POLLER)
DEFINE_FRONTEND_GET_FUNCTION(Controller, PXENVIF_CONTROLLER)

static BOOLEAN
@@ -1802,6 +1800,50 @@ FrontendGetNumQueues(
return __FrontendGetNumQueues(Frontend);
}

+static VOID
+FrontendSetSplit(
+ IN PXENVIF_FRONTEND Frontend
+ )
+{
+ PCHAR Buffer;
+ NTSTATUS status;
+
+ status = XENBUS_STORE(Read,
+ &Frontend->StoreInterface,
+ NULL,
+ __FrontendGetBackendPath(Frontend),
+ "feature-split-event-channels",
+ &Buffer);
+ if (NT_SUCCESS(status)) {
+ Frontend->Split = (BOOLEAN)strtol(Buffer, NULL, 2);
+
+ XENBUS_STORE(Free,
+ &Frontend->StoreInterface,
+ Buffer);
+ } else {
+ Frontend->Split = FALSE;
+ }
+
+ Info("%s: %s\n", __FrontendGetPath(Frontend),
+ (Frontend->Split) ? "TRUE" : "FALSE");
+}
+
+static FORCEINLINE BOOLEAN
+__FrontendIsSplit(
+ IN PXENVIF_FRONTEND Frontend
+ )
+{
+ return Frontend->Split;
+}
+
+BOOLEAN
+FrontendIsSplit(
+ IN PXENVIF_FRONTEND Frontend
+ )
+{
+ return __FrontendIsSplit(Frontend);
+}
+
static FORCEINLINE NTSTATUS
__FrontendUpdateHash(
PXENVIF_FRONTEND Frontend,
@@ -2166,22 +2208,19 @@ FrontendConnect(
goto fail3;

FrontendSetNumQueues(Frontend);
-
- status = PollerConnect(__FrontendGetPoller(Frontend));
- if (!NT_SUCCESS(status))
- goto fail4;
+ FrontendSetSplit(Frontend);

status = ReceiverConnect(__FrontendGetReceiver(Frontend));
if (!NT_SUCCESS(status))
- goto fail5;
+ goto fail4;

status = TransmitterConnect(__FrontendGetTransmitter(Frontend));
if (!NT_SUCCESS(status))
- goto fail6;
+ goto fail5;

status = ControllerConnect(__FrontendGetController(Frontend));
if (!NT_SUCCESS(status))
- goto fail7;
+ goto fail6;

Attempt = 0;
do {
@@ -2193,11 +2232,6 @@ FrontendConnect(
if (!NT_SUCCESS(status))
break;

- status = PollerStoreWrite(__FrontendGetPoller(Frontend),
- Transaction);
- if (!NT_SUCCESS(status))
- goto abort;
-
status = ReceiverStoreWrite(__FrontendGetReceiver(Frontend),
Transaction);
if (!NT_SUCCESS(status))
@@ -2241,7 +2275,7 @@ abort:
} while (status == STATUS_RETRY);

if (!NT_SUCCESS(status))
- goto fail8;
+ goto fail7;

State = XenbusStateUnknown;
while (State != XenbusStateConnected) {
@@ -2280,7 +2314,7 @@ abort:

status = STATUS_UNSUCCESSFUL;
if (State != XenbusStateConnected)
- goto fail9;
+ goto fail8;

ControllerEnable(__FrontendGetController(Frontend));

@@ -2289,34 +2323,30 @@ abort:
Trace("<====\n");
return STATUS_SUCCESS;

-fail9:
- Error("fail9\n");
-
fail8:
Error("fail8\n");

- ControllerDisconnect(__FrontendGetController(Frontend));
-
fail7:
Error("fail7\n");

- TransmitterDisconnect(__FrontendGetTransmitter(Frontend));
+ ControllerDisconnect(__FrontendGetController(Frontend));

fail6:
Error("fail6\n");

- ReceiverDisconnect(__FrontendGetReceiver(Frontend));
+ TransmitterDisconnect(__FrontendGetTransmitter(Frontend));

fail5:
Error("fail5\n");

- PollerDisconnect(__FrontendGetPoller(Frontend));
+ ReceiverDisconnect(__FrontendGetReceiver(Frontend));

fail4:
Error("fail4\n");

MacDisconnect(__FrontendGetMac(Frontend));

+ Frontend->Split = FALSE;
Frontend->NumQueues = 0;

fail3:
@@ -2351,9 +2381,9 @@ FrontendDisconnect(
ControllerDisconnect(__FrontendGetController(Frontend));
TransmitterDisconnect(__FrontendGetTransmitter(Frontend));
ReceiverDisconnect(__FrontendGetReceiver(Frontend));
- PollerDisconnect(__FrontendGetPoller(Frontend));
MacDisconnect(__FrontendGetMac(Frontend));

+ Frontend->Split = FALSE;
Frontend->NumQueues = 0;

XENBUS_DEBUG(Deregister,
@@ -2379,41 +2409,32 @@ FrontendEnable(
if (!NT_SUCCESS(status))
goto fail1;

- status = PollerEnable(__FrontendGetPoller(Frontend));
- if (!NT_SUCCESS(status))
- goto fail2;
-
status = ReceiverEnable(__FrontendGetReceiver(Frontend));
if (!NT_SUCCESS(status))
- goto fail3;
+ goto fail2;

status = TransmitterEnable(__FrontendGetTransmitter(Frontend));
if (!NT_SUCCESS(status))
- goto fail4;
+ goto fail3;

status = __FrontendUpdateHash(Frontend, &Frontend->Hash);
if (!NT_SUCCESS(status))
- goto fail5;
+ goto fail4;

(VOID) FrontendNotifyMulticastAddresses(Frontend, TRUE);

Trace("<====\n");
return STATUS_SUCCESS;

-fail5:
- Error("fail5\n");
-
- TransmitterDisable(__FrontendGetTransmitter(Frontend));
-
fail4:
Error("fail4\n");

- ReceiverDisable(__FrontendGetReceiver(Frontend));
+ TransmitterDisable(__FrontendGetTransmitter(Frontend));

fail3:
Error("fail3\n");

- PollerDisable(__FrontendGetPoller(Frontend));
+ ReceiverDisable(__FrontendGetReceiver(Frontend));

fail2:
Error("fail2\n");
@@ -2437,7 +2458,6 @@ FrontendDisable(

TransmitterDisable(__FrontendGetTransmitter(Frontend));
ReceiverDisable(__FrontendGetReceiver(Frontend));
- PollerDisable(__FrontendGetPoller(Frontend));
MacDisable(__FrontendGetMac(Frontend));

Trace("<====\n");
@@ -2849,23 +2869,19 @@ FrontendInitialize(
if (!NT_SUCCESS(status))
goto fail8;

- status = PollerInitialize(*Frontend, &(*Frontend)->Poller);
- if (!NT_SUCCESS(status))
- goto fail9;
-
status = ControllerInitialize(*Frontend, &(*Frontend)->Controller);
if (!NT_SUCCESS(status))
- goto fail10;
+ goto fail9;

KeInitializeEvent(&(*Frontend)->EjectEvent, NotificationEvent, FALSE);

status = ThreadCreate(FrontendEject, *Frontend, &(*Frontend)->EjectThread);
if (!NT_SUCCESS(status))
- goto fail11;
+ goto fail10;

status = ThreadCreate(FrontendMib, *Frontend, &(*Frontend)->MibThread);
if (!NT_SUCCESS(status))
- goto fail12;
+ goto fail11;

(*Frontend)->StatisticsCount = KeQueryMaximumProcessorCountEx(ALL_PROCESSOR_GROUPS);
(*Frontend)->Statistics = __FrontendAllocate(sizeof (XENVIF_FRONTEND_STATISTICS) *
@@ -2873,38 +2889,34 @@ FrontendInitialize(

status = STATUS_NO_MEMORY;
if ((*Frontend)->Statistics == NULL)
- goto fail13;
+ goto fail12;

Trace("<====\n");

return STATUS_SUCCESS;

-fail13:
- Error("fail13\n");
+fail12:
+ Error("fail12\n");

ThreadAlert((*Frontend)->MibThread);
ThreadJoin((*Frontend)->MibThread);
(*Frontend)->MibThread = NULL;

-fail12:
- Error("fail12\n");
+fail11:
+ Error("fail11\n");

ThreadAlert((*Frontend)->EjectThread);
ThreadJoin((*Frontend)->EjectThread);
(*Frontend)->EjectThread = NULL;

-fail11:
- Error("fail11\n");
+fail10:
+ Error("fail10\n");

RtlZeroMemory(&(*Frontend)->EjectEvent, sizeof (KEVENT));

ControllerTeardown(__FrontendGetController(*Frontend));
(*Frontend)->Controller = NULL;

-fail10:
- PollerTeardown(__FrontendGetPoller(*Frontend));
- (*Frontend)->Poller = NULL;
-
fail9:
TransmitterTeardown(__FrontendGetTransmitter(*Frontend));
(*Frontend)->Transmitter = NULL;
@@ -3012,9 +3024,6 @@ FrontendTeardown(
ControllerTeardown(__FrontendGetController(Frontend));
Frontend->Controller = NULL;

- PollerTeardown(__FrontendGetPoller(Frontend));
- Frontend->Poller = NULL;
-
TransmitterTeardown(__FrontendGetTransmitter(Frontend));
Frontend->Transmitter = NULL;

diff --git a/src/xenvif/frontend.h b/src/xenvif/frontend.h
index 7f3b7c5..8e5552e 100644
--- a/src/xenvif/frontend.h
+++ b/src/xenvif/frontend.h
@@ -123,6 +123,16 @@ FrontendGetNumQueues(
IN PXENVIF_FRONTEND Frontend
);

+extern BOOLEAN
+FrontendIsSplit(
+ IN PXENVIF_FRONTEND Frontend
+ );
+
+extern BOOLEAN
+FrontendIsSplit(
+ IN PXENVIF_FRONTEND Frontend
+ );
+
extern PCHAR
FrontendFormatPath(
IN PXENVIF_FRONTEND Frontend,
@@ -156,13 +166,6 @@ FrontendGetTransmitter(
IN PXENVIF_FRONTEND Frontend
);

-#include "poller.h"
-
-extern PXENVIF_POLLER
-FrontendGetPoller(
- IN PXENVIF_FRONTEND Frontend
- );
-
#include "controller.h"

extern PXENVIF_CONTROLLER
diff --git a/src/xenvif/poller.c b/src/xenvif/poller.c
deleted file mode 100644
index 7f18d13..0000000
--- a/src/xenvif/poller.c
+++ /dev/null
@@ -1,1454 +0,0 @@
-/* Copyright (c) Citrix Systems Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms,
- * with or without modification, are permitted provided
- * that the following conditions are met:
- *
- * * Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the
- * following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the
- * following disclaimer in the documetation and/or other
- * materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <ntddk.h>
-#include <procgrp.h>
-#include <ntstrsafe.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <xen.h>
-
-#include <debug_interface.h>
-#include <store_interface.h>
-#include <evtchn_interface.h>
-
-#include "pdo.h"
-#include "frontend.h"
-#include "transmitter.h"
-#include "receiver.h"
-#include "poller.h"
-#include "vif.h"
-#include "thread.h"
-#include "registry.h"
-#include "dbg_print.h"
-#include "assert.h"
-#include "util.h"
-
-#define MAXNAMELEN 128
-
-typedef struct _XENVIF_POLLER_INSTANCE XENVIF_POLLER_INSTANCE, *PXENVIF_POLLER_INSTANCE;
-
-typedef enum _XENVIF_POLLER_CHANNEL_TYPE {
- XENVIF_POLLER_CHANNEL_RECEIVER,
- XENVIF_POLLER_CHANNEL_TRANSMITTER,
- XENVIF_POLLER_CHANNEL_COMBINED,
- XENVIF_POLLER_CHANNEL_TYPE_COUNT
-} XENVIF_POLLER_CHANNEL_TYPE, *PXENVIF_POLLER_CHANNEL_TYPE;
-
-#define XENVIF_POLLER_CHANNEL_INVALID XENVIF_POLLER_CHANNEL_TYPE_COUNT
-
-typedef struct _XENVIF_POLLER_CHANNEL {
- PXENVIF_POLLER_INSTANCE Instance;
- XENVIF_POLLER_CHANNEL_TYPE Type;
- const CHAR *Node;
- PXENBUS_EVTCHN_CHANNEL Channel;
- ULONG Events;
-} XENVIF_POLLER_CHANNEL, *PXENVIF_POLLER_CHANNEL;
-
-struct _XENVIF_POLLER_INSTANCE {
- PXENVIF_POLLER Poller;
- ULONG Index;
- PCHAR Path;
- KSPIN_LOCK Lock;
- KDPC Dpc;
- ULONG Dpcs;
- PXENVIF_POLLER_CHANNEL Channel[XENVIF_POLLER_CHANNEL_TYPE_COUNT];
- BOOLEAN Enabled;
- LONG Pending;
-};
-
-struct _XENVIF_POLLER {
- PXENVIF_FRONTEND Frontend;
- PXENVIF_POLLER_INSTANCE *Instance;
- BOOLEAN Split;
- XENBUS_STORE_INTERFACE StoreInterface;
- XENBUS_EVTCHN_INTERFACE EvtchnInterface;
- XENBUS_DEBUG_INTERFACE DebugInterface;
- PXENBUS_DEBUG_CALLBACK DebugCallback;
-};
-
-#define XENVIF_POLLER_TAG 'LLOP'
-
-static FORCEINLINE PVOID
-__PollerAllocate(
- IN ULONG Length
- )
-{
- return __AllocatePoolWithTag(NonPagedPool, Length, XENVIF_POLLER_TAG);
-}
-
-static FORCEINLINE VOID
-__PollerFree(
- IN PVOID Buffer
- )
-{
- __FreePoolWithTag(Buffer, XENVIF_POLLER_TAG);
-}
-
-static NTSTATUS
-PollerChannelInitialize(
- IN PXENVIF_POLLER_INSTANCE Instance,
- IN ULONG Type,
- OUT PXENVIF_POLLER_CHANNEL *Channel
- )
-{
- NTSTATUS status;
-
- *Channel = __PollerAllocate(sizeof (XENVIF_POLLER_CHANNEL));
-
- status = STATUS_NO_MEMORY;
- if (*Channel == NULL)
- goto fail1;
-
- (*Channel)->Instance = Instance;
- (*Channel)->Type = Type;
-
- switch (Type) {
- case XENVIF_POLLER_CHANNEL_RECEIVER:
- (*Channel)->Node = "event-channel-rx";
- break;
-
- case XENVIF_POLLER_CHANNEL_TRANSMITTER:
- (*Channel)->Node = "event-channel-tx";
- break;
-
- case XENVIF_POLLER_CHANNEL_COMBINED:
- (*Channel)->Node = "event-channel";
- break;
-
- default:
- ASSERT(FALSE);
- break;
- }
-
- return STATUS_SUCCESS;
-
-fail1:
- Error("fail1 (%08x)\n", status);
-
- return status;
-}
-
-static BOOLEAN
-PollerChannelSetPending(
- IN PXENVIF_POLLER_CHANNEL Channel
- )
-{
- PXENVIF_POLLER_INSTANCE Instance;
- ULONG Set;
-
- Instance = Channel->Instance;
-
- switch (Channel->Type)
- {
- case XENVIF_POLLER_CHANNEL_RECEIVER:
- Set = InterlockedBitTestAndSet(&Instance->Pending,
- XENVIF_POLLER_EVENT_RECEIVE);
- break;
-
- case XENVIF_POLLER_CHANNEL_TRANSMITTER:
- Set = InterlockedBitTestAndSet(&Instance->Pending,
- XENVIF_POLLER_EVENT_TRANSMIT);
- break;
-
- case XENVIF_POLLER_CHANNEL_COMBINED:
- Set = InterlockedBitTestAndSet(&Instance->Pending,
- XENVIF_POLLER_EVENT_RECEIVE);
- Set |= InterlockedBitTestAndSet(&Instance->Pending,
- XENVIF_POLLER_EVENT_TRANSMIT);
- break;
-
- default:
- ASSERT(FALSE);
- Set = 0;
- break;
- }
-
- return (Set != 0) ? FALSE : TRUE;
-}
-
-static FORCEINLINE BOOLEAN
-__BitTest(
- IN PLONG Mask,
- IN LONG Bit
- )
-{
- return (*Mask & (1L << Bit)) ? TRUE : FALSE;
-}
-
-static BOOLEAN
-PollerChannelTestPending(
- IN PXENVIF_POLLER_CHANNEL Channel
- )
-{
- PXENVIF_POLLER_INSTANCE Instance;
-
- Instance = Channel->Instance;
-
- switch (Channel->Type)
- {
- case XENVIF_POLLER_CHANNEL_RECEIVER:
- if (__BitTest(&Instance->Pending, XENVIF_POLLER_EVENT_RECEIVE))
- return TRUE;
-
- break;
-
- case XENVIF_POLLER_CHANNEL_TRANSMITTER:
- if (__BitTest(&Instance->Pending, XENVIF_POLLER_EVENT_TRANSMIT))
- return TRUE;
-
- break;
-
- case XENVIF_POLLER_CHANNEL_COMBINED:
- if (__BitTest(&Instance->Pending, XENVIF_POLLER_EVENT_RECEIVE) ||
- __BitTest(&Instance->Pending, XENVIF_POLLER_EVENT_TRANSMIT))
- return TRUE;
-
- break;
-
- default:
- ASSERT(FALSE);
- break;
- }
-
- return FALSE;
-}
-
-KSERVICE_ROUTINE PollerChannelEvtchnCallback;
-
-BOOLEAN
-PollerChannelEvtchnCallback(
- IN PKINTERRUPT InterruptObject,
- IN PVOID Argument
- )
-{
- PXENVIF_POLLER_CHANNEL Channel = Argument;
- PXENVIF_POLLER_INSTANCE Instance;
-
- UNREFERENCED_PARAMETER(InterruptObject);
-
- ASSERT(Channel != NULL);
- Instance = Channel->Instance;
-
- Channel->Events++;
-
- if (PollerChannelSetPending(Channel) &&
- KeInsertQueueDpc(&Instance->Dpc, NULL, NULL))
- Instance->Dpcs++;
-
- return TRUE;
-}
-
-static FORCEINLINE BOOLEAN
-__PollerIsSplit(
- IN PXENVIF_POLLER Poller
- )
-{
- return Poller->Split;
-}
-
-static NTSTATUS
-PollerChannelConnect(
- IN PXENVIF_POLLER_CHANNEL Channel
- )
-{
- PXENVIF_POLLER_INSTANCE Instance;
- PXENVIF_POLLER Poller;
- PXENVIF_FRONTEND Frontend;
- PROCESSOR_NUMBER ProcNumber;
- NTSTATUS status;
-
- Instance = Channel->Instance;
- Poller = Instance->Poller;
- Frontend = Poller->Frontend;
-
- switch (Channel->Type)
- {
- case XENVIF_POLLER_CHANNEL_RECEIVER:
- case XENVIF_POLLER_CHANNEL_TRANSMITTER:
- if (!__PollerIsSplit(Poller))
- goto done;
-
- break;
-
- case XENVIF_POLLER_CHANNEL_COMBINED:
- if (__PollerIsSplit(Poller))
- goto done;
-
- break;
-
- default:
- ASSERT(FALSE);
- break;
- }
-
- Channel->Channel = XENBUS_EVTCHN(Open,
- &Poller->EvtchnInterface,
- XENBUS_EVTCHN_TYPE_UNBOUND,
- PollerChannelEvtchnCallback,
- Channel,
- FrontendGetBackendDomain(Frontend),
- TRUE);
-
- status = STATUS_UNSUCCESSFUL;
- if (Channel->Channel == NULL)
- goto fail1;
-
- status = KeGetProcessorNumberFromIndex(Instance->Index, &ProcNumber);
- ASSERT(NT_SUCCESS(status));
-
- (VOID) XENBUS_EVTCHN(Bind,
- &Poller->EvtchnInterface,
- Channel->Channel,
- ProcNumber.Group,
- ProcNumber.Number);
-
- (VOID) XENBUS_EVTCHN(Unmask,
- &Poller->EvtchnInterface,
- Channel->Channel,
- FALSE,
- TRUE);
-
-done:
- return STATUS_SUCCESS;
-
-fail1:
- Error("fail1 (%08x)\n", status);
-
- return status;
-}
-
-static NTSTATUS
-PollerChannelStoreWrite(
- IN PXENVIF_POLLER_CHANNEL Channel,
- IN PXENBUS_STORE_TRANSACTION Transaction
- )
-{
- PXENVIF_POLLER_INSTANCE Instance;
- PXENVIF_POLLER Poller;
- PCHAR Path;
- ULONG Port;
- NTSTATUS status;
-
- Instance = Channel->Instance;
- Poller = Instance->Poller;
-
- if (Channel->Channel == NULL)
- goto done;
-
- Path = (FrontendGetNumQueues(Poller->Frontend) == 1) ?
- FrontendGetPath(Poller->Frontend) :
- Instance->Path;
-
- Port = XENBUS_EVTCHN(GetPort,
- &Poller->EvtchnInterface,
- Channel->Channel);
-
- status = XENBUS_STORE(Printf,
- &Poller->StoreInterface,
- Transaction,
- Path,
- (PCHAR)Channel->Node,
- "%u",
- Port);
- if (!NT_SUCCESS(status))
- goto fail1;
-
-done:
- return STATUS_SUCCESS;
-
-fail1:
- Error("fail1 (%08x)\n", status);
-
- return status;
-}
-
-static VOID
-PollerChannelUnmask(
- IN PXENVIF_POLLER_CHANNEL Channel
- )
-{
- PXENVIF_POLLER_INSTANCE Instance;
- PXENVIF_POLLER Poller;
- BOOLEAN Pending;
-
- Instance = Channel->Instance;
- Poller = Instance->Poller;
-
- if (Channel->Channel == NULL)
- return;
-
- if (PollerChannelTestPending(Channel))
- return;
-
- Pending = XENBUS_EVTCHN(Unmask,
- &Poller->EvtchnInterface,
- Channel->Channel,
- FALSE,
- FALSE);
- if (Pending)
- (VOID) PollerChannelSetPending(Channel);
-}
-
-static VOID
-PollerChannelSend(
- IN PXENVIF_POLLER_CHANNEL Channel
- )
-{
- PXENVIF_POLLER_INSTANCE Instance;
- PXENVIF_POLLER Poller;
-
- Instance = Channel->Instance;
- Poller = Instance->Poller;
-
- XENBUS_EVTCHN(Send,
- &Poller->EvtchnInterface,
- Channel->Channel);
-}
-
-static VOID
-PollerChannelDebugCallback(
- IN PXENVIF_POLLER_CHANNEL Channel
- )
-{
- PXENVIF_POLLER_INSTANCE Instance;
- PXENVIF_POLLER Poller;
-
- Instance = Channel->Instance;
- Poller = Instance->Poller;
-
- if (Channel->Channel == NULL)
- return;
-
- XENBUS_DEBUG(Printf,
- &Poller->DebugInterface,
- "[%s]: Events = %lu\n",
- Channel->Node,
- Channel->Events);
-}
-
-static VOID
-PollerChannelDisconnect(
- IN PXENVIF_POLLER_CHANNEL Channel
- )
-{
- PXENVIF_POLLER_INSTANCE Instance;
- PXENVIF_POLLER Poller;
-
- Instance = Channel->Instance;
- Poller = Instance->Poller;
-
- if (Channel->Channel == NULL)
- return;
-
- Channel->Events = 0;
-
- XENBUS_EVTCHN(Close,
- &Poller->EvtchnInterface,
- Channel->Channel);
- Channel->Channel = NULL;
-}
-
-static VOID
-PollerChannelTeardown(
- IN PXENVIF_POLLER_CHANNEL Channel
- )
-{
- Channel->Node = NULL;
-
- Channel->Type = 0;
- Channel->Instance = NULL;
-
- ASSERT(IsZeroMemory(Channel, sizeof (XENVIF_POLLER_CHANNEL)));
- __PollerFree(Channel);
-}
-
-__drv_requiresIRQL(DISPATCH_LEVEL)
-static VOID
-PollerInstanceUnmask(
- IN PXENVIF_POLLER_INSTANCE Instance,
- IN XENVIF_POLLER_EVENT_TYPE Event
- )
-{
- PXENVIF_POLLER Poller;
- XENVIF_POLLER_CHANNEL_TYPE Type;
- PXENVIF_POLLER_CHANNEL Channel;
-
- ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
-
- Poller = Instance->Poller;
-
- KeAcquireSpinLockAtDpcLevel(&Instance->Lock);
-
- if (!Instance->Enabled)
- goto done;
-
- if (!__PollerIsSplit(Poller)) {
- Type = XENVIF_POLLER_CHANNEL_COMBINED;
- } else {
- switch (Event) {
- case XENVIF_POLLER_EVENT_RECEIVE:
- Type = XENVIF_POLLER_CHANNEL_RECEIVER;
- break;
-
- case XENVIF_POLLER_EVENT_TRANSMIT:
- Type = XENVIF_POLLER_CHANNEL_TRANSMITTER;
- break;
-
- default:
- Type = XENVIF_POLLER_CHANNEL_INVALID;
- break;
- }
- }
-
- ASSERT(Type != XENVIF_POLLER_CHANNEL_INVALID);
-
- Channel = Instance->Channel[Type];
-
- PollerChannelUnmask(Channel);
-
-done:
- KeReleaseSpinLockFromDpcLevel(&Instance->Lock);
-}
-
-__drv_functionClass(KDEFERRED_ROUTINE)
-__drv_maxIRQL(DISPATCH_LEVEL)
-__drv_minIRQL(DISPATCH_LEVEL)
-__drv_sameIRQL
-static VOID
-PollerInstanceDpc(
- IN PKDPC Dpc,
- IN PVOID Context,
- IN PVOID Argument1,
- IN PVOID Argument2
- )
-{
- PXENVIF_POLLER_INSTANCE Instance = Context;
- PXENVIF_POLLER Poller;
- PXENVIF_FRONTEND Frontend;
- BOOLEAN Enabled;
- BOOLEAN ReceiverRetry;
- BOOLEAN TransmitterRetry;
-
- UNREFERENCED_PARAMETER(Dpc);
- UNREFERENCED_PARAMETER(Argument1);
- UNREFERENCED_PARAMETER(Argument2);
-
- ASSERT(Instance != NULL);
-
- Poller = Instance->Poller;
- Frontend = Poller->Frontend;
- Enabled = FALSE;
- ReceiverRetry = FALSE;
- TransmitterRetry = FALSE;
-
- for (;;) {
- BOOLEAN NeedReceiverPoll;
- BOOLEAN NeedTransmitterPoll;
-
- KeAcquireSpinLockAtDpcLevel(&Instance->Lock);
- Enabled = Instance->Enabled;
- KeReleaseSpinLockFromDpcLevel(&Instance->Lock);
-
- if (!Enabled)
- break;
-
- NeedReceiverPoll =
- (InterlockedBitTestAndReset(&Instance->Pending,
- XENVIF_POLLER_EVENT_RECEIVE) != 0) ?
- TRUE :
- FALSE;
-
- NeedTransmitterPoll =
- (InterlockedBitTestAndReset(&Instance->Pending,
- XENVIF_POLLER_EVENT_TRANSMIT) != 0) ?
- TRUE :
- FALSE;
-
- if (!NeedReceiverPoll && !NeedTransmitterPoll)
- break;
-
- if (NeedReceiverPoll)
- {
- ReceiverRetry = ReceiverPoll(FrontendGetReceiver(Frontend),
- Instance->Index);
-
- if (!ReceiverRetry) {
- PollerInstanceUnmask(Instance, XENVIF_POLLER_EVENT_RECEIVE);
- } else {
- (VOID) InterlockedBitTestAndSet(&Instance->Pending,
- XENVIF_POLLER_EVENT_RECEIVE);
- }
- }
-
- if (NeedTransmitterPoll)
- {
- TransmitterRetry = TransmitterPoll(FrontendGetTransmitter(Frontend),
- Instance->Index);
-
- if (!TransmitterRetry) {
- PollerInstanceUnmask(Instance, XENVIF_POLLER_EVENT_TRANSMIT);
- } else {
- (VOID) InterlockedBitTestAndSet(&Instance->Pending,
- XENVIF_POLLER_EVENT_TRANSMIT);
- }
- }
- }
-
- ASSERT(!Enabled || !ReceiverRetry);
- ASSERT(!Enabled || !TransmitterRetry);
-}
-
-static NTSTATUS
-PollerInstanceInitialize(
- IN PXENVIF_POLLER Poller,
- IN LONG Index,
- OUT PXENVIF_POLLER_INSTANCE *Instance
- )
-{
- PXENVIF_FRONTEND Frontend;
- LONG Type;
- NTSTATUS status;
-
- Frontend = Poller->Frontend;
-
- *Instance = __PollerAllocate(sizeof (XENVIF_POLLER_INSTANCE));
-
- status = STATUS_NO_MEMORY;
- if (*Instance == NULL)
- goto fail1;
-
- (*Instance)->Poller = Poller;
- (*Instance)->Index = Index;
-
- for (Type = 0; Type < XENVIF_POLLER_CHANNEL_TYPE_COUNT; Type++)
- {
- PXENVIF_POLLER_CHANNEL Channel;
-
- status = PollerChannelInitialize(*Instance, Type, &Channel);
- if (!NT_SUCCESS(status))
- goto fail2;
-
- (*Instance)->Channel[Type] = Channel;
- }
-
- (*Instance)->Path = FrontendFormatPath(Frontend, Index);
- if ((*Instance)->Path == NULL)
- goto fail3;
-
- KeInitializeSpinLock(&(*Instance)->Lock);
-
- KeInitializeDpc(&(*Instance)->Dpc, PollerInstanceDpc, *Instance);
-
- return STATUS_SUCCESS;
-
-fail3:
- Error("fail3\n");
-
- Type = XENVIF_POLLER_CHANNEL_TYPE_COUNT;
-
-fail2:
- Error("fail2\n");
-
- while (--Type >= 0)
- {
- PXENVIF_POLLER_CHANNEL Channel = (*Instance)->Channel[Type];
-
- (*Instance)->Channel[Type] = NULL;
- PollerChannelTeardown(Channel);
- }
-
- (*Instance)->Index = 0;
- (*Instance)->Poller = NULL;
-
- ASSERT(IsZeroMemory(*Instance, sizeof (XENVIF_POLLER_INSTANCE)));
- __PollerFree(*Instance);
-
-fail1:
- Error("fail1 (%08x)\n", status);
-
- return status;
-}
-
-__drv_requiresIRQL(DISPATCH_LEVEL)
-static NTSTATUS
-PollerInstanceConnect(
- IN PXENVIF_POLLER_INSTANCE Instance
- )
-{
- PROCESSOR_NUMBER ProcNumber;
- LONG Type;
- NTSTATUS status;
-
- ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
-
- status = KeGetProcessorNumberFromIndex(Instance->Index, &ProcNumber);
- ASSERT(NT_SUCCESS(status));
-
- KeSetTargetProcessorDpcEx(&Instance->Dpc, &ProcNumber);
- KeSetImportanceDpc(&Instance->Dpc, MediumHighImportance);
-
- for (Type = 0; Type < XENVIF_POLLER_CHANNEL_TYPE_COUNT; Type++)
- {
- PXENVIF_POLLER_CHANNEL Channel = Instance->Channel[Type];
-
- status = PollerChannelConnect(Channel);
- if (!NT_SUCCESS(status))
- goto fail1;
- }
-
- return STATUS_SUCCESS;
-
-fail1:
- Error("fail1 (%08x)\n", status);
-
- while (--Type >= 0)
- {
- PXENVIF_POLLER_CHANNEL Channel = Instance->Channel[Type];
-
- PollerChannelDisconnect(Channel);
- }
-
- return status;
-}
-
-static NTSTATUS
-PollerInstanceStoreWrite(
- IN PXENVIF_POLLER_INSTANCE Instance,
- IN PXENBUS_STORE_TRANSACTION Transaction
- )
-{
- ULONG Type;
- NTSTATUS status;
-
- for (Type = 0; Type < XENVIF_POLLER_CHANNEL_TYPE_COUNT; Type++)
- {
- PXENVIF_POLLER_CHANNEL Channel = Instance->Channel[Type];
-
- status = PollerChannelStoreWrite(Channel, Transaction);
- if (!NT_SUCCESS(status))
- goto fail1;
- }
-
- return STATUS_SUCCESS;
-
-fail1:
- Error("fail1 (%08x)\n", status);
-
- return status;
-}
-
-__drv_requiresIRQL(DISPATCH_LEVEL)
-static NTSTATUS
-PollerInstanceEnable(
- IN PXENVIF_POLLER_INSTANCE Instance
- )
-{
- ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
-
- (VOID) InterlockedBitTestAndSet(&Instance->Pending,
- XENVIF_POLLER_EVENT_RECEIVE);
- (VOID) InterlockedBitTestAndSet(&Instance->Pending,
- XENVIF_POLLER_EVENT_TRANSMIT);
-
- KeAcquireSpinLockAtDpcLevel(&Instance->Lock);
- Instance->Enabled = TRUE;
- KeReleaseSpinLockFromDpcLevel(&Instance->Lock);
-
- (VOID) KeInsertQueueDpc(&Instance->Dpc, NULL, NULL);
-
- return STATUS_SUCCESS;
-}
-
-__drv_requiresIRQL(DISPATCH_LEVEL)
-static NTSTATUS
-PollerInstanceSend(
- IN PXENVIF_POLLER_INSTANCE Instance,
- IN XENVIF_POLLER_EVENT_TYPE Event
- )
-{
- PXENVIF_POLLER Poller;
- XENVIF_POLLER_CHANNEL_TYPE Type;
- PXENVIF_POLLER_CHANNEL Channel;
- NTSTATUS status;
-
- ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
-
- Poller = Instance->Poller;
-
- KeAcquireSpinLockAtDpcLevel(&Instance->Lock);
-
- Type = XENVIF_POLLER_CHANNEL_INVALID;
-
- if (Instance->Enabled) {
- if (!__PollerIsSplit(Poller)) {
- Type = XENVIF_POLLER_CHANNEL_COMBINED;
- } else {
- switch (Event) {
- case XENVIF_POLLER_EVENT_RECEIVE:
- Type = XENVIF_POLLER_CHANNEL_RECEIVER;
- break;
-
- case XENVIF_POLLER_EVENT_TRANSMIT:
- Type = XENVIF_POLLER_CHANNEL_TRANSMITTER;
- break;
-
- default:
- ASSERT(FALSE);
- break;
- }
- }
- }
-
- KeReleaseSpinLockFromDpcLevel(&Instance->Lock);
-
- status = STATUS_UNSUCCESSFUL;
- if (Type == XENVIF_POLLER_CHANNEL_INVALID)
- goto fail1;
-
- Channel = Instance->Channel[Type];
-
- PollerChannelSend(Channel);
-
- return STATUS_SUCCESS;
-
-fail1:
- Error("fail1 (%08x)\n", status);
-
- return status;
-}
-
-__drv_requiresIRQL(DISPATCH_LEVEL)
-static NTSTATUS
-PollerInstanceTrigger(
- IN PXENVIF_POLLER_INSTANCE Instance,
- IN XENVIF_POLLER_EVENT_TYPE Event
- )
-{
- NTSTATUS status;
-
- status = STATUS_INVALID_PARAMETER;
- if (Event >= XENVIF_POLLER_EVENT_TYPE_COUNT)
- goto fail1;
-
- (VOID) InterlockedBitTestAndSet(&Instance->Pending, Event);
-
- if (KeInsertQueueDpc(&Instance->Dpc, NULL, NULL))
- Instance->Dpcs++;
-
- return STATUS_SUCCESS;
-
-fail1:
- Error("fail1 (%08x)\n", status);
-
- return status;
-}
-
-static VOID
-PollerInstanceDebugCallback(
- IN PXENVIF_POLLER_INSTANCE Instance
- )
-{
- PXENVIF_POLLER Poller;
- ULONG Type;
-
- Poller = Instance->Poller;
-
- XENBUS_DEBUG(Printf,
- &Poller->DebugInterface,
- "[%d]: Dpcs = %lu\n",
- Instance->Index,
- Instance->Dpcs);
-
- for (Type = 0; Type < XENVIF_POLLER_CHANNEL_TYPE_COUNT; Type++)
- {
- PXENVIF_POLLER_CHANNEL Channel = Instance->Channel[Type];
-
- PollerChannelDebugCallback(Channel);
- }
-}
-
-__drv_requiresIRQL(DISPATCH_LEVEL)
-static VOID
-PollerInstanceDisable(
- IN PXENVIF_POLLER_INSTANCE Instance
- )
-{
- ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
-
- KeAcquireSpinLockAtDpcLevel(&Instance->Lock);
- Instance->Enabled = FALSE;
- KeReleaseSpinLockFromDpcLevel(&Instance->Lock);
-}
-
-__drv_requiresIRQL(DISPATCH_LEVEL)
-static VOID
-PollerInstanceDisconnect(
- IN PXENVIF_POLLER_INSTANCE Instance
- )
-{
- LONG Type;
-
- ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
-
- Instance->Dpcs = 0;
- Instance->Pending = 0;
-
- Type = XENVIF_POLLER_CHANNEL_TYPE_COUNT;
-
- while (--Type >= 0)
- {
- PXENVIF_POLLER_CHANNEL Channel = Instance->Channel[Type];
-
- PollerChannelDisconnect(Channel);
- }
-}
-
-static VOID
-PollerInstanceTeardown(
- IN PXENVIF_POLLER_INSTANCE Instance
- )
-{
- PXENVIF_POLLER Poller;
- PXENVIF_FRONTEND Frontend;
- LONG Type;
-
- ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
- KeFlushQueuedDpcs();
-
- Poller = Instance->Poller;
- Frontend = Poller->Frontend;
-
- RtlZeroMemory(&Instance->Dpc, sizeof (KDPC));
-
- RtlZeroMemory(&Instance->Lock, sizeof (KSPIN_LOCK));
-
- FrontendFreePath(Frontend, Instance->Path);
- Instance->Path = NULL;
-
- Type = XENVIF_POLLER_CHANNEL_TYPE_COUNT;
-
- while (--Type >= 0)
- {
- PXENVIF_POLLER_CHANNEL Channel = Instance->Channel[Type];
-
- Instance->Channel[Type] = NULL;
- PollerChannelTeardown(Channel);
- }
-
- Instance->Index = 0;
- Instance->Poller = NULL;
-
- ASSERT(IsZeroMemory(Instance, sizeof (XENVIF_POLLER_INSTANCE)));
- __PollerFree(Instance);
-}
-
-static VOID
-PollerDebugCallback(
- IN PVOID Argument,
- IN BOOLEAN Crashing
- )
-{
- PXENVIF_POLLER Poller = Argument;
- PXENVIF_FRONTEND Frontend;
- ULONG NumQueues;
- ULONG Index;
-
- UNREFERENCED_PARAMETER(Crashing);
-
- Frontend = Poller->Frontend;
-
- NumQueues = FrontendGetNumQueues(Frontend);
-
- for (Index = 0; Index < NumQueues; Index++) {
- PXENVIF_POLLER_INSTANCE Instance = Poller->Instance[Index];
-
- PollerInstanceDebugCallback(Instance);
- }
-}
-
-static VOID
-PollerSetSplit(
- IN PXENVIF_POLLER Poller
- )
-{
- PXENVIF_FRONTEND Frontend;
- PCHAR Buffer;
- NTSTATUS status;
-
- Frontend = Poller->Frontend;
-
- status = XENBUS_STORE(Read,
- &Poller->StoreInterface,
- NULL,
- FrontendGetBackendPath(Frontend),
- "feature-split-event-channels",
- &Buffer);
- if (NT_SUCCESS(status)) {
- Poller->Split = (BOOLEAN)strtol(Buffer, NULL, 2);
-
- XENBUS_STORE(Free,
- &Poller->StoreInterface,
- Buffer);
- } else {
- Poller->Split = FALSE;
- }
-
- Info("%s: %s\n", FrontendGetPath(Frontend),
- (Poller->Split) ? "TRUE" : "FALSE");
-}
-
-NTSTATUS
-PollerInitialize(
- IN PXENVIF_FRONTEND Frontend,
- OUT PXENVIF_POLLER *Poller
- )
-{
- LONG MaxQueues;
- LONG Index;
- NTSTATUS status;
-
- *Poller = __PollerAllocate(sizeof (XENVIF_POLLER));
-
- status = STATUS_NO_MEMORY;
- if (*Poller == NULL)
- goto fail1;
-
- FdoGetEvtchnInterface(PdoGetFdo(FrontendGetPdo(Frontend)),
- &(*Poller)->EvtchnInterface);
-
- FdoGetStoreInterface(PdoGetFdo(FrontendGetPdo(Frontend)),
- &(*Poller)->StoreInterface);
-
- FdoGetDebugInterface(PdoGetFdo(FrontendGetPdo(Frontend)),
- &(*Poller)->DebugInterface);
-
- (*Poller)->Frontend = Frontend;
-
- MaxQueues = FrontendGetMaxQueues(Frontend);
- (*Poller)->Instance = __PollerAllocate(sizeof (PXENVIF_POLLER_INSTANCE) *
- MaxQueues);
-
- status = STATUS_NO_MEMORY;
- if ((*Poller)->Instance == NULL)
- goto fail2;
-
- for (Index = 0; Index < MaxQueues; Index++) {
- PXENVIF_POLLER_INSTANCE Instance;
-
- status = PollerInstanceInitialize(*Poller, Index, &Instance);
- if (!NT_SUCCESS(status))
- goto fail3;
-
- (*Poller)->Instance[Index] = Instance;
- }
-
- return STATUS_SUCCESS;
-
-fail3:
- Error("fail3\n");
-
- while (--Index >= 0)
- {
- PXENVIF_POLLER_INSTANCE Instance = (*Poller)->Instance[Index];
-
- (*Poller)->Instance[Index] = NULL;
- PollerInstanceTeardown(Instance);
- }
-
- ASSERT(IsZeroMemory((*Poller)->Instance,
- sizeof (PXENVIF_POLLER_INSTANCE) * MaxQueues));
- __PollerFree((*Poller)->Instance);
- (*Poller)->Instance = NULL;
-
-fail2:
- Error("fail2\n");
-
- (*Poller)->Frontend = NULL;
-
- RtlZeroMemory(&(*Poller)->DebugInterface,
- sizeof (XENBUS_DEBUG_INTERFACE));
-
- RtlZeroMemory(&(*Poller)->StoreInterface,
- sizeof (XENBUS_STORE_INTERFACE));
-
- RtlZeroMemory(&(*Poller)->EvtchnInterface,
- sizeof (XENBUS_EVTCHN_INTERFACE));
-
-fail1:
- Error("fail1 (%08x)\n", status);
-
- return status;
-}
-
-NTSTATUS
-PollerConnect(
- IN PXENVIF_POLLER Poller
- )
-{
- PXENVIF_FRONTEND Frontend;
- LONG NumQueues;
- LONG Index;
- NTSTATUS status;
-
- Trace("====>\n");
-
- Frontend = Poller->Frontend;
-
- status = XENBUS_EVTCHN(Acquire, &Poller->EvtchnInterface);
- if (!NT_SUCCESS(status))
- goto fail1;
-
- status = XENBUS_STORE(Acquire, &Poller->StoreInterface);
- if (!NT_SUCCESS(status))
- goto fail2;
-
- status = XENBUS_DEBUG(Acquire, &Poller->DebugInterface);
- if (!NT_SUCCESS(status))
- goto fail3;
-
- PollerSetSplit(Poller);
-
- NumQueues = FrontendGetNumQueues(Frontend);
-
- for (Index = 0; Index < NumQueues; Index++) {
- PXENVIF_POLLER_INSTANCE Instance = Poller->Instance[Index];
-
- status = PollerInstanceConnect(Instance);
- if (!NT_SUCCESS(status))
- goto fail4;
- }
-
- status = XENBUS_DEBUG(Register,
- &Poller->DebugInterface,
- __MODULE__ "|POLLER",
- PollerDebugCallback,
- Poller,
- &Poller->DebugCallback);
- if (!NT_SUCCESS(status))
- goto fail5;
-
- Trace("<====\n");
- return STATUS_SUCCESS;
-
-fail5:
- Error("fail5\n");
-
- Index = NumQueues;
-
-fail4:
- Error("fail4\n");
-
- while (--Index >= 0)
- {
- PXENVIF_POLLER_INSTANCE Instance = Poller->Instance[Index];
-
- PollerInstanceDisconnect(Instance);
- }
-
- Poller->Split = FALSE;
-
- XENBUS_DEBUG(Release, &Poller->DebugInterface);
-
-fail3:
- Error("fail3\n");
-
- XENBUS_STORE(Release, &Poller->StoreInterface);
-
-fail2:
- Error("fail2\n");
-
- XENBUS_EVTCHN(Release, &Poller->EvtchnInterface);
-
-fail1:
- Error("fail1 (%08x)\n", status);
-
- return status;
-}
-
-NTSTATUS
-PollerStoreWrite(
- IN PXENVIF_POLLER Poller,
- IN PXENBUS_STORE_TRANSACTION Transaction
- )
-{
- PXENVIF_FRONTEND Frontend;
- LONG NumQueues;
- LONG Index;
- NTSTATUS status;
-
- Trace("====>\n");
-
- Frontend = Poller->Frontend;
-
- NumQueues = FrontendGetNumQueues(Frontend);
-
- for (Index = 0; Index < NumQueues; Index++) {
- PXENVIF_POLLER_INSTANCE Instance = Poller->Instance[Index];
-
- status = PollerInstanceStoreWrite(Instance, Transaction);
- if (!NT_SUCCESS(status))
- goto fail1;
- }
-
- Trace("<====\n");
-
- return STATUS_SUCCESS;
-
-fail1:
- Error("fail1 (%08x)\n", status);
-
- return status;
-}
-
-NTSTATUS
-PollerEnable(
- IN PXENVIF_POLLER Poller
- )
-{
- PXENVIF_FRONTEND Frontend;
- LONG NumQueues;
- LONG Index;
- NTSTATUS status;
-
- Trace("====>\n");
-
- Frontend = Poller->Frontend;
-
- NumQueues = FrontendGetNumQueues(Frontend);
-
- for (Index = 0; Index < NumQueues; Index++) {
- PXENVIF_POLLER_INSTANCE Instance = Poller->Instance[Index];
-
- status = PollerInstanceEnable(Instance);
- if (!NT_SUCCESS(status))
- goto fail1;
- }
-
- Trace("<====\n");
-
- return STATUS_SUCCESS;
-
-fail1:
- Error("fail1 (%08x)\n", status);
-
- while (--Index >= 0)
- {
- PXENVIF_POLLER_INSTANCE Instance = Poller->Instance[Index];
-
- PollerInstanceDisable(Instance);
- }
-
- return status;
-}
-
-NTSTATUS
-PollerSend(
- IN PXENVIF_POLLER Poller,
- IN ULONG Index,
- IN XENVIF_POLLER_EVENT_TYPE Event
- )
-{
- PXENVIF_FRONTEND Frontend;
- ULONG NumQueues;
- PXENVIF_POLLER_INSTANCE Instance;
- NTSTATUS status;
-
- Frontend = Poller->Frontend;
-
- NumQueues = FrontendGetNumQueues(Frontend);
-
- status = STATUS_INVALID_PARAMETER;
- if (Index >= NumQueues)
- goto fail1;
-
- Instance = Poller->Instance[Index];
-
- status = PollerInstanceSend(Instance, Event);
- if (!NT_SUCCESS(status))
- goto fail2;
-
- return STATUS_SUCCESS;
-
-fail2:
- Error("fail2\n");
-
-fail1:
- Error("fail1 (%08x)\n", status);
-
- return status;
-}
-
-NTSTATUS
-PollerTrigger(
- IN PXENVIF_POLLER Poller,
- IN ULONG Index,
- IN XENVIF_POLLER_EVENT_TYPE Event
- )
-{
- PXENVIF_FRONTEND Frontend;
- ULONG NumQueues;
- PXENVIF_POLLER_INSTANCE Instance;
- NTSTATUS status;
-
- Frontend = Poller->Frontend;
-
- NumQueues = FrontendGetNumQueues(Frontend);
-
- status = STATUS_INVALID_PARAMETER;
- if (Index >= NumQueues)
- goto fail1;
-
- Instance = Poller->Instance[Index];
-
- status = PollerInstanceTrigger(Instance, Event);
- if (!NT_SUCCESS(status))
- goto fail2;
-
- return STATUS_SUCCESS;
-
-fail2:
- Error("fail2\n");
-
-fail1:
- Error("fail1 (%08x)\n", status);
-
- return status;
-}
-
-VOID
-PollerDisable(
- IN PXENVIF_POLLER Poller
- )
-{
- PXENVIF_FRONTEND Frontend;
- LONG NumQueues;
- LONG Index;
-
- Trace("====>\n");
-
- Frontend = Poller->Frontend;
-
- NumQueues = FrontendGetNumQueues(Frontend);
- Index = NumQueues;
-
- while (--Index >= 0)
- {
- PXENVIF_POLLER_INSTANCE Instance = Poller->Instance[Index];
-
- PollerInstanceDisable(Instance);
- }
-
- Trace("<====\n");
-}
-
-VOID
-PollerDisconnect(
- IN PXENVIF_POLLER Poller
- )
-{
- PXENVIF_FRONTEND Frontend;
- LONG NumQueues;
- LONG Index;
-
- Trace("====>\n");
-
- Frontend = Poller->Frontend;
-
- XENBUS_DEBUG(Deregister,
- &Poller->DebugInterface,
- Poller->DebugCallback);
- Poller->DebugCallback = NULL;
-
- NumQueues = FrontendGetNumQueues(Frontend);
- Index = NumQueues;
-
- while (--Index >= 0)
- {
- PXENVIF_POLLER_INSTANCE Instance = Poller->Instance[Index];
-
- PollerInstanceDisconnect(Instance);
- }
-
- Poller->Split = FALSE;
-
- XENBUS_DEBUG(Release, &Poller->DebugInterface);
-
- XENBUS_STORE(Release, &Poller->StoreInterface);
-
- XENBUS_EVTCHN(Release, &Poller->EvtchnInterface);
-
- Trace("<====\n");
-}
-
-VOID
-PollerTeardown(
- IN PXENVIF_POLLER Poller
- )
-{
- PXENVIF_FRONTEND Frontend;
- LONG MaxQueues;
- LONG Index;
-
- ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
-
- Frontend = Poller->Frontend;
-
- MaxQueues = FrontendGetMaxQueues(Frontend);
- Index = MaxQueues;
-
- while (--Index >= 0)
- {
- PXENVIF_POLLER_INSTANCE Instance = Poller->Instance[Index];
-
- Poller->Instance[Index] = NULL;
- PollerInstanceTeardown(Instance);
- }
-
- ASSERT(IsZeroMemory(Poller->Instance,
- sizeof (PXENVIF_POLLER_INSTANCE) * MaxQueues));
- __PollerFree(Poller->Instance);
- Poller->Instance = NULL;
-
- Poller->Frontend = NULL;
-
- RtlZeroMemory(&Poller->DebugInterface,
- sizeof (XENBUS_DEBUG_INTERFACE));
-
- RtlZeroMemory(&Poller->StoreInterface,
- sizeof (XENBUS_STORE_INTERFACE));
-
- RtlZeroMemory(&Poller->EvtchnInterface,
- sizeof (XENBUS_EVTCHN_INTERFACE));
-
- ASSERT(IsZeroMemory(Poller, sizeof (XENVIF_POLLER)));
- __PollerFree(Poller);
-}
diff --git a/src/xenvif/poller.h b/src/xenvif/poller.h
deleted file mode 100644
index a2b32a1..0000000
--- a/src/xenvif/poller.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/* Copyright (c) Citrix Systems Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms,
- * with or without modification, are permitted provided
- * that the following conditions are met:
- *
- * * Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the
- * following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the
- * following disclaimer in the documentation and/or other
- * materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef _XENVIF_POLLER_H
-#define _XENVIF_POLLER_H
-
-#include <ntddk.h>
-
-#include <vif_interface.h>
-
-#include "frontend.h"
-
-typedef struct _XENVIF_POLLER XENVIF_POLLER, *PXENVIF_POLLER;
-
-typedef enum _XENVIF_POLLER_EVENT_TYPE {
- XENVIF_POLLER_EVENT_RECEIVE,
- XENVIF_POLLER_EVENT_TRANSMIT,
- XENVIF_POLLER_EVENT_TYPE_COUNT
-} XENVIF_POLLER_EVENT_TYPE, *PXENVIF_POLLER_EVENT_TYPE;
-
-extern NTSTATUS
-PollerInitialize(
- IN PXENVIF_FRONTEND Frontend,
- OUT PXENVIF_POLLER *Poller
- );
-
-extern NTSTATUS
-PollerConnect(
- IN PXENVIF_POLLER Poller
- );
-
-extern NTSTATUS
-PollerStoreWrite(
- IN PXENVIF_POLLER Poller,
- IN PXENBUS_STORE_TRANSACTION Transaction
- );
-
-extern NTSTATUS
-PollerEnable(
- IN PXENVIF_POLLER Poller
- );
-
-extern NTSTATUS
-PollerSend(
- IN PXENVIF_POLLER Poller,
- IN ULONG Index,
- IN XENVIF_POLLER_EVENT_TYPE Event
- );
-
-extern NTSTATUS
-PollerTrigger(
- IN PXENVIF_POLLER Poller,
- IN ULONG Index,
- IN XENVIF_POLLER_EVENT_TYPE Event
- );
-
-extern VOID
-PollerDisable(
- IN PXENVIF_POLLER Poller
- );
-
-extern VOID
-PollerDisconnect(
- IN PXENVIF_POLLER Poller
- );
-
-extern VOID
-PollerTeardown(
- IN PXENVIF_POLLER Poller
- );
-
-#endif // _XENVIF_POLLER_H
diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c
index 4e8046b..3ed5ee8 100644
--- a/src/xenvif/receiver.c
+++ b/src/xenvif/receiver.c
@@ -41,6 +41,7 @@
#include <store_interface.h>
#include <cache_interface.h>
#include <gnttab_interface.h>
+#include <evtchn_interface.h>

#include "pdo.h"
#include "registry.h"
@@ -87,6 +88,12 @@ typedef struct _XENVIF_RECEIVER_RING {
netif_rx_front_ring_t Front;
netif_rx_sring_t *Shared;
PXENBUS_GNTTAB_ENTRY Entry;
+ PXENBUS_EVTCHN_CHANNEL Channel;
+ KDPC Dpc;
+ ULONG Dpcs;
+ KTIMER Timer;
+ KDPC TimerDpc;
+ ULONG Events;
PXENVIF_RECEIVER_FRAGMENT Pending[XENVIF_RECEIVER_MAXIMUM_FRAGMENT_ID + 1];
ULONG RequestsPosted;
ULONG RequestsPushed;
@@ -98,10 +105,7 @@ typedef struct _XENVIF_RECEIVER_RING {
ULONG BackfillSize;
PXENBUS_DEBUG_CALLBACK DebugCallback;
PXENVIF_THREAD WatchdogThread;
- PLIST_ENTRY PacketQueue;
- KDPC Dpc;
- ULONG Dpcs;
- LIST_ENTRY PacketComplete;
+ LIST_ENTRY PacketList;
XENVIF_RECEIVER_HASH Hash;
} XENVIF_RECEIVER_RING, *PXENVIF_RECEIVER_RING;

@@ -124,6 +128,7 @@ struct _XENVIF_RECEIVER {
PXENVIF_FRONTEND Frontend;
XENBUS_CACHE_INTERFACE CacheInterface;
XENBUS_GNTTAB_INTERFACE GnttabInterface;
+ XENBUS_EVTCHN_INTERFACE EvtchnInterface;
PXENVIF_RECEIVER_RING *Ring;
LONG Loaned;
LONG Returned;
@@ -908,22 +913,10 @@ fail1:
}

static VOID
-ReceiverRingCompletePacket(
- IN PXENVIF_RECEIVER_RING Ring,
- IN PXENVIF_RECEIVER_PACKET Packet
- )
-{
- ReceiverRingProcessTag(Ring, Packet);
- ReceiverRingProcessChecksum(Ring, Packet);
-
- ASSERT(IsZeroMemory(&Packet->ListEntry, sizeof (LIST_ENTRY)));
- InsertTailList(&Ring->PacketComplete, &Packet->ListEntry);
-}
-
-static VOID
ReceiverRingProcessLargePacket(
IN PXENVIF_RECEIVER_RING Ring,
- IN PXENVIF_RECEIVER_PACKET Packet
+ IN PXENVIF_RECEIVER_PACKET Packet,
+ OUT PLIST_ENTRY List
)
{
PXENVIF_RECEIVER Receiver;
@@ -1011,7 +1004,8 @@ ReceiverRingProcessLargePacket(
ASSERT3U(Length, >=, SegmentSize);
Length -= SegmentSize;

- ReceiverRingCompletePacket(Ring, Segment);
+ ASSERT(IsZeroMemory(&Segment->ListEntry, sizeof (LIST_ENTRY)));
+ InsertTailList(List, &Segment->ListEntry);

if (Offload) {
ASSERT(Ring->OffloadOptions.NeedLargePacketSplit != 0);
@@ -1060,7 +1054,8 @@ ReceiverRingProcessLargePacket(
if (Receiver->AlwaysPullup != 0)
__ReceiverRingPullupPacket(Ring, Packet);

- ReceiverRingCompletePacket(Ring, Packet);
+ ASSERT(IsZeroMemory(&Packet->ListEntry, sizeof (LIST_ENTRY)));
+ InsertTailList(List, &Packet->ListEntry);
} else {
__ReceiverRingPutPacket(Ring, Packet, TRUE);
}
@@ -1097,7 +1092,8 @@ fail1:
static VOID
ReceiverRingProcessStandardPacket(
IN PXENVIF_RECEIVER_RING Ring,
- IN PXENVIF_RECEIVER_PACKET Packet
+ IN PXENVIF_RECEIVER_PACKET Packet,
+ OUT PLIST_ENTRY List
)
{
PXENVIF_RECEIVER Receiver;
@@ -1167,7 +1163,9 @@ ReceiverRingProcessStandardPacket(
Packet->Mdl.Next = Mdl;
}

- ReceiverRingCompletePacket(Ring, Packet);
+ ASSERT(IsZeroMemory(&Packet->ListEntry, sizeof (LIST_ENTRY)));
+ InsertTailList(List, &Packet->ListEntry);
+
return;

fail2:
@@ -1200,7 +1198,8 @@ fail1:
static VOID
ReceiverRingProcessPacket(
IN PXENVIF_RECEIVER_RING Ring,
- IN PXENVIF_RECEIVER_PACKET Packet
+ IN PXENVIF_RECEIVER_PACKET Packet,
+ OUT PLIST_ENTRY List
)
{
PXENVIF_RECEIVER Receiver;
@@ -1286,9 +1285,9 @@ ReceiverRingProcessPacket(
goto fail3;

if (Packet->MaximumSegmentSize != 0)
- ReceiverRingProcessLargePacket(Ring, Packet);
+ ReceiverRingProcessLargePacket(Ring, Packet, List);
else
- ReceiverRingProcessStandardPacket(Ring, Packet);
+ ReceiverRingProcessStandardPacket(Ring, Packet, List);

return;

@@ -1321,8 +1320,63 @@ fail1:
1);
}

+static VOID
+ReceiverRingProcessPackets(
+ IN PXENVIF_RECEIVER_RING Ring,
+ OUT PLIST_ENTRY List,
+ OUT PULONG Count
+ )
+{
+ PLIST_ENTRY ListEntry;
+
+ while (!IsListEmpty(&Ring->PacketList)) {
+ PXENVIF_RECEIVER_PACKET Packet;
+
+ ListEntry = RemoveHeadList(&Ring->PacketList);
+ ASSERT3P(ListEntry, !=, &Ring->PacketList);
+
+ RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
+
+ Packet = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_PACKET, ListEntry);
+ ReceiverRingProcessPacket(Ring, Packet, List);
+ }
+
+ for (ListEntry = List->Flink;
+ ListEntry != List;
+ ListEntry = ListEntry->Flink) {
+ PXENVIF_RECEIVER_PACKET Packet;
+
+ Packet = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_PACKET, ListEntry);
+
+ ReceiverRingProcessTag(Ring, Packet);
+ ReceiverRingProcessChecksum(Ring, Packet);
+
+ (*Count)++;
+ }
+}
+
+static FORCEINLINE VOID
+__drv_requiresIRQL(DISPATCH_LEVEL)
+__ReceiverRingAcquireLock(
+ IN PXENVIF_RECEIVER_RING Ring
+ )
+{
+ ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
+
+ KeAcquireSpinLockAtDpcLevel(&Ring->Lock);
+}
+
+static DECLSPEC_NOINLINE VOID
+ReceiverRingAcquireLock(
+ IN PXENVIF_RECEIVER_RING Ring
+ )
+{
+ __ReceiverRingAcquireLock(Ring);
+}
+
static FORCEINLINE VOID
-__ReceiverRingSwizzle(
+__drv_requiresIRQL(DISPATCH_LEVEL)
+__ReceiverRingReleaseLock(
IN PXENVIF_RECEIVER_RING Ring
)
{
@@ -1330,44 +1384,33 @@ __ReceiverRingSwizzle(
PXENVIF_FRONTEND Frontend;
PXENVIF_VIF_CONTEXT Context;
LIST_ENTRY List;
- PLIST_ENTRY ListEntry;
+ ULONG Count;
+ BOOLEAN More;
+
+ ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);

Receiver = Ring->Receiver;
Frontend = Receiver->Frontend;
Context = PdoGetVifContext(FrontendGetPdo(Frontend));

InitializeListHead(&List);
+ Count = 0;

- ListEntry = InterlockedExchangePointer(&Ring->PacketQueue, NULL);
-
- // Packets are held in the queue in reverse order so that the most
- // recent is always head of the list. This is necessary to allow
- // addition to the list to be done atomically.
-
- while (ListEntry != NULL) {
- PLIST_ENTRY NextEntry;
-
- NextEntry = ListEntry->Blink;
- ListEntry->Flink = ListEntry->Blink = ListEntry;
+ ReceiverRingProcessPackets(Ring, &List, &Count);
+ ASSERT(EQUIV(IsListEmpty(&List), Count == 0));
+ ASSERT(IsListEmpty(&Ring->PacketList));

- InsertHeadList(&List, ListEntry);
+ // We need to bump Loaned before dropping the lock to avoid VifDisable()
+ // returning prematurely.
+ __InterlockedAdd(&Receiver->Loaned, Count);

- ListEntry = NextEntry;
- }
-
- while (!IsListEmpty(&List)) {
- PXENVIF_RECEIVER_PACKET Packet;
-
- ListEntry = RemoveHeadList(&List);
- ASSERT3P(ListEntry, !=, &List);
+#pragma prefast(disable:26110)
+ KeReleaseSpinLockFromDpcLevel(&Ring->Lock);

- RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
+ More = !IsListEmpty(&List) ? TRUE : FALSE;

- Packet = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_PACKET, ListEntry);
- ReceiverRingProcessPacket(Ring, Packet);
- }
-
- while (!IsListEmpty(&Ring->PacketComplete)) {
+ while (More) {
+ PLIST_ENTRY ListEntry;
PXENVIF_RECEIVER_PACKET Packet;
PXENVIF_PACKET_INFO Info;
PUCHAR BaseVa;
@@ -1375,11 +1418,14 @@ __ReceiverRingSwizzle(
PETHERNET_ADDRESS DestinationAddress;
ETHERNET_ADDRESS_TYPE Type;

- ListEntry = RemoveHeadList(&Ring->PacketComplete);
- ASSERT3P(ListEntry, !=, &Ring->PacketComplete);
+ ListEntry = RemoveHeadList(&List);
+ ASSERT3P(ListEntry, !=, &List);

RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));

+ ASSERT(More);
+ More = !IsListEmpty(&List) ? TRUE : FALSE;
+
Packet = CONTAINING_RECORD(ListEntry,
XENVIF_RECEIVER_PACKET,
ListEntry);
@@ -1468,57 +1514,55 @@ __ReceiverRingSwizzle(
XENVIF_RECEIVER_UDP_PACKETS,
1);

- if (Packet->MaximumSegmentSize != 0)
+ if (Packet->MaximumSegmentSize != 0)
FrontendIncrementStatistic(Frontend,
XENVIF_RECEIVER_GSO_PACKETS,
1);

- if (Packet->Flags.IpChecksumSucceeded != 0)
- FrontendIncrementStatistic(Frontend,
- XENVIF_RECEIVER_IPV4_CHECKSUM_SUCCEEDED,
- 1);
-
- if (Packet->Flags.IpChecksumFailed != 0)
- FrontendIncrementStatistic(Frontend,
- XENVIF_RECEIVER_IPV4_CHECKSUM_FAILED,
- 1);
-
- if (Packet->Flags.IpChecksumNotValidated != 0)
- FrontendIncrementStatistic(Frontend,
- XENVIF_RECEIVER_IPV4_CHECKSUM_NOT_VALIDATED,
- 1);
-
- if (Packet->Flags.TcpChecksumSucceeded != 0)
- FrontendIncrementStatistic(Frontend,
- XENVIF_RECEIVER_TCP_CHECKSUM_SUCCEEDED,
- 1);
-
- if (Packet->Flags.TcpChecksumFailed != 0)
- FrontendIncrementStatistic(Frontend,
- XENVIF_RECEIVER_TCP_CHECKSUM_FAILED,
- 1);
-
- if (Packet->Flags.TcpChecksumNotValidated != 0)
- FrontendIncrementStatistic(Frontend,
- XENVIF_RECEIVER_TCP_CHECKSUM_NOT_VALIDATED,
- 1);
-
- if (Packet->Flags.UdpChecksumSucceeded != 0)
- FrontendIncrementStatistic(Frontend,
- XENVIF_RECEIVER_UDP_CHECKSUM_SUCCEEDED,
- 1);
-
- if (Packet->Flags.UdpChecksumFailed != 0)
- FrontendIncrementStatistic(Frontend,
- XENVIF_RECEIVER_UDP_CHECKSUM_FAILED,
- 1);
-
- if (Packet->Flags.UdpChecksumNotValidated != 0)
- FrontendIncrementStatistic(Frontend,
- XENVIF_RECEIVER_UDP_CHECKSUM_NOT_VALIDATED,
- 1);
-
- (VOID) InterlockedIncrement(&Receiver->Loaned);
+ if (Packet->Flags.IpChecksumSucceeded != 0)
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_RECEIVER_IPV4_CHECKSUM_SUCCEEDED,
+ 1);
+
+ if (Packet->Flags.IpChecksumFailed != 0)
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_RECEIVER_IPV4_CHECKSUM_FAILED,
+ 1);
+
+ if (Packet->Flags.IpChecksumNotValidated != 0)
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_RECEIVER_IPV4_CHECKSUM_NOT_VALIDATED,
+ 1);
+
+ if (Packet->Flags.TcpChecksumSucceeded != 0)
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_RECEIVER_TCP_CHECKSUM_SUCCEEDED,
+ 1);
+
+ if (Packet->Flags.TcpChecksumFailed != 0)
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_RECEIVER_TCP_CHECKSUM_FAILED,
+ 1);
+
+ if (Packet->Flags.TcpChecksumNotValidated != 0)
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_RECEIVER_TCP_CHECKSUM_NOT_VALIDATED,
+ 1);
+
+ if (Packet->Flags.UdpChecksumSucceeded != 0)
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_RECEIVER_UDP_CHECKSUM_SUCCEEDED,
+ 1);
+
+ if (Packet->Flags.UdpChecksumFailed != 0)
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_RECEIVER_UDP_CHECKSUM_FAILED,
+ 1);
+
+ if (Packet->Flags.UdpChecksumNotValidated != 0)
+ FrontendIncrementStatistic(Frontend,
+ XENVIF_RECEIVER_UDP_CHECKSUM_NOT_VALIDATED,
+ 1);

VifReceiverQueuePacket(Context,
Ring->Index,
@@ -1530,95 +1574,89 @@ __ReceiverRingSwizzle(
Packet->TagControlInformation,
&Packet->Info,
&Packet->Hash,
- !IsListEmpty(&Ring->PacketComplete) ? TRUE : FALSE,
+ More,
Packet);
+
+ --Count;
}
+
+ ASSERT3U(Count, ==, 0);
}

-static FORCEINLINE VOID
-__drv_requiresIRQL(DISPATCH_LEVEL)
-__ReceiverRingAcquireLock(
+static DECLSPEC_NOINLINE VOID
+ReceiverRingReleaseLock(
IN PXENVIF_RECEIVER_RING Ring
)
{
- ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
-
- KeAcquireSpinLockAtDpcLevel(&Ring->Lock);
+ __ReceiverRingReleaseLock(Ring);
}

-static DECLSPEC_NOINLINE VOID
-ReceiverRingAcquireLock(
+static FORCEINLINE VOID
+__ReceiverRingStop(
IN PXENVIF_RECEIVER_RING Ring
)
{
- __ReceiverRingAcquireLock(Ring);
+ Ring->Stopped = TRUE;
}

static FORCEINLINE VOID
-__drv_requiresIRQL(DISPATCH_LEVEL)
-__ReceiverRingReleaseLock(
+__ReceiverRingStart(
IN PXENVIF_RECEIVER_RING Ring
)
{
- ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
-
-#pragma prefast(disable:26110)
- KeReleaseSpinLockFromDpcLevel(&Ring->Lock);
+ Ring->Stopped = FALSE;
}

-static DECLSPEC_NOINLINE VOID
-ReceiverRingReleaseLock(
+static FORCEINLINE BOOLEAN
+__ReceiverRingIsStopped(
IN PXENVIF_RECEIVER_RING Ring
)
{
- __ReceiverRingReleaseLock(Ring);
+ return Ring->Stopped;
}

-__drv_functionClass(KDEFERRED_ROUTINE)
-__drv_maxIRQL(DISPATCH_LEVEL)
-__drv_minIRQL(PASSIVE_LEVEL)
-__drv_sameIRQL
-static VOID
-ReceiverRingDpc(
- IN PKDPC Dpc,
- IN PVOID Context,
- IN PVOID Argument1,
- IN PVOID Argument2
+static FORCEINLINE VOID
+__ReceiverRingTrigger(
+ IN PXENVIF_RECEIVER_RING Ring,
+ IN BOOLEAN Locked
)
{
- PXENVIF_RECEIVER_RING Ring = Context;
+ PXENVIF_RECEIVER Receiver;

- UNREFERENCED_PARAMETER(Dpc);
- UNREFERENCED_PARAMETER(Argument1);
- UNREFERENCED_PARAMETER(Argument2);
+ Receiver = Ring->Receiver;

- ASSERT(Ring != NULL);
+ if (!Locked)
+ __ReceiverRingAcquireLock(Ring);

- __ReceiverRingSwizzle(Ring);
-}
+ if (Ring->Connected)
+ (VOID) XENBUS_EVTCHN(Trigger,
+ &Receiver->EvtchnInterface,
+ Ring->Channel);

-static FORCEINLINE VOID
-__ReceiverRingStop(
- IN PXENVIF_RECEIVER_RING Ring
- )
-{
- Ring->Stopped = TRUE;
+ if (!Locked)
+ __ReceiverRingReleaseLock(Ring);
}

static FORCEINLINE VOID
-__ReceiverRingStart(
- IN PXENVIF_RECEIVER_RING Ring
+__ReceiverRingSend(
+ IN PXENVIF_RECEIVER_RING Ring,
+ IN BOOLEAN Locked
)
{
- Ring->Stopped = FALSE;
-}
+ PXENVIF_RECEIVER Receiver;

-static FORCEINLINE BOOLEAN
-__ReceiverRingIsStopped(
- IN PXENVIF_RECEIVER_RING Ring
- )
-{
- return Ring->Stopped;
+ Receiver = Ring->Receiver;
+
+ if (!Locked)
+ __ReceiverRingAcquireLock(Ring);
+
+ if (Ring->Connected)
+ (VOID) XENBUS_EVTCHN(Send,
+ &Receiver->EvtchnInterface,
+ Ring->Channel);
+
+ if (!Locked)
+ __ReceiverRingReleaseLock(Ring);
}

static FORCEINLINE VOID
@@ -1628,13 +1666,8 @@ __ReceiverRingReturnPacket(
IN BOOLEAN Locked
)
{
- PXENVIF_RECEIVER Receiver;
- PXENVIF_FRONTEND Frontend;
PMDL Mdl;

- Receiver = Ring->Receiver;
- Frontend = Receiver->Frontend;
-
Mdl = &Packet->Mdl;

while (Mdl != NULL) {
@@ -1658,9 +1691,7 @@ __ReceiverRingReturnPacket(

if (__ReceiverRingIsStopped(Ring)) {
__ReceiverRingStart(Ring);
- PollerTrigger(FrontendGetPoller(Frontend),
- Ring->Index,
- XENVIF_POLLER_EVENT_RECEIVE);
+ __ReceiverRingTrigger(Ring, TRUE);
}

if (!Locked)
@@ -1740,17 +1771,8 @@ __ReceiverRingPushRequests(

#pragma warning (pop)

- if (Notify) {
- PXENVIF_RECEIVER Receiver;
- PXENVIF_FRONTEND Frontend;
-
- Receiver = Ring->Receiver;
- Frontend = Receiver->Frontend;
-
- PollerSend(FrontendGetPoller(Frontend),
- Ring->Index,
- XENVIF_POLLER_EVENT_RECEIVE);
- }
+ if (Notify)
+ __ReceiverRingSend(Ring, TRUE);

Ring->RequestsPushed = Ring->RequestsPosted;
}
@@ -1882,11 +1904,6 @@ ReceiverRingDebugCallback(
(Ring->Enabled) ? "ENABLED" : "DISABLED",
(__ReceiverRingIsStopped(Ring)) ? "STOPPED" : "RUNNING");

- XENBUS_DEBUG(Printf,
- &Receiver->DebugInterface,
- "Dpcs = %lu\n",
- Ring->Dpcs);
-
// Dump front ring
XENBUS_DEBUG(Printf,
&Receiver->DebugInterface,
@@ -1911,26 +1928,14 @@ ReceiverRingDebugCallback(
Ring->RequestsPosted,
Ring->RequestsPushed,
Ring->ResponsesProcessed);
-}
-
-static FORCEINLINE VOID
-__ReceiverRingQueuePacket(
- IN PXENVIF_RECEIVER_RING Ring,
- IN PXENVIF_RECEIVER_PACKET Packet
- )
-{
- PLIST_ENTRY ListEntry;
- PLIST_ENTRY Old;
- PLIST_ENTRY New;
-
- ListEntry = &Packet->ListEntry;
-
- do {
- Old = Ring->PacketQueue;

- ListEntry->Blink = Ring->PacketQueue;
- New = ListEntry;
- } while (InterlockedCompareExchangePointer(&Ring->PacketQueue, (PVOID)New, (PVOID)Old) != Old);
+ // Dump event channel
+ XENBUS_DEBUG(Printf,
+ &Receiver->DebugInterface,
+ "[%s]: Events = %lu Dpcs = %lu\n",
+ FrontendIsSplit(Frontend) ? "RX" : "COMBINED",
+ Ring->Events,
+ Ring->Dpcs);
}

static DECLSPEC_NOINLINE BOOLEAN
@@ -1988,8 +1993,10 @@ ReceiverRingPoll(
RING_IDX WorkToDo;

RING_FINAL_CHECK_FOR_RESPONSES(&Ring->Front, WorkToDo);
- if (!WorkToDo)
- break;
+ if (WorkToDo)
+ continue;
+
+ break;
}

while (rsp_cons != rsp_prod && !Retry) {
@@ -2146,7 +2153,7 @@ ReceiverRingPoll(
Packet->Flags.Value = flags;

ASSERT(IsZeroMemory(&Packet->ListEntry, sizeof (LIST_ENTRY)));
- __ReceiverRingQueuePacket(Ring, Packet);
+ InsertTailList(&Ring->PacketList, &Packet->ListEntry);
}

if (rsp_cons - Ring->Front.rsp_cons > XENVIF_RECEIVER_BATCH(Ring))
@@ -2179,21 +2186,137 @@ ReceiverRingPoll(
if (!__ReceiverRingIsStopped(Ring))
ReceiverRingFill(Ring);

- if (Ring->PacketQueue != NULL &&
- KeInsertQueueDpc(&Ring->Dpc, NULL, NULL))
- Ring->Dpcs++;
-
done:
return Retry;

#undef XENVIF_RECEIVER_BATCH
}

+static FORCEINLINE VOID
+__ReceiverRingUnmask(
+ IN PXENVIF_RECEIVER_RING Ring
+ )
+{
+ PXENVIF_RECEIVER Receiver;
+
+ if (!Ring->Connected)
+ return;
+
+ Receiver = Ring->Receiver;
+
+ XENBUS_EVTCHN(Unmask,
+ &Receiver->EvtchnInterface,
+ Ring->Channel,
+ FALSE,
+ TRUE);
+}
+
+static FORCEINLINE BOOLEAN
+__ReceiverRingDpcTimeout(
+ IN PXENVIF_RECEIVER_RING Ring
+ )
+{
+ KDPC_WATCHDOG_INFORMATION Watchdog;
+ NTSTATUS status;
+
+ UNREFERENCED_PARAMETER(Ring);
+
+ RtlZeroMemory(&Watchdog, sizeof (Watchdog));
+
+ status = KeQueryDpcWatchdogInformation(&Watchdog);
+ ASSERT(NT_SUCCESS(status));
+
+ if (Watchdog.DpcTimeLimit == 0 ||
+ Watchdog.DpcWatchdogLimit == 0)
+ return FALSE;
+
+ if (Watchdog.DpcTimeCount > (Watchdog.DpcTimeLimit / 2) &&
+ Watchdog.DpcWatchdogCount > (Watchdog.DpcWatchdogLimit / 2))
+ return FALSE;
+
+ return TRUE;
+}
+
#define TIME_US(_us) ((_us) * 10)
#define TIME_MS(_ms) (TIME_US((_ms) * 1000))
#define TIME_S(_s) (TIME_MS((_s) * 1000))
#define TIME_RELATIVE(_t) (-(_t))

+__drv_functionClass(KDEFERRED_ROUTINE)
+__drv_maxIRQL(DISPATCH_LEVEL)
+__drv_minIRQL(DISPATCH_LEVEL)
+__drv_requiresIRQL(DISPATCH_LEVEL)
+__drv_sameIRQL
+static VOID
+ReceiverRingDpc(
+ IN PKDPC Dpc,
+ IN PVOID Context,
+ IN PVOID Argument1,
+ IN PVOID Argument2
+ )
+{
+ PXENVIF_RECEIVER_RING Ring = Context;
+
+ UNREFERENCED_PARAMETER(Dpc);
+ UNREFERENCED_PARAMETER(Argument1);
+ UNREFERENCED_PARAMETER(Argument2);
+
+ ASSERT(Ring != NULL);
+
+ for (;;) {
+ BOOLEAN Retry;
+
+ __ReceiverRingAcquireLock(Ring);
+ Retry = ReceiverRingPoll(Ring);
+ __ReceiverRingReleaseLock(Ring);
+
+ if (!Retry) {
+ __ReceiverRingUnmask(Ring);
+ break;
+ }
+
+ if (__ReceiverRingDpcTimeout(Ring)) {
+ LARGE_INTEGER Delay;
+
+ Delay.QuadPart = TIME_RELATIVE(TIME_US(100));
+
+ KeSetTimer(&Ring->Timer, Delay, &Ring->TimerDpc);
+ break;
+ }
+ }
+}
+
+KSERVICE_ROUTINE ReceiverRingEvtchnCallback;
+
+BOOLEAN
+ReceiverRingEvtchnCallback(
+ IN PKINTERRUPT InterruptObject,
+ IN PVOID Argument
+ )
+{
+ PXENVIF_RECEIVER_RING Ring = Argument;
+ PXENVIF_RECEIVER Receiver;
+ PXENVIF_FRONTEND Frontend;
+
+ UNREFERENCED_PARAMETER(InterruptObject);
+
+ ASSERT(Ring != NULL);
+
+ Ring->Events++;
+
+ if (KeInsertQueueDpc(&Ring->Dpc, NULL, NULL))
+ Ring->Dpcs++;
+
+ Receiver = Ring->Receiver;
+ Frontend = Receiver->Frontend;
+
+ if (!FrontendIsSplit(Frontend))
+ TransmitterNotify(FrontendGetTransmitter(Frontend),
+ Ring->Index);
+
+ return TRUE;
+}
+
#define XENVIF_RECEIVER_WATCHDOG_PERIOD 30

static NTSTATUS
@@ -2257,22 +2380,16 @@ ReceiverRingWatchdog(
if (Ring->Shared->rsp_prod != rsp_prod &&
Ring->Front.rsp_cons == rsp_cons) {
PXENVIF_RECEIVER Receiver;
- PXENVIF_FRONTEND Frontend;

Receiver = Ring->Receiver;
- Frontend = Receiver->Frontend;

XENBUS_DEBUG(Trigger,
&Receiver->DebugInterface,
Ring->DebugCallback);

// Try to move things along
- PollerTrigger(FrontendGetPoller(Frontend),
- Ring->Index,
- XENVIF_POLLER_EVENT_RECEIVE);
- PollerSend(FrontendGetPoller(Frontend),
- Ring->Index,
- XENVIF_POLLER_EVENT_RECEIVE);
+ __ReceiverRingTrigger(Ring, TRUE);
+ __ReceiverRingSend(Ring, TRUE);
}

KeMemoryBarrier();
@@ -2318,7 +2435,11 @@ __ReceiverRingInitialize(
if ((*Ring)->Path == NULL)
goto fail2;

- InitializeListHead(&(*Ring)->PacketComplete);
+ InitializeListHead(&(*Ring)->PacketList);
+
+ KeInitializeDpc(&(*Ring)->Dpc, ReceiverRingDpc, *Ring);
+ KeInitializeTimer(&(*Ring)->Timer);
+ KeInitializeDpc(&(*Ring)->TimerDpc, ReceiverRingDpc, *Ring);

status = RtlStringCbPrintfA(Name,
sizeof (Name),
@@ -2376,8 +2497,6 @@ __ReceiverRingInitialize(
if (!NT_SUCCESS(status))
goto fail7;

- KeInitializeThreadedDpc(&(*Ring)->Dpc, ReceiverRingDpc, *Ring);
-
return STATUS_SUCCESS;

fail7:
@@ -2405,7 +2524,11 @@ fail4:
fail3:
Error("fail3\n");

- RtlZeroMemory(&(*Ring)->PacketComplete, sizeof (LIST_ENTRY));
+ RtlZeroMemory(&(*Ring)->TimerDpc, sizeof (KDPC));
+ RtlZeroMemory(&(*Ring)->Timer, sizeof (KTIMER));
+ RtlZeroMemory(&(*Ring)->Dpc, sizeof (KDPC));
+
+ RtlZeroMemory(&(*Ring)->PacketList, sizeof (LIST_ENTRY));

FrontendFreePath(Frontend, (*Ring)->Path);
(*Ring)->Path = NULL;
@@ -2502,6 +2625,36 @@ __ReceiverRingConnect(

ASSERT(!Ring->Connected);

+ Ring->Channel = XENBUS_EVTCHN(Open,
+ &Receiver->EvtchnInterface,
+ XENBUS_EVTCHN_TYPE_UNBOUND,
+ ReceiverRingEvtchnCallback,
+ Ring,
+ FrontendGetBackendDomain(Frontend),
+ TRUE);
+
+ status = STATUS_UNSUCCESSFUL;
+ if (Ring->Channel == NULL)
+ goto fail6;
+
+ status = KeGetProcessorNumberFromIndex(Ring->Index, &ProcNumber);
+ ASSERT(NT_SUCCESS(status));
+
+ KeSetTargetProcessorDpcEx(&Ring->Dpc, &ProcNumber);
+ KeSetTargetProcessorDpcEx(&Ring->TimerDpc, &ProcNumber);
+
+ (VOID) XENBUS_EVTCHN(Bind,
+ &Receiver->EvtchnInterface,
+ Ring->Channel,
+ ProcNumber.Group,
+ ProcNumber.Number);
+
+ (VOID) XENBUS_EVTCHN(Unmask,
+ &Receiver->EvtchnInterface,
+ Ring->Channel,
+ FALSE,
+ TRUE);
+
Ring->Connected = TRUE;

status = XENBUS_DEBUG(Register,
@@ -2511,20 +2664,25 @@ __ReceiverRingConnect(
Ring,
&Ring->DebugCallback);
if (!NT_SUCCESS(status))
- goto fail6;
+ goto fail7;

- status = KeGetProcessorNumberFromIndex(Ring->Index, &ProcNumber);
- ASSERT(NT_SUCCESS(status));
+ return STATUS_SUCCESS;

- KeSetTargetProcessorDpcEx(&Ring->Dpc, &ProcNumber);
+fail7:
+ Error("fail7\n");

- return STATUS_SUCCESS;
+ Ring->Connected = FALSE;
+
+ XENBUS_EVTCHN(Close,
+ &Receiver->EvtchnInterface,
+ Ring->Channel);
+ Ring->Channel = NULL;
+
+ Ring->Events = 0;

fail6:
Error("fail6\n");

- Ring->Connected = FALSE;
-
fail5:
Error("fail5\n");

@@ -2570,6 +2728,7 @@ __ReceiverRingStoreWrite(
{
PXENVIF_RECEIVER Receiver;
PXENVIF_FRONTEND Frontend;
+ ULONG Port;
PCHAR Path;
NTSTATUS status;

@@ -2592,8 +2751,25 @@ __ReceiverRingStoreWrite(
if (!NT_SUCCESS(status))
goto fail1;

+ Port = XENBUS_EVTCHN(GetPort,
+ &Receiver->EvtchnInterface,
+ Ring->Channel);
+
+ status = XENBUS_STORE(Printf,
+ &Receiver->StoreInterface,
+ Transaction,
+ Path,
+ FrontendIsSplit(Frontend) ? "event-channel-rx" : "event-channel",
+ "%u",
+ Port);
+ if (!NT_SUCCESS(status))
+ goto fail2;
+
return STATUS_SUCCESS;

+fail2:
+ Error("fail2\n");
+
fail1:
Error("fail1 (%08x)\n", status);

@@ -2628,6 +2804,8 @@ __ReceiverRingEnable(

Ring->Enabled = TRUE;

+ (VOID) KeInsertQueueDpc(&Ring->Dpc, NULL, NULL);
+
__ReceiverRingReleaseLock(Ring);

Info("%s[%u]: <====\n",
@@ -2666,11 +2844,14 @@ __ReceiverRingDisable(
Ring->Enabled = FALSE;
Ring->Stopped = FALSE;

- if (KeInsertQueueDpc(&Ring->Dpc, NULL, NULL))
- Ring->Dpcs++;
-
__ReceiverRingReleaseLock(Ring);

+ //
+ // No new timers can be scheduled once Enabled goes to FALSE.
+ // Cancel any existing ones.
+ //
+ (VOID) KeCancelTimer(&Ring->Timer);
+
Info("%s[%u]: <====\n",
FrontendGetPath(Frontend),
Ring->Index);
@@ -2687,13 +2868,19 @@ __ReceiverRingDisconnect(
Receiver = Ring->Receiver;
Frontend = Receiver->Frontend;

- Ring->Dpcs = 0;
-
__ReceiverRingEmpty(Ring);

ASSERT(Ring->Connected);
Ring->Connected = FALSE;

+ XENBUS_EVTCHN(Close,
+ &Receiver->EvtchnInterface,
+ Ring->Channel);
+ Ring->Channel = NULL;
+
+ Ring->Events = 0;
+ Ring->Dpcs = 0;
+
ASSERT3U(Ring->ResponsesProcessed, ==, Ring->RequestsPushed);
ASSERT3U(Ring->RequestsPushed, ==, Ring->RequestsPosted);

@@ -2738,13 +2925,13 @@ __ReceiverRingTeardown(
Frontend = Receiver->Frontend;

RtlZeroMemory(&Ring->Hash, sizeof (XENVIF_RECEIVER_HASH));
+ RtlZeroMemory(&Ring->TimerDpc, sizeof (KDPC));
+ RtlZeroMemory(&Ring->Timer, sizeof (KTIMER));
+ RtlZeroMemory(&Ring->Dpc, sizeof (KDPC));

Ring->BackfillSize = 0;
Ring->OffloadOptions.Value = 0;

- KeFlushQueuedDpcs();
- RtlZeroMemory(&Ring->Dpc, sizeof (KDPC));
-
ThreadAlert(Ring->WatchdogThread);
ThreadJoin(Ring->WatchdogThread);
Ring->WatchdogThread = NULL;
@@ -2759,8 +2946,8 @@ __ReceiverRingTeardown(
Ring->PacketCache);
Ring->PacketCache = NULL;

- ASSERT(IsListEmpty(&Ring->PacketComplete));
- RtlZeroMemory(&Ring->PacketComplete, sizeof (LIST_ENTRY));
+ ASSERT(IsListEmpty(&Ring->PacketList));
+ RtlZeroMemory(&Ring->PacketList, sizeof (LIST_ENTRY));

FrontendFreePath(Frontend, Ring->Path);
Ring->Path = NULL;
@@ -2910,6 +3097,9 @@ ReceiverInitialize(
FdoGetGnttabInterface(PdoGetFdo(FrontendGetPdo(Frontend)),
&(*Receiver)->GnttabInterface);

+ FdoGetEvtchnInterface(PdoGetFdo(FrontendGetPdo(Frontend)),
+ &(*Receiver)->EvtchnInterface);
+
(*Receiver)->Frontend = Frontend;

status = XENBUS_CACHE(Acquire, &(*Receiver)->CacheInterface);
@@ -2962,6 +3152,9 @@ fail2:

(*Receiver)->Frontend = NULL;

+ RtlZeroMemory(&(*Receiver)->EvtchnInterface,
+ sizeof (XENBUS_EVTCHN_INTERFACE));
+
RtlZeroMemory(&(*Receiver)->GnttabInterface,
sizeof (XENBUS_GNTTAB_INTERFACE));

@@ -3013,17 +3206,21 @@ ReceiverConnect(
if (!NT_SUCCESS(status))
goto fail2;

- status = XENBUS_GNTTAB(Acquire, &Receiver->GnttabInterface);
+ status = XENBUS_EVTCHN(Acquire, &Receiver->EvtchnInterface);
if (!NT_SUCCESS(status))
goto fail3;

+ status = XENBUS_GNTTAB(Acquire, &Receiver->GnttabInterface);
+ if (!NT_SUCCESS(status))
+ goto fail4;
+
Index = 0;
while (Index < (LONG)FrontendGetNumQueues(Frontend)) {
PXENVIF_RECEIVER_RING Ring = Receiver->Ring[Index];

status = __ReceiverRingConnect(Ring);
if (!NT_SUCCESS(status))
- goto fail4;
+ goto fail5;

Index++;
}
@@ -3035,18 +3232,18 @@ ReceiverConnect(
Receiver,
&Receiver->DebugCallback);
if (!NT_SUCCESS(status))
- goto fail5;
+ goto fail6;

Trace("<====\n");
return STATUS_SUCCESS;

-fail5:
- Error("fail5\n");
+fail6:
+ Error("fail6\n");

Index = FrontendGetNumQueues(Frontend);

-fail4:
- Error("fail4\n");
+fail5:
+ Error("fail5\n");

while (--Index >= 0) {
PXENVIF_RECEIVER_RING Ring = Receiver->Ring[Index];
@@ -3056,6 +3253,11 @@ fail4:

XENBUS_GNTTAB(Release, &Receiver->GnttabInterface);

+fail4:
+ Error("fail4\n");
+
+ XENBUS_EVTCHN(Release, &Receiver->EvtchnInterface);
+
fail3:
Error("fail3\n");

@@ -3295,34 +3497,6 @@ fail1:
return status;
}

-BOOLEAN
-ReceiverPoll(
- IN PXENVIF_RECEIVER Receiver,
- IN ULONG Index
- )
-{
- PXENVIF_FRONTEND Frontend;
- ULONG NumQueues;
- PXENVIF_RECEIVER_RING Ring;
- BOOLEAN Retry;
-
- ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
-
- Frontend = Receiver->Frontend;
-
- NumQueues = FrontendGetNumQueues(Frontend);
- if (Index >= NumQueues)
- return FALSE;
-
- Ring = Receiver->Ring[Index];
-
- __ReceiverRingAcquireLock(Ring);
- Retry = ReceiverRingPoll(Ring);
- __ReceiverRingReleaseLock(Ring);
-
- return Retry;
-}
-
VOID
ReceiverDisable(
IN PXENVIF_RECEIVER Receiver
@@ -3371,6 +3545,8 @@ ReceiverDisconnect(

XENBUS_GNTTAB(Release, &Receiver->GnttabInterface);

+ XENBUS_EVTCHN(Release, &Receiver->EvtchnInterface);
+
XENBUS_STORE(Release, &Receiver->StoreInterface);

XENBUS_DEBUG(Release, &Receiver->DebugInterface);
@@ -3388,6 +3564,9 @@ ReceiverTeardown(

Frontend = Receiver->Frontend;

+ ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
+ KeFlushQueuedDpcs();
+
ASSERT3U(Receiver->Returned, ==, Receiver->Loaned);
Receiver->Loaned = 0;
Receiver->Returned = 0;
@@ -3407,6 +3586,9 @@ ReceiverTeardown(

Receiver->Frontend = NULL;

+ RtlZeroMemory(&Receiver->EvtchnInterface,
+ sizeof (XENBUS_EVTCHN_INTERFACE));
+
RtlZeroMemory(&Receiver->GnttabInterface,
sizeof (XENBUS_GNTTAB_INTERFACE));

@@ -3541,13 +3723,16 @@ ReceiverWaitForPackets(
LARGE_INTEGER Timeout;

ASSERT3U(KeGetCurrentIrql(), <, DISPATCH_LEVEL);
- KeFlushQueuedDpcs();

Frontend = Receiver->Frontend;

Trace("%s: ====>\n", FrontendGetPath(Frontend));

Returned = Receiver->Returned;
+
+ // Make sure Loaned is not sampled before Returned
+ KeMemoryBarrier();
+
Loaned = Receiver->Loaned;
ASSERT3S(Loaned - Returned, >=, 0);

@@ -3580,6 +3765,32 @@ ReceiverWaitForPackets(
Trace("%s: <====\n", FrontendGetPath(Frontend));
}

+VOID
+ReceiverTrigger(
+ IN PXENVIF_RECEIVER Receiver,
+ IN ULONG Index
+ )
+{
+ PXENVIF_RECEIVER_RING Ring;
+
+ Ring = Receiver->Ring[Index];
+
+ __ReceiverRingTrigger(Ring, FALSE);
+}
+
+VOID
+ReceiverSend(
+ IN PXENVIF_RECEIVER Receiver,
+ IN ULONG Index
+ )
+{
+ PXENVIF_RECEIVER_RING Ring;
+
+ Ring = Receiver->Ring[Index];
+
+ __ReceiverRingSend(Ring, FALSE);
+}
+
NTSTATUS
ReceiverSetHashAlgorithm(
IN PXENVIF_RECEIVER Receiver,
diff --git a/src/xenvif/receiver.h b/src/xenvif/receiver.h
index e1b7a88..7846f0b 100644
--- a/src/xenvif/receiver.h
+++ b/src/xenvif/receiver.h
@@ -62,12 +62,6 @@ ReceiverEnable(
IN PXENVIF_RECEIVER Receiver
);

-extern BOOLEAN
-ReceiverPoll(
- IN PXENVIF_RECEIVER Receiver,
- IN ULONG Index
- );
-
extern VOID
ReceiverDisable(
IN PXENVIF_RECEIVER Receiver
diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
index eed0a0f..770aca9 100644
--- a/src/xenvif/transmitter.c
+++ b/src/xenvif/transmitter.c
@@ -43,6 +43,7 @@
#include <cache_interface.h>
#include <gnttab_interface.h>
#include <range_set_interface.h>
+#include <evtchn_interface.h>

#include "pdo.h"
#include "frontend.h"
@@ -178,6 +179,12 @@ typedef struct _XENVIF_TRANSMITTER_RING {
netif_tx_front_ring_t Front;
netif_tx_sring_t *Shared;
PXENBUS_GNTTAB_ENTRY Entry;
+ PXENBUS_EVTCHN_CHANNEL Channel;
+ KDPC Dpc;
+ ULONG Dpcs;
+ KTIMER Timer;
+ KDPC TimerDpc;
+ ULONG Events;
BOOLEAN Connected;
BOOLEAN Enabled;
BOOLEAN Stopped;
@@ -208,6 +215,7 @@ struct _XENVIF_TRANSMITTER {
XENBUS_CACHE_INTERFACE CacheInterface;
XENBUS_GNTTAB_INTERFACE GnttabInterface;
XENBUS_RANGE_SET_INTERFACE RangeSetInterface;
+ XENBUS_EVTCHN_INTERFACE EvtchnInterface;
PXENVIF_TRANSMITTER_RING *Ring;
BOOLEAN MulticastControl;
ULONG DisableIpVersion4Gso;
@@ -762,6 +770,15 @@ TransmitterRingDebugCallback(
Ring->PacketsUnprepared,
Ring->PacketsSent,
Ring->PacketsCompleted);
+
+ if (FrontendIsSplit(Frontend)) {
+ // Dump event channel
+ XENBUS_DEBUG(Printf,
+ &Transmitter->DebugInterface,
+ "Events = %lu Dpcs = %lu\n",
+ Ring->Events,
+ Ring->Dpcs);
+ }
}

static BOOLEAN
@@ -2622,6 +2639,9 @@ TransmitterRingPoll(
RING_IDX rsp_cons;
ULONG Extra;

+ if (Retry)
+ break;
+
KeMemoryBarrier();

rsp_prod = Ring->Shared->rsp_prod;
@@ -2629,8 +2649,15 @@ TransmitterRingPoll(

KeMemoryBarrier();

- if (rsp_cons == rsp_prod || Retry)
+ if (rsp_cons == rsp_prod) {
+ RING_IDX WorkToDo;
+
+ RING_FINAL_CHECK_FOR_RESPONSES(&Ring->Front, WorkToDo);
+ if (WorkToDo)
+ continue;
+
break;
+ }

Extra = 0;
while (rsp_cons != rsp_prod && !Retry) {
@@ -2769,7 +2796,6 @@ TransmitterRingPoll(
KeMemoryBarrier();

Ring->Front.rsp_cons = rsp_cons;
- Ring->Shared->rsp_event = rsp_cons + 1;
}

done:
@@ -2779,17 +2805,64 @@ done:
}

static FORCEINLINE VOID
-__TransmitterRingPushRequests(
+__TransmitterRingTrigger(
+ IN PXENVIF_TRANSMITTER_RING Ring
+ )
+{
+ PXENVIF_TRANSMITTER Transmitter;
+ PXENVIF_FRONTEND Frontend;
+
+ Transmitter = Ring->Transmitter;
+ Frontend = Transmitter->Frontend;
+
+ if (!Ring->Connected)
+ return;
+
+ if (FrontendIsSplit(Frontend)) {
+ ASSERT(Ring->Channel != NULL);
+
+ (VOID) XENBUS_EVTCHN(Trigger,
+ &Transmitter->EvtchnInterface,
+ Ring->Channel);
+ } else {
+ ReceiverTrigger(FrontendGetReceiver(Frontend),
+ Ring->Index);
+ }
+}
+
+static FORCEINLINE VOID
+__TransmitterRingSend(
IN PXENVIF_TRANSMITTER_RING Ring
)
{
PXENVIF_TRANSMITTER Transmitter;
PXENVIF_FRONTEND Frontend;
- BOOLEAN Notify;

Transmitter = Ring->Transmitter;
Frontend = Transmitter->Frontend;

+ if (!Ring->Connected)
+ return;
+
+ if (FrontendIsSplit(Frontend)) {
+ ASSERT(Ring->Channel != NULL);
+
+ (VOID) XENBUS_EVTCHN(Send,
+ &Transmitter->EvtchnInterface,
+ Ring->Channel);
+ } else {
+ ReceiverSend(FrontendGetReceiver(Frontend),
+ Ring->Index);
+ }
+}
+
+static FORCEINLINE VOID
+__TransmitterRingPushRequests(
+ IN PXENVIF_TRANSMITTER_RING Ring
+ )
+{
+ BOOLEAN Notify;
+
if (Ring->RequestsPosted == Ring->RequestsPushed)
return;

@@ -2802,9 +2875,7 @@ __TransmitterRingPushRequests(
#pragma warning (pop)

if (Notify)
- PollerSend(FrontendGetPoller(Frontend),
- Ring->Index,
- XENVIF_POLLER_EVENT_TRANSMIT);
+ __TransmitterRingSend(Ring);

Ring->RequestsPushed = Ring->RequestsPosted;
}
@@ -3158,11 +3229,131 @@ TransmitterRingReleaseLock(
__TransmitterRingReleaseLock(Ring);
}

+static FORCEINLINE VOID
+__TransmitterRingUnmask(
+ IN PXENVIF_TRANSMITTER_RING Ring
+ )
+{
+ PXENVIF_TRANSMITTER Transmitter;
+ PXENVIF_FRONTEND Frontend;
+
+ Transmitter = Ring->Transmitter;
+ Frontend = Transmitter->Frontend;
+
+ if (!Ring->Connected || !FrontendIsSplit(Frontend))
+ return;
+
+ XENBUS_EVTCHN(Unmask,
+ &Transmitter->EvtchnInterface,
+ Ring->Channel,
+ FALSE,
+ TRUE);
+}
+
+static FORCEINLINE BOOLEAN
+__TransmitterRingDpcTimeout(
+ IN PXENVIF_TRANSMITTER_RING Ring
+ )
+{
+ KDPC_WATCHDOG_INFORMATION Watchdog;
+ NTSTATUS status;
+
+ UNREFERENCED_PARAMETER(Ring);
+
+ RtlZeroMemory(&Watchdog, sizeof (Watchdog));
+
+ status = KeQueryDpcWatchdogInformation(&Watchdog);
+ ASSERT(NT_SUCCESS(status));
+
+ if (Watchdog.DpcTimeLimit == 0 ||
+ Watchdog.DpcWatchdogLimit == 0)
+ return FALSE;
+
+ if (Watchdog.DpcTimeCount > (Watchdog.DpcTimeLimit / 2) &&
+ Watchdog.DpcWatchdogCount > (Watchdog.DpcWatchdogLimit / 2))
+ return FALSE;
+
+ return TRUE;
+}
+
#define TIME_US(_us) ((_us) * 10)
#define TIME_MS(_ms) (TIME_US((_ms) * 1000))
#define TIME_S(_s) (TIME_MS((_s) * 1000))
#define TIME_RELATIVE(_t) (-(_t))

+__drv_functionClass(KDEFERRED_ROUTINE)
+__drv_maxIRQL(DISPATCH_LEVEL)
+__drv_minIRQL(DISPATCH_LEVEL)
+__drv_requiresIRQL(DISPATCH_LEVEL)
+__drv_sameIRQL
+static VOID
+TransmitterRingDpc(
+ IN PKDPC Dpc,
+ IN PVOID Context,
+ IN PVOID Argument1,
+ IN PVOID Argument2
+ )
+{
+ PXENVIF_TRANSMITTER_RING Ring = Context;
+
+ UNREFERENCED_PARAMETER(Dpc);
+ UNREFERENCED_PARAMETER(Argument1);
+ UNREFERENCED_PARAMETER(Argument2);
+
+ ASSERT(Ring != NULL);
+
+ for (;;) {
+ BOOLEAN Retry;
+
+ __TransmitterRingAcquireLock(Ring);
+ Retry = TransmitterRingPoll(Ring);
+ __TransmitterRingReleaseLock(Ring);
+
+ if (!Retry) {
+ __TransmitterRingUnmask(Ring);
+ break;
+ }
+
+ if (__TransmitterRingDpcTimeout(Ring)) {
+ LARGE_INTEGER Delay;
+
+ Delay.QuadPart = TIME_RELATIVE(TIME_US(100));
+
+ KeSetTimer(&Ring->Timer, Delay, &Ring->TimerDpc);
+ break;
+ }
+ }
+}
+
+KSERVICE_ROUTINE TransmitterRingEvtchnCallback;
+
+BOOLEAN
+TransmitterRingEvtchnCallback(
+ IN PKINTERRUPT InterruptObject,
+ IN PVOID Argument
+ )
+{
+ PXENVIF_TRANSMITTER_RING Ring = Argument;
+ PXENVIF_TRANSMITTER Transmitter;
+ PXENVIF_FRONTEND Frontend;
+
+ UNREFERENCED_PARAMETER(InterruptObject);
+
+ ASSERT(Ring != NULL);
+
+ Transmitter = Ring->Transmitter;
+ Frontend = Transmitter->Frontend;
+
+ ASSERT(FrontendIsSplit(Frontend));
+
+ Ring->Events++;
+
+ if (KeInsertQueueDpc(&Ring->Dpc, NULL, NULL))
+ Ring->Dpcs++;
+
+ return TRUE;
+}
+
#define XENVIF_TRANSMITTER_WATCHDOG_PERIOD 30

static NTSTATUS
@@ -3221,22 +3412,16 @@ TransmitterRingWatchdog(
if (Ring->PacketsQueued == PacketsQueued &&
Ring->PacketsCompleted != PacketsQueued) {
PXENVIF_TRANSMITTER Transmitter;
- PXENVIF_FRONTEND Frontend;

Transmitter = Ring->Transmitter;
- Frontend = Transmitter->Frontend;

XENBUS_DEBUG(Trigger,
&Transmitter->DebugInterface,
Ring->DebugCallback);

// Try to move things along
- PollerTrigger(FrontendGetPoller(Frontend),
- Ring->Index,
- XENVIF_POLLER_EVENT_TRANSMIT);
- PollerSend(FrontendGetPoller(Frontend),
- Ring->Index,
- XENVIF_POLLER_EVENT_TRANSMIT);
+ __TransmitterRingTrigger(Ring);
+ __TransmitterRingSend(Ring);
}

PacketsQueued = Ring->PacketsQueued;
@@ -3281,6 +3466,10 @@ __TransmitterRingInitialize(
InitializeListHead(&(*Ring)->RequestQueue);
InitializeListHead(&(*Ring)->PacketComplete);

+ KeInitializeDpc(&(*Ring)->Dpc, TransmitterRingDpc, *Ring);
+ KeInitializeTimer(&(*Ring)->Timer);
+ KeInitializeDpc(&(*Ring)->TimerDpc, TransmitterRingDpc, *Ring);
+
status = RtlStringCbPrintfA(Name,
sizeof (Name),
"%s_transmitter_buffer",
@@ -3482,6 +3671,8 @@ fail4:
fail3:
Error("fail3\n");

+ RtlZeroMemory(&(*Ring)->Dpc, sizeof (KDPC));
+
RtlZeroMemory(&(*Ring)->PacketComplete, sizeof (LIST_ENTRY));
RtlZeroMemory(&(*Ring)->RequestQueue, sizeof (LIST_ENTRY));
RtlZeroMemory(&(*Ring)->PacketQueue, sizeof (LIST_ENTRY));
@@ -3515,6 +3706,7 @@ __TransmitterRingConnect(
PFN_NUMBER Pfn;
CHAR Name[MAXNAMELEN];
ULONG Index;
+ PROCESSOR_NUMBER ProcNumber;
NTSTATUS status;

ASSERT(!Ring->Connected);
@@ -3580,6 +3772,38 @@ __TransmitterRingConnect(

ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);

+ if (FrontendIsSplit(Frontend)) {
+ Ring->Channel = XENBUS_EVTCHN(Open,
+ &Transmitter->EvtchnInterface,
+ XENBUS_EVTCHN_TYPE_UNBOUND,
+ TransmitterRingEvtchnCallback,
+ Ring,
+ FrontendGetBackendDomain(Frontend),
+ TRUE);
+
+ status = STATUS_UNSUCCESSFUL;
+ if (Ring->Channel == NULL)
+ goto fail6;
+
+ status = KeGetProcessorNumberFromIndex(Ring->Index, &ProcNumber);
+ ASSERT(NT_SUCCESS(status));
+
+ KeSetTargetProcessorDpcEx(&Ring->Dpc, &ProcNumber);
+ KeSetTargetProcessorDpcEx(&Ring->TimerDpc, &ProcNumber);
+
+ (VOID) XENBUS_EVTCHN(Bind,
+ &Transmitter->EvtchnInterface,
+ Ring->Channel,
+ ProcNumber.Group,
+ ProcNumber.Number);
+
+ (VOID) XENBUS_EVTCHN(Unmask,
+ &Transmitter->EvtchnInterface,
+ Ring->Channel,
+ FALSE,
+ TRUE);
+ }
+
status = XENBUS_DEBUG(Register,
&Transmitter->DebugInterface,
Name,
@@ -3587,12 +3811,22 @@ __TransmitterRingConnect(
Ring,
&Ring->DebugCallback);
if (!NT_SUCCESS(status))
- goto fail6;
+ goto fail7;

Ring->Connected = TRUE;

return STATUS_SUCCESS;

+fail7:
+ Error("fail7\n");
+
+ XENBUS_EVTCHN(Close,
+ &Transmitter->EvtchnInterface,
+ Ring->Channel);
+ Ring->Channel = NULL;
+
+ Ring->Events = 0;
+
fail6:
Error("fail6\n");

@@ -3641,6 +3875,7 @@ __TransmitterRingStoreWrite(
{
PXENVIF_TRANSMITTER Transmitter;
PXENVIF_FRONTEND Frontend;
+ ULONG Port;
PCHAR Path;
NTSTATUS status;

@@ -3663,8 +3898,29 @@ __TransmitterRingStoreWrite(
if (!NT_SUCCESS(status))
goto fail1;

+ if (!FrontendIsSplit(Frontend))
+ goto done;
+
+ Port = XENBUS_EVTCHN(GetPort,
+ &Transmitter->EvtchnInterface,
+ Ring->Channel);
+
+ status = XENBUS_STORE(Printf,
+ &Transmitter->StoreInterface,
+ Transaction,
+ Path,
+ "event-channel-tx",
+ "%u",
+ Port);
+ if (!NT_SUCCESS(status))
+ goto fail2;
+
+done:
return STATUS_SUCCESS;

+fail2:
+ Error("fail2\n");
+
fail1:
Error("fail1 (%08x)\n", status);

@@ -3691,6 +3947,8 @@ __TransmitterRingEnable(
ASSERT(!Ring->Enabled);
Ring->Enabled = TRUE;

+ KeInsertQueueDpc(&Ring->Dpc, NULL, NULL);
+
__TransmitterRingReleaseLock(Ring);

Info("%s[%u]: <====\n",
@@ -3770,9 +4028,7 @@ __TransmitterRingDisable(
ASSERT(Attempt < 100);

// Try to move things along
- PollerSend(FrontendGetPoller(Frontend),
- Ring->Index,
- XENVIF_POLLER_EVENT_TRANSMIT);
+ __TransmitterRingSend(Ring);
(VOID) TransmitterRingPoll(Ring);

if (State != XenbusStateConnected)
@@ -3790,6 +4046,12 @@ __TransmitterRingDisable(

__TransmitterRingReleaseLock(Ring);

+ //
+ // No new timers can be scheduled once Enabled goes to FALSE.
+ // Cancel any existing ones.
+ //
+ (VOID) KeCancelTimer(&Ring->Timer);
+
Info("%s[%u]: <====\n",
FrontendGetPath(Frontend),
Ring->Index);
@@ -3809,6 +4071,17 @@ __TransmitterRingDisconnect(
Transmitter = Ring->Transmitter;
Frontend = Transmitter->Frontend;

+ if (Ring->Channel != NULL) {
+ XENBUS_EVTCHN(Close,
+ &Transmitter->EvtchnInterface,
+ Ring->Channel);
+ Ring->Channel = NULL;
+
+ Ring->Events = 0;
+ }
+
+ Ring->Dpcs = 0;
+
ASSERT3U(Ring->ResponsesProcessed, ==, Ring->RequestsPushed);
ASSERT3U(Ring->RequestsPushed, ==, Ring->RequestsPosted);

@@ -3852,6 +4125,12 @@ __TransmitterRingTeardown(
Transmitter = Ring->Transmitter;
Frontend = Transmitter->Frontend;

+ Ring->Dpcs = 0;
+
+ RtlZeroMemory(&Ring->TimerDpc, sizeof (KDPC));
+ RtlZeroMemory(&Ring->Timer, sizeof (KTIMER));
+ RtlZeroMemory(&Ring->Dpc, sizeof (KDPC));
+
ASSERT3U(Ring->PacketsCompleted, ==, Ring->PacketsSent);
ASSERT3U(Ring->PacketsSent, ==, Ring->PacketsPrepared - Ring->PacketsUnprepared);
ASSERT3U(Ring->PacketsPrepared, ==, Ring->PacketsCopied + Ring->PacketsGranted + Ring->PacketsFaked);
@@ -4277,6 +4556,9 @@ TransmitterInitialize(
FdoGetGnttabInterface(PdoGetFdo(FrontendGetPdo(Frontend)),
&(*Transmitter)->GnttabInterface);

+ FdoGetEvtchnInterface(PdoGetFdo(FrontendGetPdo(Frontend)),
+ &(*Transmitter)->EvtchnInterface);
+
(*Transmitter)->Frontend = Frontend;
KeInitializeSpinLock(&(*Transmitter)->Lock);

@@ -4429,10 +4711,14 @@ TransmitterConnect(
if (!NT_SUCCESS(status))
goto fail2;

- status = XENBUS_GNTTAB(Acquire, &Transmitter->GnttabInterface);
+ status = XENBUS_EVTCHN(Acquire, &Transmitter->EvtchnInterface);
if (!NT_SUCCESS(status))
goto fail3;

+ status = XENBUS_GNTTAB(Acquire, &Transmitter->GnttabInterface);
+ if (!NT_SUCCESS(status))
+ goto fail4;
+
if (Transmitter->DisableMulticastControl == 0) {
status = XENBUS_STORE(Read,
&Transmitter->StoreInterface,
@@ -4455,7 +4741,7 @@ TransmitterConnect(

status = __TransmitterRingConnect(Ring);
if (!NT_SUCCESS(status))
- goto fail4;
+ goto fail5;

Index++;
}
@@ -4467,18 +4753,18 @@ TransmitterConnect(
Transmitter,
&Transmitter->DebugCallback);
if (!NT_SUCCESS(status))
- goto fail5;
+ goto fail6;

Trace("<====\n");
return STATUS_SUCCESS;

-fail5:
- Error("fail5\n");
+fail6:
+ Error("fail6\n");

Index = FrontendGetNumQueues(Frontend);

-fail4:
- Error("fail4\n");
+fail5:
+ Error("fail5\n");

while (--Index >= 0) {
PXENVIF_TRANSMITTER_RING Ring;
@@ -4492,6 +4778,11 @@ fail4:

XENBUS_GNTTAB(Release, &Transmitter->GnttabInterface);

+fail4:
+ Error("fail4\n");
+
+ XENBUS_EVTCHN(Release, &Transmitter->EvtchnInterface);
+
fail3:
Error("fail3\n");

@@ -4628,34 +4919,6 @@ TransmitterEnable(
return STATUS_SUCCESS;
}

-BOOLEAN
-TransmitterPoll(
- IN PXENVIF_TRANSMITTER Transmitter,
- IN ULONG Index
- )
-{
- PXENVIF_FRONTEND Frontend;
- ULONG NumQueues;
- PXENVIF_TRANSMITTER_RING Ring;
- BOOLEAN Retry;
-
- ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
-
- Frontend = Transmitter->Frontend;
-
- NumQueues = FrontendGetNumQueues(Frontend);
- if (Index >= NumQueues)
- return FALSE;
-
- Ring = Transmitter->Ring[Index];
-
- __TransmitterRingAcquireLock(Ring);
- Retry = TransmitterRingPoll(Ring);
- __TransmitterRingReleaseLock(Ring);
-
- return Retry;
-}
-
VOID
TransmitterDisable(
IN PXENVIF_TRANSMITTER Transmitter
@@ -4706,6 +4969,8 @@ TransmitterDisconnect(

XENBUS_GNTTAB(Release, &Transmitter->GnttabInterface);

+ XENBUS_EVTCHN(Release, &Transmitter->EvtchnInterface);
+
XENBUS_STORE(Release, &Transmitter->StoreInterface);

XENBUS_DEBUG(Release, &Transmitter->DebugInterface);
@@ -4724,6 +4989,7 @@ TransmitterTeardown(
Frontend = Transmitter->Frontend;

ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
+ KeFlushQueuedDpcs();

Index = FrontendGetMaxQueues(Frontend);
while (--Index >= 0) {
@@ -4765,6 +5031,9 @@ TransmitterTeardown(
RtlZeroMemory(&Transmitter->DebugInterface,
sizeof (XENBUS_DEBUG_INTERFACE));

+ RtlZeroMemory(&Transmitter->EvtchnInterface,
+ sizeof (XENBUS_EVTCHN_INTERFACE));
+
Transmitter->DisableIpVersion4Gso = 0;
Transmitter->DisableIpVersion6Gso = 0;
Transmitter->AlwaysCopy = 0;
@@ -5041,6 +5310,25 @@ TransmitterQueryRingSize(
}

VOID
+TransmitterNotify(
+ IN PXENVIF_TRANSMITTER Transmitter,
+ IN ULONG Index
+ )
+{
+ PXENVIF_FRONTEND Frontend;
+ PXENVIF_TRANSMITTER_RING Ring;
+
+ Frontend = Transmitter->Frontend;
+
+ ASSERT(!FrontendIsSplit(Frontend));
+
+ Ring = Transmitter->Ring[Index];
+
+ if (KeInsertQueueDpc(&Ring->Dpc, NULL, NULL))
+ Ring->Dpcs++;
+}
+
+VOID
TransmitterQueryOffloadOptions(
IN PXENVIF_TRANSMITTER Transmitter,
OUT PXENVIF_VIF_OFFLOAD_OPTIONS Options
diff --git a/src/xenvif/transmitter.h b/src/xenvif/transmitter.h
index 2446220..d44f77e 100644
--- a/src/xenvif/transmitter.h
+++ b/src/xenvif/transmitter.h
@@ -64,12 +64,6 @@ TransmitterEnable(
IN PXENVIF_TRANSMITTER Transmitter
);

-extern BOOLEAN
-TransmitterPoll(
- IN PXENVIF_TRANSMITTER Transmitter,
- IN ULONG Index
- );
-
extern VOID
TransmitterDisable(
IN PXENVIF_TRANSMITTER Transmitter
diff --git a/src/xenvif/vif.c b/src/xenvif/vif.c
index 69ced78..ffdec50 100644
--- a/src/xenvif/vif.c
+++ b/src/xenvif/vif.c
@@ -1161,7 +1161,6 @@ __VifReceiverQueuePacket(
Hash,
More,
Cookie);
-
}

VOID
@@ -1180,10 +1179,6 @@ VifReceiverQueuePacket(
IN PVOID Cookie
)
{
- KIRQL Irql;
-
- KeRaiseIrql(DISPATCH_LEVEL, &Irql);
-
switch (Context->Version) {
case 6:
__VifReceiverQueuePacketVersion6(Context,
@@ -1234,8 +1229,6 @@ VifReceiverQueuePacket(
ASSERT(FALSE);
break;
}
-
- KeLowerIrql(Irql);
}

VOID
diff --git a/vs2015/xenvif/xenvif.vcxproj b/vs2015/xenvif/xenvif.vcxproj
index 3be0c18..8db43cb 100644
--- a/vs2015/xenvif/xenvif.vcxproj
+++ b/vs2015/xenvif/xenvif.vcxproj
@@ -73,7 +73,6 @@
<ClCompile Include="../../src/xenvif/mac.c" />
<ClCompile Include="../../src/xenvif/parse.c" />
<ClCompile Include="../../src/xenvif/pdo.c" />
- <ClCompile Include="../../src/xenvif/poller.c" />
<ClCompile Include="../../src/xenvif/receiver.c" />
<ClCompile Include="../../src/xenvif/registry.c" />
<ClCompile Include="../../src/xenvif/settings.c" />
diff --git a/vs2017/xenvif/xenvif.vcxproj b/vs2017/xenvif/xenvif.vcxproj
index f2e5d19..c6d02f9 100644
--- a/vs2017/xenvif/xenvif.vcxproj
+++ b/vs2017/xenvif/xenvif.vcxproj
@@ -81,7 +81,6 @@
<ClCompile Include="../../src/xenvif/mac.c" />
<ClCompile Include="../../src/xenvif/parse.c" />
<ClCompile Include="../../src/xenvif/pdo.c" />
- <ClCompile Include="../../src/xenvif/poller.c" />
<ClCompile Include="../../src/xenvif/receiver.c" />
<ClCompile Include="../../src/xenvif/registry.c" />
<ClCompile Include="../../src/xenvif/settings.c" />
--
2.5.3
Paul Durrant
2018-11-02 16:54:27 UTC
Permalink
This was supposed to allow better interleaving of receive and transmit
polling, but this does not really seem to help so it really only makes
the code more complex than it needs to be.

Signed-off-by: Paul Durrant <***@citrix.com>
---
src/xenvif/receiver.c | 31 ++++++-------------------------
src/xenvif/transmitter.c | 31 ++++++-------------------------
2 files changed, 12 insertions(+), 50 deletions(-)

diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c
index ed362ff..5353294 100644
--- a/src/xenvif/receiver.c
+++ b/src/xenvif/receiver.c
@@ -1975,23 +1975,19 @@ __ReceiverRingQueuePacket(
} while (InterlockedCompareExchangePointer(&Ring->PacketQueue, (PVOID)New, (PVOID)Old) != Old);
}

-static DECLSPEC_NOINLINE BOOLEAN
+static DECLSPEC_NOINLINE VOID
ReceiverRingPoll(
IN PXENVIF_RECEIVER_RING Ring
)
{
-#define XENVIF_RECEIVER_BATCH(_Ring) (RING_SIZE(&(_Ring)->Front) / 4)
-
PXENVIF_RECEIVER Receiver;
PXENVIF_FRONTEND Frontend;
- BOOLEAN Retry;

Receiver = Ring->Receiver;
Frontend = Receiver->Frontend;
- Retry = FALSE;

if (!Ring->Enabled)
- goto done;
+ return;

for (;;) {
BOOLEAN Error;
@@ -2016,9 +2012,6 @@ ReceiverRingPoll(
TailMdl = NULL;
EOP = TRUE;

- if (Retry)
- break;
-
KeMemoryBarrier();

rsp_prod = Ring->Shared->rsp_prod;
@@ -2036,7 +2029,7 @@ ReceiverRingPoll(
break;
}

- while (rsp_cons != rsp_prod && !Retry) {
+ while (rsp_cons != rsp_prod) {
netif_rx_response_t *rsp;
uint16_t id;
PXENVIF_RECEIVER_FRAGMENT Fragment;
@@ -2193,9 +2186,6 @@ ReceiverRingPoll(
__ReceiverRingQueuePacket(Ring, Packet);
}

- if (rsp_cons - Ring->Front.rsp_cons > XENVIF_RECEIVER_BATCH(Ring))
- Retry = TRUE;
-
Error = FALSE;
Info = 0;
MaximumSegmentSize = 0;
@@ -2226,11 +2216,6 @@ ReceiverRingPoll(
if (Ring->PacketQueue != NULL &&
KeInsertQueueDpc(&Ring->QueueDpc, NULL, NULL))
Ring->QueueDpcs++;
-
-done:
- return Retry;
-
-#undef XENVIF_RECEIVER_BATCH
}

static FORCEINLINE VOID
@@ -2274,16 +2259,12 @@ ReceiverRingPollDpc(
ASSERT(Ring != NULL);

for (;;) {
- BOOLEAN Retry;
-
__ReceiverRingAcquireLock(Ring);
- Retry = ReceiverRingPoll(Ring);
+ ReceiverRingPoll(Ring);
__ReceiverRingReleaseLock(Ring);

- if (!Retry) {
- __ReceiverRingUnmask(Ring);
- break;
- }
+ __ReceiverRingUnmask(Ring);
+ break;
}
}

diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
index 6895f2c..5e53f9a 100644
--- a/src/xenvif/transmitter.c
+++ b/src/xenvif/transmitter.c
@@ -2614,32 +2614,25 @@ done:
Ring->PacketsCompleted++;
}

-static DECLSPEC_NOINLINE BOOLEAN
+static DECLSPEC_NOINLINE VOID
TransmitterRingPoll(
IN PXENVIF_TRANSMITTER_RING Ring
)
{
-#define XENVIF_TRANSMITTER_BATCH(_Ring) (RING_SIZE(&(_Ring)->Front) / 4)
-
PXENVIF_TRANSMITTER Transmitter;
PXENVIF_FRONTEND Frontend;
- BOOLEAN Retry;

Transmitter = Ring->Transmitter;
Frontend = Transmitter->Frontend;
- Retry = FALSE;

if (!Ring->Enabled)
- goto done;
+ return;

for (;;) {
RING_IDX rsp_prod;
RING_IDX rsp_cons;
ULONG Extra;

- if (Retry)
- break;
-
KeMemoryBarrier();

rsp_prod = Ring->Shared->rsp_prod;
@@ -2658,7 +2651,7 @@ TransmitterRingPoll(
}

Extra = 0;
- while (rsp_cons != rsp_prod && !Retry) {
+ while (rsp_cons != rsp_prod) {
netif_tx_response_t *rsp;
uint16_t id;
PXENVIF_TRANSMITTER_FRAGMENT Fragment;
@@ -2785,9 +2778,6 @@ TransmitterRingPoll(
Packet->Completion.Status = XENVIF_TRANSMITTER_PACKET_OK;

__TransmitterRingCompletePacket(Ring, Packet);
-
- if (rsp_cons - Ring->Front.rsp_cons > XENVIF_TRANSMITTER_BATCH(Ring))
- Retry = TRUE;
}
ASSERT3U(Extra, ==, 0);

@@ -2795,11 +2785,6 @@ TransmitterRingPoll(

Ring->Front.rsp_cons = rsp_cons;
}
-
-done:
- return Retry;
-
-#undef XENVIF_TRANSMITTER_BATCH
}

static FORCEINLINE VOID
@@ -3270,16 +3255,12 @@ TransmitterRingPollDpc(
ASSERT(Ring != NULL);

for (;;) {
- BOOLEAN Retry;
-
__TransmitterRingAcquireLock(Ring);
- Retry = TransmitterRingPoll(Ring);
+ TransmitterRingPoll(Ring);
__TransmitterRingReleaseLock(Ring);

- if (!Retry) {
- __TransmitterRingUnmask(Ring);
- break;
- }
+ __TransmitterRingUnmask(Ring);
+ break;
}
}
--
2.5.3
Continue reading on narkive:
Loading...