BOOLEAN xmpReqSetRss( __in NDIS_HANDLE SynchronizeContext ) { USHORT i; UCHAR *pSecretKey; UCHAR *pTable; BOOLEAN bTable, bKey, bCpu, bHashInfo; BOOLEAN bQueue = FALSE; KIRQL OldIrql; xmpNicCtx_t *pNicCtx = SynchronizeContext; NDIS_RECEIVE_SCALE_PARAMETERS *pParams = &pNicCtx->ndisRssSet.params; static int count = 0; XMPTRACE(XMP_DBG_WRN, ("==> xmpReqSetRss Count = %d Flags = 0x%8.8lx\n", ++count, pParams->Flags)); XF_GET_SLOCK(&pNicCtx->lock); pSecretKey = ((UCHAR *) pParams) + pParams->HashSecretKeyOffset; pTable = ((UCHAR *) pParams) + pParams->IndirectionTableOffset; bTable = bKey = bCpu = bHashInfo = FALSE; if ( XMP_NIC_RSS_IS_ENABLED(pNicCtx) && !(bit(pParams->Flags, NDIS_RSS_PARAM_FLAG_DISABLE_RSS)) ) { if ( !(bit(pParams->Flags, NDIS_RSS_PARAM_FLAG_HASH_KEY_UNCHANGED)) ) bKey = TRUE; if ( !(bit(pParams->Flags, NDIS_RSS_PARAM_FLAG_ITABLE_UNCHANGED)) ) bTable = TRUE; if ( !(bit(pParams->Flags, NDIS_RSS_PARAM_FLAG_BASE_CPU_UNCHANGED )) ) bCpu = TRUE; } else { bTable = bKey = bCpu = bHashInfo = TRUE; pNicCtx->RssParamsReq.HashFunction = 0; } /* Enable RTH_CFG, RTS_ENHANCED and RMAC_STRIP_FCS to 0 */ if ( bHashInfo ) { pNicCtx->RssParamsReq.HashType = NDIS_RSS_HASH_TYPE_FROM_HASH_INFO(pParams->HashInformation); pNicCtx->RssParamsReq.HashFunction = NDIS_RSS_HASH_FUNC_FROM_HASH_INFO(pParams->HashInformation); } if ( NDIS_RSS_HASH_FUNC_FROM_HASH_INFO(pParams->HashInformation) != 0 ) { if( bCpu ) pNicCtx->RssParamsReq.BaseCpuNum = pParams->BaseCpuNumber; if ( bTable ) { pNicCtx->RssParamsReq.TableSz = pParams->IndirectionTableSize > XMP_NIC_RSS_MAX_TABLE_SZ ? XMP_NIC_RSS_MAX_TABLE_SZ : pParams->IndirectionTableSize; { ULONG TableSz = pNicCtx->RssParamsReq.TableSz; USHORT NumLsbs = 0; while (TableSz != 1) { TableSz = TableSz>>1; NumLsbs++; } pNicCtx->RssParamsReq.HashBitsSz = NumLsbs; } NdisMoveMemory(pNicCtx->RssParamsReq.Table, pTable, pNicCtx->RssParamsReq.TableSz); } if ( bKey ) { pNicCtx->RssParamsReq.SecretKeySz = pParams->HashSecretKeySize; NdisMoveMemory(pNicCtx->RssParamsReq.SecretKey, pSecretKey, pNicCtx->RssParamsReq.SecretKeySz); } } pNicCtx->RssParamsReq.Flags = pParams->Flags; KeMemoryBarrier(); if ( !pNicCtx->wiQueued ) { pNicCtx->wiQueued = TRUE; if ( !pNicCtx->wiRunning ) bQueue = TRUE; } XF_FREE_SLOCK(&pNicCtx->lock); #ifdef XMP_SET_RSS_IN_WORKER if ( bQueue ) NdisQueueIoWorkItem(pNicCtx->hSetRssWI, (NDIS_IO_WORKITEM_ROUTINE)xmpNicSetRssParameters, pNicCtx); #else xmpNicSetRssParameters(pNicCtx, NULL); #endif XMPTRACE(XMP_DBG_WRN, ("<== xmpReqSetRss\n")); return TRUE; }
BOOLEAN WorkItemQueuedForWatchdogAvoidance( _In_ NDIS_HANDLE WorkItem, _In_ volatile LONG* WorkItemQueued, _In_ NDIS_IO_WORKITEM_ROUTINE WIRoutine, _In_ PVOID WIContext ) /*++ Routine Description: This function should be called from the receive or send-complete DPCs. It queues a work item to do the receives or send-completes if the DPC watchdog timer is within 25% of the limit. This allows the processor to reach PASSIVE_LEVEL and reset the watchdog. Runs at IRQL = DISPATCH_LEVEL. Arguments: WorkItem The work item to queue WorkItemQueued Variable that stores whether a work item is currently queued WIRoutine The work routine WIContext The context passed to the work routine Return Value: TRUE - Work item queued due to watchdog timer, caller should exit DPC FALSE - Ok to continue in DPC --*/ { KDPC_WATCHDOG_INFORMATION WatchdogInfo; NTSTATUS Status; if(*WorkItemQueued) { // // We've already queued up the work item, no need to check watchdog information // return TRUE; } Status = KeQueryDpcWatchdogInformation(&WatchdogInfo); if (NT_SUCCESS(Status) // // Verify the watchdog is enabled // && WatchdogInfo.DpcWatchdogLimit != 0 // // Once we go below 25% of the watchdog limit we fall back on the work item to allow the watchdog to reset // && WatchdogInfo.DpcWatchdogCount < WatchdogInfo.DpcWatchdogLimit / 4) { // // Make sure we don't queue the work item if it's already been queued for this DPC // LONG AlreadyQueued = InterlockedCompareExchange( WorkItemQueued, TRUE, FALSE); if(!AlreadyQueued) { // // We've crossed our threshold for consecutive DPCs, schedule work item to complete this receive // DEBUGP(MP_TRACE, "Processor has spent too much time in DPC. Queueing work item to handle next receives/send-completes.\n"); NdisQueueIoWorkItem(WorkItem, WIRoutine, WIContext); } return TRUE; } // // We're still within acceptable time limits // return FALSE; }