blob: 1a0e459bfc231115ae283eeeef42406811bae0f0 [file] [log] [blame]
/******************************************************************************
*
* This file is provided under a dual license. When you use or
* distribute this software, you may choose to be licensed under
* version 2 of the GNU General Public License ("GPLv2 License")
* or BSD License.
*
* GPLv2 License
*
* Copyright(C) 2016 MediaTek Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See http://www.gnu.org/licenses/gpl-2.0.html for more details.
*
* BSD LICENSE
*
* Copyright(C) 2016 MediaTek Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
/*
** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/cnm_mem.c#2
*/
/*! \file "cnm_mem.c"
* \brief This file contain the management function of packet buffers and
* generic memory alloc/free functioin for mailbox message.
*
* A data packet has a fixed size of buffer, but a management
* packet can be equipped with a variable size of buffer.
*/
/*******************************************************************************
* C O M P I L E R F L A G S
********************************************************************************
*/
/*******************************************************************************
* E X T E R N A L R E F E R E N C E S
********************************************************************************
*/
#include "precomp.h"
/*******************************************************************************
* C O N S T A N T S
********************************************************************************
*/
/*******************************************************************************
* D A T A T Y P E S
********************************************************************************
*/
/*******************************************************************************
* P U B L I C D A T A
********************************************************************************
*/
/*******************************************************************************
* P R I V A T E D A T A
********************************************************************************
*/
static PUINT_8 apucStaRecType[STA_TYPE_INDEX_NUM] = {
(PUINT_8) "LEGACY",
(PUINT_8) "P2P",
(PUINT_8) "BOW"
};
static PUINT_8 apucStaRecRole[STA_ROLE_INDEX_NUM] = {
(PUINT_8) "ADHOC",
(PUINT_8) "CLIENT",
(PUINT_8) "AP",
(PUINT_8) "DLS"
};
#if CFG_SUPPORT_TDLS
/* The list of valid data rates. */
const UINT_8 aucValidDataRate[] = {
RATE_1M, /* RATE_1M_INDEX = 0 */
RATE_2M, /* RATE_2M_INDEX */
RATE_5_5M, /* RATE_5_5M_INDEX */
RATE_11M, /* RATE_11M_INDEX */
RATE_22M, /* RATE_22M_INDEX */
RATE_33M, /* RATE_33M_INDEX */
RATE_6M, /* RATE_6M_INDEX */
RATE_9M, /* RATE_9M_INDEX */
RATE_12M, /* RATE_12M_INDEX */
RATE_18M, /* RATE_18M_INDEX */
RATE_24M, /* RATE_24M_INDEX */
RATE_36M, /* RATE_36M_INDEX */
RATE_48M, /* RATE_48M_INDEX */
RATE_54M, /* RATE_54M_INDEX */
RATE_VHT_PHY, /* RATE_VHT_PHY_INDEX */
RATE_HT_PHY /* RATE_HT_PHY_INDEX */
};
#endif
/*******************************************************************************
* M A C R O S
********************************************************************************
*/
/*******************************************************************************
* F U N C T I O N D E C L A R A T I O N S
********************************************************************************
*/
static VOID cnmStaRoutinesForAbort(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec);
static VOID cnmStaRecHandleEventPkt(P_ADAPTER_T prAdapter, P_CMD_INFO_T prCmdInfo, PUINT_8 pucEventBuf);
static VOID
cnmStaSendRemoveCmd(P_ADAPTER_T prAdapter,
ENUM_STA_REC_CMD_ACTION_T eActionType, UINT_8 ucStaRecIndex, UINT_8 ucBssIndex);
/*******************************************************************************
* F U N C T I O N S
********************************************************************************
*/
/*----------------------------------------------------------------------------*/
/*!
* \brief
*
* \param[in]
*
* \return none
*/
/*----------------------------------------------------------------------------*/
P_MSDU_INFO_T cnmPktAllocWrapper(P_ADAPTER_T prAdapter, UINT_32 u4Length, PUINT_8 pucStr)
{
P_MSDU_INFO_T prMsduInfo;
prMsduInfo = cnmPktAlloc(prAdapter, u4Length);
DBGLOG(MEM, LOUD, "Alloc MSDU_INFO[0x%p] by [%s]\n", prMsduInfo, pucStr);
return prMsduInfo;
}
/*----------------------------------------------------------------------------*/
/*!
* \brief
*
* \param[in]
*
* \return none
*/
/*----------------------------------------------------------------------------*/
VOID cnmPktFreeWrapper(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo, PUINT_8 pucStr)
{
DBGLOG(MEM, LOUD, "Free MSDU_INFO[0x%p] by [%s]\n", prMsduInfo, pucStr);
cnmPktFree(prAdapter, prMsduInfo);
}
/*----------------------------------------------------------------------------*/
/*!
* \brief
*
* \param[in]
*
* \return none
*/
/*----------------------------------------------------------------------------*/
P_MSDU_INFO_T cnmPktAlloc(P_ADAPTER_T prAdapter, UINT_32 u4Length)
{
P_MSDU_INFO_T prMsduInfo;
P_QUE_T prQueList;
KAL_SPIN_LOCK_DECLARATION();
ASSERT(prAdapter);
prQueList = &prAdapter->rTxCtrl.rFreeMsduInfoList;
/* Get a free MSDU_INFO_T */
KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST);
QUEUE_REMOVE_HEAD(prQueList, prMsduInfo, P_MSDU_INFO_T);
KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST);
if (prMsduInfo) {
if (u4Length) {
prMsduInfo->prPacket = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, u4Length);
prMsduInfo->eSrc = TX_PACKET_MGMT;
if (prMsduInfo->prPacket == NULL) {
KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST);
QUEUE_INSERT_TAIL(prQueList, &prMsduInfo->rQueEntry);
KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST);
prMsduInfo = NULL;
}
} else {
prMsduInfo->prPacket = NULL;
}
}
#if DBG
if (prMsduInfo == NULL) {
DBGLOG(MEM, WARN, "\n");
DBGLOG(MEM, WARN, "MgtDesc#=%ld\n", prQueList->u4NumElem);
#if CFG_DBG_MGT_BUF
DBGLOG(MEM, WARN, "rMgtBufInfo: alloc#=%ld, free#=%ld, null#=%ld\n",
prAdapter->rMgtBufInfo.u4AllocCount,
prAdapter->rMgtBufInfo.u4FreeCount, prAdapter->rMgtBufInfo.u4AllocNullCount);
#endif
DBGLOG(MEM, WARN, "\n");
}
#endif
return prMsduInfo;
}
/*----------------------------------------------------------------------------*/
/*!
* \brief
*
* \param[in]
*
* \return none
*/
/*----------------------------------------------------------------------------*/
VOID cnmPktFree(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo)
{
P_QUE_T prQueList;
KAL_SPIN_LOCK_DECLARATION();
ASSERT(prAdapter);
if (!prMsduInfo)
return;
prQueList = &prAdapter->rTxCtrl.rFreeMsduInfoList;
/* ASSERT(prMsduInfo->prPacket); */
if (prMsduInfo->prPacket) {
cnmMemFree(prAdapter, prMsduInfo->prPacket);
prMsduInfo->prPacket = NULL;
}
KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST);
QUEUE_INSERT_TAIL(prQueList, &prMsduInfo->rQueEntry);
KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST);
}
/*----------------------------------------------------------------------------*/
/*!
* \brief This function is used to initial the MGMT/MSG memory pool.
*
* \param (none)
*
* \return (none)
*/
/*----------------------------------------------------------------------------*/
VOID cnmMemInit(P_ADAPTER_T prAdapter)
{
P_BUF_INFO_T prBufInfo;
/* Initialize Management buffer pool */
prBufInfo = &prAdapter->rMgtBufInfo;
kalMemZero(prBufInfo, sizeof(prAdapter->rMgtBufInfo));
prBufInfo->pucBuf = prAdapter->pucMgtBufCached;
/* Setup available memory blocks. 1 indicates FREE */
prBufInfo->rFreeBlocksBitmap = (BUF_BITMAP) BITS(0, MAX_NUM_OF_BUF_BLOCKS - 1);
/* Initialize Message buffer pool */
prBufInfo = &prAdapter->rMsgBufInfo;
kalMemZero(prBufInfo, sizeof(prAdapter->rMsgBufInfo));
prBufInfo->pucBuf = &prAdapter->aucMsgBuf[0];
/* Setup available memory blocks. 1 indicates FREE */
prBufInfo->rFreeBlocksBitmap = (BUF_BITMAP) BITS(0, MAX_NUM_OF_BUF_BLOCKS - 1);
return;
} /* end of cnmMemInit() */
/*----------------------------------------------------------------------------*/
/*!
* \brief Allocate MGMT/MSG memory pool.
*
* \param[in] eRamType Target RAM type.
* TCM blk_sz= 16bytes, BUF blk_sz= 256bytes
* \param[in] u4Length Length of the buffer to allocate.
*
* \retval !NULL Pointer to the start address of allocated memory.
* \retval NULL Fail to allocat memory
*/
/*----------------------------------------------------------------------------*/
PVOID cnmMemAlloc(IN P_ADAPTER_T prAdapter, IN ENUM_RAM_TYPE_T eRamType, IN UINT_32 u4Length)
{
P_BUF_INFO_T prBufInfo;
BUF_BITMAP rRequiredBitmap;
UINT_32 u4BlockNum;
UINT_32 i, u4BlkSzInPower;
PVOID pvMemory;
KAL_SPIN_LOCK_DECLARATION();
ASSERT(prAdapter);
if (u4Length == 0) {
DBGLOG(MEM, WARN, "%s: Length to be allocated is ZERO, skip!\n", __func__);
return NULL;
}
if (eRamType == RAM_TYPE_MSG && u4Length <= 256) {
prBufInfo = &prAdapter->rMsgBufInfo;
u4BlkSzInPower = MSG_BUF_BLOCK_SIZE_IN_POWER_OF_2;
u4BlockNum = (u4Length + MSG_BUF_BLOCK_SIZE - 1)
>> MSG_BUF_BLOCK_SIZE_IN_POWER_OF_2;
ASSERT(u4BlockNum <= MAX_NUM_OF_BUF_BLOCKS);
} else {
eRamType = RAM_TYPE_BUF;
prBufInfo = &prAdapter->rMgtBufInfo;
u4BlkSzInPower = MGT_BUF_BLOCK_SIZE_IN_POWER_OF_2;
u4BlockNum = (u4Length + MGT_BUF_BLOCK_SIZE - 1)
>> MGT_BUF_BLOCK_SIZE_IN_POWER_OF_2;
ASSERT(u4BlockNum <= MAX_NUM_OF_BUF_BLOCKS);
}
KAL_ACQUIRE_SPIN_LOCK(prAdapter, eRamType == RAM_TYPE_MSG ? SPIN_LOCK_MSG_BUF : SPIN_LOCK_MGT_BUF);
#if CFG_DBG_MGT_BUF
prBufInfo->u4AllocCount++;
#endif
if ((u4BlockNum > 0) && (u4BlockNum <= MAX_NUM_OF_BUF_BLOCKS)) {
/* Convert number of block into bit cluster */
rRequiredBitmap = BITS(0, u4BlockNum - 1);
for (i = 0; i <= (MAX_NUM_OF_BUF_BLOCKS - u4BlockNum); i++) {
/* Have available memory blocks */
if ((prBufInfo->rFreeBlocksBitmap & rRequiredBitmap)
== rRequiredBitmap) {
/* Clear corresponding bits of allocated memory blocks */
prBufInfo->rFreeBlocksBitmap &= ~rRequiredBitmap;
/* Store how many blocks be allocated */
prBufInfo->aucAllocatedBlockNum[i] = (UINT_8) u4BlockNum;
KAL_RELEASE_SPIN_LOCK(prAdapter,
eRamType == RAM_TYPE_MSG ? SPIN_LOCK_MSG_BUF : SPIN_LOCK_MGT_BUF);
/* Return the start address of allocated memory */
return (PVOID) (prBufInfo->pucBuf + (i << u4BlkSzInPower));
}
rRequiredBitmap <<= 1;
}
}
#if CFG_DBG_MGT_BUF
prBufInfo->u4AllocNullCount++;
#endif
/* kalMemAlloc() shall not included in spin_lock */
KAL_RELEASE_SPIN_LOCK(prAdapter, eRamType == RAM_TYPE_MSG ? SPIN_LOCK_MSG_BUF : SPIN_LOCK_MGT_BUF);
#ifdef LINUX
pvMemory = (PVOID) kalMemAlloc(u4Length, PHY_MEM_TYPE);
#else
pvMemory = (PVOID) NULL;
#endif
#if CFG_DBG_MGT_BUF
if (pvMemory)
GLUE_INC_REF_CNT(prAdapter->u4MemAllocDynamicCount);
#endif
return pvMemory;
} /* end of cnmMemAlloc() */
/*----------------------------------------------------------------------------*/
/*!
* \brief Release memory to MGT/MSG memory pool.
*
* \param pucMemory Start address of previous allocated memory
*
* \return (none)
*/
/*----------------------------------------------------------------------------*/
VOID cnmMemFree(IN P_ADAPTER_T prAdapter, IN PVOID pvMemory)
{
P_BUF_INFO_T prBufInfo;
UINT_32 u4BlockIndex;
BUF_BITMAP rAllocatedBlocksBitmap;
ENUM_RAM_TYPE_T eRamType;
KAL_SPIN_LOCK_DECLARATION();
ASSERT(prAdapter);
if (!pvMemory)
return;
/* Judge it belongs to which RAM type */
if (((ULONG) pvMemory >= (ULONG)&prAdapter->aucMsgBuf[0]) &&
((ULONG) pvMemory <= (ULONG)&prAdapter->aucMsgBuf[MSG_BUFFER_SIZE - 1])) {
prBufInfo = &prAdapter->rMsgBufInfo;
u4BlockIndex = ((ULONG) pvMemory - (ULONG) prBufInfo->pucBuf)
>> MSG_BUF_BLOCK_SIZE_IN_POWER_OF_2;
ASSERT(u4BlockIndex < MAX_NUM_OF_BUF_BLOCKS);
eRamType = RAM_TYPE_MSG;
} else if (((ULONG) pvMemory >= (ULONG) prAdapter->pucMgtBufCached) &&
((ULONG) pvMemory <= ((ULONG) prAdapter->pucMgtBufCached + MGT_BUFFER_SIZE - 1))) {
prBufInfo = &prAdapter->rMgtBufInfo;
u4BlockIndex = ((ULONG) pvMemory - (ULONG) prBufInfo->pucBuf)
>> MGT_BUF_BLOCK_SIZE_IN_POWER_OF_2;
ASSERT(u4BlockIndex < MAX_NUM_OF_BUF_BLOCKS);
eRamType = RAM_TYPE_BUF;
} else {
#ifdef LINUX
/* For Linux, it is supported because size is not needed */
kalMemFree(pvMemory, PHY_MEM_TYPE, 0);
#else
/* For Windows, it is not supported because of no size argument */
ASSERT(0);
#endif
#if CFG_DBG_MGT_BUF
GLUE_INC_REF_CNT(prAdapter->u4MemFreeDynamicCount);
#endif
return;
}
KAL_ACQUIRE_SPIN_LOCK(prAdapter, eRamType == RAM_TYPE_MSG ? SPIN_LOCK_MSG_BUF : SPIN_LOCK_MGT_BUF);
#if CFG_DBG_MGT_BUF
prBufInfo->u4FreeCount++;
#endif
/* Convert number of block into bit cluster */
ASSERT(prBufInfo->aucAllocatedBlockNum[u4BlockIndex] > 0);
rAllocatedBlocksBitmap = BITS(0, prBufInfo->aucAllocatedBlockNum[u4BlockIndex] - 1);
rAllocatedBlocksBitmap <<= u4BlockIndex;
/* Clear saved block count for this memory segment */
prBufInfo->aucAllocatedBlockNum[u4BlockIndex] = 0;
/* Set corresponding bit of released memory block */
prBufInfo->rFreeBlocksBitmap |= rAllocatedBlocksBitmap;
KAL_RELEASE_SPIN_LOCK(prAdapter, eRamType == RAM_TYPE_MSG ? SPIN_LOCK_MSG_BUF : SPIN_LOCK_MGT_BUF);
return;
} /* end of cnmMemFree() */
/*----------------------------------------------------------------------------*/
/*!
* \brief
*
* \param[in]
*
* \return none
*/
/*----------------------------------------------------------------------------*/
VOID cnmStaRecInit(P_ADAPTER_T prAdapter)
{
P_STA_RECORD_T prStaRec;
UINT_16 i;
for (i = 0; i < CFG_STA_REC_NUM; i++) {
prStaRec = &prAdapter->arStaRec[i];
prStaRec->ucIndex = (UINT_8) i;
prStaRec->fgIsInUse = FALSE;
}
}
/*----------------------------------------------------------------------------*/
/*!
* \brief
*
* \param[in]
*
* \return none
*/
/*----------------------------------------------------------------------------*/
P_STA_RECORD_T cnmStaRecAlloc(P_ADAPTER_T prAdapter, ENUM_STA_TYPE_T eStaType, UINT_8 ucBssIndex, PUINT_8 pucMacAddr)
{
P_STA_RECORD_T prStaRec;
UINT_16 i, k;
ASSERT(prAdapter);
for (i = 0; i < CFG_STA_REC_NUM; i++) {
prStaRec = &prAdapter->arStaRec[i];
if (!prStaRec->fgIsInUse) {
kalMemZero(prStaRec, sizeof(STA_RECORD_T));
prStaRec->ucIndex = (UINT_8) i;
prStaRec->ucBssIndex = ucBssIndex;
prStaRec->fgIsInUse = TRUE;
prStaRec->eStaType = eStaType;
prStaRec->ucBssIndex = ucBssIndex;
/* Initialize the SN caches for duplicate detection */
for (k = 0; k < TID_NUM + 1; k++) {
prStaRec->au2CachedSeqCtrl[k] = 0xFFFF;
prStaRec->afgIsIgnoreAmsduDuplicate[k] = FALSE;
}
/* Initialize SW TX queues in STA_REC */
for (k = 0; k < STA_WAIT_QUEUE_NUM; k++)
LINK_INITIALIZE(&prStaRec->arStaWaitQueue[k]);
#if CFG_ENABLE_PER_STA_STATISTICS && CFG_ENABLE_PKT_LIFETIME_PROFILE
prStaRec->u4TotalTxPktsNumber = 0;
prStaRec->u4TotalTxPktsTime = 0;
prStaRec->u4TotalRxPktsNumber = 0;
prStaRec->u4MaxTxPktsTime = 0;
#endif
for (k = 0; k < NUM_OF_PER_STA_TX_QUEUES; k++) {
QUEUE_INITIALIZE(&prStaRec->arTxQueue[k]);
QUEUE_INITIALIZE(&prStaRec->arPendingTxQueue[k]);
prStaRec->aprTargetQueue[k] = &prStaRec->arTxQueue[k];
}
break;
}
}
/* Sync to chip to allocate WTBL resource */
if (i < CFG_STA_REC_NUM) {
COPY_MAC_ADDR(prStaRec->aucMacAddr, pucMacAddr);
if (secPrivacySeekForEntry(prAdapter, prStaRec))
cnmStaSendUpdateCmd(prAdapter, prStaRec, NULL, FALSE);
#if DBG
else {
prStaRec->fgIsInUse = FALSE;
prStaRec = NULL;
ASSERT(FALSE);
}
#endif
} else {
prStaRec = NULL;
}
return prStaRec;
}
/*----------------------------------------------------------------------------*/
/*!
* \brief
*
* \param[in]
*
* \return none
*/
/*----------------------------------------------------------------------------*/
VOID cnmStaRecFree(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec)
{
UINT_8 ucStaRecIndex, ucBssIndex;
ASSERT(prAdapter);
if (!prStaRec)
return;
DBGLOG(RSN, INFO, "cnmStaRecFree %d", prStaRec->ucIndex);
ucStaRecIndex = prStaRec->ucIndex;
ucBssIndex = prStaRec->ucBssIndex;
cnmStaRoutinesForAbort(prAdapter, prStaRec);
cnmStaSendRemoveCmd(prAdapter, STA_REC_CMD_ACTION_STA, ucStaRecIndex, ucBssIndex);
}
/*----------------------------------------------------------------------------*/
/*!
* \brief
*
* \param[in]
*
* \return none
*/
/*----------------------------------------------------------------------------*/
static VOID cnmStaRoutinesForAbort(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec)
{
ASSERT(prAdapter);
if (!prStaRec)
return;
/* To do: free related resources, e.g. timers, buffers, etc */
cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer);
cnmTimerStopTimer(prAdapter, &prStaRec->rDeauthTxDoneTimer);
prStaRec->fgTransmitKeyExist = FALSE;
prStaRec->fgSetPwrMgtBit = FALSE;
if (prStaRec->pucAssocReqIe) {
kalMemFree(prStaRec->pucAssocReqIe, VIR_MEM_TYPE, prStaRec->u2AssocReqIeLen);
prStaRec->pucAssocReqIe = NULL;
prStaRec->u2AssocReqIeLen = 0;
}
qmDeactivateStaRec(prAdapter, prStaRec);
/* Update the driver part table setting */
secPrivacyFreeSta(prAdapter, prStaRec);
prStaRec->fgIsInUse = FALSE;
}
/*----------------------------------------------------------------------------*/
/*!
* \brief
*
* \param[in]
*
* \return none
*/
/*----------------------------------------------------------------------------*/
VOID cnmStaFreeAllStaByNetwork(P_ADAPTER_T prAdapter, UINT_8 ucBssIndex, UINT_8 ucStaRecIndexExcluded)
{
#if CFG_ENABLE_WIFI_DIRECT
P_BSS_INFO_T prBssInfo;
#endif
P_STA_RECORD_T prStaRec;
UINT_16 i;
if (ucBssIndex > MAX_BSS_INDEX)
return;
for (i = 0; i < CFG_STA_REC_NUM; i++) {
prStaRec = (P_STA_RECORD_T) &prAdapter->arStaRec[i];
if (prStaRec->fgIsInUse && prStaRec->ucBssIndex == ucBssIndex && i != ucStaRecIndexExcluded)
cnmStaRoutinesForAbort(prAdapter, prStaRec);
} /* end of for loop */
cnmStaSendRemoveCmd(prAdapter,
(ucStaRecIndexExcluded < CFG_STA_REC_NUM) ?
STA_REC_CMD_ACTION_BSS_EXCLUDE_STA : STA_REC_CMD_ACTION_BSS,
ucStaRecIndexExcluded, ucBssIndex);
#if CFG_ENABLE_WIFI_DIRECT
/* To do: Confirm if it is invoked here or other location, but it should
* be invoked after state sync of STA_REC
* Update system operation parameters for AP mode
*/
prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex);
if (prAdapter->fgIsP2PRegistered && prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT)
rlmUpdateParamsForAP(prAdapter, prBssInfo, FALSE);
#endif
}
/*----------------------------------------------------------------------------*/
/*!
* \brief
*
* \param[in]
*
* \return none
*/
/*----------------------------------------------------------------------------*/
P_STA_RECORD_T cnmGetStaRecByIndex(P_ADAPTER_T prAdapter, UINT_8 ucIndex)
{
P_STA_RECORD_T prStaRec;
ASSERT(prAdapter);
prStaRec = (ucIndex < CFG_STA_REC_NUM) ? &prAdapter->arStaRec[ucIndex] : NULL;
if (prStaRec && prStaRec->fgIsInUse == FALSE)
prStaRec = NULL;
return prStaRec;
}
/*----------------------------------------------------------------------------*/
/*!
* @brief Get STA_RECORD_T by Peer MAC Address(Usually TA).
*
* @param[in] pucPeerMacAddr Given Peer MAC Address.
*
* @retval Pointer to STA_RECORD_T, if found. NULL, if not found
*/
/*----------------------------------------------------------------------------*/
P_STA_RECORD_T cnmGetStaRecByAddress(P_ADAPTER_T prAdapter, UINT_8 ucBssIndex, PUINT_8 pucPeerMacAddr)
{
P_STA_RECORD_T prStaRec;
UINT_16 i;
ASSERT(prAdapter);
if (!pucPeerMacAddr)
return NULL;
for (i = 0; i < CFG_STA_REC_NUM; i++) {
prStaRec = &prAdapter->arStaRec[i];
if (prStaRec->fgIsInUse &&
prStaRec->ucBssIndex == ucBssIndex && EQUAL_MAC_ADDR(prStaRec->aucMacAddr, pucPeerMacAddr)) {
break;
}
}
return (i < CFG_STA_REC_NUM) ? prStaRec : NULL;
}
/*----------------------------------------------------------------------------*/
/*!
* @brief This function will change the ucStaState of STA_RECORD_T and also do
* event indication to HOST to sync the STA_RECORD_T in driver.
*
* @param[in] prStaRec Pointer to the STA_RECORD_T
* @param[in] u4NewState New STATE to change.
*
* @return (none)
*/
/*----------------------------------------------------------------------------*/
VOID cnmStaRecChangeState(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, UINT_8 ucNewState)
{
BOOLEAN fgNeedResp;
if (!prAdapter)
return;
if (!prStaRec) {
DBGLOG(MEM, WARN, "%s: StaRec is NULL, skip!\n", __func__);
return;
}
if (!prStaRec->fgIsInUse) {
DBGLOG(MEM, WARN, "%s: StaRec[%u] is not in use, skip!\n", __func__, prStaRec->ucIndex);
return;
}
/* Do nothing when following state transitions happen,
* other 6 conditions should be sync to FW, including 1-->1, 3-->3
*/
if ((ucNewState == STA_STATE_2 && prStaRec->ucStaState != STA_STATE_3) ||
(ucNewState == STA_STATE_1 && prStaRec->ucStaState == STA_STATE_2)) {
prStaRec->ucStaState = ucNewState;
return;
}
fgNeedResp = FALSE;
if (ucNewState == STA_STATE_3) {
/* secFsmEventStart(prAdapter, prStaRec); */
if (ucNewState != prStaRec->ucStaState) {
fgNeedResp = TRUE;
cnmDumpStaRec(prAdapter, prStaRec->ucIndex);
}
} else {
if (ucNewState != prStaRec->ucStaState && prStaRec->ucStaState == STA_STATE_3)
qmDeactivateStaRec(prAdapter, prStaRec);
fgNeedResp = FALSE;
}
prStaRec->ucStaState = ucNewState;
cnmStaSendUpdateCmd(prAdapter, prStaRec, NULL, fgNeedResp);
#if 1 /* Marked for MT6630 */
#if CFG_ENABLE_WIFI_DIRECT
/* To do: Confirm if it is invoked here or other location, but it should
* be invoked after state sync of STA_REC
* Update system operation parameters for AP mode
*/
if (prAdapter->fgIsP2PRegistered && (IS_STA_IN_P2P(prStaRec))) {
P_BSS_INFO_T prBssInfo;
prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex);
if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT)
rlmUpdateParamsForAP(prAdapter, prBssInfo, FALSE);
}
#endif
#endif
}
/*----------------------------------------------------------------------------*/
/*!
* @brief
*
* @param[in]
*
* @return (none)
*/
/*----------------------------------------------------------------------------*/
static VOID cnmStaRecHandleEventPkt(P_ADAPTER_T prAdapter, P_CMD_INFO_T prCmdInfo, PUINT_8 pucEventBuf)
{
P_EVENT_ACTIVATE_STA_REC_T prEventContent;
P_STA_RECORD_T prStaRec;
prEventContent = (P_EVENT_ACTIVATE_STA_REC_T) pucEventBuf;
prStaRec = cnmGetStaRecByIndex(prAdapter, prEventContent->ucStaRecIdx);
if (prStaRec && prStaRec->ucStaState == STA_STATE_3 &&
!kalMemCmp(&prStaRec->aucMacAddr[0], &prEventContent->aucMacAddr[0], MAC_ADDR_LEN)) {
qmActivateStaRec(prAdapter, prStaRec);
}
}
/*----------------------------------------------------------------------------*/
/*!
* @brief
*
* @param[in]
*
* @return (none)
*/
/*----------------------------------------------------------------------------*/
VOID cnmStaSendUpdateCmd(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, P_TXBF_PFMU_STA_INFO prTxBfPfmuStaInfo,
BOOLEAN fgNeedResp)
{
P_CMD_UPDATE_STA_RECORD_T prCmdContent;
WLAN_STATUS rStatus;
if (!prAdapter)
return;
if (!prStaRec) {
DBGLOG(MEM, WARN, "%s: StaRec is NULL, skip!\n", __func__);
return;
}
if (!prStaRec->fgIsInUse) {
DBGLOG(MEM, WARN, "%s: StaRec[%u] is not in use, skip!\n", __func__, prStaRec->ucIndex);
return;
}
/* To do: come out a mechanism to limit one STA_REC sync once for AP mode
* to avoid buffer empty case when many STAs are associated
* simultaneously.
*/
/* To do: how to avoid 2 times of allocated memory. Use Stack?
* One is here, the other is in wlanSendQueryCmd()
*/
prCmdContent = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(CMD_UPDATE_STA_RECORD_T));
/* To do: exception handle */
if (!prCmdContent) {
DBGLOG(MEM, WARN, "%s: CMD_ID_UPDATE_STA_RECORD command allocation failed\n", __func__);
return;
}
/* Reset command buffer */
kalMemZero(prCmdContent, sizeof(CMD_UPDATE_STA_RECORD_T));
if (prTxBfPfmuStaInfo)
memcpy(&prCmdContent->rTxBfPfmuInfo, prTxBfPfmuStaInfo, sizeof(TXBF_PFMU_STA_INFO));
prCmdContent->ucStaIndex = prStaRec->ucIndex;
prCmdContent->ucStaType = (UINT_8) prStaRec->eStaType;
kalMemCopy(&prCmdContent->aucMacAddr[0], &prStaRec->aucMacAddr[0], MAC_ADDR_LEN);
prCmdContent->u2AssocId = prStaRec->u2AssocId;
prCmdContent->u2ListenInterval = prStaRec->u2ListenInterval;
prCmdContent->ucBssIndex = prStaRec->ucBssIndex;
prCmdContent->ucDesiredPhyTypeSet = prStaRec->ucDesiredPhyTypeSet;
prCmdContent->u2DesiredNonHTRateSet = prStaRec->u2DesiredNonHTRateSet;
prCmdContent->u2BSSBasicRateSet = prStaRec->u2BSSBasicRateSet;
prCmdContent->ucMcsSet = prStaRec->ucMcsSet;
prCmdContent->ucSupMcs32 = (UINT_8) prStaRec->fgSupMcs32;
prCmdContent->u2HwDefaultFixedRateCode = prStaRec->u2HwDefaultFixedRateCode;
kalMemCopy(prCmdContent->aucRxMcsBitmask, prStaRec->aucRxMcsBitmask,
sizeof(prCmdContent->aucRxMcsBitmask) /*SUP_MCS_RX_BITMASK_OCTET_NUM */);
prCmdContent->u2RxHighestSupportedRate = prStaRec->u2RxHighestSupportedRate;
prCmdContent->u4TxRateInfo = prStaRec->u4TxRateInfo;
prCmdContent->u2HtCapInfo = prStaRec->u2HtCapInfo;
prCmdContent->ucNeedResp = (UINT_8) fgNeedResp;
#if !CFG_SLT_SUPPORT
if (prAdapter->rWifiVar.eRateSetting != FIXED_RATE_NONE) {
/* override rate configuration */
nicUpdateRateParams(prAdapter,
prAdapter->rWifiVar.eRateSetting,
&(prCmdContent->ucDesiredPhyTypeSet),
&(prCmdContent->u2DesiredNonHTRateSet),
&(prCmdContent->u2BSSBasicRateSet),
&(prCmdContent->ucMcsSet),
&(prCmdContent->ucSupMcs32), &(prCmdContent->u2HtCapInfo));
}
#endif
prCmdContent->ucIsQoS = prStaRec->fgIsQoS;
prCmdContent->ucIsUapsdSupported = prStaRec->fgIsUapsdSupported;
prCmdContent->ucStaState = prStaRec->ucStaState;
prCmdContent->ucAmpduParam = prStaRec->ucAmpduParam;
prCmdContent->u2HtExtendedCap = prStaRec->u2HtExtendedCap;
prCmdContent->u4TxBeamformingCap = prStaRec->u4TxBeamformingCap;
prCmdContent->ucAselCap = prStaRec->ucAselCap;
prCmdContent->ucRCPI = prStaRec->ucRCPI;
prCmdContent->u4VhtCapInfo = prStaRec->u4VhtCapInfo;
prCmdContent->u2VhtRxMcsMap = prStaRec->u2VhtRxMcsMap;
prCmdContent->u2VhtRxHighestSupportedDataRate = prStaRec->u2VhtRxHighestSupportedDataRate;
prCmdContent->u2VhtTxMcsMap = prStaRec->u2VhtTxMcsMap;
prCmdContent->u2VhtTxHighestSupportedDataRate = prStaRec->u2VhtTxHighestSupportedDataRate;
prCmdContent->ucVhtOpMode = prStaRec->ucVhtOpMode;
prCmdContent->ucUapsdAc = prStaRec->ucBmpTriggerAC | (prStaRec->ucBmpDeliveryAC << 4);
prCmdContent->ucUapsdSp = prStaRec->ucUapsdSp;
prCmdContent->ucWlanIndex = prStaRec->ucWlanIndex;
prCmdContent->ucBMCWlanIndex = WTBL_RESERVED_ENTRY;
prCmdContent->ucTrafficDataType = prStaRec->ucTrafficDataType;
prCmdContent->ucTxGfMode = prStaRec->ucTxGfMode;
prCmdContent->ucTxSgiMode = prStaRec->ucTxSgiMode;
prCmdContent->ucTxStbcMode = prStaRec->ucTxStbcMode;
prCmdContent->u4FixedPhyRate = prStaRec->u4FixedPhyRate;
prCmdContent->u2MaxLinkSpeed = prStaRec->u2MaxLinkSpeed;
prCmdContent->u2MinLinkSpeed = prStaRec->u2MinLinkSpeed;
prCmdContent->u4Flags = prStaRec->u4Flags;
prCmdContent->ucTxAmpdu = prAdapter->rWifiVar.ucAmpduTx;
prCmdContent->ucRxAmpdu = prAdapter->rWifiVar.ucAmpduRx;
/* AMSDU in AMPDU global configuration */
prCmdContent->ucTxAmsduInAmpdu = prAdapter->rWifiVar.ucAmsduInAmpduTx;
prCmdContent->ucRxAmsduInAmpdu = prAdapter->rWifiVar.ucAmsduInAmpduRx;
if ((prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11AC) ||
(prStaRec->u4Flags & MTK_SYNERGY_CAP_SUPPORT_24G_MCS89)) {
/* VHT pear AMSDU in AMPDU configuration */
prCmdContent->ucTxAmsduInAmpdu &= prAdapter->rWifiVar.ucVhtAmsduInAmpduTx;
prCmdContent->ucRxAmsduInAmpdu &= prAdapter->rWifiVar.ucVhtAmsduInAmpduRx;
} else if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11N) {
/* HT peer AMSDU in AMPDU configuration */
prCmdContent->ucTxAmsduInAmpdu &= prAdapter->rWifiVar.ucHtAmsduInAmpduTx;
prCmdContent->ucRxAmsduInAmpdu &= prAdapter->rWifiVar.ucHtAmsduInAmpduRx;
}
prCmdContent->u4TxMaxAmsduInAmpduLen = prAdapter->rWifiVar.u4TxMaxAmsduInAmpduLen;
prCmdContent->ucTxBaSize = prAdapter->rWifiVar.ucTxBaSize;
if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11AC)
prCmdContent->ucRxBaSize = prAdapter->rWifiVar.ucRxVhtBaSize;
else
prCmdContent->ucRxBaSize = prAdapter->rWifiVar.ucRxHtBaSize;
/* RTS Policy */
if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucSigTaRts)) {
if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucDynBwRts))
prCmdContent->ucRtsPolicy = RTS_POLICY_DYNAMIC_BW;
else
prCmdContent->ucRtsPolicy = RTS_POLICY_STATIC_BW;
} else
prCmdContent->ucRtsPolicy = RTS_POLICY_LEGACY;
DBGLOG(REQ, INFO, "Update StaRec[%u] WIDX[%u] State[%u] Type[%u] BssIdx[%u] AID[%u]\n",
prCmdContent->ucStaIndex,
prCmdContent->ucWlanIndex,
prCmdContent->ucStaState, prCmdContent->ucStaType, prCmdContent->ucBssIndex, prCmdContent->u2AssocId);
DBGLOG(REQ, INFO, "Update StaRec[%u] QoS[%u] UAPSD[%u]\n",
prCmdContent->ucStaIndex, prCmdContent->ucIsQoS, prCmdContent->ucIsUapsdSupported);
rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */
CMD_ID_UPDATE_STA_RECORD, /* ucCID */
TRUE, /* fgSetQuery */
fgNeedResp, /* fgNeedResp */
FALSE, /* fgIsOid */
fgNeedResp ? cnmStaRecHandleEventPkt : NULL, NULL,
/* pfCmdTimeoutHandler */
sizeof(CMD_UPDATE_STA_RECORD_T), /* u4SetQueryInfoLen */
(PUINT_8) prCmdContent, /* pucInfoBuffer */
NULL, /* pvSetQueryBuffer */
0 /* u4SetQueryBufferLen */
);
cnmMemFree(prAdapter, prCmdContent);
if (rStatus != WLAN_STATUS_PENDING)
DBGLOG(MEM, WARN, "%s: CMD_ID_UPDATE_STA_RECORD result 0x%08x\n", __func__, rStatus);
}
/*----------------------------------------------------------------------------*/
/*!
* @brief
*
* @param[in]
*
* @return (none)
*/
/*----------------------------------------------------------------------------*/
static VOID
cnmStaSendRemoveCmd(P_ADAPTER_T prAdapter,
ENUM_STA_REC_CMD_ACTION_T eActionType, UINT_8 ucStaRecIndex, UINT_8 ucBssIndex)
{
CMD_REMOVE_STA_RECORD_T rCmdContent;
WLAN_STATUS rStatus;
ASSERT(prAdapter);
rCmdContent.ucActionType = (UINT_8) eActionType;
rCmdContent.ucStaIndex = ucStaRecIndex;
rCmdContent.ucBssIndex = ucBssIndex;
rCmdContent.ucReserved = 0;
rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */
CMD_ID_REMOVE_STA_RECORD, /* ucCID */
TRUE, /* fgSetQuery */
FALSE, /* fgNeedResp */
FALSE, /* fgIsOid */
NULL, /* pfCmdDoneHandler */
NULL, /* pfCmdTimeoutHandler */
sizeof(CMD_REMOVE_STA_RECORD_T), /* u4SetQueryInfoLen */
(PUINT_8) &rCmdContent, /* pucInfoBuffer */
NULL, /* pvSetQueryBuffer */
0 /* u4SetQueryBufferLen */
);
if (rStatus != WLAN_STATUS_PENDING)
DBGLOG(MEM, WARN, "%s: CMD_ID_REMOVE_STA_RECORD result 0x%08x\n", __func__, rStatus);
}
PUINT_8 cnmStaRecGetTypeString(ENUM_STA_TYPE_T eStaType)
{
PUINT_8 pucTypeString = NULL;
if (eStaType & STA_TYPE_LEGACY_MASK)
pucTypeString = apucStaRecType[STA_TYPE_LEGACY_INDEX];
if (eStaType & STA_TYPE_P2P_MASK)
pucTypeString = apucStaRecType[STA_TYPE_P2P_INDEX];
if (eStaType & STA_TYPE_BOW_MASK)
pucTypeString = apucStaRecType[STA_TYPE_BOW_INDEX];
return pucTypeString;
}
PUINT_8 cnmStaRecGetRoleString(ENUM_STA_TYPE_T eStaType)
{
PUINT_8 pucRoleString = NULL;
if (eStaType & STA_TYPE_ADHOC_MASK)
pucRoleString = apucStaRecRole[STA_ROLE_ADHOC_INDEX - STA_ROLE_BASE_INDEX];
if (eStaType & STA_TYPE_CLIENT_MASK)
pucRoleString = apucStaRecRole[STA_ROLE_CLIENT_INDEX - STA_ROLE_BASE_INDEX];
if (eStaType & STA_TYPE_AP_MASK)
pucRoleString = apucStaRecRole[STA_ROLE_AP_INDEX - STA_ROLE_BASE_INDEX];
if (eStaType & STA_TYPE_DLS_MASK)
pucRoleString = apucStaRecRole[STA_ROLE_DLS_INDEX - STA_ROLE_BASE_INDEX];
return pucRoleString;
}
/*----------------------------------------------------------------------------*/
/*!
* @brief
*
* @param[in]
*
* @return (none)
*/
/*----------------------------------------------------------------------------*/
VOID cnmDumpStaRec(IN P_ADAPTER_T prAdapter, IN UINT_8 ucStaRecIdx)
{
UINT_8 ucWTEntry;
UINT_32 i;
P_BSS_INFO_T prBssInfo;
P_STA_RECORD_T prStaRec;
DEBUGFUNC("cnmDumpStaRec");
prStaRec = cnmGetStaRecByIndex(prAdapter, ucStaRecIdx);
if (!prStaRec) {
DBGLOG(SW4, INFO, "Invalid StaRec index[%u], skip dump!\n", ucStaRecIdx);
return;
}
ucWTEntry = prStaRec->ucWlanIndex;
prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex);
ASSERT(prBssInfo);
DBGLOG(SW4, INFO, "============= DUMP STA[%u] ===========\n", ucStaRecIdx);
DBGLOG(SW4, INFO,
"STA_IDX[%u] BSS_IDX[%u] MAC[" MACSTR "] TYPE[%s %s] WTBL[%u] USED[%u] State[%u]\n",
prStaRec->ucIndex, prStaRec->ucBssIndex, MAC2STR(prStaRec->aucMacAddr),
cnmStaRecGetTypeString(prStaRec->eStaType),
cnmStaRecGetRoleString(prStaRec->eStaType), ucWTEntry, prStaRec->fgIsInUse, prStaRec->ucStaState);
DBGLOG(SW4, INFO, "QoS[%u] HT/VHT[%u/%u] AID[%u] WMM[%u] UAPSD[%u] SEC[%u]\n",
prStaRec->fgIsQoS,
(prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11N) ? TRUE : FALSE,
(prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11AC) ? TRUE : FALSE,
prStaRec->u2AssocId,
prStaRec->fgIsWmmSupported, prStaRec->fgIsUapsdSupported, secIsProtectedBss(prAdapter, prBssInfo));
DBGLOG(SW4, INFO, "PhyTypeSet: BSS[0x%02x] Desired[0x%02x] NonHtBasic[0x%02x]\n",
prBssInfo->ucPhyTypeSet, prStaRec->ucDesiredPhyTypeSet, prStaRec->ucNonHTBasicPhyType);
DBGLOG(SW4, INFO,
"RateSet: BssBasic[0x%04x] Operational[0x%04x] DesiredNonHT[0x%02x] DeafultFixedRate[0x%02x]\n",
prBssInfo->u2BSSBasicRateSet, prStaRec->u2OperationalRateSet,
prStaRec->u2DesiredNonHTRateSet, prStaRec->u2HwDefaultFixedRateCode);
DBGLOG(SW4, INFO, "HT Cap[0x%04x] ExtCap[0x%04x] BeemCap[0x%08x] MCS[0x%02x] MCS32[%u]\n",
prStaRec->u2HtCapInfo,
prStaRec->u2HtExtendedCap, prStaRec->u4TxBeamformingCap, prStaRec->ucMcsSet, prStaRec->fgSupMcs32);
DBGLOG(SW4, INFO, "VHT Cap[0x%08x] TxMCS[0x%04x] RxMCS[0x%04x] VhtOpMode[0x%02x]\n",
prStaRec->u4VhtCapInfo, prStaRec->u2VhtTxMcsMap, prStaRec->u2VhtRxMcsMap, prStaRec->ucVhtOpMode);
DBGLOG(SW4, INFO, "RCPI[%u] InPS[%u] TxAllowed[%u] KeyRdy[%u] AMPDU T/R[%u/%u]\n",
prStaRec->ucRCPI,
prStaRec->fgIsInPS,
prStaRec->fgIsTxAllowed, prStaRec->fgIsTxKeyReady, prStaRec->fgTxAmpduEn, prStaRec->fgRxAmpduEn);
DBGLOG(SW4, INFO, "TxQ LEN TC[0~5] [%03u:%03u:%03u:%03u:%03u:%03u]\n",
prStaRec->aprTargetQueue[0]->u4NumElem,
prStaRec->aprTargetQueue[1]->u4NumElem,
prStaRec->aprTargetQueue[2]->u4NumElem,
prStaRec->aprTargetQueue[3]->u4NumElem);
DBGLOG(SW4, INFO, "BMP AC Delivery/Trigger[%02x/%02x]\n", prStaRec->ucBmpDeliveryAC, prStaRec->ucBmpTriggerAC);
DBGLOG(SW4, INFO, "FreeQuota: Total[%u] Delivery/NonDelivery[%u/%u]\n",
prStaRec->ucFreeQuota, prStaRec->ucFreeQuotaForDelivery, prStaRec->ucFreeQuotaForNonDelivery);
DBGLOG(SW4, INFO, "aucRxMcsBitmask: [0][0x%02x] [1][0x%02x]\n",
prStaRec->aucRxMcsBitmask[0], prStaRec->aucRxMcsBitmask[1]);
for (i = 0; i < CFG_RX_MAX_BA_TID_NUM; i++) {
if (prStaRec->aprRxReorderParamRefTbl[i]) {
DBGLOG(SW4, INFO, "<Rx BA Entry TID[%u]>\n", prStaRec->aprRxReorderParamRefTbl[i]->ucTid);
DBGLOG(SW4, INFO,
" Valid[%u] WinStart/End[%u/%u] WinSize[%u] ReOrderQueLen[%u]\n",
prStaRec->aprRxReorderParamRefTbl[i]->fgIsValid,
prStaRec->aprRxReorderParamRefTbl[i]->u2WinStart,
prStaRec->aprRxReorderParamRefTbl[i]->u2WinEnd,
prStaRec->aprRxReorderParamRefTbl[i]->u2WinSize,
prStaRec->aprRxReorderParamRefTbl[i]->rReOrderQue.u4NumElem);
DBGLOG(SW4, INFO,
" Bubble Exist[%u] SN[%u]\n",
prStaRec->aprRxReorderParamRefTbl[i]->fgHasBubble,
prStaRec->aprRxReorderParamRefTbl[i]->u2FirstBubbleSn);
}
}
DBGLOG(SW4, INFO, "============= DUMP END ===========\n");
}
UINT_32 cnmDumpMemoryStatus(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuf, IN UINT_32 u4Max)
{
UINT_32 u4Len = 0;
#if CFG_DBG_MGT_BUF
P_BUF_INFO_T prBufInfo;
LOGBUF(pucBuf, u4Max, u4Len, "\n");
LOGBUF(pucBuf, u4Max, u4Len, "============= DUMP Memory Status =============\n");
LOGBUF(pucBuf, u4Max, u4Len, "Dynamic alloc OS memory count: alloc[%u] free[%u]\n",
prAdapter->u4MemAllocDynamicCount, prAdapter->u4MemFreeDynamicCount);
prBufInfo = &prAdapter->rMsgBufInfo;
LOGBUF(pucBuf, u4Max, u4Len, "MSG memory count: alloc[%u] free[%u] null[%u] bitmap[0x%08x]\n",
prBufInfo->u4AllocCount, prBufInfo->u4FreeCount,
prBufInfo->u4AllocNullCount, (UINT_32) prBufInfo->rFreeBlocksBitmap);
prBufInfo = &prAdapter->rMgtBufInfo;
LOGBUF(pucBuf, u4Max, u4Len, "MGT memory count: alloc[%u] free[%u] null[%u] bitmap[0x%08x]\n",
prBufInfo->u4AllocCount, prBufInfo->u4FreeCount,
prBufInfo->u4AllocNullCount, (UINT_32) prBufInfo->rFreeBlocksBitmap);
LOGBUF(pucBuf, u4Max, u4Len, "============= DUMP END =============\n");
#endif
return u4Len;
}
#if CFG_SUPPORT_TDLS
/*----------------------------------------------------------------------------*/
/*!
* \brief This routine is called to add a peer record.
*
* \param[in] pvAdapter Pointer to the Adapter structure.
* \param[out] pvQueryBuf A pointer to the buffer that holds the result of
* the query.
* \param[in] u4QueryBufLen The length of the query buffer.
* \param[out] pu4QueryInfoLen If the call is successful, returns the number of
* bytes written into the query buffer. If the call
* failed due to invalid length of the query buffer,
* returns the amount of storage needed.
*
* \retval WLAN_STATUS_SUCCESS
* \retval WLAN_STATUS_INVALID_LENGTH
*/
/*----------------------------------------------------------------------------*/
WLAN_STATUS /* TDLS_STATUS //prStaRec->ucNetTypeIndex */
cnmPeerAdd(P_ADAPTER_T prAdapter, PVOID pvSetBuffer, UINT_32 u4SetBufferLen, PUINT_32 pu4SetInfoLen)
{
CMD_PEER_ADD_T *prCmd;
BSS_INFO_T *prAisBssInfo;
STA_RECORD_T *prStaRec;
/* sanity check */
if ((prAdapter == NULL) || (pvSetBuffer == NULL) || (pu4SetInfoLen == NULL))
return TDLS_STATUS_FAIL;
/* init */
*pu4SetInfoLen = sizeof(CMD_PEER_ADD_T);
prCmd = (CMD_PEER_ADD_T *) pvSetBuffer;
prAisBssInfo = prAdapter->prAisBssInfo; /* for AIS only test */
if (prAisBssInfo == NULL) {
DBGLOG(TDLS, ERROR, "[%s]prAisBssInfo is NULL!", __func__);
return TDLS_STATUS_FAIL;
}
prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) prAdapter->prAisBssInfo->ucBssIndex, prCmd->aucPeerMac);
if (prStaRec == NULL) {
prStaRec =
cnmStaRecAlloc(prAdapter, STA_TYPE_DLS_PEER,
(UINT_8) prAdapter->prAisBssInfo->ucBssIndex, prCmd->aucPeerMac);
if (prStaRec == NULL)
return TDLS_STATUS_RESOURCES;
if (prAisBssInfo) {
if (prAisBssInfo->ucBssIndex)
prStaRec->ucBssIndex = prAisBssInfo->ucBssIndex;
}
/* init the prStaRec */
/* prStaRec will be zero first in cnmStaRecAlloc() */
COPY_MAC_ADDR(prStaRec->aucMacAddr, prCmd->aucPeerMac);
prStaRec->u2BSSBasicRateSet = prAisBssInfo->u2BSSBasicRateSet;
prStaRec->u2DesiredNonHTRateSet = prAdapter->rWifiVar.ucAvailablePhyTypeSet;
prStaRec->u2OperationalRateSet = prAisBssInfo->u2OperationalRateSet;
prStaRec->ucPhyTypeSet = prAisBssInfo->ucPhyTypeSet;
prStaRec->eStaType = prCmd->eStaType;
/* NOTE(Kevin): Better to change state here, not at TX Done */
cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1);
} else {
if ((prStaRec->ucStaState > STA_STATE_1) && (IS_DLS_STA(prStaRec))) {
/* TODO: Teardown the peer */
cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1);
}
}
return TDLS_STATUS_SUCCESS;
}
/*----------------------------------------------------------------------------*/
/*!
* \brief This routine is called to update a peer record.
*
* \param[in] pvAdapter Pointer to the Adapter structure.
* \param[out] pvQueryBuf A pointer to the buffer that holds the result of
* the query.
* \param[in] u4QueryBufLen The length of the query buffer.
* \param[out] pu4QueryInfoLen If the call is successful, returns the number of
* bytes written into the query buffer. If the call
* failed due to invalid length of the query buffer,
* returns the amount of storage needed.
*
* \retval WLAN_STATUS_SUCCESS
* \retval WLAN_STATUS_INVALID_LENGTH
*/
/*----------------------------------------------------------------------------*/
WLAN_STATUS /* TDLS_STATUS */
cnmPeerUpdate(P_ADAPTER_T prAdapter, PVOID pvSetBuffer, UINT_32 u4SetBufferLen, PUINT_32 pu4SetInfoLen)
{
CMD_PEER_UPDATE_T *prCmd;
BSS_INFO_T *prAisBssInfo;
STA_RECORD_T *prStaRec;
UINT_8 ucNonHTPhyTypeSet;
UINT_16 u2OperationalRateSet = 0;
UINT_8 ucRate;
UINT_16 i, j;
/* sanity check */
if ((!prAdapter) || (!pvSetBuffer) || (!pu4SetInfoLen))
return TDLS_STATUS_FAIL;
/* init */
*pu4SetInfoLen = sizeof(CMD_PEER_ADD_T);
prCmd = (CMD_PEER_UPDATE_T *) pvSetBuffer;
prAisBssInfo = prAdapter->prAisBssInfo;
if (prAisBssInfo == NULL) {
DBGLOG(TDLS, ERROR, "[%s]prAisBssInfo is NULL!", __func__);
return TDLS_STATUS_FAIL;
}
prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) prAdapter->prAisBssInfo->ucBssIndex, prCmd->aucPeerMac);
if ((!prStaRec) || !(prStaRec->fgIsInUse))
return TDLS_STATUS_FAIL;
if (!IS_DLS_STA(prStaRec))
return TDLS_STATUS_FAIL;
if (prAisBssInfo) {
if (prAisBssInfo->ucBssIndex)
prStaRec->ucBssIndex = prAisBssInfo->ucBssIndex;
}
/* update the record join time. */
GET_CURRENT_SYSTIME(&prStaRec->rUpdateTime);
/* update Station Record - Status/Reason Code */
prStaRec->u2StatusCode = prCmd->u2StatusCode;
prStaRec->u2AssocId = 0; /* no use */
prStaRec->u2ListenInterval = 0; /* unknown */
prStaRec->fgIsQoS = TRUE;
prStaRec->fgIsUapsdSupported = (prCmd->UapsdBitmap == 0) ? FALSE : TRUE;
prStaRec->u4TxBeamformingCap = 0; /* no use */
prStaRec->ucAselCap = 0; /* no use */
prStaRec->ucRCPI = 0;
prStaRec->ucBmpTriggerAC = prCmd->UapsdBitmap;
prStaRec->ucBmpDeliveryAC = prCmd->UapsdBitmap;
prStaRec->ucUapsdSp = prCmd->UapsdMaxSp;
prStaRec->eStaType = prCmd->eStaType;
/* ++ support rate */
if (prCmd->u2SupRateLen) {
for (i = 0; i < prCmd->u2SupRateLen; i++) {
if (prCmd->aucSupRate[i]) {
ucRate = prCmd->aucSupRate[i] & RATE_MASK;
/* Search all valid data rates */
for (j = 0; j < sizeof(aucValidDataRate) / sizeof(UINT_8); j++) {
if (ucRate == aucValidDataRate[j]) {
u2OperationalRateSet |= BIT(j);
break;
}
}
}
}
prStaRec->u2OperationalRateSet = u2OperationalRateSet;
prStaRec->u2BSSBasicRateSet = prAisBssInfo->u2BSSBasicRateSet;
/* 4 <5> PHY type setting */
prStaRec->ucPhyTypeSet = 0;
if (prAisBssInfo->eBand == BAND_2G4) {
if (prCmd->fgIsSupHt)
prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_HT;
/* if not 11n only */
if (!(prStaRec->u2BSSBasicRateSet & RATE_SET_BIT_HT_PHY)) {
/* check if support 11g */
if ((prStaRec->u2OperationalRateSet & RATE_SET_OFDM))
prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_ERP;
/* if not 11g only */
if (!(prStaRec->u2BSSBasicRateSet & RATE_SET_OFDM)) {
/* check if support 11b */
if ((prStaRec->u2OperationalRateSet & RATE_SET_HR_DSSS))
prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_HR_DSSS;
}
}
} else {
if (prCmd->rVHtCap.u2CapInfo)
prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_VHT;
if (prCmd->fgIsSupHt)
prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_HT;
/* if not 11n only */
if (!(prStaRec->u2BSSBasicRateSet & RATE_SET_BIT_HT_PHY)) {
/* Support 11a definitely */
prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_OFDM;
}
}
if (IS_STA_IN_AIS(prStaRec)) {
if (!((prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION3_ENABLED)
|| (prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION3_KEY_ABSENT)
|| (prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION_DISABLED)
|| (prAdapter->prGlueInfo->u2WSCAssocInfoIELen)
#if CFG_SUPPORT_WAPI
|| (prAdapter->prGlueInfo->u2WapiAssocInfoIESz)
#endif
)) {
prStaRec->ucPhyTypeSet &= ~PHY_TYPE_BIT_HT;
}
}
prStaRec->ucDesiredPhyTypeSet = prStaRec->ucPhyTypeSet & prAdapter->rWifiVar.ucAvailablePhyTypeSet;
ucNonHTPhyTypeSet = prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11ABG;
/* Check for Target BSS's non HT Phy Types */
if (ucNonHTPhyTypeSet) {
if (ucNonHTPhyTypeSet & PHY_TYPE_BIT_ERP)
prStaRec->ucNonHTBasicPhyType = PHY_TYPE_ERP_INDEX;
else if (ucNonHTPhyTypeSet & PHY_TYPE_BIT_OFDM)
prStaRec->ucNonHTBasicPhyType = PHY_TYPE_OFDM_INDEX;
else
prStaRec->ucNonHTBasicPhyType = PHY_TYPE_HR_DSSS_INDEX;
prStaRec->fgHasBasicPhyType = TRUE;
} else {
/* Use mandatory for 11N only BSS */
ASSERT(prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N);
{
/* TODO(Kevin): which value should we set for 11n ? ERP ? */
prStaRec->ucNonHTBasicPhyType = PHY_TYPE_HR_DSSS_INDEX;
}
prStaRec->fgHasBasicPhyType = FALSE;
}
}
/* ++HT capability */
if (prCmd->fgIsSupHt) {
prAdapter->rWifiVar.eRateSetting = FIXED_RATE_NONE;
prStaRec->ucDesiredPhyTypeSet |= PHY_TYPE_BIT_HT;
prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_HT;
prStaRec->u2HtCapInfo = prCmd->rHtCap.u2CapInfo;
prStaRec->ucAmpduParam = prCmd->rHtCap.ucAmpduParamsInfo;
prStaRec->u2HtExtendedCap = prCmd->rHtCap.u2ExtHtCapInfo;
prStaRec->u4TxBeamformingCap = prCmd->rHtCap.u4TxBfCapInfo;
prStaRec->ucAselCap = prCmd->rHtCap.ucAntennaSelInfo;
prStaRec->ucMcsSet = prCmd->rHtCap.rMCS.arRxMask[0];
prStaRec->fgSupMcs32 = (prCmd->rHtCap.rMCS.arRxMask[32 / 8] & BIT(0)) ? TRUE : FALSE;
kalMemCopy(prStaRec->aucRxMcsBitmask, prCmd->rHtCap.rMCS.arRxMask, sizeof(prStaRec->aucRxMcsBitmask));
}
/* TODO ++VHT */
cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3);
return TDLS_STATUS_SUCCESS;
}
/*----------------------------------------------------------------------------*/
/*!
* @brief Get TDLS peer STA_RECORD_T by Peer MAC Address(Usually TA).
*
* @param[in] pucPeerMacAddr Given Peer MAC Address.
*
* @retval Pointer to STA_RECORD_T, if found. NULL, if not found
*/
/*----------------------------------------------------------------------------*/
P_STA_RECORD_T cnmGetTdlsPeerByAddress(P_ADAPTER_T prAdapter, UINT_8 ucBssIndex, UINT_8 aucPeerMACAddress[])
{
P_STA_RECORD_T prStaRec;
UINT_16 i;
ASSERT(prAdapter);
ASSERT(aucPeerMACAddress);
for (i = 0; i < CFG_STA_REC_NUM; i++) {
prStaRec = &prAdapter->arStaRec[i];
if (prStaRec) {
if (prStaRec->fgIsInUse &&
prStaRec->eStaType == STA_TYPE_DLS_PEER &&
EQUAL_MAC_ADDR(prStaRec->aucMacAddr, aucPeerMACAddress)) {
break;
}
}
}
return prStaRec;
}
#endif