} 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;
rsp_cons++;
Ring->ResponsesProcessed++;
+ Count++;
ASSERT3U(id, <=, XENVIF_RECEIVER_MAXIMUM_FRAGMENT_ID);
Fragment = Ring->Pending[id];
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)
)
{
PXENVIF_RECEIVER_RING Ring = Context;
+ ULONG Count;
UNREFERENCED_PARAMETER(Dpc);
UNREFERENCED_PARAMETER(Argument1);
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;
}
}
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;
rsp = RING_GET_RESPONSE(&Ring->Front, rsp_cons);
rsp_cons++;
Ring->ResponsesProcessed++;
+ Count++;
Ring->Stopped = FALSE;
Ring->Front.rsp_cons = rsp_cons;
}
+
+done:
+ return Count;
}
static FORCEINLINE VOID
if (Ring->Stopped) {
if (!Polled) {
- (VOID) TransmitterRingPoll(Ring);
+ TransmitterRingPoll(Ring);
Polled = TRUE;
}
__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;
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)
)
{
PXENVIF_TRANSMITTER_RING Ring = Context;
+ ULONG Count;
UNREFERENCED_PARAMETER(Dpc);
UNREFERENCED_PARAMETER(Argument1);
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;
}
}