static BOOLEAN IsValidHashInfo(ULONG HashInformation)
{
#define HASH_FLAGS_COMBINATION(Type, Flags) ( ((Type) & (Flags)) && !((Type) & ~(Flags)) )

    ULONG ulHashType = NDIS_RSS_HASH_TYPE_FROM_HASH_INFO(HashInformation);
    ULONG ulHashFunction = NDIS_RSS_HASH_FUNC_FROM_HASH_INFO(HashInformation);

    if (HashInformation == 0)
        return TRUE;

    if (HASH_FLAGS_COMBINATION(ulHashType, NDIS_HASH_IPV4 | NDIS_HASH_TCP_IPV4 |
                                           NDIS_HASH_IPV6 | NDIS_HASH_TCP_IPV6 |
                                           NDIS_HASH_IPV6_EX | NDIS_HASH_TCP_IPV6_EX))
        return ulHashFunction == NdisHashFunctionToeplitz;

    return FALSE;
}
Esempio n. 2
0
NDIS_STATUS
xmpSetInformation(
  IN xmpNicCtx_t             *pNicCtx,
  IN PNDIS_OID_REQUEST       NdisRequest
  )
{
  NDIS_STATUS                 Status = NDIS_STATUS_SUCCESS;
  NDIS_OID                    Oid;
  PVOID                       InformationBuffer;
  ULONG                       InformationBufferLength;
  ULONG                       BytesRead;
  ULONG                       BytesNeeded;
  ULONG                       PacketFilter;
  ULONG                       MCastCnt;
  ULONG                       HashType;
  ULONG                       validBits;
  USHORT                      i;
  xge_hal_device_t           *pHalDev;
  NDIS_RECEIVE_SCALE_PARAMETERS *pRssParam;
  xmpSetRssContext			      SetRssCtx = {0};
  static ULONG setRssCount = 10;

  pHalDev = XMP_NIC_GET_DEV(pNicCtx);
  Oid = NdisRequest->DATA.SET_INFORMATION.Oid;
  InformationBuffer = NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
  InformationBufferLength = 
    NdisRequest->DATA.SET_INFORMATION.InformationBufferLength;

  XMPTRACE(XMP_DBG_REQ, ("==> xmpSetInformation %x\n", Oid));
  BytesRead = 0;
  BytesNeeded = 0;

  switch(Oid)
  {
  case OID_802_3_MULTICAST_LIST:
    XMPTRACE(XMP_DBG_REQ, ("xmpSetInformation Multicast list\n"));
    if ( InformationBufferLength % ETH_LENGTH_OF_ADDRESS != 0 )
      return(NDIS_STATUS_INVALID_LENGTH);

    MCastCnt = InformationBufferLength / ETH_LENGTH_OF_ADDRESS;
    xmpHalMcastFilterClr(pNicCtx);
    Status = xmpHalSetMcastList(pNicCtx,
                                (UCHAR *) InformationBuffer,
                                &MCastCnt);
    BytesRead = MCastCnt * ETH_LENGTH_OF_ADDRESS;
    break;

  case OID_GEN_CURRENT_PACKET_FILTER:
    XMPTRACE(XMP_DBG_REQ, ("xmpSetInformation: packet filter\n"));
    if ( InformationBufferLength != sizeof (ULONG) )
      return ( NDIS_STATUS_INVALID_LENGTH );

    BytesRead = InformationBufferLength;
    PacketFilter = *((PULONG) InformationBuffer);
    Status = xmpSetFilter(pNicCtx, PacketFilter);
    break;

  case OID_GEN_CURRENT_LOOKAHEAD:
    XMPTRACE(XMP_DBG_REQ, ("xmpSetInformation: current lookahead\n"));
    if( InformationBufferLength < sizeof(ULONG) )
    {
      BytesNeeded = sizeof(ULONG);
      Status = NDIS_STATUS_INVALID_LENGTH;
      break;
    }
    pNicCtx->LookAheadSz = *((PULONG) InformationBuffer);
    BytesRead = sizeof(ULONG);
    Status = NDIS_STATUS_SUCCESS;
    break;

  case OID_GEN_RECEIVE_SCALE_PARAMETERS:

    XMPTRACE(XMP_DBG_INFO, ("xmpSetInformation: OID_GEN_RECEIVE_SCALE_PARAMETERS\n"));
    if ( !(XMP_NIC_RSS_IN_CONFIG(pNicCtx)) )
    {
      Status = NDIS_STATUS_NOT_SUPPORTED;
      break;
    }

    if ( InformationBufferLength < sizeof(NDIS_RECEIVE_SCALE_PARAMETERS) )
    {
      BytesNeeded = sizeof(NDIS_RECEIVE_SCALE_PARAMETERS);
      Status = NDIS_STATUS_INVALID_LENGTH;
      break;
    }
    pRssParam = (PNDIS_RECEIVE_SCALE_PARAMETERS)InformationBuffer;

#ifdef NDISTEST_BUG
    if ( !XENAMP_NDIS_OBJECT_VALID(&pRssParam->Header,
                                   NDIS_RECEIVE_SCALE_PARAMETERS_REVISION_1,
                                   NDIS_OBJECT_TYPE_RSS_PARAMETERS,
                                   sizeof(NDIS_RECEIVE_SCALE_PARAMETERS)) )
    {
      XMPTRACE(XMP_DBG_WRN, ("xmpSetInformation:RSS_PARAMETERS invalid!!"       
                             " Revision=%d Type=%d Size=%d\n",
                             pRssParam->Header.Revision,
                             pRssParam->Header.Type,
                             pRssParam->Header.Size));
      BytesRead = sizeof(NDIS_OBJECT_HEADER);
      Status = NDIS_STATUS_INVALID_PARAMETER;
      break;
    }
#endif

    BytesRead = sizeof(NDIS_RECEIVE_SCALE_PARAMETERS);

    if ( (InformationBufferLength < (pRssParam->IndirectionTableSize
                                     + pRssParam->IndirectionTableOffset)) ||
         (InformationBufferLength < (pRssParam->HashSecretKeySize
                                     + pRssParam->HashSecretKeyOffset)) )
    {
      BytesNeeded = sizeof(NDIS_RECEIVE_SCALE_PARAMETERS);
      Status = NDIS_STATUS_INVALID_LENGTH;
      break;
    }

    HashType = NDIS_RSS_HASH_TYPE_FROM_HASH_INFO(pRssParam->HashInformation);   
    /*if ( HashType != 0 || NDIS_RSS_HASH_FUNC_FROM_HASH_INFO(pRssParam->HashInformation) != 0) */
    validBits = (NDIS_HASH_IPV4 | NDIS_HASH_TCP_IPV4
#ifndef XMP_RSS_IPV4_ONLY
                 | NDIS_HASH_IPV6 | NDIS_HASH_TCP_IPV6
                 | NDIS_HASH_IPV6_EX | NDIS_HASH_TCP_IPV6_EX
#endif
                 );
    if ( ((NDIS_RSS_HASH_FUNC_FROM_HASH_INFO(pRssParam->HashInformation) !=
           NdisHashFunctionToeplitz) ||  /* the only hash function supported */
          !bit(HashType, validBits) ||    /* at least one type should be set */
          (HashType & ~validBits)) &&         /* no other type should be set */
         (!(bit(pRssParam->Flags, NDIS_RSS_PARAM_FLAG_DISABLE_RSS)) &&
          NDIS_RSS_HASH_FUNC_FROM_HASH_INFO(pRssParam->HashInformation) != 0) )
    {
      Status = NDIS_STATUS_INVALID_PARAMETER;
      break;
    }

    if ( /*(pRssParam->IndirectionTableSize < (1 << pRssParam->NumberOfLsbs)) || */
         (pRssParam->HashSecretKeySize & 0x7) ||    /* must be 8-bytes align */
         (pRssParam->HashSecretKeySize > 40)  ||      /* max secret key size */
         (pRssParam->BaseCpuNumber & (pRssParam->BaseCpuNumber - 1)) )/*pow2 */
    {
      XMPTRACE(XMP_DBG_WRN, ("xmpReqSetRss:Invalid settings: Key Size=%d"
                             " IDT size=%d BaseCpu=%d\n",
                             pRssParam->HashSecretKeySize,
                             pRssParam->IndirectionTableSize,
                             pRssParam->BaseCpuNumber));
      Status = NDIS_STATUS_INVALID_PARAMETER;
      break;
    }


    if ((pRssParam->IndirectionTableSize + pRssParam->IndirectionTableOffset) >
        (pRssParam->HashSecretKeySize + pRssParam->HashSecretKeyOffset))
      BytesRead = (pRssParam->IndirectionTableSize + 
                    pRssParam->IndirectionTableOffset);
    else
      BytesRead = (pRssParam->HashSecretKeySize +
                    pRssParam->HashSecretKeyOffset);

    SetRssCtx.pNicCtx = pNicCtx;
    SetRssCtx.pParams = pRssParam;

#if 0
    if(NdisMSynchronizeWithInterruptEx(pNicCtx->hInterrupt, 0, xmpReqSetRss, &SetRssCtx))
#endif
    if ( NDIS_RSS_HASH_FUNC_FROM_HASH_INFO(pRssParam->HashInformation) == 0 )
      bis(pRssParam->Flags, NDIS_RSS_PARAM_FLAG_DISABLE_RSS);

    if ( bit(pRssParam->Flags, NDIS_RSS_PARAM_FLAG_DISABLE_RSS) )
    {
      pNicCtx->ndisRssSet.size = sizeof(NDIS_RECEIVE_SCALE_PARAMETERS);
      pNicCtx->ndisRssSet.params.BaseCpuNumber          = 0;
      pNicCtx->ndisRssSet.params.Flags                  = 0;
      pNicCtx->ndisRssSet.params.HashInformation        = 0;
      pNicCtx->ndisRssSet.params.IndirectionTableSize   = 0;
      pNicCtx->ndisRssSet.params.IndirectionTableOffset = 0;
      pNicCtx->ndisRssSet.params.HashSecretKeySize      = 0;
      pNicCtx->ndisRssSet.params.HashSecretKeyOffset    = 0;
    }
    else
    {
      NdisMoveMemory(&pNicCtx->ndisRssSet.params, pRssParam, BytesRead);
      pNicCtx->ndisRssSet.size = BytesRead;
    }

      xmpReqSetRss(pNicCtx);
#if 0
    if ( !(setRssCount % 10) )
    {
      xmpReqSetRss(pNicCtx);
    }
    setRssCount++;
#endif
    Status = NDIS_STATUS_SUCCESS;
    break;

  case OID_OFFLOAD_ENCAPSULATION:
    XMPTRACE(XMP_DBG_OFLD, ("xmpSetInformation: offload encapsulation\n"));
    if ( InformationBufferLength < sizeof(NDIS_OFFLOAD_ENCAPSULATION) )
    {
      BytesNeeded = sizeof(NDIS_OFFLOAD_ENCAPSULATION);
      Status = NDIS_STATUS_INVALID_LENGTH;
      break;
    }

    NdisMoveMemory(&pNicCtx->OffloadEncapsulation,
                   InformationBuffer,
                   sizeof(NDIS_OFFLOAD_ENCAPSULATION));
    BytesRead = sizeof(NDIS_OFFLOAD_ENCAPSULATION);
    Status    = NDIS_STATUS_SUCCESS;
    break;

  case OID_GEN_INTERRUPT_MODERATION:
    {
      NDIS_INTERRUPT_MODERATION_PARAMETERS *pIntrModr;
      if ( InformationBufferLength < sizeof(NDIS_INTERRUPT_MODERATION_PARAMETERS) )
      {
        BytesNeeded = sizeof(NDIS_INTERRUPT_MODERATION_PARAMETERS);
        Status = NDIS_STATUS_INVALID_LENGTH;
        break;
      }
      pIntrModr  = (NDIS_INTERRUPT_MODERATION_PARAMETERS *) InformationBuffer;
      if ( !XENAMP_NDIS_OBJECT_VALID(&pIntrModr->Header,
                                 NDIS_INTERRUPT_MODERATION_PARAMETERS_REVISION_1,
                                 NDIS_OBJECT_TYPE_DEFAULT,
                                 sizeof(NDIS_INTERRUPT_MODERATION_PARAMETERS)) )
      {
        BytesRead = sizeof(NDIS_OBJECT_HEADER);
        Status = NDIS_STATUS_INVALID_DATA;
        break;
      }
     break;
    }

  case OID_TCP_OFFLOAD_PARAMETERS:
    {
      NDIS_OFFLOAD_PARAMETERS *pAdmin;
      NDIS_STATUS_INDICATION  StatusIndication;
      ULONG size;

      pAdmin  = (NDIS_OFFLOAD_PARAMETERS *) InformationBuffer;
  
      if ( InformationBufferLength < NDIS_SIZEOF_OFFLOAD_PARAMETERS_REVISION_1 )
      {
        BytesNeeded = NDIS_SIZEOF_OFFLOAD_PARAMETERS_REVISION_1;
        Status = NDIS_STATUS_INVALID_LENGTH;
        break;
      }

      if ( !XENAMP_NDIS_OBJECT_VALID(&pAdmin->Header,
                                     NDIS_OFFLOAD_PARAMETERS_REVISION_1,
                                     NDIS_OBJECT_TYPE_DEFAULT,
                                     NDIS_SIZEOF_OFFLOAD_PARAMETERS_REVISION_1 ))
      {
        BytesRead = sizeof(NDIS_OBJECT_HEADER);
        Status = NDIS_STATUS_INVALID_DATA;
        break;
      }

      XMP_NIC_SET_ADMIN_OFFLOADS(pNicCtx, pAdmin);
      xmpNicSetCkoFlags(pNicCtx);
      xmpNicInitOffloadCapabilities(pNicCtx, &pNicCtx->OffloadCapabilities);    
       /* TODO: Generate event */
      BytesRead = NDIS_SIZEOF_OFFLOAD_PARAMETERS_REVISION_1;
      Status    = NDIS_STATUS_SUCCESS;

      XENAMP_NDIS_OBJECT_INIT(&StatusIndication.Header,
         NDIS_OBJECT_TYPE_STATUS_INDICATION,
         NDIS_STATUS_INDICATION_REVISION_1,
         sizeof(NDIS_STATUS_INDICATION));

      StatusIndication.SourceHandle = pNicCtx->hMPAdapter;
      StatusIndication.PortNumber = 0;
      StatusIndication.StatusCode = NDIS_STATUS_TASK_OFFLOAD_CURRENT_CONFIG;
      StatusIndication.Flags = 0;
      StatusIndication.DestinationHandle = NULL;
      StatusIndication.RequestId = NdisRequest->RequestId;
      StatusIndication.StatusBuffer = &pNicCtx->OffloadCapabilities;
      StatusIndication.StatusBufferSize = sizeof(NDIS_OFFLOAD);
      NdisMIndicateStatusEx(pNicCtx->hMPAdapter, &StatusIndication);
    }
    break;
    
  case OID_GEN_HD_SPLIT_PARAMETERS:
     {
       NDIS_HD_SPLIT_PARAMETERS *pHdSplit;
    
       pHdSplit  = (NDIS_HD_SPLIT_PARAMETERS *) InformationBuffer;
       if ( InformationBufferLength < NDIS_SIZEOF_HD_SPLIT_PARAMETERS_REVISION_1 )
       {
         BytesNeeded = NDIS_SIZEOF_HD_SPLIT_PARAMETERS_REVISION_1;
         Status = NDIS_STATUS_INVALID_LENGTH;
         break;
       }

       if ( !XENAMP_NDIS_OBJECT_VALID(&pHdSplit->Header,
                                    NDIS_HD_SPLIT_PARAMETERS_REVISION_1,
                                    NDIS_OBJECT_TYPE_DEFAULT,                                     
                                    NDIS_SIZEOF_HD_SPLIT_PARAMETERS_REVISION_1 ))
       {
         BytesRead = sizeof(NDIS_OBJECT_HEADER);
         Status = NDIS_STATUS_INVALID_DATA;
         break;
       }
      
       if( bit(pHdSplit->HDSplitCombineFlags, NDIS_HD_SPLIT_COMBINE_ALL_HEADERS) ) 
         bis( pNicCtx->Flags, XMP_NIC_FLAGS_RX_SPLIT_COMBINE ); 
       else
         bic( pNicCtx->Flags, XMP_NIC_FLAGS_RX_SPLIT_COMBINE ); 
    }
    break;

  default:
    XMPTRACE(XMP_DBG_INFO, ("xmpSetInformation: unsupported OID=%lx\n", Oid));
    Status = xmpDiagSetInformation(
                                   pNicCtx, 
                                   Oid, 
                                   InformationBuffer, 
                                   InformationBufferLength,
                                   &BytesRead,
                                   &BytesNeeded);
    break;
  }

  NdisRequest->DATA.SET_INFORMATION.BytesRead = BytesRead;
  NdisRequest->DATA.SET_INFORMATION.BytesNeeded = BytesNeeded;

  XMPTRACE(XMP_DBG_REQ, ("<== xmpSetInformation: Status=%x\n", Status));
  return Status;
}
static
VOID RSSCalcHash_Unsafe(
                PARANDIS_RSS_PARAMS *RSSParameters,
                PVOID dataBuffer,
                PNET_PACKET_INFO packetInfo)
{
    HASH_CALC_SG_BUF_ENTRY sgBuff[3];
    ULONG hashTypes = NDIS_RSS_HASH_TYPE_FROM_HASH_INFO(RSSParameters->ActiveHashingSettings.HashInformation);

    if(packetInfo->isIP4)
    {
        if(packetInfo->isTCP && (hashTypes & NDIS_HASH_TCP_IPV4))
        {
            IPv4Header *pIpHeader = (IPv4Header *) RtlOffsetToPointer(dataBuffer, packetInfo->L2HdrLen);
            TCPHeader *pTCPHeader = (TCPHeader *) RtlOffsetToPointer(pIpHeader, packetInfo->L3HdrLen);

            sgBuff[0].chunkPtr = RtlOffsetToPointer(pIpHeader, FIELD_OFFSET(IPv4Header, ip_src));
            sgBuff[0].chunkLen = RTL_FIELD_SIZE(IPv4Header, ip_src) + RTL_FIELD_SIZE(IPv4Header, ip_dest);
            sgBuff[1].chunkPtr = RtlOffsetToPointer(pTCPHeader, FIELD_OFFSET(TCPHeader, tcp_src));
            sgBuff[1].chunkLen = RTL_FIELD_SIZE(TCPHeader, tcp_src) + RTL_FIELD_SIZE(TCPHeader, tcp_dest);

            packetInfo->RSSHash.Value = ToeplitsHash(sgBuff, 2, &RSSParameters->ActiveHashingSettings.HashSecretKey[0]);
            packetInfo->RSSHash.Type = NDIS_HASH_TCP_IPV4;
            packetInfo->RSSHash.Function = NdisHashFunctionToeplitz;
            return;
        }

        if(hashTypes & NDIS_HASH_IPV4)
        {
            sgBuff[0].chunkPtr = RtlOffsetToPointer(dataBuffer, packetInfo->L2HdrLen + FIELD_OFFSET(IPv4Header, ip_src));
            sgBuff[0].chunkLen = RTL_FIELD_SIZE(IPv4Header, ip_src) + RTL_FIELD_SIZE(IPv4Header, ip_dest);

            packetInfo->RSSHash.Value = ToeplitsHash(sgBuff, 1, RSSParameters->ActiveHashingSettings.HashSecretKey);
            packetInfo->RSSHash.Type = NDIS_HASH_IPV4;
            packetInfo->RSSHash.Function = NdisHashFunctionToeplitz;
            return;
        }
    }
    else if(packetInfo->isIP6)
    {
        if(packetInfo->isTCP)
        {
            if(hashTypes & (NDIS_HASH_TCP_IPV6 | NDIS_HASH_TCP_IPV6_EX))
            {
                IPv6Header *pIpHeader =  (IPv6Header *) RtlOffsetToPointer(dataBuffer, packetInfo->L2HdrLen);
                TCPHeader  *pTCPHeader = (TCPHeader *) RtlOffsetToPointer(pIpHeader, packetInfo->L3HdrLen);

                sgBuff[0].chunkPtr = (PCHAR) GetIP6SrcAddrForHash(dataBuffer, packetInfo, hashTypes);
                sgBuff[0].chunkLen = RTL_FIELD_SIZE(IPv6Header, ip6_src_address);
                sgBuff[1].chunkPtr = (PCHAR) GetIP6DstAddrForHash(dataBuffer, packetInfo, hashTypes);
                sgBuff[1].chunkLen = RTL_FIELD_SIZE(IPv6Header, ip6_dst_address);
                sgBuff[2].chunkPtr = RtlOffsetToPointer(pTCPHeader, FIELD_OFFSET(TCPHeader, tcp_src));
                sgBuff[2].chunkLen = RTL_FIELD_SIZE(TCPHeader, tcp_src) + RTL_FIELD_SIZE(TCPHeader, tcp_dest);

                packetInfo->RSSHash.Value = ToeplitsHash(sgBuff, 3, RSSParameters->ActiveHashingSettings.HashSecretKey);
                packetInfo->RSSHash.Type = (hashTypes & NDIS_HASH_TCP_IPV6_EX) ? NDIS_HASH_TCP_IPV6_EX : NDIS_HASH_TCP_IPV6;
                packetInfo->RSSHash.Function = NdisHashFunctionToeplitz;
                return;
            }
        }

        if(hashTypes & (NDIS_HASH_IPV6 | NDIS_HASH_IPV6_EX))
        {
            sgBuff[0].chunkPtr = (PCHAR) GetIP6SrcAddrForHash(dataBuffer, packetInfo, hashTypes);
            sgBuff[0].chunkLen = RTL_FIELD_SIZE(IPv6Header, ip6_src_address);
            sgBuff[1].chunkPtr = (PCHAR) GetIP6DstAddrForHash(dataBuffer, packetInfo, hashTypes);
            sgBuff[1].chunkLen = RTL_FIELD_SIZE(IPv6Header, ip6_dst_address);

            packetInfo->RSSHash.Value = ToeplitsHash(sgBuff, 2, RSSParameters->ActiveHashingSettings.HashSecretKey);
            packetInfo->RSSHash.Type = (hashTypes & NDIS_HASH_IPV6_EX) ? NDIS_HASH_IPV6_EX : NDIS_HASH_IPV6;
            packetInfo->RSSHash.Function = NdisHashFunctionToeplitz;
            return;
        }

        if(hashTypes & NDIS_HASH_IPV6)
        {
            IPv6Header *pIpHeader = (IPv6Header *) RtlOffsetToPointer(dataBuffer, packetInfo->L2HdrLen);

            sgBuff[0].chunkPtr = RtlOffsetToPointer(pIpHeader, FIELD_OFFSET(IPv6Header, ip6_src_address));
            sgBuff[0].chunkLen = RTL_FIELD_SIZE(IPv6Header, ip6_src_address) + RTL_FIELD_SIZE(IPv6Header, ip6_dst_address);

            packetInfo->RSSHash.Value = ToeplitsHash(sgBuff, 2, RSSParameters->ActiveHashingSettings.HashSecretKey);
            packetInfo->RSSHash.Type = NDIS_HASH_IPV6;
            packetInfo->RSSHash.Function = NdisHashFunctionToeplitz;
            return;
        }
    }

    packetInfo->RSSHash.Value = 0;
    packetInfo->RSSHash.Type = 0;
    packetInfo->RSSHash.Function = 0;
}
Esempio n. 4
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;
}