>From 1ca53f5b0576dcb0b5281bb673fcdf11f5c3a29e Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld <vrozenfe@xxxxxxxxxx> Date: Mon, 16 May 2011 21:00:20 +0300 Subject: [COMMIT] [NetKvm] From: Yan Vugenfirer <yvugenfi@xxxxxxxxxx> Fixing race condition in handling RX interrupts that caused to halt network traffic during netperf tests. --- NetKVM/Common/ParaNdis-Common.c | 41 ++++++++++++++++++++++++++++++++++---- NetKVM/Common/kdebugprint.h | 8 +------ NetKVM/Common/ndis56common.h | 2 + 3 files changed, 39 insertions(+), 12 deletions(-) diff --git a/NetKVM/Common/ParaNdis-Common.c b/NetKVM/Common/ParaNdis-Common.c index a775c84..1a51474 100644 --- a/NetKVM/Common/ParaNdis-Common.c +++ b/NetKVM/Common/ParaNdis-Common.c @@ -1741,6 +1741,7 @@ static BOOLEAN RestartQueueSynchronously(tSynchronizedContext *SyncContext) { b = !pContext->NetSendQueue->vq_ops->restart(pContext->NetSendQueue); } + ParaNdis_DebugHistory(pContext, hopDPC, (PVOID)0x20, SyncContext->Parameter, !b, 0); return b; } /********************************************************** @@ -1753,7 +1754,6 @@ ULONG ParaNdis_DPCWorkBody(PARANDIS_ADAPTER *pContext) ULONG stillRequiresProcessing = 0; ULONG interruptSources; DEBUG_ENTRY(5); - ParaNdis_DebugHistory(pContext, hopDPC, (PVOID)1, 0, 0, 0); if (pContext->bEnableInterruptHandlingDPC) { InterlockedIncrement(&pContext->counterDPCInside); @@ -1761,6 +1761,7 @@ ULONG ParaNdis_DPCWorkBody(PARANDIS_ADAPTER *pContext) { InterlockedExchange(&pContext->bDPCInactive, 0); interruptSources = InterlockedExchange(&pContext->InterruptStatus, 0); + ParaNdis_DebugHistory(pContext, hopDPC, (PVOID)1, interruptSources, 0, 0); if ((interruptSources & isControl) && pContext->bLinkDetectSupported) { ParaNdis_ReportLinkStatus(pContext); @@ -1771,8 +1772,8 @@ ULONG ParaNdis_DPCWorkBody(PARANDIS_ADAPTER *pContext) } if (interruptSources & isReceive) { - int nRestartResult = 2, nLoop = 0; - while (nRestartResult) + int nRestartResult = 0, nLoop = 0; + do { UINT n; LONG rxActive = InterlockedIncrement(&pContext->dpcReceiveActive); @@ -1783,22 +1784,33 @@ ULONG ParaNdis_DPCWorkBody(PARANDIS_ADAPTER *pContext) NdisAcquireSpinLock(&pContext->ReceiveLock); nRestartResult = ParaNdis_SynchronizeWithInterrupt( pContext, pContext->ulRxMessage, RestartQueueSynchronously, isReceive); + ParaNdis_DebugHistory(pContext, hopDPC, (PVOID)3, nRestartResult, 0, 0); NdisReleaseSpinLock(&pContext->ReceiveLock); DPrintf(nRestartResult ? 2 : 6, ("[%s] queue restarted%s", __FUNCTION__, nRestartResult ? "(Rerun)" : "(Done)")); ++nLoop; if (nLoop > MAX_RX_LOOPS) { DPrintf(0, ("[%s] Breaking Rx loop on %d-th operation", __FUNCTION__, nLoop)); + ParaNdis_DebugHistory(pContext, hopDPC, (PVOID)4, nRestartResult, 0, 0); break; } } else { InterlockedDecrement(&pContext->dpcReceiveActive); - nRestartResult = 0; + if (!nRestartResult) + { + NdisAcquireSpinLock(&pContext->ReceiveLock); + nRestartResult = ParaNdis_SynchronizeWithInterrupt( + pContext, pContext->ulRxMessage, RestartQueueSynchronously, isReceive); + ParaNdis_DebugHistory(pContext, hopDPC, (PVOID)5, nRestartResult, 0, 0); + NdisReleaseSpinLock(&pContext->ReceiveLock); + } DPrintf(1, ("[%s] Skip Rx processing no.%d", __FUNCTION__, rxActive)); + break; } - } + } while (nRestartResult); + if (nRestartResult) stillRequiresProcessing |= isReceive; } @@ -1878,6 +1890,24 @@ static BOOLEAN CheckRunningDpc(PARANDIS_ADAPTER *pContext) // todo - collect more and put out optionally PrintStatistics(pContext); } + + if (pContext->Statistics.ifHCInOctets == pContext->Counters.prevIn) + { + pContext->Counters.nRxInactivity++; + if (pContext->Counters.nRxInactivity >= 10) + { +//#define CRASH_ON_NO_RX +#if defined(CRASH_ON_NO_RX) + ONPAUSECOMPLETEPROC proc = (ONPAUSECOMPLETEPROC)(PVOID)1; + proc(pContext); +#endif + } + } + else + { + pContext->Counters.nRxInactivity = 0; + pContext->Counters.prevIn = pContext->Statistics.ifHCInOctets; + } return bReportHang; } @@ -2033,6 +2063,7 @@ VOID ParaNdis_VirtIOEnableIrqSynchronized(PARANDIS_ADAPTER *pContext, ULONG inte pContext->NetSendQueue->vq_ops->enable_interrupt(pContext->NetSendQueue, b); if (interruptSource & isReceive) pContext->NetReceiveQueue->vq_ops->enable_interrupt(pContext->NetReceiveQueue, b); + ParaNdis_DebugHistory(pContext, hopDPC, (PVOID)0x10, interruptSource, b, 0); } /********************************************************** diff --git a/NetKVM/Common/kdebugprint.h b/NetKVM/Common/kdebugprint.h index c693664..cd89480 100644 --- a/NetKVM/Common/kdebugprint.h +++ b/NetKVM/Common/kdebugprint.h @@ -39,13 +39,7 @@ void _LogOutString(int level, const char *s); #define WPP_INIT_TRACING(a,b) #define WPP_CLEANUP(a) -#define DPrintf(Level, Fmt) \ -{ \ - if (bDebugPrint && (Level) <= nDebugLevel) \ - { \ - pDebugPrint Fmt; \ - } \ -} +#define DPrintf(Level, Fmt) { if ((Level) > nDebugLevel || ! bDebugPrint ) {} else { pDebugPrint Fmt; } } #define DPrintfBypass(Level, Fmt) DPrintf(Level, Fmt) diff --git a/NetKVM/Common/ndis56common.h b/NetKVM/Common/ndis56common.h index 3f53758..f80c287 100644 --- a/NetKVM/Common/ndis56common.h +++ b/NetKVM/Common/ndis56common.h @@ -229,6 +229,8 @@ typedef struct _tagOurCounters { UINT nReusedRxBuffers; UINT nPrintDiagnostic; + ULONG64 prevIn; + UINT nRxInactivity; }tOurCounters; typedef struct _tagMaxPacketSize -- 1.7.0.2.msysgit.0 -- To unsubscribe from this list: send the line "unsubscribe kvm-commits" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html