>From 1ca53f5b0576dcb0b5281bb673fcdf11f5c3a29e Mon Sep 17 00:00:00 2001
From: Vadim Rozenfeld <vroze...@redhat.com>
Date: Mon, 16 May 2011 21:00:20 +0300
Subject: [COMMIT] [NetKvm] From: Yan Vugenfirer <yvuge...@redhat.com>

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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to