blob: 9b4f77290d5eefa6458de0e83721e10f74fe93f8 [file] [edit]
/******************************************************************************
*
* 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.
*
*****************************************************************************/
/******************************************************************************
*[File] hif_pdma.c
*[Version] v1.0
*[Revision Date] 2015-09-08
*[Author]
*[Description]
* The program provides PDMA HIF APIs
*[Copyright]
* Copyright (C) 2015 MediaTek Incorporation. All Rights Reserved.
******************************************************************************/
/*******************************************************************************
* 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"
#include "hif_pdma.h"
#include <linux/mm.h>
#ifndef CONFIG_X86
#include <asm/memory.h>
#endif
#include "mt66xx_reg.h"
/*******************************************************************************
* C O N S T A N T S
*******************************************************************************
*/
#define RX_RESPONSE_TIMEOUT (3000)
/*******************************************************************************
* 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
*******************************************************************************
*/
/*******************************************************************************
* 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
*******************************************************************************
*/
/*******************************************************************************
* F U N C T I O N S
*******************************************************************************
*/
/*----------------------------------------------------------------------------*/
/*!
* @brief check is timeout or not
*
* @param u4StartTime start time
*
* @param u4Timeout timeout value
*
* @return is timeout
*/
/*----------------------------------------------------------------------------*/
static inline bool halIsTimeout(uint32_t u4StartTime, uint32_t u4Timeout)
{
uint32_t u4CurTime = kalGetTimeTick();
uint32_t u4Time = 0;
if (u4CurTime >= u4StartTime)
u4Time = u4CurTime - u4StartTime;
else
u4Time = u4CurTime + (0xFFFFFFFF - u4StartTime);
return u4Time > u4Timeout;
}
/*----------------------------------------------------------------------------*/
/*!
* @brief Verify the CHIP ID
*
* @param prAdapter a pointer to adapter private data structure.
*
*
* @retval TRUE CHIP ID is the same as the setting compiled
* @retval FALSE CHIP ID is different from the setting compiled
*/
/*----------------------------------------------------------------------------*/
u_int8_t halVerifyChipID(IN struct ADAPTER *prAdapter)
{
struct mt66xx_chip_info *prChipInfo;
struct BUS_INFO *prBusInfo;
uint32_t u4CIR = 0;
ASSERT(prAdapter);
prChipInfo = prAdapter->chip_info;
prBusInfo = prChipInfo->bus_info;
if (prAdapter->fgIsReadRevID || !prChipInfo->should_verify_chip_id)
return TRUE;
HAL_MCR_RD(prAdapter, prBusInfo->top_cfg_base + TOP_HW_CONTROL, &u4CIR);
DBGLOG(INIT, INFO, "WCIR_CHIP_ID = 0x%x, chip_id = 0x%x\n",
(uint32_t)(u4CIR & WCIR_CHIP_ID), prChipInfo->chip_id);
if ((u4CIR & WCIR_CHIP_ID) != prChipInfo->chip_id)
return FALSE;
HAL_MCR_RD(prAdapter, prBusInfo->top_cfg_base + TOP_HW_VERSION, &u4CIR);
prAdapter->ucRevID = (uint8_t)(u4CIR & 0xF);
prAdapter->fgIsReadRevID = TRUE;
return TRUE;
}
uint32_t halRxWaitResponse(IN struct ADAPTER *prAdapter, IN uint8_t ucPortIdx,
OUT uint8_t *pucRspBuffer, IN uint32_t u4MaxRespBufferLen,
OUT uint32_t *pu4Length)
{
struct GLUE_INFO *prGlueInfo;
uint32_t u4PktLen = 0, u4Value = 0, u4Time;
u_int8_t fgStatus;
DEBUGFUNC("nicRxWaitResponse");
ASSERT(prAdapter);
prGlueInfo = prAdapter->prGlueInfo;
ASSERT(prGlueInfo);
ASSERT(pucRspBuffer);
ASSERT(ucPortIdx < 2);
u4Time = kalGetTimeTick();
u4PktLen = u4MaxRespBufferLen;
do {
if (wlanIsChipNoAck(prAdapter)) {
DBGLOG(HAL, ERROR, "Chip No Ack\n");
return WLAN_STATUS_FAILURE;
}
fgStatus = kalDevPortRead(
prGlueInfo, HIF_IMG_DL_STATUS_PORT_IDX, u4PktLen,
pucRspBuffer, HIF_RX_COALESCING_BUFFER_SIZE);
if (fgStatus) {
*pu4Length = u4PktLen;
break;
}
if (halIsTimeout(u4Time, RX_RESPONSE_TIMEOUT)) {
kalDevRegRead(prGlueInfo, CONN_HIF_ON_DBGCR01,
&u4Value);
DBGLOG(HAL, ERROR, "CONN_HIF_ON_DBGCR01[0x%x]\n",
u4Value);
return WLAN_STATUS_FAILURE;
}
/* Response packet is not ready */
kalUdelay(50);
} while (TRUE);
return WLAN_STATUS_SUCCESS;
}
/*----------------------------------------------------------------------------*/
/*!
* @brief enable global interrupt
*
* @param prAdapter pointer to the Adapter handler
*
* @return (none)
*/
/*----------------------------------------------------------------------------*/
void halEnableInterrupt(IN struct ADAPTER *prAdapter)
{
struct BUS_INFO *prBusInfo = NULL;
ASSERT(prAdapter);
prBusInfo = prAdapter->chip_info->bus_info;
if (prBusInfo->enableInterrupt)
prBusInfo->enableInterrupt(prAdapter);
prAdapter->fgIsIntEnable = TRUE;
}
/*----------------------------------------------------------------------------*/
/*!
* @brief disable global interrupt
*
* @param prAdapter pointer to the Adapter handler
*
* @return (none)
*/
/*----------------------------------------------------------------------------*/
void halDisableInterrupt(IN struct ADAPTER *prAdapter)
{
struct BUS_INFO *prBusInfo;
ASSERT(prAdapter);
prBusInfo = prAdapter->chip_info->bus_info;
if (prBusInfo->disableInterrupt)
prBusInfo->disableInterrupt(prAdapter);
prAdapter->fgIsIntEnable = FALSE;
}
static u_int8_t halDriverOwnCheckCR4(struct ADAPTER *prAdapter)
{
struct mt66xx_chip_info *prChipInfo;
uint32_t u4CurrTick;
uint32_t ready_bits;
u_int8_t fgStatus = TRUE;
u_int8_t fgReady = FALSE;
u_int8_t fgDummyReq = FALSE;
bool fgTimeout;
ASSERT(prAdapter);
prChipInfo = prAdapter->chip_info;
ready_bits = prChipInfo->sw_ready_bits;
HAL_WIFI_FUNC_READY_CHECK(prAdapter,
WIFI_FUNC_DUMMY_REQ, &fgDummyReq);
u4CurrTick = kalGetTimeTick();
/* Wait CR4 ready */
while (1) {
fgTimeout = halIsTimeout(u4CurrTick,
LP_OWN_BACK_TOTAL_DELAY_MS);
HAL_WIFI_FUNC_READY_CHECK(prAdapter, ready_bits, &fgReady);
if (fgReady) {
break;
} else if (kalIsCardRemoved(prAdapter->prGlueInfo) ||
fgIsBusAccessFailed || fgTimeout
|| wlanIsChipNoAck(prAdapter)) {
DBGLOG(INIT, INFO,
"Skip waiting CR4 ready for next %ums\n",
LP_OWN_BACK_FAILED_LOG_SKIP_MS);
fgStatus = FALSE;
#if CFG_CHIP_RESET_SUPPORT
glGetRstReason(RST_DRV_OWN_FAIL);
GL_RESET_TRIGGER(prAdapter,
RST_FLAG_CHIP_RESET);
#endif
break;
}
/* Delay for CR4 to complete its operation. */
kalUsleep_range(LP_OWN_BACK_LOOP_DELAY_MIN_US,
LP_OWN_BACK_LOOP_DELAY_MAX_US);
}
/* Send dummy cmd and clear flag */
if (fgDummyReq) {
wlanSendDummyCmd(prAdapter, FALSE);
HAL_CLEAR_DUMMY_REQ(prAdapter);
}
return fgStatus;
}
static void halDriverOwnTimeout(struct ADAPTER *prAdapter,
uint32_t u4CurrTick, u_int8_t fgTimeout)
{
if ((prAdapter->u4OwnFailedCount == 0) ||
CHECK_FOR_TIMEOUT(u4CurrTick, prAdapter->rLastOwnFailedLogTime,
MSEC_TO_SYSTIME(LP_OWN_BACK_FAILED_LOG_SKIP_MS))
) {
DBGLOG(INIT, ERROR,
"LP cannot be own back, Timeout[%u](%ums), BusAccessError[%u]",
fgTimeout,
kalGetTimeTick() - u4CurrTick,
fgIsBusAccessFailed);
DBGLOG(INIT, ERROR,
"Resetting[%u], CardRemoved[%u] NoAck[%u] Cnt[%u]\n",
kalIsResetting(),
kalIsCardRemoved(prAdapter->prGlueInfo),
wlanIsChipNoAck(prAdapter),
prAdapter->u4OwnFailedCount);
DBGLOG(INIT, INFO,
"Skip LP own back failed log for next %ums\n",
LP_OWN_BACK_FAILED_LOG_SKIP_MS);
prAdapter->u4OwnFailedLogCount++;
if (prAdapter->u4OwnFailedLogCount >
LP_OWN_BACK_FAILED_RESET_CNT) {
halShowHostCsrInfo(prAdapter);
#if CFG_CHIP_RESET_SUPPORT
/* Trigger RESET */
glGetRstReason(RST_DRV_OWN_FAIL);
GL_RESET_TRIGGER(prAdapter, RST_FLAG_CHIP_RESET);
#endif
}
GET_CURRENT_SYSTIME(&prAdapter->rLastOwnFailedLogTime);
}
prAdapter->u4OwnFailedCount++;
}
/*----------------------------------------------------------------------------*/
/*!
* \brief This routine is used to process the POWER OFF procedure.
*
* \param[in] pvAdapter Pointer to the Adapter structure.
*
* \return (none)
*/
/*----------------------------------------------------------------------------*/
u_int8_t halSetDriverOwn(IN struct ADAPTER *prAdapter)
{
struct mt66xx_chip_info *prChipInfo;
struct BUS_INFO *prBusInfo;
u_int8_t fgStatus = TRUE;
uint32_t i, u4CurrTick, u4WriteTick, u4WriteTickTemp;
u_int8_t fgTimeout;
u_int8_t fgResult;
KAL_TIME_INTERVAL_DECLARATION();
ASSERT(prAdapter);
prChipInfo = prAdapter->chip_info;
prBusInfo = prChipInfo->bus_info;
GLUE_INC_REF_CNT(prAdapter->u4PwrCtrlBlockCnt);
if (prAdapter->fgIsFwOwn == FALSE)
return fgStatus;
DBGLOG(INIT, TRACE, "DRIVER OWN Start\n");
KAL_REC_TIME_START();
u4WriteTick = 0;
u4CurrTick = kalGetTimeTick();
i = 0;
#if CFG_SUPPORT_PCIE_ASPM
glBusConfigASPM(prAdapter->prGlueInfo->rHifInfo.pdev->bus->self,
DISABLE_ASPM_L1);
glBusConfigASPM(prAdapter->prGlueInfo->rHifInfo.pdev,
DISABLE_ASPM_L1);
#endif
/* PCIE/AXI need to do clear own, then could start polling status */
HAL_LP_OWN_CLR(prAdapter, &fgResult);
fgResult = FALSE;
while (1) {
if (!prBusInfo->fgCheckDriverOwnInt ||
test_bit(GLUE_FLAG_INT_BIT, &prAdapter->prGlueInfo->ulFlag))
HAL_LP_OWN_RD(prAdapter, &fgResult);
fgTimeout = ((kalGetTimeTick() - u4CurrTick) >
LP_OWN_BACK_TOTAL_DELAY_MS) ? TRUE : FALSE;
if (fgResult) {
/* Check WPDMA FW own interrupt status and clear */
if (prBusInfo->fgCheckDriverOwnInt)
HAL_MCR_WR(prAdapter, WPDMA_INT_STA,
WPDMA_FW_CLR_OWN_INT);
prAdapter->fgIsFwOwn = FALSE;
prAdapter->u4OwnFailedCount = 0;
prAdapter->u4OwnFailedLogCount = 0;
break;
} else if ((i > LP_OWN_BACK_FAILED_RETRY_CNT) &&
(kalIsCardRemoved(prAdapter->prGlueInfo) ||
fgIsBusAccessFailed || fgTimeout ||
wlanIsChipNoAck(prAdapter))) {
halDriverOwnTimeout(prAdapter, u4CurrTick, fgTimeout);
fgStatus = FALSE;
break;
}
u4WriteTickTemp = kalGetTimeTick();
if ((i == 0) || TIME_AFTER(u4WriteTickTemp,
(u4WriteTick + LP_OWN_REQ_CLR_INTERVAL_MS))) {
/* Driver get LP ownership per 200 ms,
* to avoid iteration time not accurate
*/
HAL_LP_OWN_CLR(prAdapter, &fgResult);
u4WriteTick = u4WriteTickTemp;
}
/* Delay for LP engine to complete its operation. */
kalUsleep_range(LP_OWN_BACK_LOOP_DELAY_MIN_US,
LP_OWN_BACK_LOOP_DELAY_MAX_US);
i++;
}
/* For Low power Test */
/* 1. Driver need to polling until CR4 ready,
* then could do normal Tx/Rx
* 2. After CR4 ready, send a dummy command to change data path
* to store-forward mode
*/
if (prAdapter->fgIsFwDownloaded && prChipInfo->is_support_cr4)
fgStatus &= halDriverOwnCheckCR4(prAdapter);
if (fgStatus) {
/* Check consys enter sleep mode DummyReg(0x0F) */
if (prBusInfo->checkDummyReg)
prBusInfo->checkDummyReg(prAdapter->prGlueInfo);
}
KAL_REC_TIME_END();
DBGLOG(INIT, INFO,
"DRIVER OWN Done[%lu us]\n", KAL_GET_TIME_INTERVAL());
return fgStatus;
}
/*----------------------------------------------------------------------------*/
/*!
* \brief This routine is used to process the POWER ON procedure.
*
* \param[in] pvAdapter Pointer to the Adapter structure.
*
* \return (none)
*/
/*----------------------------------------------------------------------------*/
void halSetFWOwn(IN struct ADAPTER *prAdapter, IN u_int8_t fgEnableGlobalInt)
{
struct BUS_INFO *prBusInfo;
u_int8_t fgResult;
ASSERT(prAdapter);
ASSERT(prAdapter->u4PwrCtrlBlockCnt != 0);
prBusInfo = prAdapter->chip_info->bus_info;
/* Decrease Block to Enter Low Power Semaphore count */
GLUE_DEC_REF_CNT(prAdapter->u4PwrCtrlBlockCnt);
if (!(prAdapter->fgWiFiInSleepyState &&
(prAdapter->u4PwrCtrlBlockCnt == 0)))
return;
if (prAdapter->fgIsFwOwn == TRUE)
return;
if (nicProcessIST(prAdapter) != WLAN_STATUS_NOT_INDICATING) {
DBGLOG(INIT, STATE, "Skip FW OWN due to pending INT\n");
/* pending interrupts */
return;
}
if (fgEnableGlobalInt) {
prAdapter->fgIsIntEnableWithLPOwnSet = TRUE;
} else {
/* Write sleep mode magic num to dummy reg */
if (prBusInfo->setDummyReg)
prBusInfo->setDummyReg(prAdapter->prGlueInfo);
HAL_LP_OWN_SET(prAdapter, &fgResult);
prAdapter->fgIsFwOwn = TRUE;
#if CFG_SUPPORT_PCIE_ASPM
glBusConfigASPM(prAdapter->prGlueInfo->rHifInfo.pdev->bus->self,
ENABLE_ASPM_L1);
glBusConfigASPM(prAdapter->prGlueInfo->rHifInfo.pdev,
ENABLE_ASPM_L1);
#endif
DBGLOG(INIT, TRACE, "FW OWN:%u\n", fgResult);
}
}
void halWakeUpWiFi(IN struct ADAPTER *prAdapter)
{
struct BUS_INFO *prBusInfo;
ASSERT(prAdapter);
prBusInfo = prAdapter->chip_info->bus_info;
if (prBusInfo->wakeUpWiFi)
prBusInfo->wakeUpWiFi(prAdapter);
}
void halTxCancelSendingCmd(IN struct ADAPTER *prAdapter,
IN struct CMD_INFO *prCmdInfo)
{
}
u_int8_t halTxIsDataBufEnough(IN struct ADAPTER *prAdapter,
IN struct MSDU_INFO *prMsduInfo)
{
struct GL_HIF_INFO *prHifInfo = NULL;
struct RTMP_TX_RING *prTxRing;
prHifInfo = &prAdapter->prGlueInfo->rHifInfo;
prTxRing = &prHifInfo->TxRing[TX_RING_DATA0_IDX_0];
if ((prHifInfo->u4TxDataQLen < halGetMsduTokenFreeCnt(prAdapter)) &&
(prTxRing->u4UsedCnt + prHifInfo->u4TxDataQLen + 1 < TX_RING_SIZE))
return TRUE;
DBGLOG(HAL, TRACE,
"Low Tx Data Resource Tok[%u] Ring[%u] List[%u]\n",
halGetMsduTokenFreeCnt(prAdapter),
(TX_RING_SIZE - prTxRing->u4UsedCnt), prHifInfo->u4TxDataQLen);
return FALSE;
}
void halProcessTxInterrupt(IN struct ADAPTER *prAdapter)
{
struct BUS_INFO *prBusInfo = prAdapter->chip_info->bus_info;
struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo;
union WPDMA_INT_STA_STRUCT rIntrStatus;
rIntrStatus = (union WPDMA_INT_STA_STRUCT)prHifInfo->u4IntStatus;
if (rIntrStatus.field.tx_done & BIT(prBusInfo->tx_ring_fwdl_idx))
halWpdmaProcessCmdDmaDone(prAdapter->prGlueInfo,
TX_RING_FWDL_IDX_3);
if (rIntrStatus.field.tx_done & BIT(prBusInfo->tx_ring_cmd_idx))
halWpdmaProcessCmdDmaDone(prAdapter->prGlueInfo,
TX_RING_CMD_IDX_2);
if (rIntrStatus.field.tx_done & BIT(prBusInfo->tx_ring_data_idx)) {
halWpdmaProcessDataDmaDone(prAdapter->prGlueInfo,
TX_RING_DATA0_IDX_0);
kalSetTxEvent2Hif(prAdapter->prGlueInfo);
}
}
void halInitMsduTokenInfo(IN struct ADAPTER *prAdapter)
{
struct GL_HIF_INFO *prHifInfo;
struct HIF_MEM_OPS *prMemOps;
struct MSDU_TOKEN_INFO *prTokenInfo;
struct MSDU_TOKEN_ENTRY *prToken;
struct mt66xx_chip_info *prChipInfo;
uint32_t u4Idx;
uint32_t u4TxHeadRoomSize;
prHifInfo = &prAdapter->prGlueInfo->rHifInfo;
prMemOps = &prHifInfo->rMemOps;
prTokenInfo = &prHifInfo->rTokenInfo;
prChipInfo = prAdapter->chip_info;
prTokenInfo->i4UsedCnt = 0;
u4TxHeadRoomSize = NIC_TX_DESC_AND_PADDING_LENGTH +
prChipInfo->txd_append_size;
for (u4Idx = 0; u4Idx < HIF_TX_MSDU_TOKEN_NUM; u4Idx++) {
prToken = &prTokenInfo->arToken[u4Idx];
prToken->fgInUsed = FALSE;
prToken->prMsduInfo = NULL;
#if HIF_TX_PREALLOC_DATA_BUFFER
prToken->u4DmaLength = NIC_TX_MAX_SIZE_PER_FRAME +
u4TxHeadRoomSize;
if (prMemOps->allocTxDataBuf)
prMemOps->allocTxDataBuf(prToken, u4Idx);
if (prToken->prPacket) {
DBGLOG(HAL, TRACE,
"Msdu Entry[0x%p] Tok[%u] Buf[0x%p] len[%u]\n",
prToken, u4Idx, prToken->prPacket,
prToken->u4DmaLength);
} else {
prTokenInfo->i4UsedCnt++;
DBGLOG(HAL, WARN,
"Msdu Token Memory alloc failed[%u]\n",
u4Idx);
continue;
}
#else
prToken->prPacket = NULL;
prToken->u4DmaLength = 0;
prToken->rDmaAddr = 0;
#endif
prToken->rPktDmaAddr = 0;
prToken->u4PktDmaLength = 0;
prToken->u4Token = u4Idx;
prToken->u4CpuIdx = TX_RING_SIZE;
prTokenInfo->aprTokenStack[u4Idx] = prToken;
}
spin_lock_init(&prTokenInfo->rTokenLock);
DBGLOG(HAL, INFO, "Msdu Token Init: Tot[%u] Used[%u]\n",
HIF_TX_MSDU_TOKEN_NUM, prTokenInfo->i4UsedCnt);
}
void halUninitMsduTokenInfo(IN struct ADAPTER *prAdapter)
{
struct GL_HIF_INFO *prHifInfo;
struct HIF_MEM_OPS *prMemOps;
struct MSDU_TOKEN_INFO *prTokenInfo;
struct MSDU_TOKEN_ENTRY *prToken;
uint32_t u4Idx;
prHifInfo = &prAdapter->prGlueInfo->rHifInfo;
prMemOps = &prHifInfo->rMemOps;
prTokenInfo = &prHifInfo->rTokenInfo;
for (u4Idx = 0; u4Idx < HIF_TX_MSDU_TOKEN_NUM; u4Idx++) {
prToken = &prTokenInfo->arToken[u4Idx];
if (prToken->fgInUsed) {
if (prMemOps->unmapTxBuf) {
prMemOps->unmapTxBuf(
prHifInfo, prToken->rPktDmaAddr,
prToken->u4PktDmaLength);
prMemOps->unmapTxBuf(
prHifInfo, prToken->rDmaAddr,
prToken->u4DmaLength);
}
log_dbg(HAL, TRACE, "Clear pending Tok[%u] Msdu[0x%p] Free[%u]\n",
prToken->u4Token, prToken->prMsduInfo,
halGetMsduTokenFreeCnt(prAdapter));
#if !HIF_TX_PREALLOC_DATA_BUFFER
nicTxFreePacket(prAdapter, prToken->prMsduInfo, FALSE);
nicTxReturnMsduInfo(prAdapter, prToken->prMsduInfo);
#endif
}
#if HIF_TX_PREALLOC_DATA_BUFFER
if (prMemOps->freeBuf)
prMemOps->freeBuf(prToken->prPacket,
prToken->u4DmaLength);
prToken->prPacket = NULL;
#endif
}
prTokenInfo->i4UsedCnt = 0;
DBGLOG(HAL, INFO, "Msdu Token Uninit: Tot[%u] Used[%u]\n",
HIF_TX_MSDU_TOKEN_NUM, prTokenInfo->i4UsedCnt);
}
uint32_t halGetMsduTokenFreeCnt(IN struct ADAPTER *prAdapter)
{
struct PERF_MONITOR_T *prPerMonitor;
struct MSDU_TOKEN_INFO *prTokenInfo =
&prAdapter->prGlueInfo->rHifInfo.rTokenInfo;
prPerMonitor = &prAdapter->rPerMonitor;
prPerMonitor->u4UsedCnt = prTokenInfo->i4UsedCnt;
return HIF_TX_MSDU_TOKEN_NUM - prTokenInfo->i4UsedCnt;
}
struct MSDU_TOKEN_ENTRY *halGetMsduTokenEntry(IN struct ADAPTER *prAdapter,
uint32_t u4TokenNum)
{
struct MSDU_TOKEN_INFO *prTokenInfo =
&prAdapter->prGlueInfo->rHifInfo.rTokenInfo;
return &prTokenInfo->arToken[u4TokenNum];
}
struct MSDU_TOKEN_ENTRY *halAcquireMsduToken(IN struct ADAPTER *prAdapter)
{
struct MSDU_TOKEN_INFO *prTokenInfo =
&prAdapter->prGlueInfo->rHifInfo.rTokenInfo;
struct MSDU_TOKEN_ENTRY *prToken;
unsigned long flags = 0;
if (!halGetMsduTokenFreeCnt(prAdapter)) {
DBGLOG(HAL, INFO, "No more free MSDU token, Used[%u]\n",
prTokenInfo->i4UsedCnt);
return NULL;
}
spin_lock_irqsave(&prTokenInfo->rTokenLock, flags);
prToken = prTokenInfo->aprTokenStack[prTokenInfo->i4UsedCnt];
do_gettimeofday(&prToken->rTs);
prToken->fgInUsed = TRUE;
prTokenInfo->i4UsedCnt++;
spin_unlock_irqrestore(&prTokenInfo->rTokenLock, flags);
DBGLOG_LIMITED(HAL, TRACE,
"Acquire Entry[0x%p] Tok[%u] Buf[%p] Len[%u]\n",
prToken, prToken->u4Token,
prToken->prPacket, prToken->u4DmaLength);
return prToken;
}
/*----------------------------------------------------------------------------*/
/*!
* @brief Reset all msdu token. Return used msdu & re-init token.
*
* @param prAdapter a pointer to adapter private data structure.
*
*/
/*----------------------------------------------------------------------------*/
static void halResetMsduToken(IN struct ADAPTER *prAdapter)
{
struct GL_HIF_INFO *prHifInfo;
struct HIF_MEM_OPS *prMemOps;
struct MSDU_TOKEN_INFO *prTokenInfo;
struct MSDU_TOKEN_ENTRY *prToken;
uint32_t u4Idx = 0;
prHifInfo = &prAdapter->prGlueInfo->rHifInfo;
prMemOps = &prHifInfo->rMemOps;
prTokenInfo = &prHifInfo->rTokenInfo;
for (u4Idx = 0; u4Idx < HIF_TX_MSDU_TOKEN_NUM; u4Idx++) {
prToken = &prTokenInfo->arToken[u4Idx];
if (prToken->fgInUsed) {
if (prMemOps->unmapTxBuf) {
prMemOps->unmapTxBuf(
prHifInfo, prToken->rPktDmaAddr,
prToken->u4PktDmaLength);
prMemOps->unmapTxBuf(
prHifInfo, prToken->rDmaAddr,
prToken->u4DmaLength);
prToken->rPktDmaAddr = 0;
prToken->u4PktDmaLength = 0;
prToken->rDmaAddr = 0;
}
#if !HIF_TX_PREALLOC_DATA_BUFFER
nicTxFreePacket(prAdapter, prToken->prMsduInfo, FALSE);
nicTxReturnMsduInfo(prAdapter, prToken->prMsduInfo);
#endif
}
prToken->fgInUsed = FALSE;
prTokenInfo->aprTokenStack[u4Idx] = prToken;
}
prTokenInfo->i4UsedCnt = 0;
}
void halReturnMsduToken(IN struct ADAPTER *prAdapter, uint32_t u4TokenNum)
{
struct MSDU_TOKEN_INFO *prTokenInfo =
&prAdapter->prGlueInfo->rHifInfo.rTokenInfo;
struct MSDU_TOKEN_ENTRY *prToken;
unsigned long flags = 0;
if (!prTokenInfo->i4UsedCnt) {
DBGLOG(HAL, INFO, "MSDU token is full, Used[%u]\n",
prTokenInfo->i4UsedCnt);
return;
}
prToken = &prTokenInfo->arToken[u4TokenNum];
if (!prToken->fgInUsed) {
DBGLOG(HAL, ERROR, "Return unuse token[%u]\n", u4TokenNum);
return;
}
spin_lock_irqsave(&prTokenInfo->rTokenLock, flags);
prToken->fgInUsed = FALSE;
prTokenInfo->i4UsedCnt--;
prTokenInfo->aprTokenStack[prTokenInfo->i4UsedCnt] = prToken;
spin_unlock_irqrestore(&prTokenInfo->rTokenLock, flags);
}
/*----------------------------------------------------------------------------*/
/*!
* @brief Return all timeout msdu token.
*
* @param prAdapter a pointer to adapter private data structure.
*
*/
/*----------------------------------------------------------------------------*/
void halReturnTimeoutMsduToken(struct ADAPTER *prAdapter)
{
struct MSDU_TOKEN_INFO *prTokenInfo;
struct MSDU_TOKEN_ENTRY *prToken;
struct timeval rNowTs, rTime;
struct timeval rTimeout;
uint32_t u4Idx = 0;
ASSERT(prAdapter);
ASSERT(prAdapter->prGlueInfo);
prTokenInfo = &prAdapter->prGlueInfo->rHifInfo.rTokenInfo;
rTimeout.tv_sec = HIF_MSDU_REPORT_RETURN_TIMEOUT;
rTimeout.tv_usec = 0;
do_gettimeofday(&rNowTs);
for (u4Idx = 0; u4Idx < HIF_TX_MSDU_TOKEN_NUM; u4Idx++) {
prToken = &prTokenInfo->arToken[u4Idx];
if (!prToken->fgInUsed)
continue;
/* Ignore now time < token time */
if (halTimeCompare(&rNowTs, &prToken->rTs) < 0)
continue;
rTime.tv_sec = rNowTs.tv_sec - prToken->rTs.tv_sec;
rTime.tv_usec = rNowTs.tv_usec;
if (prToken->rTs.tv_usec > rNowTs.tv_usec) {
rTime.tv_sec -= 1;
rTime.tv_usec += SEC_TO_USEC(1);
}
rTime.tv_usec -= prToken->rTs.tv_usec;
/* Return token to free stack */
if (halTimeCompare(&rTime, &rTimeout) >= 0) {
DBGLOG(HAL, INFO,
"Free TokenId[%u] timeout[sec:%u, usec:%u]\n",
u4Idx, rTime.tv_sec, rTime.tv_usec);
halReturnMsduToken(prAdapter, u4Idx);
}
}
}
bool halHifSwInfoInit(IN struct ADAPTER *prAdapter)
{
struct GL_HIF_INFO *prHifInfo = NULL;
prHifInfo = &prAdapter->prGlueInfo->rHifInfo;
asicPcieDmaShdlInit(prAdapter);
if (!halWpdmaAllocRing(prAdapter->prGlueInfo, true))
return false;
halWpdmaInitRing(prAdapter->prGlueInfo);
halInitMsduTokenInfo(prAdapter);
prHifInfo->fgIsPowerOff = false;
return true;
}
void halRxProcessMsduReport(IN struct ADAPTER *prAdapter,
IN OUT struct SW_RFB *prSwRfb)
{
struct GL_HIF_INFO *prHifInfo;
struct HIF_MEM_OPS *prMemOps;
struct RTMP_DMACB *prTxCell;
struct RTMP_TX_RING *prTxRing;
struct HW_MAC_MSDU_REPORT *prMsduReport;
struct MSDU_TOKEN_ENTRY *prTokenEntry;
#if !HIF_TX_PREALLOC_DATA_BUFFER
struct MSDU_INFO *prMsduInfo;
#endif
struct QUE rFreeQueue;
struct QUE *prFreeQueue;
uint16_t u2TokenCnt;
uint32_t u4Idx, u4Token;
ASSERT(prAdapter);
ASSERT(prAdapter->prGlueInfo);
prHifInfo = &prAdapter->prGlueInfo->rHifInfo;
prTxRing = &prHifInfo->TxRing[TX_RING_DATA0_IDX_0];
prMemOps = &prHifInfo->rMemOps;
prFreeQueue = &rFreeQueue;
QUEUE_INITIALIZE(prFreeQueue);
prMsduReport = (struct HW_MAC_MSDU_REPORT *)prSwRfb->pucRecvBuff;
u2TokenCnt = prMsduReport->u2MsduCount;
for (u4Idx = 0; u4Idx < u2TokenCnt; u4Idx++) {
if (prMsduReport->u4Ver == 0)
u4Token = prMsduReport->au4MsduToken[u4Idx >> 1].
rFormatV1.u2MsduID[u4Idx & 1];
else
u4Token = prMsduReport->au4MsduToken[u4Idx].
rFormatV2.u2MsduID;
if (u4Token >= HIF_TX_MSDU_TOKEN_NUM) {
DBGLOG(HAL, ERROR, "Error MSDU report[%u]\n", u4Token);
DBGLOG_MEM32(HAL, ERROR, prMsduReport, 64);
prAdapter->u4HifDbgFlag |= DEG_HIF_DEFAULT_DUMP;
halPrintHifDbgInfo(prAdapter);
return;
}
prTokenEntry = halGetMsduTokenEntry(prAdapter, u4Token);
#if HIF_TX_PREALLOC_DATA_BUFFER
DBGLOG_LIMITED(HAL, TRACE,
"MsduRpt: Cnt[%u] Tok[%u] Free[%u]\n",
u2TokenCnt, u4Token,
halGetMsduTokenFreeCnt(prAdapter));
#else
prMsduInfo = prTokenEntry->prMsduInfo;
prMsduInfo->prToken = NULL;
if (!prMsduInfo->pfTxDoneHandler)
QUEUE_INSERT_TAIL(prFreeQueue,
(struct QUE_ENTRY *) prMsduInfo);
DBGLOG_LIMITED(HAL, TRACE,
"MsduRpt: Cnt[%u] Tok[%u] Msdu[0x%p] TxDone[%u] Free[%u]\n",
u2TokenCnt, u4Token, prMsduInfo,
(prMsduInfo->pfTxDoneHandler ? TRUE : FALSE),
halGetMsduTokenFreeCnt(prAdapter));
#endif
if (prMemOps->unmapTxBuf) {
prMemOps->unmapTxBuf(prHifInfo,
prTokenEntry->rPktDmaAddr,
prTokenEntry->u4PktDmaLength);
prMemOps->unmapTxBuf(prHifInfo,
prTokenEntry->rDmaAddr,
prTokenEntry->u4DmaLength);
}
if (prTokenEntry->u4CpuIdx < TX_RING_SIZE) {
prTxCell = &prTxRing->Cell[prTokenEntry->u4CpuIdx];
prTxCell->prToken = NULL;
}
prTokenEntry->u4CpuIdx = TX_RING_SIZE;
halReturnMsduToken(prAdapter, u4Token);
}
#if !HIF_TX_PREALLOC_DATA_BUFFER
nicTxMsduDoneCb(prAdapter->prGlueInfo, prFreeQueue);
#endif
/* Indicate Service Thread */
if (wlanGetTxPendingFrameCount(prAdapter) > 0)
kalSetEvent(prAdapter->prGlueInfo);
kalSetTxEvent2Hif(prAdapter->prGlueInfo);
}
void halTxUpdateCutThroughDesc(struct GLUE_INFO *prGlueInfo,
struct MSDU_INFO *prMsduInfo,
struct MSDU_TOKEN_ENTRY *prFillToken,
struct MSDU_TOKEN_ENTRY *prDataToken,
uint32_t u4Idx, bool fgIsLast)
{
struct GL_HIF_INFO *prHifInfo;
struct HIF_MEM_OPS *prMemOps;
struct mt66xx_chip_info *prChipInfo;
struct TX_DESC_OPS_T *prTxDescOps;
uint8_t *pucBufferTxD;
uint32_t u4TxHeadRoomSize;
phys_addr_t rPhyAddr = 0;
prHifInfo = &prGlueInfo->rHifInfo;
prMemOps = &prHifInfo->rMemOps;
prChipInfo = prGlueInfo->prAdapter->chip_info;
prTxDescOps = prChipInfo->prTxDescOps;
pucBufferTxD = prDataToken->prPacket;
u4TxHeadRoomSize = NIC_TX_DESC_AND_PADDING_LENGTH +
prChipInfo->txd_append_size;
if (prMemOps->mapTxBuf) {
rPhyAddr = prMemOps->mapTxBuf(
prHifInfo, pucBufferTxD, u4TxHeadRoomSize,
prMsduInfo->u2FrameLength);
} else {
if (prDataToken->rDmaAddr)
rPhyAddr = prDataToken->rDmaAddr + u4TxHeadRoomSize;
}
if (!rPhyAddr) {
DBGLOG(HAL, ERROR, "Get address error!\n");
return;
}
if (prTxDescOps->fillHifAppend)
prTxDescOps->fillHifAppend(prGlueInfo->prAdapter,
prMsduInfo, prDataToken->u4Token,
rPhyAddr, u4Idx, fgIsLast, prFillToken->prPacket);
prDataToken->rPktDmaAddr = rPhyAddr;
prDataToken->u4PktDmaLength = prMsduInfo->u2FrameLength;
}
uint32_t halTxGetPageCount(IN struct ADAPTER *prAdapter,
IN uint32_t u4FrameLength, IN u_int8_t fgIncludeDesc)
{
return 1;
}
uint32_t halTxPollingResource(IN struct ADAPTER *prAdapter, IN uint8_t ucTC)
{
return WLAN_STATUS_SUCCESS;
}
void halSerHifReset(IN struct ADAPTER *prAdapter)
{
}
void halRxReceiveRFBs(IN struct ADAPTER *prAdapter, uint32_t u4Port)
{
struct RX_CTRL *prRxCtrl;
struct SW_RFB *prSwRfb = (struct SW_RFB *) NULL;
uint8_t *pucBuf = NULL;
struct HW_MAC_RX_DESC *prRxStatus;
u_int8_t fgStatus;
uint32_t u4RxCnt;
KAL_SPIN_LOCK_DECLARATION();
DEBUGFUNC("nicRxPCIeReceiveRFBs");
ASSERT(prAdapter);
prRxCtrl = &prAdapter->rRxCtrl;
ASSERT(prRxCtrl);
u4RxCnt = halWpdmaGetRxDmaDoneCnt(prAdapter->prGlueInfo, u4Port);
while (u4RxCnt--) {
KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE);
QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList,
prSwRfb, struct SW_RFB *);
KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE);
if (!prSwRfb) {
DBGLOG(RX, WARN, "No More RFB for P[%u]\n", u4Port);
break;
}
if (u4Port == RX_RING_DATA_IDX_0) {
fgStatus = kalDevReadData(prAdapter->prGlueInfo,
u4Port, prSwRfb);
} else {
pucBuf = prSwRfb->pucRecvBuff;
ASSERT(pucBuf);
fgStatus = kalDevPortRead(prAdapter->prGlueInfo,
u4Port, CFG_RX_MAX_PKT_SIZE,
pucBuf, CFG_RX_MAX_PKT_SIZE);
}
if (!fgStatus) {
KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE);
QUEUE_INSERT_TAIL(&prRxCtrl->rFreeSwRfbList,
&prSwRfb->rQueEntry);
KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE);
continue;
}
prRxStatus = prSwRfb->prRxStatus;
ASSERT(prRxStatus);
prSwRfb->ucPacketType = (uint8_t)
HAL_RX_STATUS_GET_PKT_TYPE(prRxStatus);
DBGLOG_LIMITED(RX, LOUD, "ucPacketType = %u, ucSecMode = %u\n",
prSwRfb->ucPacketType,
(uint8_t)HAL_RX_STATUS_GET_SEC_MODE(
prRxStatus));
if (prSwRfb->ucPacketType == RX_PKT_TYPE_MSDU_REPORT) {
nicRxProcessMsduReport(prAdapter, prSwRfb);
continue;
}
GLUE_RX_SET_PKT_INT_TIME(prSwRfb->pvPacket,
prAdapter->prGlueInfo->u8HifIntTime);
GLUE_RX_SET_PKT_RX_TIME(prSwRfb->pvPacket, sched_clock());
prSwRfb->ucStaRecIdx =
secGetStaIdxByWlanIdx(prAdapter,
(uint8_t)HAL_RX_STATUS_GET_WLAN_IDX(
prRxStatus));
KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE);
QUEUE_INSERT_TAIL(&prRxCtrl->rReceivedRfbList,
&prSwRfb->rQueEntry);
RX_INC_CNT(prRxCtrl, RX_MPDU_TOTAL_COUNT);
KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE);
}
}
/*----------------------------------------------------------------------------*/
/*!
* @brief Read frames from the data port for PCIE
* I/F, fill RFB and put each frame into the rReceivedRFBList queue.
*
* @param prAdapter Pointer to the Adapter structure.
*
* @return (none)
*/
/*----------------------------------------------------------------------------*/
void halProcessRxInterrupt(IN struct ADAPTER *prAdapter)
{
struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo;
union WPDMA_INT_STA_STRUCT rIntrStatus;
rIntrStatus = (union WPDMA_INT_STA_STRUCT)prHifInfo->u4IntStatus;
prAdapter->prGlueInfo->u8HifIntTime = sched_clock();
if (rIntrStatus.field.rx_done_1)
halRxReceiveRFBs(prAdapter, RX_RING_EVT_IDX_1);
if (rIntrStatus.field.rx_done_0)
halRxReceiveRFBs(prAdapter, RX_RING_DATA_IDX_0);
}
static int32_t halWpdmaFreeRingDesc(struct GLUE_INFO *prGlueInfo,
struct RTMP_DMABUF *prDescRing)
{
struct GL_HIF_INFO *prHifInfo;
struct HIF_MEM_OPS *prMemOps;
ASSERT(prGlueInfo);
prHifInfo = &prGlueInfo->rHifInfo;
prMemOps = &prHifInfo->rMemOps;
if (prMemOps->freeDesc)
prMemOps->freeDesc(prHifInfo, prDescRing);
return TRUE;
}
bool halWpdmaAllocTxRing(struct GLUE_INFO *prGlueInfo, uint32_t u4Num,
uint32_t u4Size, uint32_t u4DescSize, bool fgAllocMem)
{
struct GL_HIF_INFO *prHifInfo;
struct HIF_MEM_OPS *prMemOps;
struct RTMP_TX_RING *pTxRing;
struct RTMP_DMABUF *prTxDesc;
struct RTMP_DMACB *prTxCell;
phys_addr_t RingBasePa;
void *RingBaseVa;
uint32_t u4Idx;
ASSERT(prGlueInfo);
prHifInfo = &prGlueInfo->rHifInfo;
prMemOps = &prHifInfo->rMemOps;
prTxDesc = &prHifInfo->TxDescRing[u4Num];
/* Don't re-alloc memory when second time call alloc ring */
prTxDesc->AllocSize = u4Size * u4DescSize;
if (fgAllocMem && prMemOps->allocTxDesc)
prMemOps->allocTxDesc(prHifInfo, prTxDesc, u4Num);
if (prTxDesc->AllocVa == NULL) {
DBGLOG(HAL, ERROR, "TxDescRing[%d] allocation failed\n", u4Num);
return false;
}
DBGLOG(HAL, TRACE, "TxDescRing[%p]: total %lu bytes allocated\n",
prTxDesc->AllocVa, prTxDesc->AllocSize);
/* Save PA & VA for further operation */
RingBasePa = prTxDesc->AllocPa;
RingBaseVa = prTxDesc->AllocVa;
/*
* Initialize Tx Ring Descriptor and associated buffer memory
*/
pTxRing = &prHifInfo->TxRing[u4Num];
for (u4Idx = 0; u4Idx < u4Size; u4Idx++) {
prTxCell = &pTxRing->Cell[u4Idx];
prTxCell->pPacket = NULL;
prTxCell->pBuffer = NULL;
/* Init Tx Ring Size, Va, Pa variables */
prTxCell->AllocSize = u4DescSize;
prTxCell->AllocVa = RingBaseVa;
prTxCell->AllocPa = RingBasePa;
prTxCell->prToken = NULL;
RingBasePa += u4DescSize;
RingBaseVa += u4DescSize;
if (fgAllocMem && prMemOps->allocTxCmdBuf)
prMemOps->allocTxCmdBuf(&prTxCell->DmaBuf,
u4Num, u4Idx);
}
DBGLOG(HAL, TRACE, "TxRing[%d]: total %d entry allocated\n",
u4Num, u4Idx);
return true;
}
bool halWpdmaAllocRxRing(struct GLUE_INFO *prGlueInfo, uint32_t u4Num,
uint32_t u4Size, uint32_t u4DescSize,
uint32_t u4BufSize, bool fgAllocMem)
{
struct GL_HIF_INFO *prHifInfo;
struct HIF_MEM_OPS *prMemOps;
struct RTMP_RX_RING *pRxRing;
struct RTMP_DMABUF *prRxDesc;
struct RTMP_DMABUF *pDmaBuf;
struct RTMP_DMACB *prRxCell;
struct RXD_STRUCT *pRxD;
phys_addr_t RingBasePa;
void *RingBaseVa;
uint32_t u4Idx;
ASSERT(prGlueInfo);
prHifInfo = &prGlueInfo->rHifInfo;
prMemOps = &prHifInfo->rMemOps;
prRxDesc = &prHifInfo->RxDescRing[u4Num];
/* Don't re-alloc memory when second time call alloc ring */
prRxDesc->AllocSize = u4Size * u4DescSize;
if (fgAllocMem && prMemOps->allocRxDesc)
prMemOps->allocRxDesc(prHifInfo, prRxDesc, u4Num);
if (prRxDesc->AllocVa == NULL) {
DBGLOG(HAL, ERROR, "RxDescRing allocation failed!!\n");
return false;
}
DBGLOG(HAL, TRACE, "RxDescRing[%p]: total %lu bytes allocated\n",
prRxDesc->AllocVa, prRxDesc->AllocSize);
/* Initialize Rx Ring and associated buffer memory */
RingBasePa = prRxDesc->AllocPa;
RingBaseVa = prRxDesc->AllocVa;
pRxRing = &prHifInfo->RxRing[u4Num];
pRxRing->u4BufSize = u4BufSize;
pRxRing->u4RingSize = u4Size;
pRxRing->fgRxSegPkt = FALSE;
for (u4Idx = 0; u4Idx < u4Size; u4Idx++) {
/* Init RX Ring Size, Va, Pa variables */
prRxCell = &pRxRing->Cell[u4Idx];
prRxCell->AllocSize = u4DescSize;
prRxCell->AllocVa = RingBaseVa;
prRxCell->AllocPa = RingBasePa;
prRxCell->prToken = NULL;
/* Offset to next ring descriptor address */
RingBasePa += u4DescSize;
RingBaseVa += u4DescSize;
/* Setup Rx associated Buffer size & allocate share memory */
pDmaBuf = &prRxCell->DmaBuf;
pDmaBuf->AllocSize = u4BufSize;
if (fgAllocMem && prMemOps->allocRxBuf)
prRxCell->pPacket = prMemOps->allocRxBuf(
prHifInfo, pDmaBuf, u4Num, u4Idx);
if (pDmaBuf->AllocVa == NULL) {
log_dbg(HAL, ERROR, "\nFailed to allocate RxRing buffer idx[%u]\n",
u4Idx);
return false;
}
/* Write RxD buffer address & allocated buffer length */
pRxD = (struct RXD_STRUCT *)prRxCell->AllocVa;
pRxD->SDPtr0 = ((uint64_t)pDmaBuf->AllocPa) &
DMA_LOWER_32BITS_MASK;
pRxD->SDPtr1 = (((uint64_t)pDmaBuf->AllocPa >>
DMA_BITS_OFFSET) & DMA_HIGHER_4BITS_MASK);
pRxD->SDLen0 = u4BufSize;
pRxD->DMADONE = 0;
}
DBGLOG(HAL, TRACE, "Rx[%d] Ring: total %d entry allocated\n",
u4Num, u4Idx);
return true;
}
void halHifRst(struct GLUE_INFO *prGlueInfo)
{
/* Reset dmashdl and wpdma */
kalDevRegWrite(prGlueInfo, CONN_HIF_RST, 0x00000000);
kalDevRegWrite(prGlueInfo, CONN_HIF_RST, 0x00000030);
}
bool halWpdmaAllocRing(struct GLUE_INFO *prGlueInfo, bool fgAllocMem)
{
struct GL_HIF_INFO *prHifInfo;
int32_t u4Num, u4Index;
ASSERT(prGlueInfo);
prHifInfo = &prGlueInfo->rHifInfo;
/*
* Allocate all ring descriptors, include TxD, RxD, MgmtD.
* Although each size is different, to prevent cacheline and alignment
* issue, I intentional set them all to 64 bytes
*/
for (u4Num = 0; u4Num < NUM_OF_TX_RING; u4Num++) {
if (!halWpdmaAllocTxRing(prGlueInfo, u4Num, TX_RING_SIZE,
TXD_SIZE, fgAllocMem)) {
DBGLOG(HAL, ERROR, "AllocTxRing[%d] fail\n", u4Num);
return false;
}
}
/* Data Rx path */
if (!halWpdmaAllocRxRing(prGlueInfo, RX_RING_DATA_IDX_0,
RX_RING0_SIZE, RXD_SIZE,
CFG_RX_MAX_PKT_SIZE, fgAllocMem)) {
DBGLOG(HAL, ERROR, "AllocRxRing[0] fail\n");
return false;
}
/* Event Rx path */
if (!halWpdmaAllocRxRing(prGlueInfo, RX_RING_EVT_IDX_1,
RX_RING1_SIZE, RXD_SIZE,
RX_BUFFER_AGGRESIZE, fgAllocMem)) {
DBGLOG(HAL, ERROR, "AllocRxRing[1] fail\n");
return false;
}
/* Initialize all transmit related software queues */
/* Init TX rings index pointer */
for (u4Index = 0; u4Index < NUM_OF_TX_RING; u4Index++) {
prHifInfo->TxRing[u4Index].TxSwUsedIdx = 0;
prHifInfo->TxRing[u4Index].TxCpuIdx = 0;
}
return true;
}
void halWpdmaFreeRing(struct GLUE_INFO *prGlueInfo)
{
struct GL_HIF_INFO *prHifInfo;
struct HIF_MEM_OPS *prMemOps;
struct RTMP_TX_RING *pTxRing;
struct RTMP_RX_RING *pRxRing;
struct TXD_STRUCT *pTxD;
struct RTMP_DMACB *prDmaCb;
void *pPacket, *pBuffer;
uint32_t i, j;
prHifInfo = &prGlueInfo->rHifInfo;
prMemOps = &prHifInfo->rMemOps;
/* Free Tx Ring Packet */
for (i = 0; i < NUM_OF_TX_RING; i++) {
pTxRing = &prHifInfo->TxRing[i];
for (j = 0; j < TX_RING_SIZE; j++) {
pTxD = (struct TXD_STRUCT *) (pTxRing->Cell[j].AllocVa);
pPacket = pTxRing->Cell[j].pPacket;
pBuffer = pTxRing->Cell[j].pBuffer;
if (prMemOps->unmapTxBuf && pPacket)
prMemOps->unmapTxBuf(
prHifInfo, pTxRing->Cell[j].PacketPa,
pTxD->SDLen0);
pTxRing->Cell[j].pPacket = NULL;
if (prMemOps->freeBuf && pBuffer)
prMemOps->freeBuf(pBuffer, pTxD->SDLen0);
pTxRing->Cell[j].pBuffer = NULL;
}
halWpdmaFreeRingDesc(prGlueInfo, &prHifInfo->TxDescRing[i]);
}
for (i = 0; i < NUM_OF_RX_RING; i++) {
pRxRing = &prHifInfo->RxRing[i];
for (j = 0; j < pRxRing->u4RingSize; j++) {
prDmaCb = &pRxRing->Cell[j];
if (prMemOps->unmapRxBuf && prDmaCb->DmaBuf.AllocVa)
prMemOps->unmapRxBuf(prHifInfo,
prDmaCb->DmaBuf.AllocPa,
prDmaCb->DmaBuf.AllocSize);
if (prMemOps->freePacket && prDmaCb->pPacket)
prMemOps->freePacket(prDmaCb->pPacket);
}
halWpdmaFreeRingDesc(prGlueInfo, &prHifInfo->RxDescRing[i]);
}
}
/*----------------------------------------------------------------------------*/
/*!
* @brief enable firmware download.
*
* @param[in] fgEnable 1 for fw download, 0 for normal data operation.
*
* @return (none)
*/
/*----------------------------------------------------------------------------*/
void halEnableFWDownload(IN struct ADAPTER *prAdapter, IN u_int8_t fgEnable)
{
struct mt66xx_chip_info *prChipInfo;
ASSERT(prAdapter);
prChipInfo = prAdapter->chip_info;
if (prChipInfo->asicEnableFWDownload)
prChipInfo->asicEnableFWDownload(prAdapter, fgEnable);
}
static u_int8_t halWpdmaWaitIdle(struct GLUE_INFO *prGlueInfo,
int32_t round, int32_t wait_us)
{
int32_t i = 0;
union WPDMA_GLO_CFG_STRUCT GloCfg;
do {
kalDevRegRead(prGlueInfo, WPDMA_GLO_CFG, &GloCfg.word);
if ((GloCfg.field.TxDMABusy == 0) &&
(GloCfg.field.RxDMABusy == 0)) {
DBGLOG(HAL, TRACE,
"==> DMAIdle, GloCfg=0x%x\n", GloCfg.word);
return TRUE;
}
kalUdelay(wait_us);
} while ((i++) < round);
DBGLOG(HAL, INFO, "==> DMABusy, GloCfg=0x%x\n", GloCfg.word);
return FALSE;
}
void halWpdmaInitRing(struct GLUE_INFO *prGlueInfo)
{
struct GL_HIF_INFO *prHifInfo;
struct BUS_INFO *prBusInfo;
ASSERT(prGlueInfo);
prHifInfo = &prGlueInfo->rHifInfo;
prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info;
/* Set DMA global configuration except TX_DMA_EN and RX_DMA_EN bits */
if (prBusInfo->pdmaSetup)
prBusInfo->pdmaSetup(prGlueInfo, FALSE);
halWpdmaWaitIdle(prGlueInfo, 100, 1000);
/* Reset DMA Index */
kalDevRegWrite(prGlueInfo, WPDMA_RST_PTR, 0xFFFFFFFF);
halWpdmaInitTxRing(prGlueInfo);
/* Init RX Ring0 Base/Size/Index pointer CSR */
halWpdmaInitRxRing(prGlueInfo);
if (prBusInfo->pdmaSetup)
prBusInfo->pdmaSetup(prGlueInfo, TRUE);
/* Write sleep mode magic num to dummy reg */
if (prBusInfo->setDummyReg)
prBusInfo->setDummyReg(prGlueInfo);
}
void halWpdmaInitTxRing(IN struct GLUE_INFO *prGlueInfo)
{
struct GL_HIF_INFO *prHifInfo = NULL;
struct BUS_INFO *prBusInfo = NULL;
struct RTMP_TX_RING *prTxRing = NULL;
struct RTMP_DMACB *prTxCell;
uint32_t i = 0, offset = 0, phy_addr = 0;
uint32_t phy_addr_ext = 0, ext_offset = 0;
prHifInfo = &prGlueInfo->rHifInfo;
prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info;
/* reset all TX Ring register */
for (i = 0; i < NUM_OF_TX_RING; i++) {
prTxRing = &prHifInfo->TxRing[i];
prTxCell = &prTxRing->Cell[0];
if (i == TX_RING_CMD_IDX_2)
offset = prBusInfo->tx_ring_cmd_idx * MT_RINGREG_DIFF;
else
offset = i * MT_RINGREG_DIFF;
phy_addr = ((uint64_t)prTxCell->AllocPa) &
DMA_LOWER_32BITS_MASK;
phy_addr_ext = (((uint64_t)prTxCell->AllocPa >>
DMA_BITS_OFFSET) & DMA_HIGHER_4BITS_MASK);
ext_offset = i * MT_RINGREG_EXT_DIFF;
prTxRing->TxSwUsedIdx = 0;
prTxRing->u4UsedCnt = 0;
prTxRing->TxCpuIdx = 0;
prTxRing->hw_desc_base = MT_TX_RING_BASE + offset;
prTxRing->hw_desc_base_ext = MT_TX_RING_BASE_EXT + ext_offset;
prTxRing->hw_cidx_addr = MT_TX_RING_CIDX + offset;
prTxRing->hw_didx_addr = MT_TX_RING_DIDX + offset;
prTxRing->hw_cnt_addr = MT_TX_RING_CNT + offset;
kalDevRegWrite(prGlueInfo, prTxRing->hw_desc_base, phy_addr);
kalDevRegWrite(prGlueInfo, prTxRing->hw_desc_base_ext,
phy_addr_ext);
kalDevRegWrite(prGlueInfo, prTxRing->hw_cidx_addr,
prTxRing->TxCpuIdx);
kalDevRegWrite(prGlueInfo, prTxRing->hw_cnt_addr,
TX_RING_SIZE);
DBGLOG(HAL, TRACE, "-->TX_RING_%d[0x%x]: Base=0x%x, Cnt=%d!\n",
i, prHifInfo->TxRing[i].hw_desc_base,
phy_addr, TX_RING_SIZE);
}
}
void halWpdmaInitRxRing(IN struct GLUE_INFO *prGlueInfo)
{
struct GL_HIF_INFO *prHifInfo = NULL;
struct RTMP_RX_RING *prRxRing = NULL;
uint32_t i = 0, offset = 0, phy_addr = 0;
uint32_t phy_addr_ext = 0, ext_offset = 0;
ASSERT(prGlueInfo);
prHifInfo = &prGlueInfo->rHifInfo;
/* reset all RX Ring register */
for (i = 0; i < NUM_OF_RX_RING; i++) {
prRxRing = &prHifInfo->RxRing[i];
offset = i * MT_RINGREG_DIFF;
phy_addr = ((uint64_t)prRxRing->Cell[0].AllocPa &
DMA_LOWER_32BITS_MASK);
phy_addr_ext = (((uint64_t)prRxRing->Cell[0].AllocPa >>
DMA_BITS_OFFSET) & DMA_HIGHER_4BITS_MASK);
ext_offset = i * MT_RINGREG_EXT_DIFF;
prRxRing->RxCpuIdx = prRxRing->u4RingSize - 1;
prRxRing->hw_desc_base = MT_RX_RING_BASE + offset;
prRxRing->hw_desc_base_ext = MT_RX_RING_BASE_EXT + ext_offset;
prRxRing->hw_cidx_addr = MT_RX_RING_CIDX + offset;
prRxRing->hw_didx_addr = MT_RX_RING_DIDX + offset;
prRxRing->hw_cnt_addr = MT_RX_RING_CNT + offset;
kalDevRegWrite(prGlueInfo, prRxRing->hw_desc_base, phy_addr);
kalDevRegWrite(prGlueInfo, prRxRing->hw_desc_base_ext,
phy_addr_ext);
kalDevRegWrite(prGlueInfo, prRxRing->hw_cidx_addr,
prRxRing->RxCpuIdx);
kalDevRegWrite(prGlueInfo, prRxRing->hw_cnt_addr,
prRxRing->u4RingSize);
prRxRing->fgIsDumpLog = false;
DBGLOG(HAL, TRACE, "-->RX_RING_%d[0x%x]: Base=0x%x, Cnt=%d\n",
i, prRxRing->hw_desc_base,
phy_addr, prRxRing->u4RingSize);
}
}
void halWpdmaProcessCmdDmaDone(IN struct GLUE_INFO *prGlueInfo,
IN uint16_t u2Port)
{
struct GL_HIF_INFO *prHifInfo = NULL;
struct HIF_MEM_OPS *prMemOps;
struct RTMP_TX_RING *prTxRing;
struct TXD_STRUCT *pTxD;
phys_addr_t PacketPa = 0;
void *pBuffer = NULL;
uint32_t u4SwIdx, u4DmaIdx;
ASSERT(prGlueInfo);
prHifInfo = &prGlueInfo->rHifInfo;
prMemOps = &prHifInfo->rMemOps;
prTxRing = &prHifInfo->TxRing[u2Port];
kalDevRegRead(prGlueInfo, prTxRing->hw_didx_addr, &u4DmaIdx);
u4SwIdx = prTxRing->TxSwUsedIdx;
do {
pBuffer = prTxRing->Cell[u4SwIdx].pBuffer;
PacketPa = prTxRing->Cell[u4SwIdx].PacketPa;
pTxD = (struct TXD_STRUCT *) prTxRing->Cell[u4SwIdx].AllocVa;
if (pTxD->DMADONE == 0)
break;
log_dbg(HAL, TRACE, "DMA done: port[%u] dma[%u] idx[%u] done[%u] pkt[0x%p] used[%u]\n",
u2Port, u4DmaIdx, u4SwIdx, pTxD->DMADONE,
prTxRing->Cell[u4SwIdx].pPacket, prTxRing->u4UsedCnt);
if (prMemOps->unmapTxBuf && PacketPa)
prMemOps->unmapTxBuf(prHifInfo, PacketPa, pTxD->SDLen0);
pTxD->DMADONE = 0;
if (prMemOps->freeBuf && pBuffer)
prMemOps->freeBuf(pBuffer, 0);
prTxRing->Cell[u4SwIdx].pBuffer = NULL;
prTxRing->Cell[u4SwIdx].pPacket = NULL;
prTxRing->u4UsedCnt--;
if (u2Port == TX_RING_CMD_IDX_2)
nicTxReleaseResource_PSE(prGlueInfo->prAdapter,
TC4_INDEX,
nicTxGetPageCount(prGlueInfo->prAdapter,
pTxD->SDLen0, TRUE), TRUE);
INC_RING_INDEX(u4SwIdx, TX_RING_SIZE);
} while (u4SwIdx != u4DmaIdx);
prTxRing->TxSwUsedIdx = u4SwIdx;
}
void halWpdmaProcessDataDmaDone(IN struct GLUE_INFO *prGlueInfo,
IN uint16_t u2Port)
{
struct GL_HIF_INFO *prHifInfo = NULL;
uint32_t u4SwIdx, u4DmaIdx;
struct RTMP_TX_RING *prTxRing;
ASSERT(prGlueInfo);
prHifInfo = &prGlueInfo->rHifInfo;
prTxRing = &prHifInfo->TxRing[u2Port];
kalDevRegRead(prGlueInfo, prTxRing->hw_didx_addr, &u4DmaIdx);
u4SwIdx = prTxRing->TxSwUsedIdx;
if (u4DmaIdx > u4SwIdx)
prTxRing->u4UsedCnt -= u4DmaIdx - u4SwIdx;
else if (u4DmaIdx < u4SwIdx)
prTxRing->u4UsedCnt -= (TX_RING_SIZE + u4DmaIdx) - u4SwIdx;
else {
/* DMA index == SW used index */
if (prTxRing->u4UsedCnt == TX_RING_SIZE)
prTxRing->u4UsedCnt = 0;
}
DBGLOG(HAL, TRACE,
"DMA done: port[%u] dma[%u] idx[%u] used[%u]\n", u2Port,
u4DmaIdx, u4SwIdx, prTxRing->u4UsedCnt);
prTxRing->TxSwUsedIdx = u4DmaIdx;
}
uint32_t halWpdmaGetRxDmaDoneCnt(IN struct GLUE_INFO *prGlueInfo,
IN uint8_t ucRingNum)
{
struct RTMP_RX_RING *prRxRing;
struct GL_HIF_INFO *prHifInfo;
uint32_t u4MaxCnt, u4CpuIdx, u4DmaIdx, u4RxPktCnt;
prHifInfo = &prGlueInfo->rHifInfo;
prRxRing = &prHifInfo->RxRing[ucRingNum];
kalDevRegRead(prGlueInfo, prRxRing->hw_cnt_addr, &u4MaxCnt);
kalDevRegRead(prGlueInfo, prRxRing->hw_cidx_addr, &u4CpuIdx);
kalDevRegRead(prGlueInfo, prRxRing->hw_didx_addr, &u4DmaIdx);
if (u4MaxCnt == 0 || u4MaxCnt > RX_RING_SIZE)
return 0;
if (u4CpuIdx > u4DmaIdx)
u4RxPktCnt = u4MaxCnt + u4DmaIdx - u4CpuIdx - 1;
else if (u4CpuIdx < u4DmaIdx)
u4RxPktCnt = u4DmaIdx - u4CpuIdx - 1;
else
u4RxPktCnt = u4MaxCnt - 1;
return u4RxPktCnt;
}
bool halWpdmaWriteCmd(IN struct GLUE_INFO *prGlueInfo,
IN struct CMD_INFO *prCmdInfo, IN uint8_t ucTC)
{
struct GL_HIF_INFO *prHifInfo = NULL;
struct HIF_MEM_OPS *prMemOps;
struct RTMP_TX_RING *prTxRing;
struct RTMP_DMACB *pTxCell;
struct TXD_STRUCT *pTxD;
uint16_t u2Port = TX_RING_CMD_IDX_2;
uint32_t u4TotalLen;
void *pucSrc = NULL;
ASSERT(prGlueInfo);
prHifInfo = &prGlueInfo->rHifInfo;
prMemOps = &prHifInfo->rMemOps;
prTxRing = &prHifInfo->TxRing[u2Port];
u4TotalLen = prCmdInfo->u4TxdLen + prCmdInfo->u4TxpLen;
if (prMemOps->allocRuntimeMem)
pucSrc = prMemOps->allocRuntimeMem(u4TotalLen);
kalDevRegRead(prGlueInfo, prTxRing->hw_cidx_addr, &prTxRing->TxCpuIdx);
if (prTxRing->TxCpuIdx >= TX_RING_SIZE) {
DBGLOG(HAL, ERROR, "Error TxCpuIdx[%u]\n", prTxRing->TxCpuIdx);
if (prMemOps->freeBuf)
prMemOps->freeBuf(pucSrc, u4TotalLen);
return FALSE;
}
pTxCell = &prTxRing->Cell[prTxRing->TxCpuIdx];
pTxD = (struct TXD_STRUCT *)pTxCell->AllocVa;
pTxCell->pPacket = (void *)prCmdInfo;
pTxCell->pBuffer = pucSrc;
if (prMemOps->copyCmd &&
!prMemOps->copyCmd(prHifInfo, pTxCell, pucSrc,
prCmdInfo->pucTxd, prCmdInfo->u4TxdLen,
prCmdInfo->pucTxp, prCmdInfo->u4TxpLen)) {
if (prMemOps->freeBuf)
prMemOps->freeBuf(pucSrc, u4TotalLen);
ASSERT(0);
return FALSE;
}
pTxD->SDPtr0 = (uint64_t)pTxCell->PacketPa & DMA_LOWER_32BITS_MASK;
pTxD->SDPtr0Ext = ((uint64_t)pTxCell->PacketPa >> DMA_BITS_OFFSET) &
DMA_HIGHER_4BITS_MASK;
pTxD->SDLen0 = u4TotalLen;
pTxD->SDPtr1 = 0;
pTxD->SDLen1 = 0;
pTxD->LastSec0 = 1;
pTxD->LastSec1 = 0;
pTxD->Burst = 0;
pTxD->DMADONE = 0;
/* Increase TX_CTX_IDX, but write to register later. */
INC_RING_INDEX(prTxRing->TxCpuIdx, TX_RING_SIZE);
prTxRing->u4UsedCnt++;
kalDevRegWrite(prGlueInfo, prTxRing->hw_cidx_addr, prTxRing->TxCpuIdx);
DBGLOG(HAL, TRACE,
"%s: CmdInfo[0x%p], TxD[0x%p/%u] TxP[0x%p/%u] CPU idx[%u] Used[%u]\n",
__func__, prCmdInfo, prCmdInfo->pucTxd, prCmdInfo->u4TxdLen,
prCmdInfo->pucTxp, prCmdInfo->u4TxpLen,
prTxRing->TxCpuIdx, prTxRing->u4UsedCnt);
DBGLOG_MEM32(HAL, TRACE, prCmdInfo->pucTxd, prCmdInfo->u4TxdLen);
return TRUE;
}
static bool halWpdmaFillTxRing(struct GLUE_INFO *prGlueInfo,
struct MSDU_TOKEN_ENTRY *prToken)
{
struct GL_HIF_INFO *prHifInfo = NULL;
struct mt66xx_chip_info *prChipInfo;
struct RTMP_TX_RING *prTxRing;
struct RTMP_DMACB *pTxCell;
struct TXD_STRUCT *pTxD;
uint16_t u2Port = TX_RING_DATA0_IDX_0;
ASSERT(prGlueInfo);
prHifInfo = &prGlueInfo->rHifInfo;
prChipInfo = prGlueInfo->prAdapter->chip_info;
prTxRing = &prHifInfo->TxRing[u2Port];
kalDevRegRead(prGlueInfo, prTxRing->hw_cidx_addr, &prTxRing->TxCpuIdx);
if (prTxRing->TxCpuIdx >= TX_RING_SIZE) {
DBGLOG(HAL, ERROR, "Error TxCpuIdx[%u]\n", prTxRing->TxCpuIdx);
halReturnMsduToken(prGlueInfo->prAdapter, prToken->u4Token);
return FALSE;
}
pTxCell = &prTxRing->Cell[prTxRing->TxCpuIdx];
prToken->u4CpuIdx = prTxRing->TxCpuIdx;
pTxCell->prToken = prToken;
pTxD = (struct TXD_STRUCT *)pTxCell->AllocVa;
pTxD->SDPtr0 = (uint64_t)prToken->rDmaAddr & DMA_LOWER_32BITS_MASK;
pTxD->SDPtr0Ext = ((uint64_t)prToken->rDmaAddr >> DMA_BITS_OFFSET) &
DMA_HIGHER_4BITS_MASK;
pTxD->SDLen0 = NIC_TX_DESC_AND_PADDING_LENGTH +
prChipInfo->txd_append_size;
if (prChipInfo->is_support_cr4)
pTxD->SDLen0 += HIF_TX_PAYLOAD_LENGTH;
pTxD->SDPtr1 = 0;
pTxD->SDLen1 = 0;
pTxD->LastSec0 = 1;
pTxD->LastSec1 = 0;
pTxD->Burst = 0;
pTxD->DMADONE = 0;
/* Increase TX_CTX_IDX, but write to register later. */
INC_RING_INDEX(prTxRing->TxCpuIdx, TX_RING_SIZE);
/* Update HW Tx DMA ring */
prTxRing->u4UsedCnt++;
kalDevRegWrite(prGlueInfo, prTxRing->hw_cidx_addr, prTxRing->TxCpuIdx);
DBGLOG_LIMITED(HAL, TRACE, "Tx Data: CPU idx[0x%x] Used[%u]\n",
prTxRing->TxCpuIdx, prTxRing->u4UsedCnt);
return TRUE;
}
static bool halFlushToken(struct GLUE_INFO *prGlueInfo,
struct MSDU_TOKEN_ENTRY *prToken)
{
struct GL_HIF_INFO *prHifInfo = NULL;
struct HIF_MEM_OPS *prMemOps;
ASSERT(prGlueInfo);
prHifInfo = &prGlueInfo->rHifInfo;
prMemOps = &prHifInfo->rMemOps;
if (prMemOps->mapTxBuf) {
prToken->rDmaAddr = prMemOps->mapTxBuf(
prHifInfo, prToken->prPacket, 0, prToken->u4DmaLength);
if (!prToken->rDmaAddr)
return false;
}
if (prMemOps->flushCache)
prMemOps->flushCache(prHifInfo, prToken->prPacket,
prToken->u4DmaLength);
return true;
}
static bool halWpdmaWriteData(struct GLUE_INFO *prGlueInfo,
struct MSDU_INFO *prMsduInfo,
struct MSDU_TOKEN_ENTRY *prFillToken,
struct MSDU_TOKEN_ENTRY *prToken,
uint32_t u4Idx, uint32_t u4Num)
{
struct GL_HIF_INFO *prHifInfo = NULL;
struct mt66xx_chip_info *prChipInfo;
bool fgIsLast = (u4Idx + 1) == u4Num;
ASSERT(prGlueInfo);
prHifInfo = &prGlueInfo->rHifInfo;
prChipInfo = prGlueInfo->prAdapter->chip_info;
/* Update Tx descriptor */
halTxUpdateCutThroughDesc(prGlueInfo, prMsduInfo, prFillToken,
prToken, u4Idx, fgIsLast);
/* Update token exclude FillToken */
if (prToken != prFillToken) {
if (!halFlushToken(prGlueInfo, prToken))
return false;
}
/* Update FillToken */
if (fgIsLast) {
if (!halFlushToken(prGlueInfo, prFillToken))
return false;
halWpdmaFillTxRing(prGlueInfo, prFillToken);
}
return true;
}
void halWpdamFreeMsdu(struct GLUE_INFO *prGlueInfo,
struct MSDU_INFO *prMsduInfo,
bool fgSetEvent)
{
DBGLOG(HAL, LOUD, "Tx Data: Msdu[0x%p], TokFree[%u] TxDone[%u]\n",
prMsduInfo, halGetMsduTokenFreeCnt(prGlueInfo->prAdapter),
(prMsduInfo->pfTxDoneHandler ? TRUE : FALSE));
nicTxReleaseResource_PSE(prGlueInfo->prAdapter, prMsduInfo->ucTC,
nicTxGetPageCount(prGlueInfo->prAdapter,
prMsduInfo->u2FrameLength, TRUE), TRUE);
#if HIF_TX_PREALLOC_DATA_BUFFER
if (!prMsduInfo->pfTxDoneHandler) {
nicTxFreePacket(prGlueInfo->prAdapter, prMsduInfo, FALSE);
nicTxReturnMsduInfo(prGlueInfo->prAdapter, prMsduInfo);
}
#endif
if (fgSetEvent && wlanGetTxPendingFrameCount(prGlueInfo->prAdapter))
kalSetEvent(prGlueInfo);
}
bool halWpdmaWriteMsdu(struct GLUE_INFO *prGlueInfo,
struct MSDU_INFO *prMsduInfo,
struct list_head *prCurList)
{
struct GL_HIF_INFO *prHifInfo = NULL;
struct HIF_MEM_OPS *prMemOps;
struct MSDU_TOKEN_ENTRY *prToken = NULL;
struct sk_buff *prSkb;
uint8_t *pucSrc;
uint32_t u4TotalLen;
ASSERT(prGlueInfo);
ASSERT(prMsduInfo);
prHifInfo = &prGlueInfo->rHifInfo;
prMemOps = &prHifInfo->rMemOps;
prSkb = (struct sk_buff *)prMsduInfo->prPacket;
pucSrc = prSkb->data;
u4TotalLen = prSkb->len;
/* Acquire MSDU token */
prToken = halAcquireMsduToken(prGlueInfo->prAdapter);
if (!prToken) {
DBGLOG(HAL, ERROR, "Write MSDU acquire token fail\n");
return false;
}
#if HIF_TX_PREALLOC_DATA_BUFFER
if (prMemOps->copyTxData)
prMemOps->copyTxData(prToken, pucSrc, u4TotalLen);
#else
prToken->prMsduInfo = prMsduInfo;
prToken->prPacket = pucSrc;
prToken->u4DmaLength = u4TotalLen;
prMsduInfo->prToken = prToken;
#endif
if (!halWpdmaWriteData(prGlueInfo, prMsduInfo, prToken,
prToken, 0, 1)) {
halReturnMsduToken(prGlueInfo->prAdapter, prToken->u4Token);
return false;
}
if (prCurList) {
list_del(prCurList);
prHifInfo->u4TxDataQLen--;
}
halWpdamFreeMsdu(prGlueInfo, prMsduInfo, true);
return true;
}
bool halWpdmaWriteAmsdu(struct GLUE_INFO *prGlueInfo,
struct list_head *prList,
uint32_t u4Num, uint16_t u2Size)
{
struct GL_HIF_INFO *prHifInfo = NULL;
struct HIF_MEM_OPS *prMemOps;
struct RTMP_TX_RING *prTxRing;
struct list_head *prCur, *prNext;
struct TX_DATA_REQ *prTxReq;
struct MSDU_TOKEN_ENTRY *prFillToken = NULL, *prToken = NULL;
struct MSDU_INFO *prMsduInfo;
struct AMSDU_MAC_TX_DESC *prTxD = NULL;
struct sk_buff *prSkb;
uint8_t *pucSrc;
uint32_t u4TotalLen, u4Idx, u4FreeToken, u4FreeRing;
bool fgIsLast;
ASSERT(prGlueInfo);
prHifInfo = &prGlueInfo->rHifInfo;
prMemOps = &prHifInfo->rMemOps;
prTxRing = &prHifInfo->TxRing[TX_RING_DATA0_IDX_0];
u4FreeToken = halGetMsduTokenFreeCnt(prGlueInfo->prAdapter);
u4FreeRing = TX_RING_SIZE - prTxRing->u4UsedCnt;
if ((u4FreeToken < u4Num) || (u4FreeRing <= 1)) {
DBGLOG(HAL, WARN,
"Amsdu low tx res acquire[%u], tok[%u], ring[%u]\n",
u4Num, u4FreeToken, u4FreeRing);
return false;
}
prCur = prList;
for (u4Idx = 0; u4Idx < u4Num; u4Idx++) {
prTxReq = list_entry(prCur, struct TX_DATA_REQ, list);
prMsduInfo = prTxReq->prMsduInfo;
prSkb = (struct sk_buff *)prMsduInfo->prPacket;
pucSrc = prSkb->data;
u4TotalLen = prSkb->len;
fgIsLast = (u4Idx == u4Num - 1);
/* Acquire MSDU token */
prToken = halAcquireMsduToken(prGlueInfo->prAdapter);
if (!prToken) {
DBGLOG(HAL, ERROR, "Write AMSDU acquire token fail\n");
return false;
}
#if HIF_TX_PREALLOC_DATA_BUFFER
if (prMemOps->copyTxData)
prMemOps->copyTxData(prToken, pucSrc, u4TotalLen);
#else
prToken->prMsduInfo = prMsduInfo;
prToken->prPacket = pucSrc;
prToken->u4DmaLength = u4TotalLen;
prMsduInfo->prToken = prToken;
#endif
if (!prFillToken) {
prFillToken = prToken;
prTxD = (struct AMSDU_MAC_TX_DESC *)prToken->prPacket;
}
if (fgIsLast) {
prTxD->u2TxByteCount = u2Size;
prTxD->u4DW1 |= TXD_DW1_AMSDU_C;
}
if (!halWpdmaWriteData(prGlueInfo, prMsduInfo, prFillToken,
prToken, u4Idx, u4Num)) {
halReturnMsduToken(prGlueInfo->prAdapter,
prToken->u4Token);
return false;
}
prCur = prCur->next;
}
prCur = prList;
for (u4Idx = 0; u4Idx < u4Num; u4Idx++) {
prNext = prCur->next;
prTxReq = list_entry(prCur, struct TX_DATA_REQ, list);
prMsduInfo = prTxReq->prMsduInfo;
list_del(prCur);
prHifInfo->u4TxDataQLen--;
halWpdamFreeMsdu(prGlueInfo, prMsduInfo, true);
prCur = prNext;
}
DBGLOG(HAL, LOUD, "Amsdu num:%d tx byte: %d\n", u4Num, u2Size);
return true;
}
u_int8_t halIsStaticMapBusAddr(IN uint32_t u4Addr)
{
if (u4Addr < MAX_PCIE_BUS_STATIC_MAP_ADDR)
return TRUE;
else
return FALSE;
}
u_int8_t halChipToStaticMapBusAddr(IN struct GLUE_INFO *prGlueInfo,
IN uint32_t u4ChipAddr,
OUT uint32_t *pu4BusAddr)
{
struct BUS_INFO *prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info;
uint32_t u4StartAddr, u4EndAddr, u4BusAddr;
uint32_t u4Idx = 0;
if (halIsStaticMapBusAddr(u4ChipAddr)) {
*pu4BusAddr = u4ChipAddr;
return TRUE;
}
while (TRUE) {
u4StartAddr = prBusInfo->bus2chip[u4Idx].u4ChipAddr;
u4EndAddr = prBusInfo->bus2chip[u4Idx].u4ChipAddr +
prBusInfo->bus2chip[u4Idx].u4Range;
/* End of mapping table */
if (u4EndAddr == 0x0)
return FALSE;
if ((u4ChipAddr >= u4StartAddr) && (u4ChipAddr <= u4EndAddr)) {
u4BusAddr = (u4ChipAddr - u4StartAddr) +
prBusInfo->bus2chip[u4Idx].u4BusAddr;
break;
}
u4Idx++;
}
*pu4BusAddr = u4BusAddr;
return TRUE;
}
u_int8_t halGetDynamicMapReg(IN struct GLUE_INFO *prGlueInfo,
IN uint32_t u4ChipAddr, OUT uint32_t *pu4Value)
{
struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo;
uint32_t u4ReMapReg, u4BusAddr;
if (!halChipToStaticMapBusAddr(prGlueInfo, MCU_CFG_PCIE_REMAP2,
&u4ReMapReg))
return FALSE;
RTMP_IO_WRITE32(prHifInfo, u4ReMapReg, u4ChipAddr & PCIE_REMAP2_MASK);
u4BusAddr = PCIE_REMAP2_BUS_ADDR + (u4ChipAddr & ~PCIE_REMAP2_MASK);
RTMP_IO_READ32(prHifInfo, u4BusAddr, pu4Value);
return TRUE;
}
u_int8_t halSetDynamicMapReg(IN struct GLUE_INFO *prGlueInfo,
IN uint32_t u4ChipAddr, IN uint32_t u4Value)
{
struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo;
uint32_t u4ReMapReg, u4BusAddr;
if (!halChipToStaticMapBusAddr(prGlueInfo, MCU_CFG_PCIE_REMAP2,
&u4ReMapReg))
return FALSE;
RTMP_IO_WRITE32(prHifInfo, u4ReMapReg, u4ChipAddr & PCIE_REMAP2_MASK);
u4BusAddr = PCIE_REMAP2_BUS_ADDR + (u4ChipAddr & ~PCIE_REMAP2_MASK);
RTMP_IO_WRITE32(prHifInfo, u4BusAddr, u4Value);
return TRUE;
}
u_int8_t halIsPendingRx(IN struct ADAPTER *prAdapter)
{
/* TODO: check pending Rx
* if previous Rx handling is break due to lack of SwRfb
*/
return FALSE;
}
uint32_t halGetValidCoalescingBufSize(IN struct ADAPTER *prAdapter)
{
uint32_t u4BufSize;
if (HIF_TX_COALESCING_BUFFER_SIZE > HIF_RX_COALESCING_BUFFER_SIZE)
u4BufSize = HIF_TX_COALESCING_BUFFER_SIZE;
else
u4BufSize = HIF_RX_COALESCING_BUFFER_SIZE;
return u4BufSize;
}
uint32_t halAllocateIOBuffer(IN struct ADAPTER *prAdapter)
{
return WLAN_STATUS_SUCCESS;
}
uint32_t halReleaseIOBuffer(IN struct ADAPTER *prAdapter)
{
return WLAN_STATUS_SUCCESS;
}
void halProcessAbnormalInterrupt(IN struct ADAPTER *prAdapter)
{
}
void halProcessSoftwareInterrupt(IN struct ADAPTER *prAdapter)
{
struct GLUE_INFO *prGlueInfo;
struct GL_HIF_INFO *prHifInfo;
struct ERR_RECOVERY_CTRL_T *prErrRecoveryCtrl;
uint32_t u4Status = 0;
if (prAdapter == NULL || prAdapter->prGlueInfo == NULL) {
DBGLOG(HAL, ERROR, "prAdapter or prGlueInfo is NULL\n");
return;
}
prGlueInfo = prAdapter->prGlueInfo;
prHifInfo = &prGlueInfo->rHifInfo;
prErrRecoveryCtrl = &prHifInfo->rErrRecoveryCtl;
kalDevRegRead(prGlueInfo, MCU2HOST_SW_INT_STA, &u4Status);
if (u4Status & ERROR_DETECT_MASK) {
prErrRecoveryCtrl->u4Status = u4Status;
kalDevRegWrite(prGlueInfo, MCU2HOST_SW_INT_STA,
ERROR_DETECT_MASK);
halHwRecoveryFromError(prAdapter);
}
}
static void halHwRecoveryTimeout(unsigned long arg)
{
struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *)arg;
struct ADAPTER *prAdapter = NULL;
ASSERT(prGlueInfo);
prAdapter = prGlueInfo->prAdapter;
ASSERT(prAdapter);
DBGLOG(HAL, ERROR, "SER timer Timeout\n");
#if CFG_CHIP_RESET_SUPPORT
GL_RESET_TRIGGER(prAdapter, RST_FLAG_CHIP_RESET);
#endif
}
void halSetDrvSer(struct ADAPTER *prAdapter)
{
ASSERT(prAdapter);
ASSERT(prAdapter->prGlueInfo);
DBGLOG(HAL, INFO, "Set Driver Ser\n");
kalDevRegWrite(prAdapter->prGlueInfo, HOST2MCU_SW_INT_SET,
MCU_INT_DRIVER_SER);
}
void halInitSerTimer(IN struct ADAPTER *prAdapter)
{
struct GLUE_INFO *prGlueInfo;
struct GL_HIF_INFO *prHifInfo;
prGlueInfo = prAdapter->prGlueInfo;
prHifInfo = &prGlueInfo->rHifInfo;
init_timer(&prHifInfo->rSerTimer);
prHifInfo->rSerTimer.function = halHwRecoveryTimeout;
prHifInfo->rSerTimer.data = (unsigned long)prGlueInfo;
prHifInfo->rSerTimer.expires =
jiffies + HIF_SER_TIMEOUT * HZ / MSEC_PER_SEC;
add_timer(&prHifInfo->rSerTimer);
DBGLOG(HAL, INFO, "Start SER timer\n");
}
void halHwRecoveryFromError(IN struct ADAPTER *prAdapter)
{
struct GLUE_INFO *prGlueInfo;
struct GL_HIF_INFO *prHifInfo;
struct BUS_INFO *prBusInfo = NULL;
struct ERR_RECOVERY_CTRL_T *prErrRecoveryCtrl;
uint32_t u4Status = 0;
prGlueInfo = prAdapter->prGlueInfo;
prHifInfo = &prGlueInfo->rHifInfo;
prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info;
prErrRecoveryCtrl = &prHifInfo->rErrRecoveryCtl;
u4Status = prErrRecoveryCtrl->u4Status;
prErrRecoveryCtrl->u4Status = 0;
switch (prErrRecoveryCtrl->eErrRecovState) {
case ERR_RECOV_STOP_IDLE:
case ERR_RECOV_EVENT_REENTRY:
if (u4Status & ERROR_DETECT_STOP_PDMA) {
if (!prHifInfo->fgIsErrRecovery) {
prHifInfo->fgIsErrRecovery = TRUE;
halInitSerTimer(prAdapter);
}
DBGLOG(HAL, INFO,
"SER(E) Host stop PDMA tx/rx ring operation\n");
nicSerStopTxRx(prAdapter);
DBGLOG(HAL, INFO,
"SER(F) Host ACK PDMA tx/rx ring stop operation\n");
kalDevRegWrite(prGlueInfo, HOST2MCU_SW_INT_SET,
MCU_INT_PDMA0_STOP_DONE);
/* re-call for change status to stop dma0 */
prErrRecoveryCtrl->eErrRecovState =
ERR_RECOV_STOP_IDLE_DONE;
halHwRecoveryFromError(prAdapter);
} else {
DBGLOG(HAL, ERROR, "SER CurStat=%u Event=%x\n",
prErrRecoveryCtrl->eErrRecovState, u4Status);
}
break;
case ERR_RECOV_STOP_PDMA0:
if (u4Status & ERROR_DETECT_RESET_DONE) {
DBGLOG(HAL, INFO, "SER(L) Host re-initialize PDMA\n");
/* only reset TXD & RXD */
halWpdmaAllocRing(prAdapter->prGlueInfo, false);
halResetMsduToken(prAdapter);
DBGLOG(HAL, INFO, "SER(M) Host enable PDMA\n");
halWpdmaInitRing(prGlueInfo);
kalDevRegWrite(prGlueInfo, WPDMA_PAUSE_TX_Q, 0);
DBGLOG(HAL, INFO,
"SER(N) Host interrupt N9 PDMA ring init done\n");
prErrRecoveryCtrl->eErrRecovState =
ERR_RECOV_RESET_PDMA0;
kalDevRegWrite(prGlueInfo, HOST2MCU_SW_INT_SET,
MCU_INT_PDMA0_INIT_DONE);
} else {
DBGLOG(HAL, ERROR, "SER CurStat=%u Event=%x\n",
prErrRecoveryCtrl->eErrRecovState, u4Status);
}
break;
case ERR_RECOV_RESET_PDMA0:
if (u4Status & ERROR_DETECT_RECOVERY_DONE) {
DBGLOG(HAL, INFO,
"SER(Q) Host interrupt N9 SER handle done\n");
prErrRecoveryCtrl->eErrRecovState =
ERR_RECOV_WAIT_N9_NORMAL;
kalDevRegWrite(prGlueInfo, HOST2MCU_SW_INT_SET,
MCU_INT_PDMA0_RECOVERY_DONE);
} else {
DBGLOG(HAL, ERROR, "SER CurStat=%u Event=%x\n",
prErrRecoveryCtrl->eErrRecovState, u4Status);
}
break;
case ERR_RECOV_STOP_IDLE_DONE:
prErrRecoveryCtrl->eErrRecovState = ERR_RECOV_STOP_PDMA0;
break;
case ERR_RECOV_WAIT_N9_NORMAL:
if (u4Status & ERROR_DETECT_N9_NORMAL_STATE) {
del_timer(&prHifInfo->rSerTimer);
/* update Beacon frame if operating in AP mode. */
DBGLOG(HAL, INFO, "SER(T) Host re-initialize BCN\n");
nicSerReInitBeaconFrame(prAdapter);
kalDevKickCmd(prAdapter->prGlueInfo);
kalDevKickData(prAdapter->prGlueInfo);
halRxReceiveRFBs(prAdapter, RX_RING_EVT_IDX_1);
halRxReceiveRFBs(prAdapter, RX_RING_DATA_IDX_0);
prHifInfo->fgIsErrRecovery = FALSE;
nicSerStartTxRx(prAdapter);
prErrRecoveryCtrl->eErrRecovState = ERR_RECOV_STOP_IDLE;
} else if (u4Status & ERROR_DETECT_STOP_PDMA) {
DBGLOG(HAL, ERROR, "SER re-entry CurStat=%u Event=%x\n",
prErrRecoveryCtrl->eErrRecovState, u4Status);
prErrRecoveryCtrl->eErrRecovState =
ERR_RECOV_EVENT_REENTRY;
halHwRecoveryFromError(prAdapter);
} else {
DBGLOG(HAL, ERROR, "SER CurStat=%u Event=%x\n",
prErrRecoveryCtrl->eErrRecovState, u4Status);
}
break;
default:
DBGLOG(HAL, ERROR, "SER CurStat=%u Event=%x!!!\n",
prErrRecoveryCtrl->eErrRecovState, u4Status);
break;
}
}
#if CFG_SUPPORT_PCIE_L2
/*----------------------------------------------------------------------------*/
/*!
* @brief Send HIF_CTRL command to inform FW allow send packet/event to host
* suspend = 0
*
* @param prAdapter Pointer to the Adapter structure.
*
* @return (void)
*/
/*----------------------------------------------------------------------------*/
void halPreResumeCmd(IN struct ADAPTER *prAdapter)
{
struct CMD_HIF_CTRL rCmdHifCtrl;
uint32_t rStatus;
rCmdHifCtrl.ucHifType = ENUM_HIF_TYPE_PCIE;
rCmdHifCtrl.ucHifDirection = ENUM_HIF_TX;
rCmdHifCtrl.ucHifStop = 0;
rCmdHifCtrl.ucHifSuspend = 0;
rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */
CMD_ID_HIF_CTRL, /* ucCID */
TRUE, /* fgSetQuery */
FALSE, /* fgNeedResp */
FALSE, /* fgIsOid */
NULL, /* nicEventHifCtrl */
NULL, /* pfCmdTimeoutHandler */
sizeof(struct CMD_HIF_CTRL),
(uint8_t *)&rCmdHifCtrl, /* pucInfoBuffer */
NULL, /* pvSetQueryBuffer */
0 /* u4SetQueryBufferLen */
);
if (kalIsResetting())
return;
ASSERT(rStatus == WLAN_STATUS_PENDING);
}
/*----------------------------------------------------------------------------*/
/*!
* @brief Send HIF_CTRL command to inform FW stop send packet/event to host
* suspend = 1
*
* @param prAdapter Pointer to the Adapter structure.
*
* @return (void)
*/
/*----------------------------------------------------------------------------*/
void halPreSuspendCmd(IN struct ADAPTER *prAdapter)
{
struct CMD_HIF_CTRL rCmdHifCtrl;
uint32_t rStatus;
rCmdHifCtrl.ucHifType = ENUM_HIF_TYPE_PCIE;
rCmdHifCtrl.ucHifDirection = ENUM_HIF_TX;
rCmdHifCtrl.ucHifStop = 1;
rCmdHifCtrl.ucHifSuspend = 1;
rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */
CMD_ID_HIF_CTRL, /* ucCID */
TRUE, /* fgSetQuery */
FALSE, /* fgNeedResp */
FALSE, /* fgIsOid */
NULL, /* nicEventHifCtrl */
NULL, /* pfCmdTimeoutHandler */
sizeof(struct CMD_HIF_CTRL),
(uint8_t *)&rCmdHifCtrl, /* pucInfoBuffer */
NULL, /* pvSetQueryBuffer */
0 /* u4SetQueryBufferLen */
);
if (kalIsResetting())
return;
ASSERT(rStatus == WLAN_STATUS_PENDING);
}
#endif
void halDeAggRxPktWorker(struct work_struct *work)
{
}
void halRxTasklet(unsigned long data)
{
}
void halTxCompleteTasklet(unsigned long data)
{
}
/* Hif power off wifi */
uint32_t halHifPowerOffWifi(IN struct ADAPTER *prAdapter)
{
struct GL_HIF_INFO *prHifInfo = NULL;
uint32_t rStatus = WLAN_STATUS_SUCCESS;
prHifInfo = &prAdapter->prGlueInfo->rHifInfo;
DBGLOG(INIT, INFO, "Power off Wi-Fi!\n");
nicDisableInterrupt(prAdapter);
ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter);
/* Power off Wi-Fi */
wlanSendNicPowerCtrlCmd(prAdapter, TRUE);
prHifInfo->fgIsPowerOff = true;
/* prAdapter->fgWiFiInSleepyState = TRUE; */
RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE);
rStatus = wlanCheckWifiFunc(prAdapter, FALSE);
return rStatus;
}
u_int8_t halIsTxResourceControlEn(IN struct ADAPTER *prAdapter)
{
return FALSE;
}
void halTxResourceResetHwTQCounter(IN struct ADAPTER *prAdapter)
{
}
uint32_t halGetHifTxPageSize(IN struct ADAPTER *prAdapter)
{
return HIF_TX_PAGE_SIZE;
}
/*----------------------------------------------------------------------------*/
/*!
* @brief Check if HIF state is READY for upper layer cfg80211
*
* @param prAdapter Pointer to the Adapter structure.
*
* @return (TRUE: ready, FALSE: not ready)
*/
/*----------------------------------------------------------------------------*/
bool halIsHifStateReady(IN struct ADAPTER *prAdapter, uint8_t *pucState)
{
/* PCIE owner should implement this function */
return TRUE;
}
/*----------------------------------------------------------------------------*/
/*!
* @brief Check if HIF state is during supend process
*
* @param prAdapter Pointer to the Adapter structure.
*
* @return (TRUE: suspend, reject the caller action. FALSE: not suspend)
*/
/*----------------------------------------------------------------------------*/
bool halIsHifStateSuspend(IN struct ADAPTER *prAdapter)
{
/* PCIE owner should implement this function */
return FALSE;
}