Exemple #1
0
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;
}