repository: C:/dev/kvm-guest-drivers-windows
branch: master
commit 738df9db5cec3199894839c265f72cfd72974d57
Author: Yan Vugenfirer <[email protected]>
Date: Tue Apr 27 16:57:36 2010 +0300
[WIN-GUEST-DRIVERS] Add complete support for MSI interrupts
Signed-off-by: Yan Vugenfirer [email protected]
diff --git a/NetKVM/Common/ParaNdis-Common.c b/NetKVM/Common/ParaNdis-Common.c
index 35ec8e3..3c64cb0 100644
--- a/NetKVM/Common/ParaNdis-Common.c
+++ b/NetKVM/Common/ParaNdis-Common.c
@@ -916,8 +916,6 @@ NDIS_STATUS ParaNdis_FinishInitialization(PARANDIS_ADAPTER
*pContext)
#if !defined(UNIFY_LOCKS)
NdisAllocateSpinLock(&pContext->ReceiveLock);
#endif
- NdisAllocateSpinLock(&pContext->DPCLock);
-
InitializeListHead(&pContext->NetReceiveBuffers);
InitializeListHead(&pContext->NetReceiveBuffersWaiting);
@@ -926,20 +924,6 @@ NDIS_STATUS ParaNdis_FinishInitialization(PARANDIS_ADAPTER
*pContext)
status = ParaNdis_FinishSpecificInitialization(pContext);
- if (pContext->bBatchReceive && status == NDIS_STATUS_SUCCESS)
- {
- // prepare the buffer for batch data indication
- // just to be on the safe side - double the number,
pContext->NetMaxReceiveBuffers is enough
- pContext->maxPacketsInBatch = pContext->NetMaxReceiveBuffers *
2;
- pContext->pBatchOfPackets =
- ParaNdis_AllocateMemory(pContext,
sizeof(tPacketIndicationType) * pContext->maxPacketsInBatch);
- if (!pContext->pBatchOfPackets)
- {
- pContext->maxPacketsInBatch = 0;
- status = NDIS_STATUS_RESOURCES;
- }
- }
-
if (status == NDIS_STATUS_SUCCESS)
{
status = ParaNdis_VirtIONetInit(pContext);
@@ -1028,6 +1012,22 @@ static void VirtIONetRelease(PARANDIS_ADAPTER *pContext)
}
+static void PreventDPCServicing(PARANDIS_ADAPTER *pContext)
+{
+ LONG inside;;
+ pContext->bEnableInterruptHandlingDPC = FALSE;
+ do
+ {
+ inside = InterlockedIncrement(&pContext->counterDPCInside);
+ InterlockedDecrement(&pContext->counterDPCInside);
+ if (inside > 1)
+ {
+ DPrintf(0, ("[%s] waiting!", __FUNCTION__));
+ NdisMSleep(20000);
+ }
+ } while (inside > 1);
+}
+
/**********************************************************
Frees all the resources allocated when the context initialized,
calling also version-dependent part
@@ -1048,9 +1048,7 @@ VOID ParaNdis_CleanupContext(PARANDIS_ADAPTER *pContext)
//DPrintf(0, ("cleanup %d", nActive));
}
- NdisAcquireSpinLock(&pContext->DPCLock);
- pContext->bEnableInterruptHandlingDPC = FALSE;
- NdisReleaseSpinLock(&pContext->DPCLock);
+ PreventDPCServicing(pContext);
/****************************************
ensure all the incoming packets returned,
@@ -1065,11 +1063,6 @@ VOID ParaNdis_CleanupContext(PARANDIS_ADAPTER *pContext)
}
VirtIONetRelease(pContext);
- if (pContext->pBatchOfPackets)
- {
- NdisFreeMemory(pContext->pBatchOfPackets, 0, 0);
- }
-
ParaNdis_FinalizeCleanup(pContext);
if (pContext->SendLock.SpinLock)
@@ -1083,10 +1076,6 @@ VOID ParaNdis_CleanupContext(PARANDIS_ADAPTER *pContext)
NdisFreeSpinLock(&pContext->ReceiveLock);
}
#endif
- if (pContext->DPCLock.SpinLock)
- {
- NdisFreeSpinLock(&pContext->DPCLock);
- }
if (pContext->AdapterResources.ulIOAddress)
{
@@ -1095,7 +1084,7 @@ VOID ParaNdis_CleanupContext(PARANDIS_ADAPTER *pContext)
pContext->AdapterResources.ulIOAddress,
pContext->AdapterResources.IOLength,
pContext->pIoPortOffset);
-
+ pContext->AdapterResources.ulIOAddress = 0;
}
}
@@ -1115,32 +1104,48 @@ VOID ParaNdis_OnShutdown(PARANDIS_ADAPTER *pContext)
Handles hardware interrupt
Parameters:
context
- void *pDescriptor - pIONetDescriptor to return
+ ULONG knownInterruptSources - bitmask of
Return value:
TRUE, if it is our interrupt
sets *pRunDpc to TRUE if the DPC should be fired
***********************************************************/
BOOLEAN ParaNdis_OnInterrupt(
PARANDIS_ADAPTER *pContext,
- BOOLEAN *pRunDpc)
+ OUT BOOLEAN *pRunDpc,
+ ULONG knownInterruptSources)
{
ULONG status;
- BOOLEAN b;
- status = VirtIODeviceISR(&pContext->IODevice);
- // ignore interrupts with invalid status bits
- if (
- status == VIRTIO_NET_INVALID_INTERRUPT_STATUS ||
- pContext->powerState != NetDeviceStateD0
- )
- status = 0;
- InterlockedOr(&pContext->InterruptStatus, (LONG)status);
- b = !!status;
- *pRunDpc = b;
- if (b)
+ BOOLEAN b = FALSE;
+ if (knownInterruptSources == isAny)
+ {
+ status = VirtIODeviceISR(&pContext->IODevice);
+ // ignore interrupts with invalid status bits
+ if (
+ status == VIRTIO_NET_INVALID_INTERRUPT_STATUS ||
+ pContext->powerState != NetDeviceStateD0
+ )
+ status = 0;
+ if (status)
+ {
+ *pRunDpc = TRUE;
+ b = TRUE;
+
NdisGetCurrentSystemTime(&pContext->LastInterruptTimeStamp);
+ ParaNdis_VirtIOEnableIrqSynchronized(pContext, isAny,
FALSE);
+ status = (status & 2) ? isControl : 0;
+ status |= isReceive | isTransmit;
+ InterlockedOr(&pContext->InterruptStatus, (LONG)status);
+ }
+ }
+ else
{
+ b = TRUE;
+ *pRunDpc = TRUE;
NdisGetCurrentSystemTime(&pContext->LastInterruptTimeStamp);
- ParaNdis_VirtIOEnableInterrupt(pContext, FALSE);
+ InterlockedOr(&pContext->InterruptStatus,
(LONG)knownInterruptSources);
+ ParaNdis_VirtIOEnableIrqSynchronized(pContext,
knownInterruptSources, FALSE);
+ status = knownInterruptSources;
}
+ DPrintf(5, ("[%s](src%X)=>st%X", __FUNCTION__, knownInterruptSources,
status));
return b;
}
@@ -1244,11 +1249,16 @@ UINT ParaNdis_VirtIONetReleaseTransmitBuffers(
{
NdisGetCurrentSystemTime(&pContext->LastTxCompletionTimeStamp);
pContext->bDoKickOnNoBuffer = TRUE;
+ pContext->nDetectedStoppedTx = 0;
}
DEBUG_EXIT_STATUS((i ? 3 : 5), i);
return i;
}
+/*********************************************************
+Called with from ProcessTx routine with TxLock held
+Uses pContext->sgTxGatherTable
+***********************************************************/
tCopyPacketResult ParaNdis_DoSubmitPacket(PARANDIS_ADAPTER *pContext,
tTxOperationParameters *Params)
{
tCopyPacketResult result;
@@ -1604,6 +1614,10 @@ static UINT ParaNdis_ProcessRxPath(PARANDIS_ADAPTER
*pContext)
UINT len, headerSize = pContext->nVirtioHeaderSize;
eInspectedPacketType packetType = iptInvalid;
UINT nReceived = 0, nRetrieved = 0, nReported = 0;
+ tPacketIndicationType *pBatchOfPackets;
+ UINT maxPacketsInBatch =
pContext->NetMaxReceiveBuffers;
+ pBatchOfPackets = pContext->bBatchReceive ?
+ ParaNdis_AllocateMemory(pContext, maxPacketsInBatch *
sizeof(tPacketIndicationType)) : NULL;
NdisAcquireSpinLock(&pContext->ReceiveLock);
while ((uLoopCount++ < pContext->uRXPacketsDPCLimit) && NULL !=
(pBuffersDescriptor =
pContext->NetReceiveQueue->vq_ops->get_buf(pContext->NetReceiveQueue, &len)))
{
@@ -1622,7 +1636,7 @@ static UINT ParaNdis_ProcessRxPath(PARANDIS_ADAPTER
*pContext)
{
BOOLEAN b = FALSE;
ULONG length = len - headerSize;
- if (!pContext->pBatchOfPackets)
+ if (!pBatchOfPackets)
{
NdisReleaseSpinLock(&pContext->ReceiveLock);
b = NULL != ParaNdis_IndicateReceivedPacket(
@@ -1643,7 +1657,7 @@ static UINT ParaNdis_ProcessRxPath(PARANDIS_ADAPTER
*pContext)
TRUE,
pBuffersDescriptor);
b = packet != NULL;
- if (b) pContext->pBatchOfPackets[nReceived] =
packet;
+ if (b) pBatchOfPackets[nReceived] = packet;
}
if (!b)
{
@@ -1673,10 +1687,11 @@ static UINT ParaNdis_ProcessRxPath(PARANDIS_ADAPTER
*pContext)
pContext->Statistics.ifHCInUcastOctets += length;
break;
}
- if (pContext->pBatchOfPackets && nReceived ==
pContext->maxPacketsInBatch)
+ if (pBatchOfPackets && nReceived ==
maxPacketsInBatch)
{
+ DPrintf(1, ("[%s] received %d buffers",
__FUNCTION__, nReceived));
NdisReleaseSpinLock(&pContext->ReceiveLock);
-
ParaNdis_IndicateReceivedBatch(pContext, nReceived);
+
ParaNdis_IndicateReceivedBatch(pContext, pBatchOfPackets, nReceived);
NdisAcquireSpinLock(&pContext->ReceiveLock);
nReceived = 0;
}
@@ -1690,12 +1705,12 @@ static UINT ParaNdis_ProcessRxPath(PARANDIS_ADAPTER
*pContext)
}
ParaNdis_DebugHistory(pContext, hopReceiveStat, NULL, nRetrieved,
nReported, pContext->NetNofReceiveBuffers);
NdisReleaseSpinLock(&pContext->ReceiveLock);
- if (nReceived)
+ if (nReceived && pBatchOfPackets)
{
DPrintf(1, ("[%s] received %d buffers", __FUNCTION__,
nReceived));
- if (pContext->pBatchOfPackets)
- ParaNdis_IndicateReceivedBatch(pContext, nReceived);
+ ParaNdis_IndicateReceivedBatch(pContext, pBatchOfPackets,
nReceived);
}
+ if (pBatchOfPackets) NdisFreeMemory(pBatchOfPackets, 0, 0);
return nRetrieved;
}
@@ -1713,71 +1728,82 @@ void ParaNdis_ReportLinkStatus(PARANDIS_ADAPTER
*pContext)
ParaNdis_IndicateConnect(pContext, bConnected, FALSE);
}
-BOOLEAN ParaNdis_MiniportSynchronizeInterruptEnable(IN PVOID
SynchronizeContext)
-{
- PARANDIS_ADAPTER *pContext = (PARANDIS_ADAPTER *)SynchronizeContext;
-
- DEBUG_ENTRY(6);
- ParaNdis_VirtIOEnableInterrupt(pContext, TRUE);
- return TRUE;
+static BOOLEAN RestartQueueSynchronously(tSynchronizedContext *SyncContext)
+{
+ PARANDIS_ADAPTER *pContext = SyncContext->pContext;
+ BOOLEAN b = 0;
+ if (SyncContext->Parameter & isReceive)
+ {
+ b =
!pContext->NetReceiveQueue->vq_ops->restart(pContext->NetReceiveQueue);
+ }
+ if (SyncContext->Parameter & isTransmit)
+ {
+ b =
!pContext->NetSendQueue->vq_ops->restart(pContext->NetSendQueue);
+ }
+ return b;
}
-
/**********************************************************
DPC implementation, common for both NDIS
Parameters:
context
***********************************************************/
-void ParaNdis_DPCWorkBody(PARANDIS_ADAPTER *pContext)
+ULONG ParaNdis_DPCWorkBody(PARANDIS_ADAPTER *pContext)
{
- int nRestartResult = 2, nLoop = 0;
- LONG interruptStatus;
+ ULONG stillRequiresProcessing = 0;
+ ULONG interruptSources;
DEBUG_ENTRY(5);
- NdisAcquireSpinLock(&pContext->DPCLock);
- ParaNdis_DebugHistory(pContext, hopDPC, NULL, 1,
pContext->InterruptStatus, 0);
- if (pContext->bEnableInterruptHandlingDPC)
- {
- pContext->bDPCInactive = FALSE;
- interruptStatus =
InterlockedExchange(&pContext->InterruptStatus, 0);
-#ifdef VIRTIO_SIGNAL_ERROR
- if (interruptStatus & 4)
- {
- DPrintf(0, ("[%s] ERROR signaled by hardware!!!!!",
__FUNCTION__));
- }
-#endif
- if (interruptStatus & 2)
- {
- if (pContext->bLinkDetectSupported)
ParaNdis_ReportLinkStatus(pContext);
- }
- ParaNdis_ProcessTx(pContext, TRUE);
- while (nRestartResult)
+ ParaNdis_DebugHistory(pContext, hopDPC, (PVOID)1, 0, 0, 0);
+ if (pContext->bEnableInterruptHandlingDPC)
+ {
+ InterlockedIncrement(&pContext->counterDPCInside);
+ if (pContext->bEnableInterruptHandlingDPC)
{
- UINT n = ParaNdis_ProcessRxPath(pContext);
- if (nRestartResult == 1 && !n)
+ InterlockedExchange(&pContext->bDPCInactive, 0);
+ interruptSources =
InterlockedExchange(&pContext->InterruptStatus, 0);
+ if ((interruptSources & isControl) &&
pContext->bLinkDetectSupported)
+ {
+ ParaNdis_ReportLinkStatus(pContext);
+ }
+ if (interruptSources & isTransmit)
{
- DPrintf(0, ("[%s] Rx restarted by mistake",
__FUNCTION__));
+ ParaNdis_ProcessTx(pContext, TRUE);
}
- NdisAcquireSpinLock(&pContext->ReceiveLock);
- nRestartResult =
!pContext->NetReceiveQueue->vq_ops->restart(pContext->NetReceiveQueue);
- NdisReleaseSpinLock(&pContext->ReceiveLock);
- DPrintf(nRestartResult ? 2 : 6, ("[%s] queue
restarted%s", __FUNCTION__, nRestartResult ? "(Rerun)" : ""));
- ++nLoop;
- if (nRestartResult && pContext->InterruptStatus)
+ if (interruptSources & isReceive)
{
- DPrintf(2, ("[%s] another dpc already
scheduled(%d)", __FUNCTION__, nLoop));
- break;
+ int nRestartResult = 2, nLoop = 0;
+ while (nRestartResult)
+ {
+ UINT n =
ParaNdis_ProcessRxPath(pContext);
+
+
NdisAcquireSpinLock(&pContext->ReceiveLock);
+ nRestartResult =
ParaNdis_SynchronizeWithInterrupt(
+ pContext,
pContext->ulRxMessage, RestartQueueSynchronously, isReceive);
+
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));
+ break;
+ }
+ }
+ if (nRestartResult) stillRequiresProcessing |=
isReceive;
}
- if (nLoop == 1000)
+
+ if (interruptSources & isTransmit)
{
- DPrintf(0, ("[%s] Too many (%d) Rx restarts,
prevent infinite loop", __FUNCTION__, nLoop));
- break;
+ NdisAcquireSpinLock(&pContext->SendLock);
+ if (ParaNdis_SynchronizeWithInterrupt(pContext,
pContext->ulTxMessage, RestartQueueSynchronously, isTransmit))
+ stillRequiresProcessing |= isTransmit;
+ NdisReleaseSpinLock(&pContext->SendLock);
}
}
+ InterlockedDecrement(&pContext->counterDPCInside);
+ ParaNdis_DebugHistory(pContext, hopDPC, NULL,
stillRequiresProcessing, pContext->nofFreeHardwareBuffers,
pContext->nofFreeTxDescriptors);
}
- ParaNdis_DebugHistory(pContext, hopDPC, NULL, 0,
pContext->nofFreeHardwareBuffers, pContext->nofFreeTxDescriptors);
- NdisReleaseSpinLock(&pContext->DPCLock);
-
- ParaNdis_SyncInterruptEnable(pContext);
+ return stillRequiresProcessing;
}
/**********************************************************
@@ -1790,47 +1816,31 @@ static BOOLEAN CheckRunningDpc(PARANDIS_ADAPTER
*pContext)
{
BOOLEAN bStopped;
BOOLEAN bReportHang = FALSE;
- NdisAcquireSpinLock(&pContext->DPCLock);
- bStopped = pContext->bDPCInactive;
- pContext->bDPCInactive = TRUE;
- NdisReleaseSpinLock(&pContext->DPCLock);
+ bStopped = 0 != InterlockedExchange(&pContext->bDPCInactive, TRUE);
if (bStopped)
{
pContext->nDetectedInactivity++;
if (pContext->nEnableDPCChecker)
{
- DPrintf(0, ("[%s] - NO ACTIVITY!", __FUNCTION__));
- if (!pContext->Limits.nPrintDiagnostic)
PrintStatistics(pContext);
- if (pContext->nEnableDPCChecker > 1)
+ if (pContext->NetTxPacketsToReturn)
{
- int isrStatus1, isrStatus2;
- isrStatus1 =
VirtIODeviceISR(&pContext->IODevice);
- isrStatus2 =
VirtIODeviceISR(&pContext->IODevice);
- if (isrStatus1 || isrStatus2)
+ DPrintf(0, ("[%s] - NO ACTIVITY!",
__FUNCTION__));
+ if (!pContext->Limits.nPrintDiagnostic)
PrintStatistics(pContext);
+ if (pContext->nEnableDPCChecker > 1)
{
- DPrintf(0, ("WARNING: Interrupt status
%d=>%d", isrStatus1, isrStatus2));
+ int isrStatus1, isrStatus2;
+ isrStatus1 =
VirtIODeviceISR(&pContext->IODevice);
+ isrStatus2 =
VirtIODeviceISR(&pContext->IODevice);
+ if (isrStatus1 || isrStatus2)
+ {
+ DPrintf(0, ("WARNING: Interrupt
status %d=>%d", isrStatus1, isrStatus2));
+ }
}
+ // simulateDPC
+ InterlockedOr(&pContext->InterruptStatus,
isAny);
+ ParaNdis_DPCWorkBody(pContext);
}
- // simulateDPC
- ParaNdis_DPCWorkBody(pContext);
- }
- else
- {
- // this works only without scatter-gather...
- // TODO: provide some kind of detection also for SG case
- NdisAcquireSpinLock(&pContext->SendLock);
- if (pContext->NetTxPacketsToReturn &&
!pContext->nofFreeTxDescriptors)
- {
- DPrintf(0, ("[%s] - Tx path does not transfer
data!", __FUNCTION__));
- bReportHang = TRUE;
- pContext->nDetectedStoppedTx++;
- // TODO: remove it when the problem solved
- // just to be able to make breakpoint or dump
in QEMU
- // when such a problem happens
- WriteVirtIODeviceByte(pContext->IODevice.addr +
VIRTIO_PCI_ISR, 1);
- }
- NdisReleaseSpinLock(&pContext->SendLock);
}
}
else
@@ -1838,6 +1848,18 @@ static BOOLEAN CheckRunningDpc(PARANDIS_ADAPTER
*pContext)
pContext->nDetectedInactivity = 0;
}
+ NdisAcquireSpinLock(&pContext->SendLock);
+ if (pContext->nofFreeHardwareBuffers !=
pContext->maxFreeHardwareBuffers)
+ {
+ if (pContext->nDetectedStoppedTx++ > 1)
+ {
+ DPrintf(0, ("[%s] - Suspicious Tx inactivity (%d)!",
__FUNCTION__, pContext->nofFreeHardwareBuffers));
+ //bReportHang = TRUE;
+ WriteVirtIODeviceByte(pContext->IODevice.addr +
VIRTIO_PCI_ISR, 0);
+ }
+ }
+ NdisReleaseSpinLock(&pContext->SendLock);
+
if (pContext->Limits.nPrintDiagnostic &&
++pContext->Counters.nPrintDiagnostic >=
pContext->Limits.nPrintDiagnostic)
@@ -1881,13 +1903,13 @@ u32 ReadVirtIODeviceRegister(ULONG_PTR ulRegister)
NdisRawReadPortUlong(ulRegister, &ulValue);
- DPrintf(6, ("%s> R[%x] = %x\n", __FUNCTION__, (ULONG)ulRegister,
ulValue) );
+ DPrintf(6, ("[%s]R[%x]=%x", __FUNCTION__, (ULONG)ulRegister, ulValue) );
return ulValue;
}
void WriteVirtIODeviceRegister(ULONG_PTR ulRegister, u32 ulValue)
{
- DPrintf(6, ("%s> R[%x] = %x\n", __FUNCTION__, (ULONG)ulRegister,
ulValue) );
+ DPrintf(6, ("[%s]R[%x]=%x", __FUNCTION__, (ULONG)ulRegister, ulValue) );
NdisRawWritePortUlong(ulRegister, ulValue);
}
@@ -1898,14 +1920,14 @@ u8 ReadVirtIODeviceByte(ULONG_PTR ulRegister)
NdisRawReadPortUchar(ulRegister, &bValue);
- DPrintf(6, ("%s> R[%x] = %x\n", __FUNCTION__, (ULONG)ulRegister,
bValue) );
+ DPrintf(6, ("[%s]R[%x]=%x", __FUNCTION__, (ULONG)ulRegister, bValue) );
return bValue;
}
void WriteVirtIODeviceByte(ULONG_PTR ulRegister, u8 bValue)
{
- DPrintf(6, ("%s> R[%x] = %x\n", __FUNCTION__, (ULONG)ulRegister,
bValue) );
+ DPrintf(6, ("[%s]R[%x]=%x", __FUNCTION__, (ULONG)ulRegister, bValue) );
NdisRawWritePortUchar(ulRegister, bValue);
}
@@ -1916,7 +1938,7 @@ u16 ReadVirtIODeviceWord(ULONG_PTR ulRegister)
NdisRawReadPortUshort(ulRegister, &wValue);
- DPrintf(6, ("%s> R[%x] = %x\n", __FUNCTION__, (ULONG)ulRegister,
wValue) );
+ DPrintf(6, ("[%s]R[%x]=%x\n", __FUNCTION__, (ULONG)ulRegister, wValue)
);
return wValue;
}
@@ -1980,7 +2002,7 @@ NDIS_STATUS ParaNdis_SetMulticastList(
if (length)
NdisMoveMemory(pContext->MulticastList, Buffer, length);
pContext->MulticastListSize = length;
- DPrintf(0, ("[%s] New multicast list of %d bytes",
__FUNCTION__, length));
+ DPrintf(1, ("[%s] New multicast list of %d bytes",
__FUNCTION__, length));
*pBytesRead = length;
status = NDIS_STATUS_SUCCESS;
}
@@ -1988,16 +2010,19 @@ NDIS_STATUS ParaNdis_SetMulticastList(
}
/**********************************************************
-
+Callable from synchronized routine or interrupt handler
+to enable or disable Rx and/or Tx interrupt generation
Parameters:
-Return value:
+ context
+ interruptSource - isReceive, isTransmit
+ b - 1/0 enable/disable
***********************************************************/
-VOID ParaNdis_VirtIOEnableInterrupt(
- PARANDIS_ADAPTER *pContext,
- BOOLEAN bEnable)
+VOID ParaNdis_VirtIOEnableIrqSynchronized(PARANDIS_ADAPTER *pContext, ULONG
interruptSource, BOOLEAN b)
{
-
pContext->NetSendQueue->vq_ops->enable_interrupt(pContext->NetSendQueue,
bEnable);
-
pContext->NetReceiveQueue->vq_ops->enable_interrupt(pContext->NetReceiveQueue,
bEnable);
+ if (interruptSource & isTransmit)
+
pContext->NetSendQueue->vq_ops->enable_interrupt(pContext->NetSendQueue, b);
+ if (interruptSource & isReceive)
+
pContext->NetReceiveQueue->vq_ops->enable_interrupt(pContext->NetReceiveQueue,
b);
}
/**********************************************************
@@ -2060,6 +2085,7 @@ VOID ParaNdis_PowerOn(PARANDIS_ADAPTER *pContext)
VirtIODeviceRenewVirtualQueue(pContext->NetReceiveQueue);
VirtIODeviceRenewVirtualQueue(pContext->NetSendQueue);
+ ParaNdis_RestoreDeviceConfigurationAfterReset(pContext);
InitializeListHead(&TempList);
/* submit all the receive buffers */
@@ -2109,9 +2135,7 @@ VOID ParaNdis_PowerOff(PARANDIS_ADAPTER *pContext)
ParaNdis_Suspend(pContext);
pContext->powerState = NetDeviceStateD3;
- NdisAcquireSpinLock(&pContext->DPCLock);
- pContext->bEnableInterruptHandlingDPC = FALSE;
- NdisReleaseSpinLock(&pContext->DPCLock);
+ PreventDPCServicing(pContext);
/*******************************************************************
shutdown queues to have all the receive buffers under our
control
@@ -2143,5 +2167,12 @@ VOID ParaNdis_PowerOff(PARANDIS_ADAPTER *pContext)
ParaNdis_DebugHistory(pContext, hopPowerOff, NULL, 0, 0, 0);
}
+void ParaNdis_CallOnBugCheck(PARANDIS_ADAPTER *pContext)
+{
+ if (pContext->AdapterResources.ulIOAddress)
+ {
+ WriteVirtIODeviceByte(pContext->IODevice.addr + VIRTIO_PCI_ISR,
1);
+ }
+}
diff --git a/NetKVM/Common/ParaNdis-Debug.c b/NetKVM/Common/ParaNdis-Debug.c
index 86b9cae..ad3d56c 100644
--- a/NetKVM/Common/ParaNdis-Debug.c
+++ b/NetKVM/Common/ParaNdis-Debug.c
@@ -272,6 +272,7 @@ static UINT FillDataOnBugCheck()
pSave->nofReadyTxBuffers = p->nofFreeHardwareBuffers;
pSave->LastInterruptTimeStamp = p->LastInterruptTimeStamp;
pSave->LastTxCompletionTimeStamp = p->LastTxCompletionTimeStamp;
+ ParaNdis_CallOnBugCheck(p);
++n;
}
return n;
diff --git a/NetKVM/Common/ndis56common.h b/NetKVM/Common/ndis56common.h
index 3fd23a8..d8a25af 100644
--- a/NetKVM/Common/ndis56common.h
+++ b/NetKVM/Common/ndis56common.h
@@ -54,9 +54,6 @@
#error "Something is wrong with our versioning"
#endif
-//define to start really using MSI-X interrupt in Vista+
-//#define VIRTIO_USE_MSIX_INTERRUPT
-
//define to see when the status register is unreadable(see
ParaNdis_ResetVirtIONetDevice)
//#define VIRTIO_RESET_VERIFY
@@ -65,8 +62,10 @@
// define if qemu supports logging to static IO port for synchronization
// of driver output with qemu printouts; in this case define the port number
-//#define VIRTIO_DBG_USE_IOPORT 0x99
+// #define VIRTIO_DBG_USE_IOPORT 0x99
+// to be set to real limit later
+#define MAX_RX_LOOPS 1000
/* The feature bitmap for virtio net */
#define VIRTIO_NET_F_CSUM 0 /* Host handles pkts w/ partial csum */
@@ -96,6 +95,17 @@
#define PARANDIS_MIN_LSO_SEGMENTS 2
#define PARANDIS_MAX_LSO_SIZE 0xF000
+typedef enum _tagInterruptSource
+{
+ isReceive = 0x01,
+ isTransmit = 0x02,
+ isControl = 0x04,
+ isUnknown = 0x08,
+ isBothTransmitReceive = isReceive | isTransmit,
+ isAny = isReceive | isTransmit | isControl | isUnknown,
+ isDisable = 0x80
+}tInterruptSource;
+
static const ULONG PARANDIS_PACKET_FILTERS =
NDIS_PACKET_TYPE_DIRECTED |
NDIS_PACKET_TYPE_MULTICAST |
@@ -242,7 +252,6 @@ typedef struct _tagPARANDIS_ADAPTER
LARGE_INTEGER LastTxCompletionTimeStamp;
LARGE_INTEGER LastInterruptTimeStamp;
BOOLEAN bConnected;
- BOOLEAN bDPCInactive;
BOOLEAN bEnableInterruptHandlingDPC;
BOOLEAN bEnableInterruptChecking;
BOOLEAN bDoInterruptRecovery;
@@ -260,6 +269,8 @@ typedef struct _tagPARANDIS_ADAPTER
BOOLEAN bSurprizeRemoved;
BOOLEAN bUsingMSIX;
NDIS_DEVICE_POWER_STATE powerState;
+ LONG counterDPCInside;
+ LONG bDPCInactive;
LONG InterruptStatus;
ULONG ulPriorityVlanSetting;
ULONG VlanId;
@@ -289,7 +300,6 @@ typedef struct _tagPARANDIS_ADAPTER
NDIS_SPIN_LOCK ReceiveLock;
};
#endif
- NDIS_SPIN_LOCK DPCLock;
NDIS_STATISTICS_INFO Statistics;
tOurCounters Counters;
tOurCounters Limits;
@@ -324,13 +334,17 @@ typedef struct _tagPARANDIS_ADAPTER
LONG NetTxPacketsToReturn;
/* total of Rx buffer in turnaround */
UINT NetMaxReceiveBuffers;
- tPacketIndicationType *pBatchOfPackets;
- UINT maxPacketsInBatch;
struct VirtIOBufferDescriptor *sgTxGatherTable;
UINT nPnpEventIndex;
NDIS_DEVICE_PNP_EVENT PnpEvents[16];
tOffloadSettings Offload;
NDIS_OFFLOAD_PARAMETERS InitialOffloadParameters;
+ // we keep these members common for XP and Vista
+ // for XP and non-MSI case of Vista they are set to zero
+ ULONG ulRxMessage;
+ ULONG ulTxMessage;
+ ULONG ulControlMessage;
+
#if NDIS60_MINIPORT
// Vista +
PIO_INTERRUPT_MESSAGE_INFO pMSIXInfoTable;
@@ -354,6 +368,7 @@ typedef struct _tagPARANDIS_ADAPTER
LIST_ENTRY TxWaitingList;
NDIS_EVENT HaltEvent;
NDIS_TIMER ConnectTimer;
+ NDIS_TIMER DPCPostProcessTimer;
BOOLEAN bDmaInitialized;
#endif
}PARANDIS_ADAPTER, *PPARANDIS_ADAPTER;
@@ -365,6 +380,13 @@ typedef struct _tagCopyPacketResult
enum tCopyPacketError { cpeOK, cpeNoBuffer, cpeInternalError,
cpeTooLarge } error;
}tCopyPacketResult;
+typedef struct _tagSynchronizedContext
+{
+ PARANDIS_ADAPTER *pContext;
+ ULONG Parameter;
+}tSynchronizedContext;
+
+typedef BOOLEAN (*tSynchronizedProcedure)(tSynchronizedContext *context);
/**********************************************************
LAZZY release procedure returns buffers to VirtIO
@@ -430,13 +452,7 @@ void ParaNdis_VirtIONetReuseRecvBuffer(
UINT ParaNdis_VirtIONetReleaseTransmitBuffers(
PARANDIS_ADAPTER *pContext);
-void ParaNdis_DPCWorkBody(
- PARANDIS_ADAPTER *pContext);
-
-BOOLEAN ParaNdis_MiniportSynchronizeInterruptEnable(
- IN PVOID SynchronizeContext);
-
-void ParaNdis_SyncInterruptEnable(
+ULONG ParaNdis_DPCWorkBody(
PARANDIS_ADAPTER *pContext);
NDIS_STATUS ParaNdis_SetMulticastList(
@@ -446,9 +462,10 @@ NDIS_STATUS ParaNdis_SetMulticastList(
PUINT pBytesRead,
PUINT pBytesNeeded);
-VOID ParaNdis_VirtIOEnableInterrupt(
+VOID ParaNdis_VirtIOEnableIrqSynchronized(
PARANDIS_ADAPTER *pContext,
- BOOLEAN bEnable);
+ ULONG interruptSource,
+ BOOLEAN b);
VOID ParaNdis_OnPnPEvent(
PARANDIS_ADAPTER *pContext,
@@ -458,7 +475,8 @@ VOID ParaNdis_OnPnPEvent(
BOOLEAN ParaNdis_OnInterrupt(
PARANDIS_ADAPTER *pContext,
- BOOLEAN *pRunDpc);
+ BOOLEAN *pRunDpc,
+ ULONG knownInterruptSources);
VOID ParaNdis_OnShutdown(
PARANDIS_ADAPTER *pContext);
@@ -532,6 +550,8 @@ tCopyPacketResult ParaNdis_DoSubmitPacket(PARANDIS_ADAPTER
*pContext, tTxOperati
void ParaNdis_ResetOffloadSettings(PARANDIS_ADAPTER *pContext,
tOffloadSettingsFlags *pDest, PULONG from);
+void ParaNdis_CallOnBugCheck(PARANDIS_ADAPTER *pContext);
+
/*****************************************************
Procedures to implement for NDIS specific implementation
******************************************************/
@@ -558,6 +578,7 @@ tPacketIndicationType ParaNdis_IndicateReceivedPacket(
VOID ParaNdis_IndicateReceivedBatch(
PARANDIS_ADAPTER *pContext,
+ tPacketIndicationType *pBatch,
ULONG nofPackets);
@@ -584,6 +605,12 @@ BOOLEAN ParaNdis_SetTimer(
NDIS_HANDLE timer,
LONG millies);
+BOOLEAN ParaNdis_SynchronizeWithInterrupt(
+ PARANDIS_ADAPTER *pContext,
+ ULONG messageId,
+ tSynchronizedProcedure procedure,
+ ULONG parameter);
+
VOID ParaNdis_Suspend(
PARANDIS_ADAPTER *pContext);
@@ -635,6 +662,9 @@ void ParaNdis_IndicateConnect(
BOOLEAN bConnected,
BOOLEAN bForce);
+void ParaNdis_RestoreDeviceConfigurationAfterReset(
+ PARANDIS_ADAPTER *pContext);
+
#endif //-OFFLOAD_UNIT_TEST
typedef enum _tagppResult
diff --git a/NetKVM/wlh/ParaNdis6-Driver.c b/NetKVM/wlh/ParaNdis6-Driver.c
index 1ceaef6..9e7a06a 100644
--- a/NetKVM/wlh/ParaNdis6-Driver.c
+++ b/NetKVM/wlh/ParaNdis6-Driver.c
@@ -16,6 +16,11 @@
//#define NO_VISTA_POWER_MANAGEMENT
+//by default printouts from resource filtering are invisible
+//change it to 2 or smaller to make it visible always
+ULONG bDisableMSI = FALSE;
+LONG resourceFilterLevel = 3;
+
#ifdef WPP_EVENT_TRACING
#include "ParaNdis6-Driver.tmh"
#endif
@@ -141,66 +146,18 @@ static VOID ConnectTimerCallback(
ParaNdis_ReportLinkStatus(pContext);
}
-#define VISTA_RECOVERY_CANCEL_TIMER
1
-#define VISTA_RECOVERY_RUN_DPC
2
-#define VISTA_RECOVERY_INFO_ONLY_SECOND_READ 4
-
-
-static UCHAR MiniportSynchronizeInterruptProcedure(PVOID SynchronizeContext)
-{
- PARANDIS_ADAPTER *pContext = (PARANDIS_ADAPTER *)SynchronizeContext;
- BOOLEAN b1;
- UCHAR val = ParaNdis_OnInterrupt(pContext, &b1);
- if (val)
- {
- // we read the interrupt, in any case run the DRC
- val = VISTA_RECOVERY_RUN_DPC;
- b1 = !VirtIODeviceISR(&pContext->IODevice);
- // if we read it again, it does not mean anything
- if (b1) val |= VISTA_RECOVERY_INFO_ONLY_SECOND_READ;
- }
- else
- {
- // we did not read the interrupt
- val = (pContext->ulIrqReceived > 1) ?
VISTA_RECOVERY_CANCEL_TIMER : 0;
- }
- return val;
-}
-
-
-
/**********************************************************
This is timer procedure for Interrupt recovery timer
***********************************************************/
-static VOID InteruptRecoveryTimerCallback(
+static VOID InterruptRecoveryTimerCallback(
IN PVOID SystemSpecific1,
IN PVOID FunctionContext,
IN PVOID SystemSpecific2,
IN PVOID SystemSpecific3
)
{
- UCHAR val;
PARANDIS_ADAPTER *pContext = (PARANDIS_ADAPTER *)FunctionContext;
- val = NdisMSynchronizeWithInterruptEx(
- pContext->InterruptHandle,
- 0,
- MiniportSynchronizeInterruptProcedure,
- pContext);
- if (val & VISTA_RECOVERY_RUN_DPC)
- ParaNdis_DPCWorkBody(pContext);
- /* this does not happen and as such, not related to the problem
- if (val == VISTA_RECOVERY_RUN_DPC)
- {
- DPrintf(0, ("[%s] The interrupt was still set", __FUNCTION__));
- }
- */
- if (~val & VISTA_RECOVERY_CANCEL_TIMER)
- ParaNdis_SetTimer(pContext->InterruptRecoveryTimer, 15);
- else
- {
- DPrintf(0, ("[%s] Cancelled", __FUNCTION__));
- }
- DEBUG_EXIT_STATUS(5, val);
+ ParaNdis6_OnInterruptRecoveryTimer(pContext);
}
@@ -223,7 +180,7 @@ static NDIS_STATUS CreateTimers(PARANDIS_ADAPTER *pContext)
status = NdisAllocateTimerObject(pContext->MiniportHandle, &tch,
&pContext->ConnectTimer);
if (status == NDIS_STATUS_SUCCESS)
{
- tch.TimerFunction = InteruptRecoveryTimerCallback;
+ tch.TimerFunction = InterruptRecoveryTimerCallback;
status = NdisAllocateTimerObject(pContext->MiniportHandle,
&tch, &pContext->InterruptRecoveryTimer);
}
DEBUG_EXIT_STATUS(2, status);
@@ -413,7 +370,10 @@ static NDIS_STATUS ParaNdis6_Initialize(
if (pContext->ulMilliesToConnect)
ParaNdis_SetTimer(pContext->ConnectTimer,
pContext->ulMilliesToConnect);
if (pContext->bDoInterruptRecovery)
- ParaNdis_SetTimer(pContext->InterruptRecoveryTimer,
15); //15 mSec is the recovery timeout
+ {
+ //200 mSec for first shot of recovery circuit
+ ParaNdis_SetTimer(pContext->InterruptRecoveryTimer,
200);
+ }
}
DEBUG_EXIT_STATUS(status ? 0 : 2, status);
return status;
@@ -834,8 +794,9 @@ static PIO_RESOURCE_REQUIREMENTS_LIST
ParseFilterResourceIrp(
BOOLEAN bRemoveMSIResources)
{
tRRLData newRRLData;
+ ULONG nRemoved = 0;
PIO_RESOURCE_REQUIREMENTS_LIST newPrrl = NULL;
- DPrintf(0, ("[%s]%s", __FUNCTION__, bRemoveMSIResources ? "(Remove MSI
resources...)" : ""));
+ DPrintf(resourceFilterLevel, ("[%s]%s", __FUNCTION__,
bRemoveMSIResources ? "(Remove MSI resources...)" : ""));
if (MiniportAddDeviceContext && prrl) newPrrl =
(PIO_RESOURCE_REQUIREMENTS_LIST)NdisAllocateMemoryWithTagPriority(
MiniportAddDeviceContext,
prrl->ListSize,
@@ -846,7 +807,7 @@ static PIO_RESOURCE_REQUIREMENTS_LIST
ParseFilterResourceIrp(
{
ULONG n, offset;
PVOID p = &prrl->List[0];
- DPrintf(0, ("[%s] %d bytes, %d lists", __FUNCTION__,
prrl->ListSize, prrl->AlternativeLists));
+ DPrintf(resourceFilterLevel, ("[%s] %d bytes, %d lists",
__FUNCTION__, prrl->ListSize, prrl->AlternativeLists));
offset = RtlPointerToOffset(prrl, p);
for (n = 0; n < prrl->AlternativeLists && offset <
prrl->ListSize; ++n)
{
@@ -855,7 +816,7 @@ static PIO_RESOURCE_REQUIREMENTS_LIST
ParseFilterResourceIrp(
if ((offset + sizeof(*pior)) < prrl->ListSize)
{
IO_RESOURCE_DESCRIPTOR *pd =
&pior->Descriptors[0];
- DPrintf(0, ("[%s]+%d %d:%d descriptors follow",
__FUNCTION__, offset, n, pior->Count));
+ DPrintf(resourceFilterLevel, ("[%s]+%d %d:%d
descriptors follow", __FUNCTION__, offset, n, pior->Count));
offset += RtlPointerToOffset(p, pd);
AddNewResourceList(&newRRLData, pior);
for (nDesc = 0; nDesc < pior->Count; ++nDesc)
@@ -863,10 +824,11 @@ static PIO_RESOURCE_REQUIREMENTS_LIST
ParseFilterResourceIrp(
BOOLEAN bRemove = FALSE;
if ((offset + sizeof(*pd)) <=
prrl->ListSize)
{
- DPrintf(0, ("[%s]+%d %d: type
%d, flags %X, option %X",
- __FUNCTION__, offset,
nDesc, pd->Type, pd->Flags, pd->Option));
+ DPrintf(resourceFilterLevel,
("[%s]+%d %d: type %d, flags %X, option %X", __FUNCTION__, offset, nDesc,
pd->Type, pd->Flags, pd->Option));
if (pd->Type ==
CmResourceTypeInterrupt)
{
+
+ //DPrintf(1, ("
policy %d, affinity %X", pd->u.Interrupt.AffinityPolicy,
pd->u.Interrupt.TargetedProcessors));
if (pd->Flags &
CM_RESOURCE_INTERRUPT_MESSAGE)
{
bRemove =
bRemoveMSIResources;
@@ -882,6 +844,7 @@ static PIO_RESOURCE_REQUIREMENTS_LIST
ParseFilterResourceIrp(
}
}
if (!bRemove)
AddNewResourceDescriptor(&newRRLData, pd);
+ else nRemoved++;
}
offset += sizeof(*pd);
pd = (IO_RESOURCE_DESCRIPTOR
*)RtlOffsetToPointer(prrl, offset);
@@ -891,7 +854,10 @@ static PIO_RESOURCE_REQUIREMENTS_LIST
ParseFilterResourceIrp(
}
}
}
-
+ if (bRemoveMSIResources && nRemoved)
+ {
+ DPrintf(0, ("[%s] %d resources removed", __FUNCTION__,
nRemoved));
+ }
return newPrrl;
}
@@ -907,12 +873,8 @@ we just enumerate allocated resources and do not modify
them.
*******************************************************************/
static NDIS_STATUS ParaNdis6_FilterResource(IN NDIS_HANDLE
MiniportAddDeviceContext, IN PIRP Irp)
{
- BOOLEAN bRemoveMSI = FALSE;
PIO_RESOURCE_REQUIREMENTS_LIST prrl =
(PIO_RESOURCE_REQUIREMENTS_LIST)(PVOID)Irp->IoStatus.Information;
-#if !defined(VIRTIO_USE_MSIX_INTERRUPT)
- bRemoveMSI = TRUE;
-#endif
- if (bRemoveMSI)
+ if (bDisableMSI)
{
// traverse the resource requirements list, clean up all the
MSI resources
PIO_RESOURCE_REQUIREMENTS_LIST newPrrl =
ParseFilterResourceIrp(MiniportAddDeviceContext, prrl, TRUE);
@@ -920,8 +882,8 @@ static NDIS_STATUS ParaNdis6_FilterResource(IN NDIS_HANDLE
MiniportAddDeviceCon
{
Irp->IoStatus.Information = (ULONG_PTR)newPrrl;
NdisFreeMemory(prrl, 0, 0);
- DPrintf(0, ("[%s] Reparsing resources using new
requirements...", __FUNCTION__));
- // just parse and print after MSI cleanup, this time do
not remove amything and do not reallocate the list
+ DPrintf(resourceFilterLevel, ("[%s] Reparsing resources
after filtering...", __FUNCTION__));
+ // just parse and print after MSI cleanup, this time do
not remove anything and do not reallocate the list
ParseFilterResourceIrp(NULL, newPrrl, FALSE);
}
}
@@ -957,6 +919,61 @@ static NDIS_STATUS ParaNdis6_SetOptions(IN NDIS_HANDLE
NdisDriverHandle, IN ND
return status;
}
+static NDIS_STATUS ReadGlobalConfigurationEntry(NDIS_HANDLE cfg, const char
*_name, PULONG pValue)
+{
+ NDIS_STATUS status;
+ PNDIS_CONFIGURATION_PARAMETER pParam = NULL;
+ NDIS_STRING name;
+ const char *statusName;
+ NDIS_PARAMETER_TYPE ParameterType = NdisParameterInteger;
+ NdisInitializeString(&name, (PUCHAR)_name);
+ NdisReadConfiguration(
+ &status,
+ &pParam,
+ cfg,
+ &name,
+ ParameterType);
+ if (status == NDIS_STATUS_SUCCESS)
+ {
+ *pValue = pParam->ParameterData.IntegerData;
+ statusName = "value";
+ }
+ else
+ {
+ statusName = "nothing";
+ }
+ DPrintf(2, ("[%s] %s read for %s - 0x%x", __FUNCTION__, statusName,
_name, *pValue));
+ NdisFreeString(name);
+ return status;
+}
+
+static void RetrieveDriverConfiguration()
+{
+ NDIS_CONFIGURATION_OBJECT co;
+ NDIS_HANDLE cfg, params;
+ NDIS_STATUS status;
+ DEBUG_ENTRY(2);
+ co.Header.Type = NDIS_OBJECT_TYPE_CONFIGURATION_OBJECT;
+ co.Header.Revision = NDIS_CONFIGURATION_OBJECT_REVISION_1;
+ co.Header.Size = sizeof(co);
+ co.Flags = 0;
+ co.NdisHandle = DriverHandle;
+ status = NdisOpenConfigurationEx(&co, &cfg);
+ if (status == NDIS_STATUS_SUCCESS)
+ {
+ NDIS_STRING paramsName;
+ NdisInitializeString(¶msName, (PUCHAR)"Parameters");
+ NdisOpenConfigurationKeyByName(&status, cfg, ¶msName,
¶ms);
+ if (status == NDIS_STATUS_SUCCESS)
+ {
+ ReadGlobalConfigurationEntry(params, "DisableMSI",
&bDisableMSI);
+ ReadGlobalConfigurationEntry(params, "EarlyDebug",
(PULONG)&resourceFilterLevel);
+ NdisCloseConfiguration(params);
+ }
+ NdisCloseConfiguration(cfg);
+ }
+}
+
/**********************************************************
Driver entry point:
Register miniport driver
@@ -1028,6 +1045,10 @@ NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,
PUNICODE_STRING pRegistryPath
NULL,
KE_PROCESSOR_CHANGE_ADD_EXISTING);
}
+ if (status == NDIS_STATUS_SUCCESS)
+ {
+ RetrieveDriverConfiguration();
+ }
DEBUG_EXIT_STATUS(status ? 0 : 4, status);
return status;
}
diff --git a/NetKVM/wlh/ParaNdis6-Impl.c b/NetKVM/wlh/ParaNdis6-Impl.c
index d781fd8..7a74a08 100644
--- a/NetKVM/wlh/ParaNdis6-Impl.c
+++ b/NetKVM/wlh/ParaNdis6-Impl.c
@@ -175,6 +175,18 @@ VOID ParaNdis_FreePhysicalMemory(
pAddresses->Physical);
}
+BOOLEAN ParaNdis_SynchronizeWithInterrupt(
+ PARANDIS_ADAPTER *pContext,
+ ULONG messageId,
+ tSynchronizedProcedure procedure,
+ ULONG parameter)
+{
+ tSynchronizedContext SyncContext;
+ SyncContext.pContext = pContext;
+ SyncContext.Parameter = parameter;
+ return NdisMSynchronizeWithInterruptEx(pContext->InterruptHandle,
messageId, procedure, &SyncContext);
+}
+
/**********************************************************
NDIS-required procedure for hardware interrupt registration
Parameters:
@@ -183,7 +195,7 @@ Parameters:
static VOID MiniportDisableInterruptEx(IN PVOID MiniportInterruptContext)
{
DEBUG_ENTRY(0);
- ParaNdis_VirtIOEnableInterrupt((PARANDIS_ADAPTER
*)MiniportInterruptContext, FALSE);
+ ParaNdis_VirtIOEnableIrqSynchronized((PARANDIS_ADAPTER
*)MiniportInterruptContext, isAny, FALSE);
}
/**********************************************************
@@ -194,7 +206,7 @@ Parameters:
static VOID MiniportEnableInterruptEx(IN PVOID MiniportInterruptContext)
{
DEBUG_ENTRY(0);
- ParaNdis_VirtIOEnableInterrupt((PARANDIS_ADAPTER
*)MiniportInterruptContext, TRUE);
+ ParaNdis_VirtIOEnableIrqSynchronized((PARANDIS_ADAPTER
*)MiniportInterruptContext, isAny, TRUE);
}
/**********************************************************
@@ -214,13 +226,21 @@ static BOOLEAN MiniportInterrupt(
{
PARANDIS_ADAPTER *pContext = (PARANDIS_ADAPTER
*)MiniportInterruptContext;
BOOLEAN b;
- b = ParaNdis_OnInterrupt(pContext, QueueDefaultInterruptDpc);
+ b = ParaNdis_OnInterrupt(pContext, QueueDefaultInterruptDpc, isAny);
*TargetProcessors = 0;
pContext->ulIrqReceived += b;
-
return b;
}
+static ULONG MessageToInterruptSource(PARANDIS_ADAPTER *pContext, ULONG
MessageId)
+{
+ ULONG interruptSource = 0;
+ if (MessageId == pContext->ulRxMessage) interruptSource |= isReceive;
+ if (MessageId == pContext->ulTxMessage) interruptSource |= isTransmit;
+ if (MessageId == pContext->ulControlMessage) interruptSource |=
isControl;
+ return interruptSource;
+}
+
/**********************************************************
NDIS-required procedure for MSI hardware interrupt handling
Parameters:
@@ -238,24 +258,15 @@ static BOOLEAN MiniportMSIInterrupt(
OUT PULONG TargetProcessors
)
{
- BOOLEAN b = MiniportInterrupt(MiniportInterruptContext,
QueueDefaultInterruptDpc, TargetProcessors);
+ PARANDIS_ADAPTER *pContext = (PARANDIS_ADAPTER
*)MiniportInterruptContext;
+ BOOLEAN b;
+ ULONG interruptSource = MessageToInterruptSource(pContext, MessageId);
+ b = ParaNdis_OnInterrupt(pContext, QueueDefaultInterruptDpc,
interruptSource);
+ pContext->ulIrqReceived += b;
return b;
}
/**********************************************************
-Syncronize interrupt enable from DPC
-Parameters:
- context
-***********************************************************/
-void ParaNdis_SyncInterruptEnable(PARANDIS_ADAPTER *pContext)
-{
- NdisMSynchronizeWithInterruptEx(pContext->InterruptHandle,
- 0,
-
ParaNdis_MiniportSynchronizeInterruptEnable,
-
pContext);
-}
-
-/**********************************************************
NDIS-required procedure for DPC handling
Parameters:
PVOID MiniportInterruptContext (Adapter context)
@@ -268,8 +279,15 @@ static VOID MiniportInterruptDPC(
)
{
PARANDIS_ADAPTER *pContext = (PARANDIS_ADAPTER
*)MiniportInterruptContext;
- DEBUG_ENTRY(3);
- ParaNdis_DPCWorkBody(pContext);
+ ULONG requiresProcessing;
+ DEBUG_ENTRY(5);
+ requiresProcessing = ParaNdis_DPCWorkBody(pContext);
+ if (requiresProcessing)
+ {
+ DPrintf(4, ("[%s] Queued additional DPC for %d", __FUNCTION__,
requiresProcessing));
+ InterlockedOr(&pContext->InterruptStatus, requiresProcessing);
+ NdisMQueueDpc(pContext->InterruptHandle, 0, 1 <<
KeGetCurrentProcessorNumber(), pContext);
+ }
}
/**********************************************************
@@ -287,8 +305,15 @@ static VOID MiniportMSIInterruptDpc(
)
{
PARANDIS_ADAPTER *pContext = (PARANDIS_ADAPTER
*)MiniportInterruptContext;
- DPrintf(0, ("[%s] (Message %d)", __FUNCTION__, MessageId));
- ParaNdis_DPCWorkBody(pContext);
+ ULONG interruptSource = MessageToInterruptSource(pContext, MessageId);
+ DPrintf(5, ("[%s] (Message %d, source %d)", __FUNCTION__, MessageId,
interruptSource));
+ interruptSource = ParaNdis_DPCWorkBody(pContext);
+ if (interruptSource)
+ {
+ DPrintf(4, ("[%s] Queued additional DPC for %d", __FUNCTION__,
interruptSource));
+ InterlockedOr(&pContext->InterruptStatus, interruptSource);
+ NdisMQueueDpc(pContext->InterruptHandle, MessageId, 1 <<
KeGetCurrentProcessorNumber(), pContext);
+ }
}
static VOID MiniportDisableMSIInterrupt(
@@ -296,8 +321,10 @@ static VOID MiniportDisableMSIInterrupt(
IN ULONG MessageId
)
{
- DEBUG_ENTRY(0);
- ParaNdis_VirtIOEnableInterrupt((PARANDIS_ADAPTER
*)MiniportInterruptContext, FALSE);
+ PARANDIS_ADAPTER *pContext = (PARANDIS_ADAPTER
*)MiniportInterruptContext;
+ ULONG interruptSource = MessageToInterruptSource(pContext, MessageId);
+ DPrintf(0, ("[%s] (Message %d)", __FUNCTION__, MessageId));
+ ParaNdis_VirtIOEnableIrqSynchronized(pContext, interruptSource, FALSE);
}
static VOID MiniportEnableMSIInterrupt(
@@ -305,8 +332,10 @@ static VOID MiniportEnableMSIInterrupt(
IN ULONG MessageId
)
{
- DEBUG_ENTRY(0);
- ParaNdis_VirtIOEnableInterrupt((PARANDIS_ADAPTER
*)MiniportInterruptContext, TRUE);
+ PARANDIS_ADAPTER *pContext = (PARANDIS_ADAPTER
*)MiniportInterruptContext;
+ ULONG interruptSource = MessageToInterruptSource(pContext, MessageId);
+ DPrintf(0, ("[%s] (Message %d)", __FUNCTION__, MessageId));
+ ParaNdis_VirtIOEnableIrqSynchronized(pContext, interruptSource, TRUE);
}
@@ -327,32 +356,83 @@ static VOID SharedMemAllocateCompleteHandler(
}
-static NDIS_STATUS SetInterruptMessage(PARANDIS_ADAPTER *pContext, UINT
queueIndex, ULONG messageData)
+static NDIS_STATUS SetInterruptMessage(PARANDIS_ADAPTER *pContext, UINT
queueIndex)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
- ULONG val = messageData - 1;
+ ULONG val;
+ ULONG messageIndex = queueIndex <
pContext->pMSIXInfoTable->MessageCount ?
+ queueIndex : (pContext->pMSIXInfoTable->MessageCount - 1);
+ PULONG pMessage = NULL;
switch (queueIndex)
{
- case 0: case 1: // queue interrupt:
+ case 0: // Rx queue interrupt:
+ WriteVirtIODeviceWord(pContext->IODevice.addr +
VIRTIO_PCI_QUEUE_SEL, (u16)queueIndex);
+ WriteVirtIODeviceWord(pContext->IODevice.addr +
VIRTIO_PCI_CONFIG + 2, (u16)messageIndex);
+ val = ReadVirtIODeviceWord(pContext->IODevice.addr +
VIRTIO_PCI_CONFIG + 2);
+ pMessage = &pContext->ulRxMessage;
+ break;
+ case 1: // Tx queue interrupt:
WriteVirtIODeviceWord(pContext->IODevice.addr +
VIRTIO_PCI_QUEUE_SEL, (u16)queueIndex);
- WriteVirtIODeviceWord(pContext->IODevice.addr +
VIRTIO_PCI_CONFIG + 2, (u16)messageData);
+ WriteVirtIODeviceWord(pContext->IODevice.addr +
VIRTIO_PCI_CONFIG + 2, (u16)messageIndex);
val = ReadVirtIODeviceWord(pContext->IODevice.addr +
VIRTIO_PCI_CONFIG + 2);
+ pMessage = &pContext->ulTxMessage;
break;
case 2: // config interrupt
- WriteVirtIODeviceWord(pContext->IODevice.addr +
VIRTIO_PCI_CONFIG, (u16)messageData);
+ WriteVirtIODeviceWord(pContext->IODevice.addr +
VIRTIO_PCI_CONFIG, (u16)messageIndex);
val = ReadVirtIODeviceWord(pContext->IODevice.addr +
VIRTIO_PCI_CONFIG);
+ pMessage = &pContext->ulControlMessage;
break;
default:
break;
}
- if (val != messageData)
+
+ if (val != messageIndex)
{
- DPrintf(0, ("[%s] ERROR: Wrong MSI-X message for
q%d(w%X,r%X)!", __FUNCTION__, queueIndex, messageData, val));
+ DPrintf(0, ("[%s] ERROR: Wrong MSI-X message for
q%d(w%X,r%X)!", __FUNCTION__, queueIndex, messageIndex, val));
status = NDIS_STATUS_DEVICE_FAILED;
}
+ if (pMessage) *pMessage = messageIndex;
+ return status;
+}
+
+static NDIS_STATUS ConfigureMSIXVectors(PARANDIS_ADAPTER *pContext)
+{
+ NDIS_STATUS status = NDIS_STATUS_RESOURCES;
+ UINT i;
+ PIO_INTERRUPT_MESSAGE_INFO pTable = pContext->pMSIXInfoTable;
+ if (pTable && pTable->MessageCount)
+ {
+ status = NDIS_STATUS_SUCCESS;
+ DPrintf(0, ("[%s] Using MSIX interrupts (%d messages, irql %d)",
+ __FUNCTION__, pTable->MessageCount,
pTable->UnifiedIrql));
+ for (i = 0; i < pContext->pMSIXInfoTable->MessageCount; ++i)
+ {
+ DPrintf(0, ("[%s] MSIX message%d=%08X=>%I64X",
+ __FUNCTION__, i,
+ pTable->MessageInfo[i].MessageData,
+ pTable->MessageInfo[i].MessageAddress));
+ }
+ for (i = 0; i < 3 && status == NDIS_STATUS_SUCCESS; ++i)
+ {
+ status = SetInterruptMessage(pContext, i);
+ }
+ }
+ if (status == NDIS_STATUS_SUCCESS)
+ {
+ DPrintf(0, ("[%s] Using message %d for RX queue", __FUNCTION__,
pContext->ulRxMessage));
+ DPrintf(0, ("[%s] Using message %d for TX queue", __FUNCTION__,
pContext->ulTxMessage));
+ DPrintf(0, ("[%s] Using message %d for controls", __FUNCTION__,
pContext->ulControlMessage));
+ }
return status;
}
+void ParaNdis_RestoreDeviceConfigurationAfterReset(
+ PARANDIS_ADAPTER *pContext)
+{
+ ConfigureMSIXVectors(pContext);
+}
+
+
/**********************************************************
NDIS6-related final initialization:
Installing interrupt handler
@@ -378,7 +458,6 @@ NDIS_STATUS
ParaNdis_FinishSpecificInitialization(PARANDIS_ADAPTER *pContext)
mic.EnableInterruptHandler = MiniportEnableInterruptEx;
mic.InterruptDpcHandler = MiniportInterruptDPC;
mic.InterruptHandler = MiniportInterrupt;
-#ifdef VIRTIO_USE_MSIX_INTERRUPT
if (pContext->bUsingMSIX)
{
mic.MsiSupported = TRUE;
@@ -388,7 +467,6 @@ NDIS_STATUS
ParaNdis_FinishSpecificInitialization(PARANDIS_ADAPTER *pContext)
mic.MessageInterruptHandler = MiniportMSIInterrupt;
mic.MessageInterruptDpcHandler = MiniportMSIInterruptDpc;
}
-#endif
PoolParams.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
PoolParams.Header.Size = sizeof(PoolParams);
PoolParams.Header.Revision = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
@@ -434,28 +512,8 @@ NDIS_STATUS
ParaNdis_FinishSpecificInitialization(PARANDIS_ADAPTER *pContext)
{
if (NDIS_CONNECT_MESSAGE_BASED == mic.InterruptType)
{
- UINT i;
- DPrintf(0, ("[%s] Using MSIX interrupts (%d messages,
irql %d)",
- __FUNCTION__,
mic.MessageInfoTable->MessageCount, mic.MessageInfoTable->UnifiedIrql));
- for (i = 0; mic.MessageInfoTable && i <
mic.MessageInfoTable->MessageCount; ++i)
- {
- DPrintf(0, ("[%s] MSIX message%d=%08X=>%I64X",
- __FUNCTION__, i,
-
mic.MessageInfoTable->MessageInfo[i].MessageData,
-
mic.MessageInfoTable->MessageInfo[i].MessageAddress));
- }
- status = SetInterruptMessage(pContext, 0, 0);
- if (NDIS_STATUS_SUCCESS == status)
- {
- i = mic.MessageInfoTable->MessageCount > 1 ? 1
: 0;
- status = SetInterruptMessage(pContext, 1, i);
- }
- if (NDIS_STATUS_SUCCESS == status)
- {
- i = mic.MessageInfoTable->MessageCount > 2 ? 2
: 0;
- status = SetInterruptMessage(pContext, 2, i);
- }
pContext->pMSIXInfoTable = mic.MessageInfoTable;
+ status = ConfigureMSIXVectors(pContext);
//pContext->bDoInterruptRecovery = FALSE;
}
else if (pContext->bUsingMSIX)
@@ -661,21 +719,22 @@ tPacketIndicationType ParaNdis_IndicateReceivedPacket(
VOID ParaNdis_IndicateReceivedBatch(
PARANDIS_ADAPTER *pContext,
+ tPacketIndicationType *pBatch,
ULONG nofPackets)
{
ULONG i;
- PNET_BUFFER_LIST pPrev = pContext->pBatchOfPackets[0];
+ PNET_BUFFER_LIST pPrev = pBatch[0];
NET_BUFFER_LIST_NEXT_NBL(pPrev) = NULL;
for (i = 1; i < nofPackets; ++i)
{
- PNET_BUFFER_LIST pNBL = pContext->pBatchOfPackets[i];
+ PNET_BUFFER_LIST pNBL = pBatch[i];
NET_BUFFER_LIST_NEXT_NBL(pPrev) = pNBL;
NET_BUFFER_LIST_NEXT_NBL(pNBL) = NULL;
pPrev = pNBL;
}
NdisMIndicateReceiveNetBufferLists(
pContext->MiniportHandle,
- pContext->pBatchOfPackets[0],
+ pBatch[0],
0,
nofPackets,
0);
@@ -1936,4 +1995,56 @@ VOID ParaNdis6_CancelSendNetBufferLists(
DEBUG_EXIT_STATUS(0, nCancelled);
}
+#define VISTA_RECOVERY_CANCEL_TIMER
1
+#define VISTA_RECOVERY_RUN_DPC
2
+#define VISTA_RECOVERY_INFO_ONLY_SECOND_READ 4
+
+
+static UCHAR MiniportSyncRecoveryProcedure(PVOID SynchronizeContext)
+{
+ PARANDIS_ADAPTER *pContext = (PARANDIS_ADAPTER *)SynchronizeContext;
+ BOOLEAN b;
+ UCHAR val = 0;
+ if (pContext->ulIrqReceived)
+ {
+ val = VISTA_RECOVERY_CANCEL_TIMER;
+ }
+ else
+ {
+ b = ParaNdis_OnInterrupt(pContext, &b, isAny);
+ if (b)
+ {
+ // we read the interrupt, in any case run the DRC
+ val = VISTA_RECOVERY_RUN_DPC;
+ b = !VirtIODeviceISR(&pContext->IODevice);
+ // if we read it again, it does not mean anything
+ if (b) val |= VISTA_RECOVERY_INFO_ONLY_SECOND_READ;
+ }
+ }
+ return val;
+}
+
+
+VOID ParaNdis6_OnInterruptRecoveryTimer(PARANDIS_ADAPTER *pContext)
+{
+ UCHAR val;
+ val = NdisMSynchronizeWithInterruptEx(
+ pContext->InterruptHandle,
+ 0,
+ MiniportSyncRecoveryProcedure,
+ pContext);
+ if (val & VISTA_RECOVERY_RUN_DPC)
+ {
+ InterlockedOr(&pContext->InterruptStatus, isAny);
+ ParaNdis_DPCWorkBody(pContext);
+ }
+ if (~val & VISTA_RECOVERY_CANCEL_TIMER)
+ ParaNdis_SetTimer(pContext->InterruptRecoveryTimer, 15);
+ else
+ {
+ DPrintf(0, ("[%s] Cancelled", __FUNCTION__));
+ }
+ DEBUG_EXIT_STATUS(5, val);
+}
+
#endif // NDIS60_MINIPORT
diff --git a/NetKVM/wlh/ParaNdis6-Oid.c b/NetKVM/wlh/ParaNdis6-Oid.c
index 35a7d2b..e71e80c 100644
--- a/NetKVM/wlh/ParaNdis6-Oid.c
+++ b/NetKVM/wlh/ParaNdis6-Oid.c
@@ -490,7 +490,7 @@ NDIS_STATUS ParaNdis_OnSetPower(PARANDIS_ADAPTER *pContext,
tOidDesc *pOid)
static void DumpOffloadStructure(NDIS_OFFLOAD *po, LPCSTR message)
{
- int level = 0;
+ int level = 1;
ULONG *pul;
DPrintf(level, ("[%s](%s)", __FUNCTION__, message));
pul = (ULONG *)&po->Checksum.IPv4Transmit;
diff --git a/NetKVM/wlh/ParaNdis6.h b/NetKVM/wlh/ParaNdis6.h
index 9deaddb..3c1fa7f 100644
--- a/NetKVM/wlh/ParaNdis6.h
+++ b/NetKVM/wlh/ParaNdis6.h
@@ -59,6 +59,9 @@ NDIS_STATUS ParaNdis6_ReceivePauseRestart(
ONPAUSECOMPLETEPROC Callback
);
+VOID ParaNdis6_OnInterruptRecoveryTimer(
+ PARANDIS_ADAPTER *pContext);
+
/* returns number of buffers that have been sent */
UINT ParaNdis6_CopyDataFromSingleNBL(PARANDIS_ADAPTER *pContext,
PNET_BUFFER_LIST pNBL);
diff --git a/NetKVM/wlh/netkvm.inf b/NetKVM/wlh/netkvm.inf
index e0f1846..8143375 100644
--- a/NetKVM/wlh/netkvm.inf
+++ b/NetKVM/wlh/netkvm.inf
@@ -27,12 +27,12 @@ DriverPackageDisplayName = %kvmnet6.DeviceDesc%
AddReg = kvmnet6.EnableMSI
[kvmnet6.EnableMSI]
-HKR, "Interrupt Management",, 0x00000010
-HKR, "Interrupt Management\MessageSignaledInterruptProperties",, 0x00000010
+;HKR, "Interrupt Management",, 0x00000010
+;HKR, "Interrupt Management\MessageSignaledInterruptProperties",, 0x00000010
HKR, "Interrupt Management\MessageSignaledInterruptProperties",
MSISupported, 0x00010001, 1
HKR, "Interrupt Management\MessageSignaledInterruptProperties",
MessageNumberLimit, 0x00010001, 4
-HKR, "Interrupt Management\Affinity Policy",, 0x00000010
-HKR, "Interrupt Management\Affinity Policy", DevicePolicy, 0x00010001, 1
+;HKR, "Interrupt Management\Affinity Policy",, 0x00000010
+HKR, "Interrupt Management\Affinity Policy", DevicePolicy, 0x00010001, 0
HKR, "Interrupt Management\Affinity Policy", DevicePriority, 0x00010001, 2
@@ -250,7 +250,9 @@ HKR, , EventMessageFile, 0x00020000,
"%%SystemRoot%%\System32\netevent.dll"
HKR, , TypesSupported, 0x00010001, 7
[TextModeFlags.Reg]
-HKR, , TextModeFlags, 0x00010001, 0x0001
+HKR,,TextModeFlags,0x00010001, 0x0001
+HKR,Parameters,DisableMSI,,"0"
+HKR,Parameters,EarlyDebug,,"3"
[SourceDisksNames]
1 = %DiskId1%,,,""
diff --git a/NetKVM/wxp/ParaNdis5-Driver.c b/NetKVM/wxp/ParaNdis5-Driver.c
index 12aeeef..160f579 100644
--- a/NetKVM/wxp/ParaNdis5-Driver.c
+++ b/NetKVM/wxp/ParaNdis5-Driver.c
@@ -22,8 +22,6 @@
static NDIS_HANDLE DriverHandle;
static ULONG gID = 0;
-static DRIVER_UNLOAD ParaVirtualNICUnload;
-
/******************************************************
Unload handler, only responsibility is cleanup WPP
*******************************************************/
@@ -322,6 +320,7 @@ static VOID ParaNdis5_Halt(
NdisSetEvent(&pContext->HaltEvent);
WaitHaltEvent(pContext, "Receive");
ParaNdis_CleanupContext(pContext);
+ NdisCancelTimer(&pContext->DPCPostProcessTimer, &bUnused);
ParaNdis_DebugHistory(pContext, hopHalt, NULL, 0, 0, 0);
ParaNdis_DebugRegisterMiniport(pContext, FALSE);
NdisFreeMemory(pContext, 0, 0);
@@ -339,18 +338,6 @@ static BOOLEAN ParaNdis5_CheckForHang(IN NDIS_HANDLE
MiniportAdapterContext)
return ParaNdis_CheckForHang(pContext);
}
-
-
-/*************************************************************
-Required NDIS procedure, just calls regular (Common) DPC processing
-*************************************************************/
-static VOID ParaNdis5_HandleDPC(IN NDIS_HANDLE MiniportAdapterContext)
-{
- PARANDIS_ADAPTER *pContext = (PARANDIS_ADAPTER *)MiniportAdapterContext;
- DEBUG_ENTRY(7);
- ParaNdis_DPCWorkBody(pContext);
-}
-
/*************************************************************
Required NDIS procedure
Responsible for hardware interrupt handling
@@ -362,7 +349,7 @@ static VOID ParaNdis5_MiniportISR(OUT PBOOLEAN
InterruptRecognized,
PARANDIS_ADAPTER *pContext = (PARANDIS_ADAPTER *)MiniportAdapterContext;
BOOLEAN b;
*QueueMiniportHandleInterrupt = FALSE;
- b = ParaNdis_OnInterrupt(pContext, QueueMiniportHandleInterrupt);
+ b = ParaNdis_OnInterrupt(pContext, QueueMiniportHandleInterrupt, isAny);
*InterruptRecognized = b;
DEBUG_EXIT_STATUS(7, (ULONG)b);
}
diff --git a/NetKVM/wxp/ParaNdis5-Impl.c b/NetKVM/wxp/ParaNdis5-Impl.c
index 0808811..1e4a401 100644
--- a/NetKVM/wxp/ParaNdis5-Impl.c
+++ b/NetKVM/wxp/ParaNdis5-Impl.c
@@ -158,6 +158,29 @@ BOOLEAN ParaNdis_InitialAllocatePhysicalMemory(
return pAddresses->Virtual != NULL;
}
+/**********************************************************
+Callback of timer for pending events cleanup after regular DPC processing
+Parameters:
+ context (on FunctionContext)
+ all the rest are irrelevant
+***********************************************************/
+static VOID OnDPCPostProcessTimer(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3
+ )
+{
+ PARANDIS_ADAPTER *pContext = (PARANDIS_ADAPTER *)FunctionContext;
+ ULONG requiresProcessing;
+ requiresProcessing = ParaNdis_DPCWorkBody(pContext);
+ if (requiresProcessing)
+ {
+ // we need to request additional DPC
+ InterlockedOr(&pContext->InterruptStatus, requiresProcessing);
+ NdisSetTimer(&pContext->DPCPostProcessTimer, 10);
+ }
+}
/**********************************************************
NDIS5 implementation of shared memory freeing
@@ -205,6 +228,7 @@ NDIS_STATUS ParaNdis_FinishSpecificInitialization(
InitializeListHead(&pContext->SendQueue);
InitializeListHead(&pContext->TxWaitingList);
NdisInitializeTimer(&pContext->ConnectTimer, OnConnectTimer, pContext);
+ NdisInitializeTimer(&pContext->DPCPostProcessTimer,
OnDPCPostProcessTimer, pContext);
status = NdisMRegisterInterrupt(
&pContext->Interrupt,
@@ -466,11 +490,12 @@ tPacketIndicationType ParaNdis_IndicateReceivedPacket(
VOID ParaNdis_IndicateReceivedBatch(
PARANDIS_ADAPTER *pContext,
+ tPacketIndicationType *pBatch,
ULONG nofPackets)
{
NdisMIndicateReceivePacket(
pContext->MiniportHandle,
- pContext->pBatchOfPackets,
+ pBatch,
nofPackets);
}
@@ -1237,18 +1262,6 @@ NDIS_STATUS ParaNdis5_StopSend(PARANDIS_ADAPTER
*pContext, BOOLEAN bStop, ONPAUS
}
/**********************************************************
-Syncronize interrupt enable from DPC
-Parameters:
- context
-***********************************************************/
-void ParaNdis_SyncInterruptEnable(PARANDIS_ADAPTER *pContext)
-{
- NdisMSynchronizeWithInterrupt(&pContext->Interrupt,
-
ParaNdis_MiniportSynchronizeInterruptEnable,
- pContext);
-}
-
-/**********************************************************
Pause or resume receive operation:
Parameters:
context
@@ -1291,5 +1304,38 @@ NDIS_STATUS ParaNdis5_StopReceive(
return status;
}
+/*************************************************************
+Required NDIS procedure, spawns regular (Common) DPC processing
+*************************************************************/
+VOID ParaNdis5_HandleDPC(IN NDIS_HANDLE MiniportAdapterContext)
+{
+ PARANDIS_ADAPTER *pContext = (PARANDIS_ADAPTER *)MiniportAdapterContext;
+ ULONG requiresProcessing;
+ BOOLEAN unused;
+ DEBUG_ENTRY(7);
+ // we do not need the timer, as DPC will do all the job
+ // this is not a problem if the timer procedure is already running,
+ // we need to do our job anyway
+ NdisCancelTimer(&pContext->DPCPostProcessTimer, &unused);
+ requiresProcessing = ParaNdis_DPCWorkBody(pContext);
+ if (requiresProcessing)
+ {
+ // we need to request additional DPC
+ InterlockedOr(&pContext->InterruptStatus, requiresProcessing);
+ NdisSetTimer(&pContext->DPCPostProcessTimer, 10);
+ }
+}
+
+BOOLEAN ParaNdis_SynchronizeWithInterrupt(
+ PARANDIS_ADAPTER *pContext,
+ ULONG messageId,
+ tSynchronizedProcedure procedure,
+ ULONG parameter)
+{
+ tSynchronizedContext SyncContext;
+ SyncContext.pContext = pContext;
+ SyncContext.Parameter = parameter;
+ return NdisMSynchronizeWithInterrupt(&pContext->Interrupt, procedure,
&SyncContext);
+}
#endif //defined(NDIS51_MINIPORT) || defined(NDIS50_MINIPORT)
diff --git a/NetKVM/wxp/ParaNdis5.h b/NetKVM/wxp/ParaNdis5.h
index 43d347a..f02563b 100644
--- a/NetKVM/wxp/ParaNdis5.h
+++ b/NetKVM/wxp/ParaNdis5.h
@@ -54,6 +54,8 @@ NDIS_STATUS ParaNdis5_StopReceive(
BOOLEAN bStop,
ONPAUSECOMPLETEPROC Callback
);
+VOID ParaNdis5_HandleDPC(
+ IN NDIS_HANDLE MiniportAdapterContext);
typedef struct _tagPowerWorkItem
{
--
To unsubscribe from this list: send the line "unsubscribe kvm-commits" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html