| /****************************************************************************** |
| * |
| * 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/nic/nic_rx.c#5 |
| */ |
| |
| /*! \file nic_rx.c |
| * \brief Functions that provide many rx-related functions |
| * |
| * This file includes the functions used to process RFB and dispatch RFBs to |
| * the appropriate related rx functions for protocols. |
| */ |
| |
| |
| /******************************************************************************* |
| * 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 "que_mgt.h" |
| |
| #ifndef LINUX |
| #include <limits.h> |
| #else |
| #include <linux/limits.h> |
| #endif |
| |
| /******************************************************************************* |
| * 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 |
| ******************************************************************************** |
| */ |
| |
| #if CFG_MGMT_FRAME_HANDLING |
| static PROCESS_RX_MGT_FUNCTION apfnProcessRxMgtFrame[MAX_NUM_OF_FC_SUBTYPES] = { |
| #if CFG_SUPPORT_AAA |
| aaaFsmRunEventRxAssoc, /* subtype 0000: Association request */ |
| #else |
| NULL, /* subtype 0000: Association request */ |
| #endif /* CFG_SUPPORT_AAA */ |
| saaFsmRunEventRxAssoc, /* subtype 0001: Association response */ |
| #if CFG_SUPPORT_AAA |
| aaaFsmRunEventRxAssoc, /* subtype 0010: Reassociation request */ |
| #else |
| NULL, /* subtype 0010: Reassociation request */ |
| #endif /* CFG_SUPPORT_AAA */ |
| saaFsmRunEventRxAssoc, /* subtype 0011: Reassociation response */ |
| #if CFG_SUPPORT_ADHOC || CFG_ENABLE_WIFI_DIRECT |
| bssProcessProbeRequest, /* subtype 0100: Probe request */ |
| #else |
| NULL, /* subtype 0100: Probe request */ |
| #endif /* CFG_SUPPORT_ADHOC */ |
| scanProcessBeaconAndProbeResp, /* subtype 0101: Probe response */ |
| NULL, /* subtype 0110: reserved */ |
| NULL, /* subtype 0111: reserved */ |
| scanProcessBeaconAndProbeResp, /* subtype 1000: Beacon */ |
| NULL, /* subtype 1001: ATIM */ |
| saaFsmRunEventRxDisassoc, /* subtype 1010: Disassociation */ |
| authCheckRxAuthFrameTransSeq, /* subtype 1011: Authentication */ |
| saaFsmRunEventRxDeauth, /* subtype 1100: Deauthentication */ |
| nicRxProcessActionFrame, /* subtype 1101: Action */ |
| NULL, /* subtype 1110: reserved */ |
| NULL /* subtype 1111: reserved */ |
| }; |
| #endif |
| |
| static RX_EVENT_HANDLER_T arEventTable[] = { |
| {EVENT_ID_RX_ADDBA, qmHandleEventRxAddBa}, |
| {EVENT_ID_RX_DELBA, qmHandleEventRxDelBa}, |
| {EVENT_ID_CHECK_REORDER_BUBBLE, qmHandleEventCheckReorderBubble}, |
| {EVENT_ID_LINK_QUALITY, nicEventLinkQuality}, |
| {EVENT_ID_LAYER_0_EXT_MAGIC_NUM, nicEventLayer0ExtMagic}, |
| {EVENT_ID_MIC_ERR_INFO, nicEventMicErrorInfo}, |
| {EVENT_ID_SCAN_DONE, nicEventScanDone}, |
| {EVENT_ID_NLO_DONE, nicEventNloDone}, |
| {EVENT_ID_TX_DONE, nicTxProcessTxDoneEvent}, |
| {EVENT_ID_SLEEPY_INFO, nicEventSleepyNotify}, |
| #if CFG_ENABLE_BT_OVER_WIFI |
| {EVENT_ID_BT_OVER_WIFI, nicEventBtOverWifi}, |
| #endif |
| {EVENT_ID_STATISTICS, nicEventStatistics}, |
| {EVENT_ID_WLAN_INFO, nicEventWlanInfo}, |
| {EVENT_ID_MIB_INFO, nicEventMibInfo}, |
| #if CFG_SUPPORT_LAST_SEC_MCS_INFO |
| {EVENT_ID_TX_MCS_INFO, nicEventTxMcsInfo}, |
| #endif |
| {EVENT_ID_CH_PRIVILEGE, cnmChMngrHandleChEvent}, |
| {EVENT_ID_BSS_ABSENCE_PRESENCE, qmHandleEventBssAbsencePresence}, |
| {EVENT_ID_STA_CHANGE_PS_MODE, qmHandleEventStaChangePsMode}, |
| {EVENT_ID_STA_UPDATE_FREE_QUOTA, qmHandleEventStaUpdateFreeQuota}, |
| {EVENT_ID_BSS_BEACON_TIMEOUT, nicEventBeaconTimeout}, |
| {EVENT_ID_UPDATE_NOA_PARAMS, nicEventUpdateNoaParams}, |
| {EVENT_ID_STA_AGING_TIMEOUT, nicEventStaAgingTimeout}, |
| {EVENT_ID_AP_OBSS_STATUS, nicEventApObssStatus}, |
| {EVENT_ID_ROAMING_STATUS, nicEventRoamingStatus}, |
| {EVENT_ID_SEND_DEAUTH, nicEventSendDeauth}, |
| {EVENT_ID_UPDATE_RDD_STATUS, nicEventUpdateRddStatus}, |
| {EVENT_ID_UPDATE_BWCS_STATUS, nicEventUpdateBwcsStatus}, |
| {EVENT_ID_UPDATE_BCM_DEBUG, nicEventUpdateBcmDebug}, |
| {EVENT_ID_ADD_PKEY_DONE, nicEventAddPkeyDone}, |
| {EVENT_ID_ICAP_DONE, nicEventIcapDone}, |
| {EVENT_ID_DEBUG_MSG, nicEventDebugMsg}, |
| {EVENT_ID_TDLS, nicEventTdls}, |
| {EVENT_ID_DUMP_MEM, nicEventDumpMem}, |
| #if CFG_ASSERT_DUMP |
| {EVENT_ID_ASSERT_DUMP, nicEventAssertDump}, |
| #endif |
| #if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST |
| {EVENT_ID_CAL_ALL_DONE, nicEventCalAllDone}, |
| #endif |
| {EVENT_ID_HIF_CTRL, nicEventHifCtrl}, |
| {EVENT_ID_RDD_SEND_PULSE, nicEventRddSendPulse}, |
| #if (CFG_SUPPORT_DFS_MASTER == 1) |
| {EVENT_ID_UPDATE_COEX_PHYRATE, nicEventUpdateCoexPhyrate}, |
| {EVENT_ID_RDD_REPORT, cnmRadarDetectEvent}, |
| {EVENT_ID_CSA_DONE, cnmCsaDoneEvent}, |
| #else |
| {EVENT_ID_UPDATE_COEX_PHYRATE, nicEventUpdateCoexPhyrate}, |
| #endif |
| #if (CFG_WOW_SUPPORT == 1) |
| {EVENT_ID_WOW_WAKEUP_REASON, nicEventWakeUpReason}, |
| #endif |
| {EVENT_ID_CSI_DATA, nicEventCSIData}, |
| |
| #if CFG_SUPPORT_REPLAY_DETECTION |
| {EVENT_ID_GET_GTK_REKEY_DATA, nicEventGetGtkDataSync}, |
| #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 |
| ******************************************************************************** |
| */ |
| |
| /******************************************************************************* |
| * F U N C T I O N S |
| ******************************************************************************** |
| */ |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Initialize the RFBs |
| * |
| * @param prAdapter Pointer to the Adapter structure. |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID nicRxInitialize(IN P_ADAPTER_T prAdapter) |
| { |
| P_RX_CTRL_T prRxCtrl; |
| PUINT_8 pucMemHandle; |
| P_SW_RFB_T prSwRfb = (P_SW_RFB_T) NULL; |
| UINT_32 i; |
| |
| DEBUGFUNC("nicRxInitialize"); |
| |
| ASSERT(prAdapter); |
| prRxCtrl = &prAdapter->rRxCtrl; |
| |
| /* 4 <0> Clear allocated memory. */ |
| kalMemZero((PVOID) prRxCtrl->pucRxCached, prRxCtrl->u4RxCachedSize); |
| |
| /* 4 <1> Initialize the RFB lists */ |
| QUEUE_INITIALIZE(&prRxCtrl->rFreeSwRfbList); |
| QUEUE_INITIALIZE(&prRxCtrl->rReceivedRfbList); |
| QUEUE_INITIALIZE(&prRxCtrl->rIndicatedRfbList); |
| |
| pucMemHandle = prRxCtrl->pucRxCached; |
| for (i = CFG_RX_MAX_PKT_NUM; i != 0; i--) { |
| prSwRfb = (P_SW_RFB_T) pucMemHandle; |
| |
| if (nicRxSetupRFB(prAdapter, prSwRfb)) { |
| DBGLOG(RX, ERROR, "nicRxInitialize failed: Cannot allocate packet buffer for SwRfb!\n"); |
| return; |
| } |
| nicRxReturnRFB(prAdapter, prSwRfb); |
| |
| pucMemHandle += ALIGN_4(sizeof(SW_RFB_T)); |
| } |
| |
| ASSERT(prRxCtrl->rFreeSwRfbList.u4NumElem == CFG_RX_MAX_PKT_NUM); |
| /* Check if the memory allocation consist with this initialization function */ |
| ASSERT((UINT_32) (pucMemHandle - prRxCtrl->pucRxCached) == prRxCtrl->u4RxCachedSize); |
| |
| /* 4 <2> Clear all RX counters */ |
| RX_RESET_ALL_CNTS(prRxCtrl); |
| |
| prRxCtrl->pucRxCoalescingBufPtr = prAdapter->pucCoalescingBufCached; |
| |
| #if CFG_HIF_STATISTICS |
| prRxCtrl->u4TotalRxAccessNum = 0; |
| prRxCtrl->u4TotalRxPacketNum = 0; |
| #endif |
| |
| #if CFG_HIF_RX_STARVATION_WARNING |
| prRxCtrl->u4QueuedCnt = 0; |
| prRxCtrl->u4DequeuedCnt = 0; |
| #endif |
| |
| } /* end of nicRxInitialize() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Uninitialize the RFBs |
| * |
| * @param prAdapter Pointer to the Adapter structure. |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID nicRxUninitialize(IN P_ADAPTER_T prAdapter) |
| { |
| P_RX_CTRL_T prRxCtrl; |
| P_SW_RFB_T prSwRfb = (P_SW_RFB_T) NULL; |
| |
| KAL_SPIN_LOCK_DECLARATION(); |
| |
| ASSERT(prAdapter); |
| prRxCtrl = &prAdapter->rRxCtrl; |
| ASSERT(prRxCtrl); |
| |
| nicRxFlush(prAdapter); |
| |
| do { |
| KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); |
| QUEUE_REMOVE_HEAD(&prRxCtrl->rReceivedRfbList, prSwRfb, P_SW_RFB_T); |
| KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); |
| if (prSwRfb) { |
| if (prSwRfb->pvPacket) |
| kalPacketFree(prAdapter->prGlueInfo, prSwRfb->pvPacket); |
| prSwRfb->pvPacket = NULL; |
| } else { |
| break; |
| } |
| } while (TRUE); |
| |
| do { |
| KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); |
| QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfb, P_SW_RFB_T); |
| KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); |
| if (prSwRfb) { |
| if (prSwRfb->pvPacket) |
| kalPacketFree(prAdapter->prGlueInfo, prSwRfb->pvPacket); |
| prSwRfb->pvPacket = NULL; |
| } else { |
| break; |
| } |
| } while (TRUE); |
| |
| } /* end of nicRxUninitialize() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Fill RFB |
| * |
| * @param prAdapter pointer to the Adapter handler |
| * @param prSWRfb specify the RFB to receive rx data |
| * |
| * @return (none) |
| * |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID nicRxFillRFB(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb) |
| { |
| P_HW_MAC_RX_DESC_T prRxStatus; |
| |
| UINT_32 u4PktLen = 0; |
| /* UINT_32 u4MacHeaderLen; */ |
| UINT_32 u4HeaderOffset; |
| UINT_16 u2RxStatusOffset; |
| |
| DEBUGFUNC("nicRxFillRFB"); |
| |
| ASSERT(prAdapter); |
| ASSERT(prSwRfb); |
| |
| prRxStatus = prSwRfb->prRxStatus; |
| ASSERT(prRxStatus); |
| |
| u4PktLen = (UINT_32) HAL_RX_STATUS_GET_RX_BYTE_CNT(prRxStatus); |
| u4HeaderOffset = (UINT_32) (HAL_RX_STATUS_GET_HEADER_OFFSET(prRxStatus)); |
| /* u4MacHeaderLen = (UINT_32)(HAL_RX_STATUS_GET_HEADER_LEN(prRxStatus)); */ |
| |
| /* DBGLOG(RX, TRACE, ("u4HeaderOffset = %d, u4MacHeaderLen = %d\n", */ |
| /* u4HeaderOffset, u4MacHeaderLen)); */ |
| u2RxStatusOffset = sizeof(HW_MAC_RX_DESC_T); |
| prSwRfb->ucGroupVLD = (UINT_8) HAL_RX_STATUS_GET_GROUP_VLD(prRxStatus); |
| if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_4)) { |
| prSwRfb->prRxStatusGroup4 = (P_HW_MAC_RX_STS_GROUP_4_T) ((P_UINT_8) prRxStatus + u2RxStatusOffset); |
| u2RxStatusOffset += sizeof(HW_MAC_RX_STS_GROUP_4_T); |
| |
| } |
| if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_1)) { |
| prSwRfb->prRxStatusGroup1 = (P_HW_MAC_RX_STS_GROUP_1_T) ((P_UINT_8) prRxStatus + u2RxStatusOffset); |
| u2RxStatusOffset += sizeof(HW_MAC_RX_STS_GROUP_1_T); |
| |
| } |
| if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_2)) { |
| prSwRfb->prRxStatusGroup2 = (P_HW_MAC_RX_STS_GROUP_2_T) ((P_UINT_8) prRxStatus + u2RxStatusOffset); |
| u2RxStatusOffset += sizeof(HW_MAC_RX_STS_GROUP_2_T); |
| |
| } |
| if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_3)) { |
| prSwRfb->prRxStatusGroup3 = (P_HW_MAC_RX_STS_GROUP_3_T) ((P_UINT_8) prRxStatus + u2RxStatusOffset); |
| u2RxStatusOffset += sizeof(HW_MAC_RX_STS_GROUP_3_T); |
| } |
| |
| prSwRfb->u2RxStatusOffst = u2RxStatusOffset; |
| prSwRfb->pvHeader = (PUINT_8) prRxStatus + u2RxStatusOffset + u4HeaderOffset; |
| prSwRfb->u2PacketLen = (UINT_16) (u4PktLen - (u2RxStatusOffset + u4HeaderOffset)); |
| prSwRfb->u2HeaderLen = (UINT_16) HAL_RX_STATUS_GET_HEADER_LEN(prRxStatus); |
| prSwRfb->ucWlanIdx = (UINT_8) HAL_RX_STATUS_GET_WLAN_IDX(prRxStatus); |
| prSwRfb->ucStaRecIdx = secGetStaIdxByWlanIdx(prAdapter, (UINT_8) HAL_RX_STATUS_GET_WLAN_IDX(prRxStatus)); |
| prSwRfb->prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); |
| |
| /* DBGLOG(RX, TRACE, ("Dump Rx packet, u2PacketLen = %d\n", prSwRfb->u2PacketLen)); */ |
| /* DBGLOG_MEM8(RX, TRACE, prSwRfb->pvHeader, prSwRfb->u2PacketLen); */ |
| |
| #if 0 |
| if (prHifRxHdr->ucReorder & HIF_RX_HDR_80211_HEADER_FORMAT) { |
| prSwRfb->u4HifRxHdrFlag |= HIF_RX_HDR_FLAG_802_11_FORMAT; |
| DBGLOG(RX, TRACE, "HIF_RX_HDR_FLAG_802_11_FORMAT\n"); |
| } |
| |
| if (prHifRxHdr->ucReorder & HIF_RX_HDR_DO_REORDER) { |
| prSwRfb->u4HifRxHdrFlag |= HIF_RX_HDR_FLAG_DO_REORDERING; |
| DBGLOG(RX, TRACE, "HIF_RX_HDR_FLAG_DO_REORDERING\n"); |
| |
| /* Get Seq. No and TID, Wlan Index info */ |
| if (prHifRxHdr->u2SeqNoTid & HIF_RX_HDR_BAR_FRAME) { |
| prSwRfb->u4HifRxHdrFlag |= HIF_RX_HDR_FLAG_BAR_FRAME; |
| DBGLOG(RX, TRACE, "HIF_RX_HDR_FLAG_BAR_FRAME\n"); |
| } |
| |
| prSwRfb->u2SSN = prHifRxHdr->u2SeqNoTid & HIF_RX_HDR_SEQ_NO_MASK; |
| prSwRfb->ucTid = (UINT_8) ((prHifRxHdr->u2SeqNoTid & HIF_RX_HDR_TID_MASK) |
| >> HIF_RX_HDR_TID_OFFSET); |
| DBGLOG(RX, TRACE, "u2SSN = %d, ucTid = %d\n", prSwRfb->u2SSN, prSwRfb->ucTid); |
| } |
| |
| if (prHifRxHdr->ucReorder & HIF_RX_HDR_WDS) { |
| prSwRfb->u4HifRxHdrFlag |= HIF_RX_HDR_FLAG_AMP_WDS; |
| DBGLOG(RX, TRACE, "HIF_RX_HDR_FLAG_AMP_WDS\n"); |
| } |
| #endif |
| } |
| |
| #if CFG_TCP_IP_CHKSUM_OFFLOAD || CFG_TCP_IP_CHKSUM_OFFLOAD_NDIS_60 |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Fill checksum status in RFB |
| * |
| * @param prAdapter pointer to the Adapter handler |
| * @param prSWRfb the RFB to receive rx data |
| * @param u4TcpUdpIpCksStatus specify the Checksum status |
| * |
| * @return (none) |
| * |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID nicRxFillChksumStatus(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb, IN UINT_32 u4TcpUdpIpCksStatus) |
| { |
| |
| ASSERT(prAdapter); |
| ASSERT(prSwRfb); |
| |
| if (prAdapter->u4CSUMFlags != CSUM_NOT_SUPPORTED) { |
| if (u4TcpUdpIpCksStatus & RX_CS_TYPE_IPv4) { /* IPv4 packet */ |
| prSwRfb->aeCSUM[CSUM_TYPE_IPV6] = CSUM_RES_NONE; |
| if (u4TcpUdpIpCksStatus & RX_CS_STATUS_IP) { /* IP packet csum failed */ |
| prSwRfb->aeCSUM[CSUM_TYPE_IPV4] = CSUM_RES_FAILED; |
| } else { |
| prSwRfb->aeCSUM[CSUM_TYPE_IPV4] = CSUM_RES_SUCCESS; |
| } |
| |
| if (u4TcpUdpIpCksStatus & RX_CS_TYPE_TCP) { /* TCP packet */ |
| prSwRfb->aeCSUM[CSUM_TYPE_UDP] = CSUM_RES_NONE; |
| if (u4TcpUdpIpCksStatus & RX_CS_STATUS_TCP) { /* TCP packet csum failed */ |
| prSwRfb->aeCSUM[CSUM_TYPE_TCP] = CSUM_RES_FAILED; |
| } else { |
| prSwRfb->aeCSUM[CSUM_TYPE_TCP] = CSUM_RES_SUCCESS; |
| } |
| } else if (u4TcpUdpIpCksStatus & RX_CS_TYPE_UDP) { /* UDP packet */ |
| prSwRfb->aeCSUM[CSUM_TYPE_TCP] = CSUM_RES_NONE; |
| if (u4TcpUdpIpCksStatus & RX_CS_STATUS_UDP) { /* UDP packet csum failed */ |
| prSwRfb->aeCSUM[CSUM_TYPE_UDP] = CSUM_RES_FAILED; |
| } else { |
| prSwRfb->aeCSUM[CSUM_TYPE_UDP] = CSUM_RES_SUCCESS; |
| } |
| } else { |
| prSwRfb->aeCSUM[CSUM_TYPE_UDP] = CSUM_RES_NONE; |
| prSwRfb->aeCSUM[CSUM_TYPE_TCP] = CSUM_RES_NONE; |
| } |
| } else if (u4TcpUdpIpCksStatus & RX_CS_TYPE_IPv6) { /* IPv6 packet */ |
| prSwRfb->aeCSUM[CSUM_TYPE_IPV4] = CSUM_RES_NONE; |
| prSwRfb->aeCSUM[CSUM_TYPE_IPV6] = CSUM_RES_SUCCESS; |
| |
| if (u4TcpUdpIpCksStatus & RX_CS_TYPE_TCP) { /* TCP packet */ |
| prSwRfb->aeCSUM[CSUM_TYPE_UDP] = CSUM_RES_NONE; |
| if (u4TcpUdpIpCksStatus & RX_CS_STATUS_TCP) { /* TCP packet csum failed */ |
| prSwRfb->aeCSUM[CSUM_TYPE_TCP] = CSUM_RES_FAILED; |
| } else { |
| prSwRfb->aeCSUM[CSUM_TYPE_TCP] = CSUM_RES_SUCCESS; |
| } |
| } else if (u4TcpUdpIpCksStatus & RX_CS_TYPE_UDP) { /* UDP packet */ |
| prSwRfb->aeCSUM[CSUM_TYPE_TCP] = CSUM_RES_NONE; |
| if (u4TcpUdpIpCksStatus & RX_CS_STATUS_UDP) { /* UDP packet csum failed */ |
| prSwRfb->aeCSUM[CSUM_TYPE_UDP] = CSUM_RES_FAILED; |
| } else { |
| prSwRfb->aeCSUM[CSUM_TYPE_UDP] = CSUM_RES_SUCCESS; |
| } |
| } else { |
| prSwRfb->aeCSUM[CSUM_TYPE_UDP] = CSUM_RES_NONE; |
| prSwRfb->aeCSUM[CSUM_TYPE_TCP] = CSUM_RES_NONE; |
| } |
| } else { |
| prSwRfb->aeCSUM[CSUM_TYPE_IPV4] = CSUM_RES_NONE; |
| prSwRfb->aeCSUM[CSUM_TYPE_IPV6] = CSUM_RES_NONE; |
| } |
| } |
| |
| } |
| #endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief rxDefragMPDU() is used to defragment the incoming packets. |
| * |
| * \param[in] prSWRfb The RFB which is being processed. |
| * \param[in] UINT_16 u2FrameCtrl |
| * |
| * \retval NOT NULL Receive the last fragment data |
| * \retval NULL Receive the fragment packet which is not the last |
| */ |
| /*----------------------------------------------------------------------------*/ |
| P_SW_RFB_T incRxDefragMPDU(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSWRfb, OUT P_QUE_T prReturnedQue) |
| { |
| |
| P_SW_RFB_T prOutputSwRfb = (P_SW_RFB_T) NULL; |
| #if 1 |
| P_RX_CTRL_T prRxCtrl; |
| P_FRAG_INFO_T prFragInfo; |
| UINT_32 i = 0, j; |
| UINT_16 u2SeqCtrl, u2FrameCtrl; |
| UINT_8 ucFragNum; |
| BOOLEAN fgFirst = FALSE; |
| BOOLEAN fgLast = FALSE; |
| OS_SYSTIME rCurrentTime; |
| P_WLAN_MAC_HEADER_T prWlanHeader = NULL; |
| P_HW_MAC_RX_DESC_T prRxStatus = NULL; |
| P_HW_MAC_RX_STS_GROUP_4_T prRxStatusGroup4 = NULL; |
| |
| DEBUGFUNC("nicRx: rxmDefragMPDU\n"); |
| |
| ASSERT(prSWRfb); |
| |
| prRxCtrl = &prAdapter->rRxCtrl; |
| |
| prRxStatus = prSWRfb->prRxStatus; |
| ASSERT(prRxStatus); |
| |
| if (HAL_RX_STATUS_IS_HEADER_TRAN(prRxStatus) == FALSE) { |
| prWlanHeader = (P_WLAN_MAC_HEADER_T) prSWRfb->pvHeader; |
| prSWRfb->u2SequenceControl = prWlanHeader->u2SeqCtrl; |
| u2FrameCtrl = prWlanHeader->u2FrameCtrl; |
| } else { |
| prRxStatusGroup4 = prSWRfb->prRxStatusGroup4; |
| prSWRfb->u2SequenceControl = HAL_RX_STATUS_GET_SEQFrag_NUM(prRxStatusGroup4); |
| u2FrameCtrl = HAL_RX_STATUS_GET_FRAME_CTL_FIELD(prRxStatusGroup4); |
| } |
| u2SeqCtrl = prSWRfb->u2SequenceControl; |
| ucFragNum = (UINT_8) (u2SeqCtrl & MASK_SC_FRAG_NUM); |
| prSWRfb->u2FrameCtrl = u2FrameCtrl; |
| |
| if (!(u2FrameCtrl & MASK_FC_MORE_FRAG)) { |
| /* The last fragment frame */ |
| if (ucFragNum) { |
| DBGLOG(RX, LOUD, |
| "FC %04x M %04x SQ %04x\n", u2FrameCtrl, (u2FrameCtrl & MASK_FC_MORE_FRAG), u2SeqCtrl); |
| fgLast = TRUE; |
| } |
| /* Non-fragment frame */ |
| else |
| return prSWRfb; |
| } |
| /* The fragment frame except the last one */ |
| else { |
| if (ucFragNum == 0) { |
| DBGLOG(RX, LOUD, |
| "FC %04x M %04x SQ %04x\n", u2FrameCtrl, (u2FrameCtrl & MASK_FC_MORE_FRAG), u2SeqCtrl); |
| fgFirst = TRUE; |
| } else { |
| DBGLOG(RX, LOUD, |
| "FC %04x M %04x SQ %04x\n", u2FrameCtrl, (u2FrameCtrl & MASK_FC_MORE_FRAG), u2SeqCtrl); |
| } |
| } |
| |
| GET_CURRENT_SYSTIME(&rCurrentTime); |
| |
| for (j = 0; j < MAX_NUM_CONCURRENT_FRAGMENTED_MSDUS; j++) { |
| prFragInfo = &prSWRfb->prStaRec->rFragInfo[j]; |
| if (prFragInfo->pr1stFrag) { |
| /* I. If the receive timer for the MSDU or MMPDU that is stored in the |
| * fragments queue exceeds dot11MaxReceiveLifetime, we discard the |
| * uncompleted fragments. |
| * II. If we didn't receive the last MPDU for a period, we use |
| * this function for remove frames. |
| */ |
| if (CHECK_FOR_EXPIRATION(rCurrentTime, prFragInfo->rReceiveLifetimeLimit)) { |
| |
| /* cnmPktFree((P_PKT_INFO_T)prFragInfo->pr1stFrag, TRUE); */ |
| prFragInfo->pr1stFrag->eDst = RX_PKT_DESTINATION_NULL; |
| QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prFragInfo->pr1stFrag); |
| |
| prFragInfo->pr1stFrag = (P_SW_RFB_T) NULL; |
| } |
| } |
| } |
| |
| for (i = 0; i < MAX_NUM_CONCURRENT_FRAGMENTED_MSDUS; i++) { |
| |
| prFragInfo = &prSWRfb->prStaRec->rFragInfo[i]; |
| |
| if (fgFirst) { /* looking for timed-out frag buffer */ |
| |
| if (prFragInfo->pr1stFrag == (P_SW_RFB_T) NULL) /* find a free frag buffer */ |
| break; |
| } else { /* looking for a buffer with desired next seqctrl */ |
| |
| if (prFragInfo->pr1stFrag == (P_SW_RFB_T) NULL) |
| continue; |
| |
| if (RXM_IS_QOS_DATA_FRAME(u2FrameCtrl)) { |
| if (RXM_IS_QOS_DATA_FRAME(prFragInfo->pr1stFrag->u2FrameCtrl)) { |
| if (u2SeqCtrl == prFragInfo->u2NextFragSeqCtrl) |
| break; |
| } |
| } else { |
| if (!RXM_IS_QOS_DATA_FRAME(prFragInfo->pr1stFrag->u2FrameCtrl)) { |
| if (u2SeqCtrl == prFragInfo->u2NextFragSeqCtrl) |
| break; |
| } |
| } |
| } |
| } |
| |
| if (i >= MAX_NUM_CONCURRENT_FRAGMENTED_MSDUS) { |
| |
| /* Can't find a proper FRAG_INFO_T. |
| * I. 1st Fragment MPDU, all of the FragInfo are exhausted |
| * II. 2nd ~ (n-1)th Fragment MPDU, can't find the right FragInfo for defragment. |
| * Because we won't process fragment frame outside this function, so |
| * we should free it right away. |
| */ |
| nicRxReturnRFB(prAdapter, prSWRfb); |
| |
| return (P_SW_RFB_T) NULL; |
| } |
| |
| ASSERT(prFragInfo); |
| |
| /* retrieve Rx payload */ |
| prSWRfb->u2HeaderLen = HAL_RX_STATUS_GET_HEADER_LEN(prRxStatus); |
| prSWRfb->pucPayload = (PUINT_8) (((ULONG) prSWRfb->pvHeader) + prSWRfb->u2HeaderLen); |
| prSWRfb->u2PayloadLength = |
| (UINT_16) (HAL_RX_STATUS_GET_RX_BYTE_CNT(prRxStatus) - ((ULONG) prSWRfb->pucPayload - (ULONG) prRxStatus)); |
| |
| if (fgFirst) { |
| DBGLOG(RX, LOUD, "rxDefragMPDU first\n"); |
| |
| SET_EXPIRATION_TIME(prFragInfo->rReceiveLifetimeLimit, |
| TU_TO_SYSTIME(DOT11_RECEIVE_LIFETIME_TU_DEFAULT)); |
| |
| prFragInfo->pr1stFrag = prSWRfb; |
| |
| prFragInfo->pucNextFragStart = |
| (PUINT_8) prSWRfb->pucRecvBuff + HAL_RX_STATUS_GET_RX_BYTE_CNT(prRxStatus); |
| |
| prFragInfo->u2NextFragSeqCtrl = u2SeqCtrl + 1; |
| DBGLOG(RX, LOUD, "First: nextFragmentSeqCtrl = %04x, u2SeqCtrl = %04x\n", |
| prFragInfo->u2NextFragSeqCtrl, u2SeqCtrl); |
| |
| /* prSWRfb->fgFragmented = TRUE; */ |
| /* whsu: todo for checksum */ |
| } else { |
| prFragInfo->pr1stFrag->prRxStatus->u2RxByteCount += prSWRfb->u2PayloadLength; |
| |
| if (prFragInfo->pr1stFrag->prRxStatus->u2RxByteCount > CFG_RX_MAX_PKT_SIZE) { |
| |
| prFragInfo->pr1stFrag->eDst = RX_PKT_DESTINATION_NULL; |
| QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prFragInfo->pr1stFrag); |
| |
| prFragInfo->pr1stFrag = (P_SW_RFB_T) NULL; |
| |
| nicRxReturnRFB(prAdapter, prSWRfb); |
| } else { |
| kalMemCopy(prFragInfo->pucNextFragStart, prSWRfb->pucPayload, prSWRfb->u2PayloadLength); |
| /* [6630] update rx byte count and packet length */ |
| prFragInfo->pr1stFrag->u2PacketLen += prSWRfb->u2PayloadLength; |
| prFragInfo->pr1stFrag->u2PayloadLength += prSWRfb->u2PayloadLength; |
| |
| if (fgLast) { /* The last one, free the buffer */ |
| DBGLOG(RX, LOUD, "Defrag: finished\n"); |
| |
| prOutputSwRfb = prFragInfo->pr1stFrag; |
| |
| prFragInfo->pr1stFrag = (P_SW_RFB_T) NULL; |
| } else { |
| DBGLOG(RX, LOUD, "Defrag: mid fraged\n"); |
| |
| prFragInfo->pucNextFragStart += prSWRfb->u2PayloadLength; |
| |
| prFragInfo->u2NextFragSeqCtrl++; |
| } |
| |
| nicRxReturnRFB(prAdapter, prSWRfb); |
| } |
| } |
| |
| /* DBGLOG_MEM8(RXM, INFO, */ |
| /* prFragInfo->pr1stFrag->pucPayload, */ |
| /* prFragInfo->pr1stFrag->u2PayloadLength); */ |
| #endif |
| return prOutputSwRfb; |
| } /* end of rxmDefragMPDU() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Do duplicate detection |
| * |
| * @param prSwRfb Pointer to the RX packet |
| * |
| * @return TRUE: a duplicate, FALSE: not a duplicate |
| */ |
| /*----------------------------------------------------------------------------*/ |
| BOOLEAN nicRxIsDuplicateFrame(IN OUT P_SW_RFB_T prSwRfb) |
| { |
| |
| /* Non-QoS Unicast Data or Unicast MMPDU: SC Cache #4; |
| * QoS Unicast Data: SC Cache #0~3; |
| * Broadcast/Multicast: RetryBit == 0 |
| */ |
| UINT_32 u4SeqCtrlCacheIdx; |
| UINT_16 u2SequenceControl, u2FrameCtrl; |
| BOOLEAN fgIsDuplicate = FALSE, fgIsAmsduSubframe = FALSE; |
| P_WLAN_MAC_HEADER_T prWlanHeader = NULL; |
| P_HW_MAC_RX_DESC_T prRxStatus = NULL; |
| P_HW_MAC_RX_STS_GROUP_4_T prRxStatusGroup4 = NULL; |
| |
| DEBUGFUNC("nicRx: Enter rxmIsDuplicateFrame()\n"); |
| |
| ASSERT(prSwRfb); |
| |
| /* Situations in which the STC_REC is missing include: |
| * (1) Probe Request (2) (Re)Association Request (3) IBSS data frames (4) Probe Response |
| */ |
| if (!prSwRfb->prStaRec) |
| return FALSE; |
| |
| prRxStatus = prSwRfb->prRxStatus; |
| ASSERT(prRxStatus); |
| |
| fgIsAmsduSubframe = HAL_RX_STATUS_GET_PAYLOAD_FORMAT(prRxStatus); |
| if (HAL_RX_STATUS_IS_HEADER_TRAN(prRxStatus) == FALSE) { |
| prWlanHeader = (P_WLAN_MAC_HEADER_T) prSwRfb->pvHeader; |
| u2SequenceControl = prWlanHeader->u2SeqCtrl; |
| u2FrameCtrl = prWlanHeader->u2FrameCtrl; |
| } else { |
| prRxStatusGroup4 = prSwRfb->prRxStatusGroup4; |
| u2SequenceControl = HAL_RX_STATUS_GET_SEQFrag_NUM(prRxStatusGroup4); |
| u2FrameCtrl = HAL_RX_STATUS_GET_FRAME_CTL_FIELD(prRxStatusGroup4); |
| } |
| prSwRfb->u2SequenceControl = u2SequenceControl; |
| |
| /* Case 1: Unicast QoS data */ |
| if (RXM_IS_QOS_DATA_FRAME(u2FrameCtrl)) { /* WLAN header shall exist when doing duplicate detection */ |
| if (prSwRfb->prStaRec->aprRxReorderParamRefTbl[prSwRfb->ucTid]) { |
| |
| /* QoS data with an RX BA agreement |
| * Case 1: The packet is not an AMPDU subframe, so the RetryBit may be set to 1 (TBC). |
| * Case 2: The RX BA agreement was just established. Some enqueued packets may not be |
| * sent with aggregation. |
| */ |
| |
| DBGLOG(RX, LOUD, "RX: SC=0x%X (BA Entry present)\n", u2SequenceControl); |
| |
| /* Update the SN cache in order to ensure the correctness of duplicate |
| * removal in case the BA agreement is deleted |
| */ |
| prSwRfb->prStaRec->au2CachedSeqCtrl[prSwRfb->ucTid] = u2SequenceControl; |
| |
| /* debug */ |
| #if 0 |
| DBGLOG(RXM, LOUD, "RXM: SC= 0x%X (Cache[%d] updated) with BA\n", |
| u2SequenceControl, prSwRfb->ucTID); |
| |
| if (g_prMqm->arRxBaTable[prSwRfb->prStaRec->aucRxBaTable[prSwRfb->ucTID]].ucStatus == |
| BA_ENTRY_STATUS_DELETING) { |
| DBGLOG(RXM, LOUD, |
| "RXM: SC= 0x%X (Cache[%d] updated) with DELETING BA ****************\n", |
| u2SequenceControl, prSwRfb->ucTID); |
| } |
| #endif |
| |
| /* HW scoreboard shall take care Case 1. Let the layer layer handle Case 2. */ |
| return FALSE; /* Not a duplicate */ |
| } |
| |
| if (prSwRfb->prStaRec->ucDesiredPhyTypeSet & (PHY_TYPE_BIT_HT | PHY_TYPE_BIT_VHT)) { |
| u4SeqCtrlCacheIdx = prSwRfb->ucTid; |
| } else { |
| if (prSwRfb->ucTid < 8) { /* UP = 0~7 */ |
| u4SeqCtrlCacheIdx = aucTid2ACI[prSwRfb->ucTid]; |
| } else { |
| DBGLOG(RX, WARN, |
| "RXM: (Warning) Unknown QoS Data with TID=%d\n", prSwRfb->ucTid); |
| |
| return TRUE; /* Will be dropped */ |
| } |
| } |
| } |
| /* Case 2: Unicast non-QoS data or MMPDUs */ |
| else |
| u4SeqCtrlCacheIdx = TID_NUM; |
| |
| /* If this is a retransmission */ |
| if (u2FrameCtrl & MASK_FC_RETRY) { |
| if (u2SequenceControl != prSwRfb->prStaRec->au2CachedSeqCtrl[u4SeqCtrlCacheIdx]) { |
| prSwRfb->prStaRec->au2CachedSeqCtrl[u4SeqCtrlCacheIdx] = u2SequenceControl; |
| if (fgIsAmsduSubframe == RX_PAYLOAD_FORMAT_FIRST_SUB_AMSDU) |
| prSwRfb->prStaRec->afgIsIgnoreAmsduDuplicate[u4SeqCtrlCacheIdx] = TRUE; |
| DBGLOG(RX, LOUD, "RXM: SC= 0x%X (Cache[%lu] updated)\n", u2SequenceControl, u4SeqCtrlCacheIdx); |
| } else { |
| /* A duplicate. */ |
| if (prSwRfb->prStaRec->afgIsIgnoreAmsduDuplicate[u4SeqCtrlCacheIdx]) { |
| if (fgIsAmsduSubframe == RX_PAYLOAD_FORMAT_LAST_SUB_AMSDU) |
| prSwRfb->prStaRec->afgIsIgnoreAmsduDuplicate[u4SeqCtrlCacheIdx] = FALSE; |
| } else { |
| fgIsDuplicate = TRUE; |
| DBGLOG(RX, LOUD, "RXM: SC= 0x%X (Cache[%lu] duplicate)\n", |
| u2SequenceControl, u4SeqCtrlCacheIdx); |
| } |
| } |
| } |
| |
| /* Not a retransmission */ |
| else { |
| |
| prSwRfb->prStaRec->au2CachedSeqCtrl[u4SeqCtrlCacheIdx] = u2SequenceControl; |
| prSwRfb->prStaRec->afgIsIgnoreAmsduDuplicate[u4SeqCtrlCacheIdx] = FALSE; |
| |
| DBGLOG(RX, LOUD, "RXM: SC= 0x%X (Cache[%lu] updated)\n", u2SequenceControl, u4SeqCtrlCacheIdx); |
| } |
| |
| return fgIsDuplicate; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Process packet doesn't need to do buffer reordering |
| * |
| * @param prAdapter pointer to the Adapter handler |
| * @param prSWRfb the RFB to receive rx data |
| * |
| * @return (none) |
| * |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID nicRxProcessPktWithoutReorder(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) |
| { |
| P_RX_CTRL_T prRxCtrl; |
| P_TX_CTRL_T prTxCtrl; |
| BOOL fgIsRetained = FALSE; |
| UINT_32 u4CurrentRxBufferCount; |
| /* P_STA_RECORD_T prStaRec = (P_STA_RECORD_T)NULL; */ |
| |
| DEBUGFUNC("nicRxProcessPktWithoutReorder"); |
| /* DBGLOG(RX, TRACE, ("\n")); */ |
| |
| ASSERT(prAdapter); |
| ASSERT(prSwRfb); |
| |
| prRxCtrl = &prAdapter->rRxCtrl; |
| ASSERT(prRxCtrl); |
| |
| prTxCtrl = &prAdapter->rTxCtrl; |
| ASSERT(prTxCtrl); |
| |
| u4CurrentRxBufferCount = prRxCtrl->rFreeSwRfbList.u4NumElem; |
| /* QM USED = $A, AVAILABLE COUNT = $B, INDICATED TO OS = $C |
| * TOTAL = $A + $B + $C |
| * |
| * Case #1 (Retain) |
| * ------------------------------------------------------- |
| * $A + $B < THRESHOLD := $A + $B + $C < THRESHOLD + $C := $TOTAL - THRESHOLD < $C |
| * => $C used too much, retain |
| * |
| * Case #2 (Non-Retain) |
| * ------------------------------------------------------- |
| * $A + $B > THRESHOLD := $A + $B + $C > THRESHOLD + $C := $TOTAL - THRESHOLD > $C |
| * => still available for $C to use |
| * |
| */ |
| |
| #if defined(LINUX) |
| fgIsRetained = FALSE; |
| #else |
| fgIsRetained = (((u4CurrentRxBufferCount + |
| qmGetRxReorderQueuedBufferCount(prAdapter) + |
| prTxCtrl->i4PendingFwdFrameCount) < CFG_RX_RETAINED_PKT_THRESHOLD) ? TRUE : FALSE); |
| #endif |
| |
| /* DBGLOG(RX, INFO, ("fgIsRetained = %d\n", fgIsRetained)); */ |
| #if CFG_ENABLE_PER_STA_STATISTICS |
| if (prSwRfb->prStaRec && (prAdapter->rWifiVar.rWfdConfigureSettings.ucWfdEnable > 0)) |
| prSwRfb->prStaRec->u4TotalRxPktsNumber++; |
| #endif |
| if (kalProcessRxPacket(prAdapter->prGlueInfo, |
| prSwRfb->pvPacket, |
| prSwRfb->pvHeader, |
| (UINT_32) prSwRfb->u2PacketLen, fgIsRetained, prSwRfb->aeCSUM) != WLAN_STATUS_SUCCESS) { |
| DBGLOG(RX, ERROR, "kalProcessRxPacket return value != WLAN_STATUS_SUCCESS\n"); |
| ASSERT(0); |
| |
| nicRxReturnRFB(prAdapter, prSwRfb); |
| return; |
| } |
| |
| #if CFG_SUPPORT_MULTITHREAD |
| if (HAL_IS_RX_DIRECT(prAdapter)) { |
| kalRxIndicateOnePkt(prAdapter->prGlueInfo, |
| (PVOID) GLUE_GET_PKT_DESCRIPTOR(GLUE_GET_PKT_QUEUE_ENTRY(prSwRfb->pvPacket))); |
| RX_ADD_CNT(prRxCtrl, RX_DATA_INDICATION_COUNT, 1); |
| if (fgIsRetained) |
| RX_ADD_CNT(prRxCtrl, RX_DATA_RETAINED_COUNT, 1); |
| } else { |
| KAL_SPIN_LOCK_DECLARATION(); |
| |
| KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_TO_OS_QUE); |
| QUEUE_INSERT_TAIL(&(prAdapter->rRxQueue), (P_QUE_ENTRY_T) GLUE_GET_PKT_QUEUE_ENTRY(prSwRfb->pvPacket)); |
| KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_TO_OS_QUE); |
| |
| prRxCtrl->ucNumIndPacket++; |
| kalSetTxEvent2Rx(prAdapter->prGlueInfo); |
| } |
| #else |
| prRxCtrl->apvIndPacket[prRxCtrl->ucNumIndPacket] = prSwRfb->pvPacket; |
| prRxCtrl->ucNumIndPacket++; |
| #endif |
| |
| #ifndef LINUX |
| if (fgIsRetained) { |
| prRxCtrl->apvRetainedPacket[prRxCtrl->ucNumRetainedPacket] = prSwRfb->pvPacket; |
| prRxCtrl->ucNumRetainedPacket++; |
| } else |
| #endif |
| prSwRfb->pvPacket = NULL; |
| |
| |
| /* Return RFB */ |
| if (nicRxSetupRFB(prAdapter, prSwRfb)) { |
| DBGLOG(RX, WARN, "Cannot allocate packet buffer for SwRfb!\n"); |
| if (!timerPendingTimer(&prAdapter->rPacketDelaySetupTimer)) { |
| DBGLOG(RX, WARN, "Start ReturnIndicatedRfb Timer (%u)\n", RX_RETURN_INDICATED_RFB_TIMEOUT_SEC); |
| cnmTimerStartTimer(prAdapter, &prAdapter->rPacketDelaySetupTimer, |
| SEC_TO_MSEC(RX_RETURN_INDICATED_RFB_TIMEOUT_SEC)); |
| } |
| } |
| nicRxReturnRFB(prAdapter, prSwRfb); |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Process forwarding data packet |
| * |
| * @param prAdapter pointer to the Adapter handler |
| * @param prSWRfb the RFB to receive rx data |
| * |
| * @return (none) |
| * |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID nicRxProcessForwardPkt(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) |
| { |
| P_MSDU_INFO_T prMsduInfo, prRetMsduInfoList; |
| P_TX_CTRL_T prTxCtrl; |
| P_RX_CTRL_T prRxCtrl; |
| |
| KAL_SPIN_LOCK_DECLARATION(); |
| |
| DEBUGFUNC("nicRxProcessForwardPkt"); |
| |
| ASSERT(prAdapter); |
| ASSERT(prSwRfb); |
| |
| prTxCtrl = &prAdapter->rTxCtrl; |
| prRxCtrl = &prAdapter->rRxCtrl; |
| |
| prMsduInfo = cnmPktAlloc(prAdapter, 0); |
| |
| if (prMsduInfo && |
| kalProcessRxPacket(prAdapter->prGlueInfo, |
| prSwRfb->pvPacket, |
| prSwRfb->pvHeader, |
| (UINT_32) prSwRfb->u2PacketLen, |
| prRxCtrl->rFreeSwRfbList.u4NumElem < |
| CFG_RX_RETAINED_PKT_THRESHOLD ? TRUE : FALSE, prSwRfb->aeCSUM) == WLAN_STATUS_SUCCESS) { |
| |
| /* parsing forward frame */ |
| wlanProcessTxFrame(prAdapter, (P_NATIVE_PACKET) (prSwRfb->pvPacket)); |
| /* pack into MSDU_INFO_T */ |
| nicTxFillMsduInfo(prAdapter, prMsduInfo, (P_NATIVE_PACKET) (prSwRfb->pvPacket)); |
| |
| prMsduInfo->eSrc = TX_PACKET_FORWARDING; |
| prMsduInfo->ucBssIndex = secGetBssIdxByWlanIdx(prAdapter, prSwRfb->ucWlanIdx); |
| |
| /* release RX buffer (to rIndicatedRfbList) */ |
| prSwRfb->pvPacket = NULL; |
| nicRxReturnRFB(prAdapter, prSwRfb); |
| |
| /* increase forward frame counter */ |
| GLUE_INC_REF_CNT(prTxCtrl->i4PendingFwdFrameCount); |
| |
| /* send into TX queue */ |
| KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); |
| prRetMsduInfoList = qmEnqueueTxPackets(prAdapter, prMsduInfo); |
| KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); |
| |
| if (prRetMsduInfoList != NULL) { /* TX queue refuses queuing the packet */ |
| nicTxFreeMsduInfoPacket(prAdapter, prRetMsduInfoList); |
| nicTxReturnMsduInfo(prAdapter, prRetMsduInfoList); |
| } |
| /* indicate service thread for sending */ |
| if (prTxCtrl->i4PendingFwdFrameCount > 0) |
| kalSetEvent(prAdapter->prGlueInfo); |
| } else { /* no TX resource */ |
| DBGLOG(QM, INFO, "No Tx MSDU_INFO for forwarding frames\n"); |
| nicRxReturnRFB(prAdapter, prSwRfb); |
| } |
| |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Process broadcast data packet for both host and forwarding |
| * |
| * @param prAdapter pointer to the Adapter handler |
| * @param prSWRfb the RFB to receive rx data |
| * |
| * @return (none) |
| * |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID nicRxProcessGOBroadcastPkt(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) |
| { |
| P_SW_RFB_T prSwRfbDuplicated; |
| P_TX_CTRL_T prTxCtrl; |
| P_RX_CTRL_T prRxCtrl; |
| P_HW_MAC_RX_DESC_T prRxStatus; |
| |
| KAL_SPIN_LOCK_DECLARATION(); |
| |
| DEBUGFUNC("nicRxProcessGOBroadcastPkt"); |
| |
| ASSERT(prAdapter); |
| ASSERT(prSwRfb); |
| |
| prTxCtrl = &prAdapter->rTxCtrl; |
| prRxCtrl = &prAdapter->rRxCtrl; |
| |
| prRxStatus = prSwRfb->prRxStatus; |
| ASSERT(prRxStatus); |
| |
| ASSERT(CFG_NUM_OF_QM_RX_PKT_NUM >= 16); |
| |
| if (prRxCtrl->rFreeSwRfbList.u4NumElem |
| >= (CFG_RX_MAX_PKT_NUM - (CFG_NUM_OF_QM_RX_PKT_NUM - 16 /* Reserved for others */))) { |
| |
| /* 1. Duplicate SW_RFB_T */ |
| KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); |
| QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfbDuplicated, P_SW_RFB_T); |
| KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); |
| |
| if (prSwRfbDuplicated) { |
| kalMemCopy(prSwRfbDuplicated->pucRecvBuff, |
| prSwRfb->pucRecvBuff, ALIGN_4(prRxStatus->u2RxByteCount + HIF_RX_HW_APPENDED_LEN)); |
| |
| prSwRfbDuplicated->ucPacketType = RX_PKT_TYPE_RX_DATA; |
| prSwRfbDuplicated->ucStaRecIdx = prSwRfb->ucStaRecIdx; |
| nicRxFillRFB(prAdapter, prSwRfbDuplicated); |
| |
| /* 2. Modify eDst */ |
| prSwRfbDuplicated->eDst = RX_PKT_DESTINATION_FORWARD; |
| |
| /* 4. Forward */ |
| nicRxProcessForwardPkt(prAdapter, prSwRfbDuplicated); |
| } |
| } else { |
| DBGLOG(RX, WARN, |
| "Stop to forward BMC packet due to less free Sw Rfb %lu\n", prRxCtrl->rFreeSwRfbList.u4NumElem); |
| } |
| |
| /* 3. Indicate to host */ |
| prSwRfb->eDst = RX_PKT_DESTINATION_HOST; |
| nicRxProcessPktWithoutReorder(prAdapter, prSwRfb); |
| |
| } |
| |
| #if CFG_SUPPORT_SNIFFER |
| VOID nicRxFillRadiotapMCS(IN OUT P_MONITOR_RADIOTAP_T prMonitorRadiotap, IN P_HW_MAC_RX_STS_GROUP_3_T prRxStatusGroup3) |
| { |
| UINT_8 ucFrMode; |
| UINT_8 ucShortGI; |
| UINT_8 ucRxMode; |
| UINT_8 ucLDPC; |
| UINT_8 ucSTBC; |
| UINT_8 ucNess; |
| |
| ucFrMode = (((prRxStatusGroup3)->u4RxVector[0] & RX_VT_FR_MODE_MASK) >> RX_VT_FR_MODE_OFFSET); |
| /* VHTA1 B0-B1 */ |
| ucShortGI = ((prRxStatusGroup3)->u4RxVector[0] & RX_VT_SHORT_GI) ? 1 : 0; /* HT_shortgi */ |
| ucRxMode = (((prRxStatusGroup3)->u4RxVector[0] & RX_VT_RX_MODE_MASK) >> RX_VT_RX_MODE_OFFSET); |
| ucLDPC = ((prRxStatusGroup3)->u4RxVector[0] & RX_VT_LDPC) ? 1 : 0; /* HT_adcode */ |
| ucSTBC = (((prRxStatusGroup3)->u4RxVector[0] & RX_VT_STBC_MASK) >> RX_VT_STBC_OFFSET); /* HT_stbc */ |
| ucNess = (((prRxStatusGroup3)->u4RxVector[0] & RX_VT_NESS_MASK) >> RX_VT_NESS_OFFSET); /* HT_extltf */ |
| |
| prMonitorRadiotap->ucMcsKnown = (BITS(0, 6) | (((ucNess & BIT(1)) >> 1) << 7)); |
| |
| prMonitorRadiotap->ucMcsFlags = ((ucFrMode) | |
| (ucShortGI << 2) | |
| ((ucRxMode & BIT(0)) << 3) | |
| (ucLDPC << 4) | (ucSTBC << 5) | ((ucNess & BIT(0)) << 7)); |
| /* Bit[6:0] for 802.11n, mcs0 ~ mcs7 */ |
| prMonitorRadiotap->ucMcsMcs = ((prRxStatusGroup3)->u4RxVector[0] & RX_VT_RX_RATE_MASK); |
| } |
| |
| VOID nicRxFillRadiotapVHT(IN OUT P_MONITOR_RADIOTAP_T prMonitorRadiotap, IN P_HW_MAC_RX_STS_GROUP_3_T prRxStatusGroup3) |
| { |
| UINT_8 ucSTBC; |
| UINT_8 ucTxopPsNotAllow; |
| UINT_8 ucShortGI; |
| UINT_8 ucNsym; |
| UINT_8 ucLdpcExtraOfdmSym; |
| UINT_8 ucBeamFormed; |
| UINT_8 ucFrMode; |
| UINT_8 ucNsts; |
| UINT_8 ucMcs; |
| |
| prMonitorRadiotap->u2VhtKnown = RADIOTAP_VHT_ALL_KNOWN; |
| prMonitorRadiotap->u2VhtKnown &= ~RADIOTAP_VHT_SHORT_GI_NSYM_KNOWN; |
| |
| ucSTBC = (((prRxStatusGroup3)->u4RxVector[0] & RX_VT_STBC_MASK) >> RX_VT_STBC_OFFSET); /* BIT[7]: VHTA1 B3 */ |
| ucTxopPsNotAllow = ((prRxStatusGroup3)->u4RxVector[0] & RX_VT_TXOP_PS_NOT_ALLOWED) ? 1 : 0; /* VHTA1 B22 */ |
| /* |
| *ucNsym = ((prRxStatusGroup3)->u4RxVector[0] & RX_VT_SHORT_GI_NSYM) ? 1 : 0; //VHTA2 B1 |
| */ |
| ucNsym = 0; /* Invalid in MT6632*/ |
| ucShortGI = ((prRxStatusGroup3)->u4RxVector[0] & RX_VT_SHORT_GI) ? 1 : 0; /* VHTA2 B0 */ |
| ucLdpcExtraOfdmSym = ((prRxStatusGroup3)->u4RxVector[0] & RX_VT_LDPC_EXTRA_OFDM_SYM) ? 1 : 0; /* VHTA2 B3 */ |
| ucBeamFormed = ((prRxStatusGroup3)->u4RxVector[0] & RX_VT_BEAMFORMED) ? 1 : 0; /* VHTA2 B8 */ |
| prMonitorRadiotap->ucVhtFlags = ((ucSTBC) | |
| (ucTxopPsNotAllow << 1) | |
| (ucShortGI << 2) | (ucNsym << 3) | (ucLdpcExtraOfdmSym << 4) | (ucBeamFormed << 5)); |
| |
| ucFrMode = (((prRxStatusGroup3)->u4RxVector[0] & RX_VT_FR_MODE_MASK) >> RX_VT_FR_MODE_OFFSET); |
| /* VHTA1 B0-B1 */ |
| switch (ucFrMode) { |
| case RX_VT_FR_MODE_20: |
| prMonitorRadiotap->ucVhtBandwidth = 0; |
| break; |
| case RX_VT_FR_MODE_40: |
| prMonitorRadiotap->ucVhtBandwidth = 1; |
| break; |
| case RX_VT_FR_MODE_80: |
| prMonitorRadiotap->ucVhtBandwidth = 4; |
| break; |
| case RX_VT_FR_MODE_160: |
| prMonitorRadiotap->ucVhtBandwidth = 11; |
| break; |
| default: |
| prMonitorRadiotap->ucVhtBandwidth = 0; |
| } |
| |
| /* Set to 0~7 for 1~8 space time streams */ |
| ucNsts = (((prRxStatusGroup3)->u4RxVector[1] & RX_VT_NSTS_MASK) >> RX_VT_NSTS_OFFSET) + 1; |
| /* VHTA1 B10-B12 */ |
| |
| /* Bit[3:0] for 802.11ac, mcs0 ~ mcs9 */ |
| ucMcs = ((prRxStatusGroup3)->u4RxVector[0] & RX_VT_RX_RATE_AC_MASK); |
| |
| prMonitorRadiotap->aucVhtMcsNss[0] = ((ucMcs << 4) | (ucNsts - ucSTBC)); /* STBC = Nsts - Nss */ |
| |
| /* |
| *prMonitorRadiotap->ucVhtCoding = |
| * (((prRxStatusGroup3)->u4RxVector[0] & RX_VT_CODING_MASK) >> RX_VT_CODING_OFFSET); |
| */ |
| prMonitorRadiotap->ucVhtCoding = 0; /* Invalid in MT6632*/ |
| |
| /* VHTA2 B2-B3 */ |
| |
| prMonitorRadiotap->ucVhtGroupId = |
| (((((prRxStatusGroup3)->u4RxVector[1] & RX_VT_GROUPID_1_MASK) >> RX_VT_GROUPID_1_OFFSET) << 2) | |
| (((prRxStatusGroup3)->u4RxVector[0] & RX_VT_GROUPID_0_MASK) >> RX_VT_GROUPID_0_OFFSET)); |
| /* VHTA1 B4-B9 */ |
| /* VHTA1 B13-B21 */ |
| prMonitorRadiotap->u2VhtPartialAid = ((((prRxStatusGroup3)->u4RxVector[2] & RX_VT_AID_1_MASK) << 4) | |
| (((prRxStatusGroup3)->u4RxVector[1] & RX_VT_AID_0_MASK) >> |
| RX_VT_AID_0_OFFSET)); |
| |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Process HIF monitor packet |
| * |
| * @param prAdapter pointer to the Adapter handler |
| * @param prSWRfb the RFB to receive rx data |
| * |
| * @return (none) |
| * |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID nicRxProcessMonitorPacket(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb) |
| { |
| struct sk_buff *prSkb = NULL; |
| P_RX_CTRL_T prRxCtrl; |
| P_HW_MAC_RX_DESC_T prRxStatus; |
| P_HW_MAC_RX_STS_GROUP_2_T prRxStatusGroup2; |
| P_HW_MAC_RX_STS_GROUP_3_T prRxStatusGroup3; |
| MONITOR_RADIOTAP_T rMonitorRadiotap; |
| RADIOTAP_FIELD_VENDOR_T rRadiotapFieldVendor; |
| PUINT_8 prVendorNsOffset; |
| UINT_32 u4VendorNsLen; |
| UINT_32 u4RadiotapLen; |
| UINT_32 u4ItPresent; |
| UINT_8 aucMtkOui[] = VENDOR_OUI_MTK; |
| UINT_8 ucRxRate; |
| UINT_8 ucRxMode; |
| UINT_8 ucChanNum; |
| UINT_8 ucMcs; |
| UINT_8 ucFrMode; |
| UINT_8 ucShortGI; |
| UINT_32 u4PhyRate; |
| |
| #if CFG_SUPPORT_MULTITHREAD |
| KAL_SPIN_LOCK_DECLARATION(); |
| #endif |
| |
| DEBUGFUNC("nicRxProcessMonitorPacket"); |
| |
| ASSERT(prAdapter); |
| ASSERT(prSwRfb); |
| |
| prRxCtrl = &prAdapter->rRxCtrl; |
| |
| nicRxFillRFB(prAdapter, prSwRfb); |
| |
| /* can't parse radiotap info if no rx vector */ |
| if (((prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_2)) == 0) || ((prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_3)) == 0)) { |
| nicRxReturnRFB(prAdapter, prSwRfb); |
| return; |
| } |
| |
| prRxStatus = prSwRfb->prRxStatus; |
| prRxStatusGroup2 = prSwRfb->prRxStatusGroup2; |
| prRxStatusGroup3 = prSwRfb->prRxStatusGroup3; |
| |
| /* Bit Number 30 Vendor Namespace */ |
| u4VendorNsLen = sizeof(RADIOTAP_FIELD_VENDOR_T); |
| rRadiotapFieldVendor.aucOUI[0] = aucMtkOui[0]; |
| rRadiotapFieldVendor.aucOUI[1] = aucMtkOui[1]; |
| rRadiotapFieldVendor.aucOUI[2] = aucMtkOui[2]; |
| rRadiotapFieldVendor.ucSubNamespace = 0; |
| rRadiotapFieldVendor.u2DataLen = u4VendorNsLen - 6; |
| /* VHTA1 B0-B1 */ |
| rRadiotapFieldVendor.ucData = (((prRxStatusGroup3)->u4RxVector[0] & RX_VT_FR_MODE_MASK) >> |
| RX_VT_FR_MODE_OFFSET); |
| |
| ucRxMode = (((prRxStatusGroup3)->u4RxVector[0] & RX_VT_RX_MODE_MASK) >> RX_VT_RX_MODE_OFFSET); |
| |
| if (ucRxMode == RX_VT_VHT_MODE) { |
| u4RadiotapLen = RADIOTAP_LEN_VHT; |
| u4ItPresent = RADIOTAP_FIELDS_VHT; |
| } else if ((ucRxMode == RX_VT_MIXED_MODE) || (ucRxMode == RX_VT_GREEN_MODE)) { |
| u4RadiotapLen = RADIOTAP_LEN_HT; |
| u4ItPresent = RADIOTAP_FIELDS_HT; |
| } else { |
| u4RadiotapLen = RADIOTAP_LEN_LEGACY; |
| u4ItPresent = RADIOTAP_FIELDS_LEGACY; |
| } |
| |
| /* Radiotap Header & Bit Number 30 Vendor Namespace */ |
| prVendorNsOffset = (PUINT_8) &rMonitorRadiotap + u4RadiotapLen; |
| u4RadiotapLen += u4VendorNsLen; |
| kalMemSet(&rMonitorRadiotap, 0, sizeof(MONITOR_RADIOTAP_T)); |
| kalMemCopy(prVendorNsOffset, (PUINT_8) &rRadiotapFieldVendor, u4VendorNsLen); |
| rMonitorRadiotap.u2ItLen = cpu_to_le16(u4RadiotapLen); |
| rMonitorRadiotap.u4ItPresent = u4ItPresent; |
| |
| /* Bit Number 0 TSFT */ |
| rMonitorRadiotap.u8MacTime = (prRxStatusGroup2->u4Timestamp); |
| |
| /* Bit Number 1 FLAGS */ |
| if (HAL_RX_STATUS_IS_FRAG(prRxStatus) == TRUE) |
| rMonitorRadiotap.ucFlags |= BIT(3); |
| |
| if (HAL_RX_STATUS_IS_FCS_ERROR(prRxStatus) == TRUE) |
| rMonitorRadiotap.ucFlags |= BIT(6); |
| |
| /* Bit Number 2 RATE */ |
| if ((ucRxMode == RX_VT_LEGACY_CCK) || (ucRxMode == RX_VT_LEGACY_OFDM)) { |
| /* Bit[2:0] for Legacy CCK, Bit[3:0] for Legacy OFDM */ |
| ucRxRate = ((prRxStatusGroup3)->u4RxVector[0] & BITS(0, 3)); |
| rMonitorRadiotap.ucRate = nicGetHwRateByPhyRate(ucRxRate); |
| } else { |
| ucMcs = ((prRxStatusGroup3)->u4RxVector[0] & RX_VT_RX_RATE_AC_MASK); |
| /* VHTA1 B0-B1 */ |
| ucFrMode = (((prRxStatusGroup3)->u4RxVector[0] & RX_VT_FR_MODE_MASK) >> RX_VT_FR_MODE_OFFSET); |
| ucShortGI = ((prRxStatusGroup3)->u4RxVector[0] & RX_VT_SHORT_GI) ? 1 : 0; /* VHTA2 B0 */ |
| |
| /* ucRate(500kbs) = u4PhyRate(100kbps) / 5, max ucRate = 0xFF */ |
| u4PhyRate = nicGetPhyRateByMcsRate(ucMcs, ucFrMode, ucShortGI); |
| if (u4PhyRate > 1275) |
| rMonitorRadiotap.ucRate = 0xFF; |
| else |
| rMonitorRadiotap.ucRate = u4PhyRate / 5; |
| } |
| |
| /* Bit Number 3 CHANNEL */ |
| if (ucRxMode == RX_VT_LEGACY_CCK) |
| rMonitorRadiotap.u2ChFlags |= BIT(5); |
| else /* OFDM */ |
| rMonitorRadiotap.u2ChFlags |= BIT(6); |
| |
| ucChanNum = HAL_RX_STATUS_GET_CHNL_NUM(prRxStatus); |
| if (HAL_RX_STATUS_GET_RF_BAND(prRxStatus) == BAND_2G4) { |
| rMonitorRadiotap.u2ChFlags |= BIT(7); |
| rMonitorRadiotap.u2ChFrequency = (ucChanNum * 5 + 2407); |
| } else { /* BAND_5G */ |
| rMonitorRadiotap.u2ChFlags |= BIT(8); |
| rMonitorRadiotap.u2ChFrequency = (ucChanNum * 5 + 5000); |
| } |
| |
| /* Bit Number 5 ANT SIGNAL */ |
| rMonitorRadiotap.ucAntennaSignal = RCPI_TO_dBm(HAL_RX_STATUS_GET_RCPI0(prSwRfb->prRxStatusGroup3)); |
| |
| /* Bit Number 6 ANT NOISE */ |
| rMonitorRadiotap.ucAntennaNoise = ((((prRxStatusGroup3)->u4RxVector[5] & RX_VT_NF0_MASK) >> 1) + 128); |
| |
| /* Bit Number 11 ANT, Invalid for MT6632 and MT7615 */ |
| rMonitorRadiotap.ucAntenna = ((prRxStatusGroup3)->u4RxVector[2] & RX_VT_SEL_ANT) ? 1 : 0; |
| |
| /* Bit Number 19 MCS */ |
| if ((u4ItPresent & RADIOTAP_FIELD_MCS)) |
| nicRxFillRadiotapMCS(&rMonitorRadiotap, prRxStatusGroup3); |
| |
| /* Bit Number 20 AMPDU */ |
| if (HAL_RX_STATUS_IS_AMPDU_SUB_FRAME(prRxStatus)) { |
| if (HAL_RX_STATUS_GET_RXV_SEQ_NO(prRxStatus)) |
| ++prRxCtrl->u4AmpduRefNum; |
| rMonitorRadiotap.u4AmpduRefNum = prRxCtrl->u4AmpduRefNum; |
| } |
| |
| /* Bit Number 21 VHT */ |
| if ((u4ItPresent & RADIOTAP_FIELD_VHT)) |
| nicRxFillRadiotapVHT(&rMonitorRadiotap, prRxStatusGroup3); |
| |
| prSwRfb->pvHeader -= u4RadiotapLen; |
| kalMemCopy(prSwRfb->pvHeader, &rMonitorRadiotap, u4RadiotapLen); |
| |
| prSkb = (struct sk_buff *)(prSwRfb->pvPacket); |
| prSkb->data = (unsigned char *)(prSwRfb->pvHeader); |
| |
| skb_reset_tail_pointer(prSkb); |
| skb_trim(prSkb, 0); |
| skb_put(prSkb, (u4RadiotapLen + prSwRfb->u2PacketLen)); |
| |
| #if CFG_SUPPORT_MULTITHREAD |
| KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_TO_OS_QUE); |
| QUEUE_INSERT_TAIL(&(prAdapter->rRxQueue), (P_QUE_ENTRY_T) GLUE_GET_PKT_QUEUE_ENTRY(prSwRfb->pvPacket)); |
| KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_TO_OS_QUE); |
| |
| prRxCtrl->ucNumIndPacket++; |
| kalSetTxEvent2Rx(prAdapter->prGlueInfo); |
| #else |
| prRxCtrl->apvIndPacket[prRxCtrl->ucNumIndPacket] = prSwRfb->pvPacket; |
| prRxCtrl->ucNumIndPacket++; |
| #endif |
| |
| prSwRfb->pvPacket = NULL; |
| /* Return RFB */ |
| if (nicRxSetupRFB(prAdapter, prSwRfb)) { |
| DBGLOG(RX, WARN, "Cannot allocate packet buffer for SwRfb!\n"); |
| if (!timerPendingTimer(&prAdapter->rPacketDelaySetupTimer)) { |
| DBGLOG(RX, WARN, "Start ReturnIndicatedRfb Timer (%u)\n", RX_RETURN_INDICATED_RFB_TIMEOUT_SEC); |
| cnmTimerStartTimer(prAdapter, &prAdapter->rPacketDelaySetupTimer, |
| SEC_TO_MSEC(RX_RETURN_INDICATED_RFB_TIMEOUT_SEC)); |
| } |
| } |
| nicRxReturnRFB(prAdapter, prSwRfb); |
| } |
| #endif |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Process HIF data packet |
| * |
| * @param prAdapter pointer to the Adapter handler |
| * @param prSWRfb the RFB to receive rx data |
| * |
| * @return (none) |
| * |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID nicRxProcessDataPacket(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb) |
| { |
| P_RX_CTRL_T prRxCtrl; |
| P_SW_RFB_T prRetSwRfb, prNextSwRfb; |
| P_HW_MAC_RX_DESC_T prRxStatus; |
| BOOLEAN fgDrop; |
| struct mt66xx_chip_info *prChipInfo; |
| |
| DEBUGFUNC("nicRxProcessDataPacket"); |
| /* DBGLOG(INIT, TRACE, ("\n")); */ |
| |
| ASSERT(prAdapter); |
| ASSERT(prSwRfb); |
| |
| fgDrop = FALSE; |
| |
| prRxStatus = prSwRfb->prRxStatus; |
| prRxCtrl = &prAdapter->rRxCtrl; |
| prChipInfo = prAdapter->chip_info; |
| |
| /* Check AMPDU_nERR_Bitmap */ |
| prSwRfb->fgDataFrame = TRUE; |
| prSwRfb->fgFragFrame = FALSE; |
| prSwRfb->fgReorderBuffer = FALSE; |
| |
| /* BA session */ |
| if ((prRxStatus->u2StatusFlag & RXS_DW2_AMPDU_nERR_BITMAP) == RXS_DW2_AMPDU_nERR_VALUE) |
| prSwRfb->fgReorderBuffer = TRUE; |
| /* non BA session */ |
| else if ((prRxStatus->u2StatusFlag & RXS_DW2_RX_nERR_BITMAP) == RXS_DW2_RX_nERR_VALUE) { |
| if ((prRxStatus->u2StatusFlag & RXS_DW2_RX_nDATA_BITMAP) == RXS_DW2_RX_nDATA_VALUE) |
| prSwRfb->fgDataFrame = FALSE; |
| |
| if ((prRxStatus->u2StatusFlag & RXS_DW2_RX_FRAG_BITMAP) == RXS_DW2_RX_FRAG_VALUE) |
| prSwRfb->fgFragFrame = TRUE; |
| |
| } else { |
| fgDrop = TRUE; |
| if (!HAL_RX_STATUS_IS_ICV_ERROR(prRxStatus) |
| && HAL_RX_STATUS_IS_TKIP_MIC_ERROR(prRxStatus)) { |
| P_STA_RECORD_T prStaRec; |
| |
| prStaRec = cnmGetStaRecByAddress(prAdapter, |
| prAdapter->prAisBssInfo->ucBssIndex, |
| prAdapter->rWlanInfo.rCurrBssId.arMacAddress); |
| if (prStaRec) { |
| DBGLOG(RSN, EVENT, "MIC_ERR_PKT\n"); |
| rsnTkipHandleMICFailure(prAdapter, prStaRec, 0); |
| } |
| } |
| #if UNIFIED_MAC_RX_FORMAT |
| else if (HAL_RX_STATUS_IS_LLC_MIS(prRxStatus) |
| && !HAL_RX_STATUS_IS_ERROR(prRxStatus) |
| && !FEAT_SUP_LLC_VLAN_RX(prChipInfo)) { |
| PUINT_16 pu2EtherType; |
| |
| nicRxFillRFB(prAdapter, prSwRfb); |
| |
| pu2EtherType = (PUINT_16)((PUINT_8)prSwRfb->pvHeader + 2*MAC_ADDR_LEN); |
| |
| /* If ethernet type is VLAN, do not drop it. Pass up to driver process */ |
| if (prSwRfb->u2HeaderLen >= ETH_HLEN |
| && *pu2EtherType == NTOHS(ETH_P_VLAN)) |
| fgDrop = FALSE; |
| } |
| #else |
| else if (HAL_RX_STATUS_IS_LLC_MIS(prRxStatus)) { |
| DBGLOG(RSN, EVENT, ("LLC_MIS_ERR\n")); |
| fgDrop = FALSE; /* Drop after send de-auth */ |
| } |
| #endif |
| } |
| |
| #if 0 /* Check 1x Pkt */ |
| if (prSwRfb->u2PacketLen > 14) { |
| PUINT_8 pc = (PUINT_8) prSwRfb->pvHeader; |
| UINT_16 u2Etype = 0; |
| |
| u2Etype = (pc[ETHER_TYPE_LEN_OFFSET] << 8) | (pc[ETHER_TYPE_LEN_OFFSET + 1]); |
| |
| #if CFG_SUPPORT_WAPI |
| if (u2Etype == ETH_P_1X || u2Etype == ETH_WPI_1X) |
| DBGLOG(RSN, INFO, "R1X len=%d\n", prSwRfb->u2PacketLen); |
| #else |
| if (u2Etype == ETH_P_1X) |
| DBGLOG(RSN, INFO, "R1X len=%d\n", prSwRfb->u2PacketLen); |
| #endif |
| else if (u2Etype == ETH_P_PRE_1X) |
| DBGLOG(RSN, INFO, "Pre R1X len=%d\n", prSwRfb->u2PacketLen); |
| } |
| #endif |
| |
| #if CFG_TCP_IP_CHKSUM_OFFLOAD || CFG_TCP_IP_CHKSUM_OFFLOAD_NDIS_60 |
| if (prAdapter->fgIsSupportCsumOffload && fgDrop == FALSE) { |
| UINT_32 u4TcpUdpIpCksStatus; |
| PUINT_32 pu4Temp; |
| |
| pu4Temp = (PUINT_32) prRxStatus; |
| u4TcpUdpIpCksStatus = *(pu4Temp + (ALIGN_4(prRxStatus->u2RxByteCount) >> 2)); |
| nicRxFillChksumStatus(prAdapter, prSwRfb, u4TcpUdpIpCksStatus); |
| } |
| #endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ |
| |
| /* if(secCheckClassError(prAdapter, prSwRfb, prStaRec) == TRUE && */ |
| if (prAdapter->fgTestMode == FALSE && fgDrop == FALSE) { |
| #if CFG_HIF_RX_STARVATION_WARNING |
| prRxCtrl->u4QueuedCnt++; |
| #endif |
| nicRxFillRFB(prAdapter, prSwRfb); |
| GLUE_SET_PKT_BSS_IDX(prSwRfb->pvPacket, secGetBssIdxByWlanIdx(prAdapter, prSwRfb->ucWlanIdx)); |
| |
| prRetSwRfb = qmHandleRxPackets(prAdapter, prSwRfb); |
| if (prRetSwRfb != NULL) { |
| do { |
| #if CFG_SUPPORT_MSP |
| if (prRetSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_3)) { |
| prAdapter->arStaRec[prRetSwRfb->ucStaRecIdx].u4RxVector0 = |
| HAL_RX_VECTOR_GET_RX_VECTOR(prRetSwRfb->prRxStatusGroup3, 0); |
| |
| prAdapter->arStaRec[prRetSwRfb->ucStaRecIdx].u4RxVector1 = |
| HAL_RX_VECTOR_GET_RX_VECTOR(prRetSwRfb->prRxStatusGroup3, 1); |
| |
| prAdapter->arStaRec[prRetSwRfb->ucStaRecIdx].u4RxVector2 = |
| HAL_RX_VECTOR_GET_RX_VECTOR(prRetSwRfb->prRxStatusGroup3, 2); |
| |
| prAdapter->arStaRec[prRetSwRfb->ucStaRecIdx].u4RxVector3 = |
| HAL_RX_VECTOR_GET_RX_VECTOR(prRetSwRfb->prRxStatusGroup3, 3); |
| |
| prAdapter->arStaRec[prRetSwRfb->ucStaRecIdx].u4RxVector4 = |
| HAL_RX_VECTOR_GET_RX_VECTOR(prRetSwRfb->prRxStatusGroup3, 4); |
| } |
| #endif |
| /* save next first */ |
| prNextSwRfb = (P_SW_RFB_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prRetSwRfb); |
| |
| switch (prRetSwRfb->eDst) { |
| case RX_PKT_DESTINATION_HOST: |
| nicRxProcessPktWithoutReorder(prAdapter, prRetSwRfb); |
| break; |
| |
| case RX_PKT_DESTINATION_FORWARD: |
| nicRxProcessForwardPkt(prAdapter, prRetSwRfb); |
| break; |
| |
| case RX_PKT_DESTINATION_HOST_WITH_FORWARD: |
| nicRxProcessGOBroadcastPkt(prAdapter, prRetSwRfb); |
| break; |
| |
| case RX_PKT_DESTINATION_NULL: |
| nicRxReturnRFB(prAdapter, prRetSwRfb); |
| RX_INC_CNT(prRxCtrl, RX_DST_NULL_DROP_COUNT); |
| RX_INC_CNT(prRxCtrl, RX_DROP_TOTAL_COUNT); |
| break; |
| |
| default: |
| break; |
| } |
| #if CFG_HIF_RX_STARVATION_WARNING |
| prRxCtrl->u4DequeuedCnt++; |
| #endif |
| prRetSwRfb = prNextSwRfb; |
| } while (prRetSwRfb); |
| } |
| } else { |
| nicRxReturnRFB(prAdapter, prSwRfb); |
| RX_INC_CNT(prRxCtrl, RX_CLASS_ERR_DROP_COUNT); |
| RX_INC_CNT(prRxCtrl, RX_DROP_TOTAL_COUNT); |
| } |
| } |
| |
| #if 1 |
| VOID nicRxProcessEventPacket(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb) |
| { |
| P_CMD_INFO_T prCmdInfo; |
| P_WIFI_EVENT_T prEvent; |
| UINT_32 u4Idx, u4Size; |
| |
| ASSERT(prAdapter); |
| ASSERT(prSwRfb); |
| |
| prEvent = (P_WIFI_EVENT_T) prSwRfb->pucRecvBuff; |
| |
| if (prEvent->ucEID != EVENT_ID_DEBUG_MSG && prEvent->ucEID != EVENT_ID_ASSERT_DUMP) { |
| DBGLOG(NIC, INFO, "RX EVENT: ID[0x%02X] SEQ[%u] LEN[%u]\n", |
| prEvent->ucEID, prEvent->ucSeqNum, prEvent->u2PacketLength); |
| } |
| |
| /* Event handler table */ |
| u4Size = sizeof(arEventTable) / sizeof(RX_EVENT_HANDLER_T); |
| |
| for (u4Idx = 0; u4Idx < u4Size; u4Idx++) { |
| if (prEvent->ucEID == arEventTable[u4Idx].eEID) { |
| arEventTable[u4Idx].pfnHandler(prAdapter, prEvent); |
| |
| break; |
| } |
| } |
| |
| /* Event cannot be found in event handler table, use default action */ |
| if (u4Idx >= u4Size) { |
| prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); |
| |
| if (prCmdInfo != NULL) { |
| if (prCmdInfo->pfCmdDoneHandler) |
| prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, prEvent->aucBuffer); |
| else if (prCmdInfo->fgIsOid) |
| kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_SUCCESS); |
| |
| /* return prCmdInfo */ |
| cmdBufFreeCmdInfo(prAdapter, prCmdInfo); |
| } else { |
| DBGLOG(RX, WARN, "UNHANDLED RX EVENT: ID[0x%02X] SEQ[%u] LEN[%u]\n", |
| prEvent->ucEID, prEvent->ucSeqNum, prEvent->u2PacketLength); |
| } |
| } |
| |
| /* Reset Chip NoAck flag */ |
| if (prAdapter->fgIsChipNoAck) { |
| DBGLOG(RX, WARN, "Got response from chip, clear NoAck flag!\n"); |
| WARN_ON(TRUE); |
| } |
| prAdapter->ucOidTimeoutCount = 0; |
| prAdapter->fgIsChipNoAck = FALSE; |
| |
| nicRxReturnRFB(prAdapter, prSwRfb); |
| } |
| #else |
| BOOLEAN fgKeepPrintCoreDump = FALSE; |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Process HIF event packet |
| * |
| * @param prAdapter pointer to the Adapter handler |
| * @param prSWRfb the RFB to receive rx data |
| * |
| * @return (none) |
| * |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID nicRxProcessEventPacket(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb) |
| { |
| P_CMD_INFO_T prCmdInfo; |
| /* P_MSDU_INFO_T prMsduInfo; */ |
| P_WIFI_EVENT_T prEvent; |
| P_GLUE_INFO_T prGlueInfo; |
| BOOLEAN fgIsNewVersion; |
| /*#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 1)*/ |
| UINT_32 u4QueryInfoLen; |
| /*#endif*/ |
| /*#if (CFG_EEPROM_PAGE_ACCESS == 1)*/ |
| P_EVENT_ACCESS_EFUSE prEventEfuseAccess; |
| P_EVENT_EFUSE_FREE_BLOCK_T prEventGetFreeBlock; |
| /*#endif*/ |
| DEBUGFUNC("nicRxProcessEventPacket"); |
| /* DBGLOG(INIT, TRACE, ("\n")); */ |
| |
| ASSERT(prAdapter); |
| ASSERT(prSwRfb); |
| |
| prEvent = (P_WIFI_EVENT_T) prSwRfb->pucRecvBuff; |
| prGlueInfo = prAdapter->prGlueInfo; |
| |
| if (prEvent->ucEID != EVENT_ID_DEBUG_MSG |
| #if CFG_ASSERT_DUMP |
| && prEvent->ucEID != EVENT_ID_ASSERT_DUMP |
| #endif |
| ) { |
| DBGLOG(INIT, INFO, "RX EVENT: ID[0x%02X] SEQ[%u] LEN[%u]\n", |
| prEvent->ucEID, prEvent->ucSeqNum, prEvent->u2PacketLength); |
| } |
| |
| /* Event Handling */ |
| switch (prEvent->ucEID) { |
| #if 0 /* It is removed now */ |
| case EVENT_ID_CMD_RESULT: |
| prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); |
| |
| if (prCmdInfo != NULL) { |
| P_EVENT_CMD_RESULT prCmdResult; |
| |
| prCmdResult = (P_EVENT_CMD_RESULT) ((PUINT_8) prEvent + EVENT_HDR_SIZE); |
| |
| /* CMD_RESULT should be only in response to Set commands */ |
| ASSERT(prCmdInfo->fgSetQuery == FALSE || prCmdInfo->fgNeedResp == TRUE); |
| |
| if (prCmdResult->ucStatus == 0) { /* success */ |
| if (prCmdInfo->pfCmdDoneHandler) { |
| prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, prEvent->aucBuffer); |
| } else if (prCmdInfo->fgIsOid == TRUE) { |
| kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, |
| 0, WLAN_STATUS_SUCCESS); |
| } |
| } else if (prCmdResult->ucStatus == 1) { /* reject */ |
| if (prCmdInfo->fgIsOid == TRUE) |
| kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, |
| 0, WLAN_STATUS_FAILURE); |
| } else if (prCmdResult->ucStatus == 2) { /* unknown CMD */ |
| if (prCmdInfo->fgIsOid == TRUE) |
| kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, |
| 0, WLAN_STATUS_NOT_SUPPORTED); |
| } |
| /* return prCmdInfo */ |
| cmdBufFreeCmdInfo(prAdapter, prCmdInfo); |
| } |
| |
| break; |
| #endif |
| |
| #if 0 |
| case EVENT_ID_CONNECTION_STATUS: |
| /* OBSELETE */ |
| { |
| P_EVENT_CONNECTION_STATUS prConnectionStatus; |
| |
| prConnectionStatus = (P_EVENT_CONNECTION_STATUS) (prEvent->aucBuffer); |
| |
| DbgPrint("RX EVENT: EVENT_ID_CONNECTION_STATUS = %d\n", prConnectionStatus->ucMediaStatus); |
| if (prConnectionStatus->ucMediaStatus == PARAM_MEDIA_STATE_DISCONNECTED) { |
| /* disconnected */ |
| if (kalGetMediaStateIndicated(prGlueInfo) != PARAM_MEDIA_STATE_DISCONNECTED) { |
| |
| kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); |
| |
| prAdapter->rWlanInfo.u4SysTime = kalGetTimeTick(); |
| } |
| } else if (prConnectionStatus->ucMediaStatus == PARAM_MEDIA_STATE_CONNECTED) { /* connected */ |
| prAdapter->rWlanInfo.u4SysTime = kalGetTimeTick(); |
| |
| /* fill information for association result */ |
| prAdapter->rWlanInfo.rCurrBssId.rSsid.u4SsidLen = prConnectionStatus->ucSsidLen; |
| kalMemCopy(prAdapter->rWlanInfo.rCurrBssId.rSsid.aucSsid, |
| prConnectionStatus->aucSsid, prConnectionStatus->ucSsidLen); |
| |
| kalMemCopy(prAdapter->rWlanInfo.rCurrBssId.arMacAddress, |
| prConnectionStatus->aucBssid, MAC_ADDR_LEN); |
| /* @FIXME */ |
| prAdapter->rWlanInfo.rCurrBssId.u4Privacy = prConnectionStatus->ucEncryptStatus; |
| prAdapter->rWlanInfo.rCurrBssId.rRssi = 0; /* @FIXME */ |
| /* @FIXME */ |
| prAdapter->rWlanInfo.rCurrBssId.eNetworkTypeInUse = PARAM_NETWORK_TYPE_AUTOMODE; |
| prAdapter->rWlanInfo.rCurrBssId.rConfiguration.u4BeaconPeriod |
| = prConnectionStatus->u2BeaconPeriod; |
| prAdapter->rWlanInfo.rCurrBssId.rConfiguration.u4ATIMWindow |
| = prConnectionStatus->u2ATIMWindow; |
| prAdapter->rWlanInfo.rCurrBssId.rConfiguration.u4DSConfig |
| = prConnectionStatus->u4FreqInKHz; |
| prAdapter->rWlanInfo.ucNetworkType = prConnectionStatus->ucNetworkType; |
| |
| switch (prConnectionStatus->ucInfraMode) { |
| case 0: |
| prAdapter->rWlanInfo.rCurrBssId.eOpMode = NET_TYPE_IBSS; |
| break; |
| case 1: |
| prAdapter->rWlanInfo.rCurrBssId.eOpMode = NET_TYPE_INFRA; |
| break; |
| case 2: |
| default: |
| prAdapter->rWlanInfo.rCurrBssId.eOpMode = NET_TYPE_AUTO_SWITCH; |
| break; |
| } |
| /* always indicate to OS according to MSDN (re-association/roaming) */ |
| kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_MEDIA_CONNECT, NULL, 0); |
| } |
| } |
| break; |
| |
| case EVENT_ID_SCAN_RESULT: |
| /* OBSELETE */ |
| break; |
| #endif |
| |
| case EVENT_ID_RX_ADDBA: |
| /* The FW indicates that an RX BA agreement will be established */ |
| qmHandleEventRxAddBa(prAdapter, prEvent); |
| break; |
| |
| case EVENT_ID_RX_DELBA: |
| /* The FW indicates that an RX BA agreement has been deleted */ |
| qmHandleEventRxDelBa(prAdapter, prEvent); |
| break; |
| |
| case EVENT_ID_CHECK_REORDER_BUBBLE: |
| qmHandleEventCheckReorderBubble(prAdapter, prEvent); |
| break; |
| |
| case EVENT_ID_LINK_QUALITY: |
| #if CFG_ENABLE_WIFI_DIRECT && CFG_SUPPORT_P2P_RSSI_QUERY |
| if (prEvent->u2PacketLen == EVENT_HDR_SIZE + sizeof(EVENT_LINK_QUALITY_EX)) { |
| P_EVENT_LINK_QUALITY_EX prLqEx = (P_EVENT_LINK_QUALITY_EX) (prEvent->aucBuffer); |
| |
| if (prLqEx->ucIsLQ0Rdy) |
| nicUpdateLinkQuality(prAdapter, 0, (P_EVENT_LINK_QUALITY) prLqEx); |
| if (prLqEx->ucIsLQ1Rdy) |
| nicUpdateLinkQuality(prAdapter, 1, (P_EVENT_LINK_QUALITY) prLqEx); |
| } else { |
| /* For old FW, P2P may invoke link quality query, and make driver flag becone TRUE. */ |
| DBGLOG(P2P, WARN, "Old FW version, not support P2P RSSI query.\n"); |
| |
| /* Must not use NETWORK_TYPE_P2P_INDEX, cause the structure is mismatch. */ |
| nicUpdateLinkQuality(prAdapter, 0, (P_EVENT_LINK_QUALITY) (prEvent->aucBuffer)); |
| } |
| #else |
| /*only support ais query */ |
| { |
| UINT_8 ucBssIndex; |
| P_BSS_INFO_T prBssInfo; |
| |
| for (ucBssIndex = 0; ucBssIndex < BSS_INFO_NUM; ucBssIndex++) { |
| prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; |
| |
| if ((prBssInfo->eNetworkType == NETWORK_TYPE_AIS) |
| && (prBssInfo->fgIsInUse)) |
| break; |
| } |
| |
| if (ucBssIndex >= BSS_INFO_NUM) |
| ucBssIndex = 1; /* No hit(bss1 for default ais network) */ |
| /* printk("=======> rssi with bss%d ,%d\n",ucBssIndex, |
| * ((P_EVENT_LINK_QUALITY_V2)(prEvent->aucBuffer))->rLq[ucBssIndex].cRssi); |
| */ |
| nicUpdateLinkQuality(prAdapter, ucBssIndex, (P_EVENT_LINK_QUALITY_V2) (prEvent->aucBuffer)); |
| } |
| |
| #endif |
| |
| /* command response handling */ |
| prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); |
| |
| if (prCmdInfo != NULL) { |
| if (prCmdInfo->pfCmdDoneHandler) |
| prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, prEvent->aucBuffer); |
| else if (prCmdInfo->fgIsOid) |
| kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_SUCCESS); |
| /* return prCmdInfo */ |
| cmdBufFreeCmdInfo(prAdapter, prCmdInfo); |
| } |
| #ifndef LINUX |
| if (prAdapter->rWlanInfo.eRssiTriggerType == ENUM_RSSI_TRIGGER_GREATER && |
| prAdapter->rWlanInfo.rRssiTriggerValue >= (PARAM_RSSI) (prAdapter->rLinkQuality.cRssi)) { |
| prAdapter->rWlanInfo.eRssiTriggerType = ENUM_RSSI_TRIGGER_TRIGGERED; |
| |
| kalIndicateStatusAndComplete(prGlueInfo, |
| WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, |
| (PVOID)&(prAdapter->rWlanInfo.rRssiTriggerValue), |
| sizeof(PARAM_RSSI)); |
| } else if (prAdapter->rWlanInfo.eRssiTriggerType == ENUM_RSSI_TRIGGER_LESS |
| && prAdapter->rWlanInfo.rRssiTriggerValue <= (PARAM_RSSI) (prAdapter->rLinkQuality.cRssi)) { |
| prAdapter->rWlanInfo.eRssiTriggerType = ENUM_RSSI_TRIGGER_TRIGGERED; |
| |
| kalIndicateStatusAndComplete(prGlueInfo, |
| WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, |
| (PVOID)&(prAdapter->rWlanInfo.rRssiTriggerValue), |
| sizeof(PARAM_RSSI)); |
| } |
| #endif |
| |
| break; |
| |
| /*#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 1)*/ |
| case EVENT_ID_LAYER_0_EXT_MAGIC_NUM: |
| if ((prEvent->ucExtenEID) == EXT_EVENT_ID_CMD_RESULT) { |
| |
| u4QueryInfoLen = sizeof(PARAM_CUSTOM_EFUSE_BUFFER_MODE_T); |
| |
| prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); |
| |
| if (prCmdInfo != NULL) { |
| if ((prCmdInfo->fgIsOid) != 0) { |
| kalOidComplete(prAdapter->prGlueInfo, |
| prCmdInfo->fgSetQuery, |
| u4QueryInfoLen, |
| WLAN_STATUS_SUCCESS); |
| /* return prCmdInfo */ |
| cmdBufFreeCmdInfo(prAdapter, prCmdInfo); |
| } |
| } |
| } |
| /*#if (CFG_EEPROM_PAGE_ACCESS == 1)*/ |
| |
| else if ((prEvent->ucExtenEID) == EXT_EVENT_ID_CMD_EFUSE_ACCESS) { |
| u4QueryInfoLen = sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T); |
| prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); |
| prEventEfuseAccess = (P_EVENT_ACCESS_EFUSE) (prEvent->aucBuffer); |
| |
| /* Efuse block size 16 */ |
| kalMemCopy(prAdapter->aucEepromVaule, prEventEfuseAccess->aucData, 16); |
| |
| if (prCmdInfo != NULL) { |
| if ((prCmdInfo->fgIsOid) != 0) { |
| kalOidComplete(prAdapter->prGlueInfo, |
| prCmdInfo->fgSetQuery, |
| u4QueryInfoLen, |
| WLAN_STATUS_SUCCESS); |
| /* return prCmdInfo */ |
| cmdBufFreeCmdInfo(prAdapter, prCmdInfo); |
| |
| } |
| } |
| } |
| |
| else if ((prEvent->ucExtenEID) == EXT_EVENT_ID_EFUSE_FREE_BLOCK) { |
| u4QueryInfoLen = sizeof(PARAM_CUSTOM_EFUSE_FREE_BLOCK_T); |
| prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); |
| prEventGetFreeBlock = (P_EVENT_EFUSE_FREE_BLOCK_T) (prEvent->aucBuffer); |
| prAdapter->u4FreeBlockNum = prEventGetFreeBlock->u2FreeBlockNum; |
| |
| if (prCmdInfo != NULL) { |
| if ((prCmdInfo->fgIsOid) != 0) { |
| kalOidComplete(prAdapter->prGlueInfo, |
| prCmdInfo->fgSetQuery, |
| u4QueryInfoLen, |
| WLAN_STATUS_SUCCESS); |
| /* return prCmdInfo */ |
| cmdBufFreeCmdInfo(prAdapter, prCmdInfo); |
| } |
| } |
| } |
| /*#endif*/ |
| break; |
| /*#endif*/ |
| |
| case EVENT_ID_MIC_ERR_INFO: |
| { |
| P_EVENT_MIC_ERR_INFO prMicError; |
| /* P_PARAM_AUTH_EVENT_T prAuthEvent; */ |
| P_STA_RECORD_T prStaRec; |
| |
| DBGLOG(RSN, EVENT, "EVENT_ID_MIC_ERR_INFO\n"); |
| |
| prMicError = (P_EVENT_MIC_ERR_INFO) (prEvent->aucBuffer); |
| prStaRec = cnmGetStaRecByAddress(prAdapter, |
| prAdapter->prAisBssInfo->ucBssIndex, |
| prAdapter->rWlanInfo.rCurrBssId.arMacAddress); |
| ASSERT(prStaRec); |
| |
| if (prStaRec) |
| rsnTkipHandleMICFailure(prAdapter, prStaRec, (BOOLEAN) prMicError->u4Flags); |
| else |
| DBGLOG(RSN, INFO, "No STA rec!!\n"); |
| #if 0 |
| prAuthEvent = (P_PARAM_AUTH_EVENT_T) prAdapter->aucIndicationEventBuffer; |
| |
| /* Status type: Authentication Event */ |
| prAuthEvent->rStatus.eStatusType = ENUM_STATUS_TYPE_AUTHENTICATION; |
| |
| /* Authentication request */ |
| prAuthEvent->arRequest[0].u4Length = sizeof(PARAM_AUTH_REQUEST_T); |
| kalMemCopy((PVOID) prAuthEvent->arRequest[0].arBssid, |
| (PVOID) prAdapter->rWlanInfo.rCurrBssId.arMacAddress, /* whsu:Todo? */ |
| PARAM_MAC_ADDR_LEN); |
| |
| if (prMicError->u4Flags != 0) |
| prAuthEvent->arRequest[0].u4Flags = PARAM_AUTH_REQUEST_GROUP_ERROR; |
| else |
| prAuthEvent->arRequest[0].u4Flags = PARAM_AUTH_REQUEST_PAIRWISE_ERROR; |
| |
| kalIndicateStatusAndComplete(prAdapter->prGlueInfo, |
| WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, |
| (PVOID) prAuthEvent, |
| sizeof(PARAM_STATUS_INDICATION_T) + sizeof(PARAM_AUTH_REQUEST_T)); |
| #endif |
| } |
| break; |
| |
| #if 0 /* Marked for MT6630 */ |
| case EVENT_ID_ASSOC_INFO: |
| { |
| P_EVENT_ASSOC_INFO prAssocInfo; |
| |
| prAssocInfo = (P_EVENT_ASSOC_INFO) (prEvent->aucBuffer); |
| |
| kalHandleAssocInfo(prAdapter->prGlueInfo, prAssocInfo); |
| } |
| break; |
| |
| case EVENT_ID_802_11_PMKID: |
| { |
| P_PARAM_AUTH_EVENT_T prAuthEvent; |
| PUINT_8 cp; |
| UINT_32 u4LenOfUsedBuffer; |
| |
| prAuthEvent = (P_PARAM_AUTH_EVENT_T) prAdapter->aucIndicationEventBuffer; |
| |
| prAuthEvent->rStatus.eStatusType = ENUM_STATUS_TYPE_CANDIDATE_LIST; |
| |
| u4LenOfUsedBuffer = (UINT_32) (prEvent->u2PacketLength - 8); |
| |
| prAuthEvent->arRequest[0].u4Length = u4LenOfUsedBuffer; |
| |
| cp = (PUINT_8) &prAuthEvent->arRequest[0]; |
| |
| /* Status type: PMKID Candidatelist Event */ |
| kalMemCopy(cp, (P_EVENT_PMKID_CANDIDATE_LIST_T) (prEvent->aucBuffer), |
| prEvent->u2PacketLength - 8); |
| |
| kalIndicateStatusAndComplete(prAdapter->prGlueInfo, |
| WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, |
| (PVOID) prAuthEvent, |
| sizeof(PARAM_STATUS_INDICATION_T) + u4LenOfUsedBuffer); |
| } |
| break; |
| #endif |
| |
| #if 0 |
| case EVENT_ID_ACTIVATE_STA_REC_T: |
| { |
| P_EVENT_ACTIVATE_STA_REC_T prActivateStaRec; |
| |
| prActivateStaRec = (P_EVENT_ACTIVATE_STA_REC_T) (prEvent->aucBuffer); |
| |
| DbgPrint("RX EVENT: EVENT_ID_ACTIVATE_STA_REC_T Index:%d, MAC:[" MACSTR |
| "]\n", prActivateStaRec->ucStaRecIdx, MAC2STR(prActivateStaRec->aucMacAddr)); |
| |
| qmActivateStaRec(prAdapter, |
| (UINT_32) prActivateStaRec->ucStaRecIdx, |
| ((prActivateStaRec->fgIsQoS) ? TRUE : FALSE), |
| prActivateStaRec->ucNetworkTypeIndex, |
| ((prActivateStaRec->fgIsAP) ? TRUE : FALSE), prActivateStaRec->aucMacAddr); |
| |
| } |
| break; |
| |
| case EVENT_ID_DEACTIVATE_STA_REC_T: |
| { |
| P_EVENT_DEACTIVATE_STA_REC_T prDeactivateStaRec; |
| |
| prDeactivateStaRec = (P_EVENT_DEACTIVATE_STA_REC_T) (prEvent->aucBuffer); |
| |
| DbgPrint("RX EVENT: EVENT_ID_DEACTIVATE_STA_REC_T Index:%d, MAC:[" MACSTR |
| "]\n", prDeactivateStaRec->ucStaRecIdx); |
| |
| qmDeactivateStaRec(prAdapter, prDeactivateStaRec->ucStaRecIdx); |
| } |
| break; |
| #endif |
| |
| case EVENT_ID_SCAN_DONE: |
| fgIsNewVersion = TRUE; |
| scnEventScanDone(prAdapter, (P_EVENT_SCAN_DONE) (prEvent->aucBuffer), fgIsNewVersion); |
| break; |
| |
| case EVENT_ID_NLO_DONE: |
| DBGLOG(INIT, INFO, "EVENT_ID_NLO_DONE\n"); |
| scnEventNloDone(prAdapter, (P_EVENT_NLO_DONE_T) (prEvent->aucBuffer)); |
| #if CFG_SUPPORT_PNO |
| prAdapter->prAisBssInfo->fgIsPNOEnable = FALSE; |
| if (prAdapter->prAisBssInfo->fgIsNetRequestInActive && prAdapter->prAisBssInfo->fgIsPNOEnable) { |
| UNSET_NET_ACTIVE(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); |
| DBGLOG(INIT, INFO, "INACTIVE AIS from ACTIVEto disable PNO\n"); |
| /* sync with firmware */ |
| nicDeactivateNetwork(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); |
| } |
| #endif |
| break; |
| |
| case EVENT_ID_TX_DONE: |
| #if 1 |
| nicTxProcessTxDoneEvent(prAdapter, prEvent); |
| #else |
| { |
| P_EVENT_TX_DONE_T prTxDone; |
| |
| prTxDone = (P_EVENT_TX_DONE_T) (prEvent->aucBuffer); |
| |
| DBGLOG(INIT, INFO, "EVENT_ID_TX_DONE WIDX:PID[%u:%u] Status[%u] SN[%u]\n", |
| prTxDone->ucWlanIndex, prTxDone->ucPacketSeq, prTxDone->ucStatus, |
| prTxDone->u2SequenceNumber); |
| |
| /* call related TX Done Handler */ |
| prMsduInfo = nicGetPendingTxMsduInfo(prAdapter, prTxDone->ucWlanIndex, prTxDone->ucPacketSeq); |
| |
| #if CFG_SUPPORT_802_11V_TIMING_MEASUREMENT |
| DBGLOG(INIT, TRACE, "EVENT_ID_TX_DONE u4TimeStamp = %x u2AirDelay = %x\n", |
| prTxDone->au4Reserved1, prTxDone->au4Reserved2); |
| |
| wnmReportTimingMeas(prAdapter, prMsduInfo->ucStaRecIndex, |
| prTxDone->au4Reserved1, prTxDone->au4Reserved1 + prTxDone->au4Reserved2); |
| #endif |
| |
| if (prMsduInfo) { |
| prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, |
| (ENUM_TX_RESULT_CODE_T) (prTxDone->ucStatus)); |
| |
| if (prMsduInfo->eSrc == TX_PACKET_MGMT) |
| cnmMgtPktFree(prAdapter, prMsduInfo); |
| else |
| nicTxReturnMsduInfo(prAdapter, prMsduInfo); |
| } |
| } |
| #endif |
| break; |
| |
| case EVENT_ID_SLEEPY_INFO: |
| #if defined(_HIF_USB) |
| #else |
| { |
| P_EVENT_SLEEPY_INFO_T prEventSleepyNotify; |
| |
| prEventSleepyNotify = (P_EVENT_SLEEPY_INFO_T) (prEvent->aucBuffer); |
| |
| /* DBGLOG(RX, INFO, ("ucSleepyState = %d\n", prEventSleepyNotify->ucSleepyState)); */ |
| |
| prAdapter->fgWiFiInSleepyState = (BOOLEAN) (prEventSleepyNotify->ucSleepyState); |
| |
| #if CFG_SUPPORT_MULTITHREAD |
| if (prEventSleepyNotify->ucSleepyState) |
| kalSetFwOwnEvent2Hif(prGlueInfo); |
| #endif |
| } |
| #endif |
| break; |
| case EVENT_ID_BT_OVER_WIFI: |
| #if CFG_ENABLE_BT_OVER_WIFI |
| { |
| UINT_8 aucTmp[sizeof(AMPC_EVENT) + sizeof(BOW_LINK_DISCONNECTED)]; |
| P_EVENT_BT_OVER_WIFI prEventBtOverWifi; |
| P_AMPC_EVENT prBowEvent; |
| P_BOW_LINK_CONNECTED prBowLinkConnected; |
| P_BOW_LINK_DISCONNECTED prBowLinkDisconnected; |
| |
| prEventBtOverWifi = (P_EVENT_BT_OVER_WIFI) (prEvent->aucBuffer); |
| |
| /* construct event header */ |
| prBowEvent = (P_AMPC_EVENT) aucTmp; |
| |
| if (prEventBtOverWifi->ucLinkStatus == 0) { |
| /* Connection */ |
| prBowEvent->rHeader.ucEventId = BOW_EVENT_ID_LINK_CONNECTED; |
| prBowEvent->rHeader.ucSeqNumber = 0; |
| prBowEvent->rHeader.u2PayloadLength = sizeof(BOW_LINK_CONNECTED); |
| |
| /* fill event body */ |
| prBowLinkConnected = (P_BOW_LINK_CONNECTED) (prBowEvent->aucPayload); |
| prBowLinkConnected->rChannel.ucChannelNum = prEventBtOverWifi->ucSelectedChannel; |
| kalMemZero(prBowLinkConnected->aucPeerAddress, MAC_ADDR_LEN); /* @FIXME */ |
| |
| kalIndicateBOWEvent(prAdapter->prGlueInfo, prBowEvent); |
| } else { |
| /* Disconnection */ |
| prBowEvent->rHeader.ucEventId = BOW_EVENT_ID_LINK_DISCONNECTED; |
| prBowEvent->rHeader.ucSeqNumber = 0; |
| prBowEvent->rHeader.u2PayloadLength = sizeof(BOW_LINK_DISCONNECTED); |
| |
| /* fill event body */ |
| prBowLinkDisconnected = (P_BOW_LINK_DISCONNECTED) (prBowEvent->aucPayload); |
| prBowLinkDisconnected->ucReason = 0; /* @FIXME */ |
| kalMemZero(prBowLinkDisconnected->aucPeerAddress, MAC_ADDR_LEN); /* @FIXME */ |
| |
| kalIndicateBOWEvent(prAdapter->prGlueInfo, prBowEvent); |
| } |
| } |
| break; |
| #endif |
| case EVENT_ID_STATISTICS: |
| /* buffer statistics for further query */ |
| prAdapter->fgIsStatValid = TRUE; |
| prAdapter->rStatUpdateTime = kalGetTimeTick(); |
| kalMemCopy(&prAdapter->rStatStruct, prEvent->aucBuffer, sizeof(EVENT_STATISTICS)); |
| |
| /* command response handling */ |
| prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); |
| |
| if (prCmdInfo != NULL) { |
| if (prCmdInfo->pfCmdDoneHandler) |
| prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, prEvent->aucBuffer); |
| else if (prCmdInfo->fgIsOid) |
| kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_SUCCESS); |
| /* return prCmdInfo */ |
| cmdBufFreeCmdInfo(prAdapter, prCmdInfo); |
| } |
| |
| break; |
| |
| #if CFG_SUPPORT_MSP |
| case EVENT_ID_WLAN_INFO: |
| /* buffer statistics for further query */ |
| prAdapter->fgIsStatValid = TRUE; |
| prAdapter->rStatUpdateTime = kalGetTimeTick(); |
| kalMemCopy(&prAdapter->rEventWlanInfo, prEvent->aucBuffer, sizeof(EVENT_WLAN_INFO)); |
| |
| DBGLOG(RSN, INFO, "EVENT_ID_WLAN_INFO"); |
| /* command response handling */ |
| prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); |
| |
| if (prCmdInfo != NULL) { |
| if (prCmdInfo->pfCmdDoneHandler) |
| prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, prEvent->aucBuffer); |
| else if (prCmdInfo->fgIsOid) |
| kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_SUCCESS); |
| /* return prCmdInfo */ |
| cmdBufFreeCmdInfo(prAdapter, prCmdInfo); |
| } |
| |
| break; |
| |
| case EVENT_ID_MIB_INFO: |
| /* buffer statistics for further query */ |
| prAdapter->fgIsStatValid = TRUE; |
| prAdapter->rStatUpdateTime = kalGetTimeTick(); |
| |
| DBGLOG(RSN, INFO, "EVENT_ID_MIB_INFO"); |
| /* command response handling */ |
| prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); |
| |
| if (prCmdInfo != NULL) { |
| if (prCmdInfo->pfCmdDoneHandler) |
| prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, prEvent->aucBuffer); |
| else if (prCmdInfo->fgIsOid) |
| kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_SUCCESS); |
| /* return prCmdInfo */ |
| cmdBufFreeCmdInfo(prAdapter, prCmdInfo); |
| } |
| |
| break; |
| #endif |
| case EVENT_ID_CH_PRIVILEGE: |
| cnmChMngrHandleChEvent(prAdapter, prEvent); |
| break; |
| |
| case EVENT_ID_BSS_ABSENCE_PRESENCE: |
| qmHandleEventBssAbsencePresence(prAdapter, prEvent); |
| break; |
| |
| case EVENT_ID_STA_CHANGE_PS_MODE: |
| qmHandleEventStaChangePsMode(prAdapter, prEvent); |
| break; |
| #if CFG_ENABLE_WIFI_DIRECT |
| case EVENT_ID_STA_UPDATE_FREE_QUOTA: |
| qmHandleEventStaUpdateFreeQuota(prAdapter, prEvent); |
| break; |
| #endif |
| case EVENT_ID_BSS_BEACON_TIMEOUT: |
| DBGLOG(INIT, INFO, "EVENT_ID_BSS_BEACON_TIMEOUT\n"); |
| |
| if (prAdapter->fgDisBcnLostDetection == FALSE) { |
| P_BSS_INFO_T prBssInfo = (P_BSS_INFO_T) NULL; |
| P_EVENT_BSS_BEACON_TIMEOUT_T prEventBssBeaconTimeout; |
| |
| prEventBssBeaconTimeout = (P_EVENT_BSS_BEACON_TIMEOUT_T) (prEvent->aucBuffer); |
| |
| if (prEventBssBeaconTimeout->ucBssIndex >= BSS_INFO_NUM) |
| break; |
| |
| DBGLOG(INIT, INFO, "Reason code: %d\n", prEventBssBeaconTimeout->ucReasonCode); |
| |
| prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prEventBssBeaconTimeout->ucBssIndex); |
| |
| if (prEventBssBeaconTimeout->ucBssIndex == prAdapter->prAisBssInfo->ucBssIndex) |
| aisBssBeaconTimeout(prAdapter); |
| #if CFG_ENABLE_WIFI_DIRECT |
| else if (prBssInfo->eNetworkType == NETWORK_TYPE_P2P) |
| p2pRoleFsmRunEventBeaconTimeout(prAdapter, prBssInfo); |
| #endif |
| #if CFG_ENABLE_BT_OVER_WIFI |
| else if (GET_BSS_INFO_BY_INDEX(prAdapter, prEventBssBeaconTimeout->ucBssIndex)->eNetworkType == |
| NETWORK_TYPE_BOW) { |
| /* ToDo:: Nothing */ |
| } |
| #endif |
| else { |
| DBGLOG(RX, ERROR, |
| "EVENT_ID_BSS_BEACON_TIMEOUT: (ucBssIndex = %d)\n", |
| prEventBssBeaconTimeout->ucBssIndex); |
| } |
| } |
| |
| break; |
| case EVENT_ID_UPDATE_NOA_PARAMS: |
| #if CFG_ENABLE_WIFI_DIRECT |
| if (prAdapter->fgIsP2PRegistered) { |
| P_EVENT_UPDATE_NOA_PARAMS_T prEventUpdateNoaParam; |
| |
| prEventUpdateNoaParam = (P_EVENT_UPDATE_NOA_PARAMS_T) (prEvent->aucBuffer); |
| |
| if (GET_BSS_INFO_BY_INDEX(prAdapter, prEventUpdateNoaParam->ucBssIndex)->eNetworkType == |
| NETWORK_TYPE_P2P) { |
| p2pProcessEvent_UpdateNOAParam(prAdapter, prEventUpdateNoaParam->ucBssIndex, |
| prEventUpdateNoaParam); |
| } else { |
| ASSERT(0); |
| } |
| } |
| #else |
| ASSERT(0); |
| #endif |
| break; |
| |
| case EVENT_ID_STA_AGING_TIMEOUT: |
| #if CFG_ENABLE_WIFI_DIRECT |
| { |
| if (prAdapter->fgDisStaAgingTimeoutDetection == FALSE) { |
| P_EVENT_STA_AGING_TIMEOUT_T prEventStaAgingTimeout; |
| P_STA_RECORD_T prStaRec; |
| P_BSS_INFO_T prBssInfo = (P_BSS_INFO_T) NULL; |
| |
| prEventStaAgingTimeout = (P_EVENT_STA_AGING_TIMEOUT_T) (prEvent->aucBuffer); |
| prStaRec = cnmGetStaRecByIndex(prAdapter, prEventStaAgingTimeout->ucStaRecIdx); |
| if (prStaRec == NULL) |
| break; |
| |
| DBGLOG(INIT, INFO, "EVENT_ID_STA_AGING_TIMEOUT %u " MACSTR "\n", |
| prEventStaAgingTimeout->ucStaRecIdx, MAC2STR(prStaRec->aucMacAddr)); |
| |
| prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); |
| |
| bssRemoveClient(prAdapter, prBssInfo, prStaRec); |
| |
| /* Call False Auth */ |
| if (prAdapter->fgIsP2PRegistered) { |
| p2pFuncDisconnect(prAdapter, prBssInfo, prStaRec, TRUE, |
| REASON_CODE_DISASSOC_INACTIVITY); |
| } |
| |
| } |
| /* gDisStaAgingTimeoutDetection */ |
| } |
| #endif |
| break; |
| |
| case EVENT_ID_AP_OBSS_STATUS: |
| #if CFG_ENABLE_WIFI_DIRECT |
| if (prAdapter->fgIsP2PRegistered) |
| rlmHandleObssStatusEventPkt(prAdapter, (P_EVENT_AP_OBSS_STATUS_T) prEvent->aucBuffer); |
| #endif |
| break; |
| |
| case EVENT_ID_ROAMING_STATUS: |
| #if CFG_SUPPORT_ROAMING |
| { |
| P_CMD_ROAMING_TRANSIT_T prTransit; |
| |
| prTransit = (P_CMD_ROAMING_TRANSIT_T) (prEvent->aucBuffer); |
| roamingFsmProcessEvent(prAdapter, prTransit); |
| } |
| #endif /* CFG_SUPPORT_ROAMING */ |
| break; |
| case EVENT_ID_SEND_DEAUTH: |
| #if DBG |
| { |
| P_WLAN_MAC_HEADER_T prWlanMacHeader; |
| |
| prWlanMacHeader = (P_WLAN_MAC_HEADER_T) &prEvent->aucBuffer[0]; |
| DBGLOG(RX, INFO, "nicRx: aucAddr1: " MACSTR "\n", MAC2STR(prWlanMacHeader->aucAddr1)); |
| DBGLOG(RX, INFO, "nicRx: aucAddr2: " MACSTR "\n", MAC2STR(prWlanMacHeader->aucAddr2)); |
| } |
| #endif |
| /* receive packets without StaRec */ |
| prSwRfb->pvHeader = (P_WLAN_MAC_HEADER_T) &prEvent->aucBuffer[0]; |
| if (authSendDeauthFrame(prAdapter, |
| NULL, |
| NULL, |
| prSwRfb, |
| REASON_CODE_CLASS_3_ERR, |
| (PFN_TX_DONE_HANDLER) NULL) == WLAN_STATUS_SUCCESS) { |
| DBGLOG(RX, INFO, "Send Deauth Error\n"); |
| } |
| break; |
| |
| #if CFG_SUPPORT_RDD_TEST_MODE |
| case EVENT_ID_UPDATE_RDD_STATUS: |
| { |
| P_EVENT_RDD_STATUS_T prEventRddStatus; |
| |
| prEventRddStatus = (P_EVENT_RDD_STATUS_T) (prEvent->aucBuffer); |
| |
| prAdapter->ucRddStatus = prEventRddStatus->ucRddStatus; |
| } |
| |
| break; |
| #endif |
| |
| #if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS |
| case EVENT_ID_UPDATE_BWCS_STATUS: |
| { |
| P_PTA_IPC_T prEventBwcsStatus; |
| |
| prEventBwcsStatus = (P_PTA_IPC_T) (prEvent->aucBuffer); |
| |
| #if CFG_SUPPORT_BCM_BWCS_DEBUG |
| DBGLOG(RSN, EVENT, "BCM BWCS Event: %02x%02x%02x%02x\n", |
| prEventBwcsStatus->u.aucBTPParams[0], |
| prEventBwcsStatus->u.aucBTPParams[1], |
| prEventBwcsStatus->u.aucBTPParams[2], prEventBwcsStatus->u.aucBTPParams[3]); |
| #endif |
| |
| kalIndicateStatusAndComplete(prAdapter->prGlueInfo, |
| WLAN_STATUS_BWCS_UPDATE, |
| (PVOID) prEventBwcsStatus, sizeof(PTA_IPC_T)); |
| } |
| |
| break; |
| |
| case EVENT_ID_UPDATE_BCM_DEBUG: |
| { |
| P_PTA_IPC_T prEventBwcsStatus; |
| |
| prEventBwcsStatus = (P_PTA_IPC_T) (prEvent->aucBuffer); |
| |
| #if CFG_SUPPORT_BCM_BWCS_DEBUG |
| DBGLOG(RSN, EVENT, "BCM FW status: %02x%02x%02x%02x\n", |
| prEventBwcsStatus->u.aucBTPParams[0], |
| prEventBwcsStatus->u.aucBTPParams[1], |
| prEventBwcsStatus->u.aucBTPParams[2], prEventBwcsStatus->u.aucBTPParams[3]); |
| #endif |
| } |
| |
| break; |
| #endif |
| case EVENT_ID_ADD_PKEY_DONE: |
| { |
| P_EVENT_ADD_KEY_DONE_INFO prAddKeyDone; |
| P_STA_RECORD_T prStaRec; |
| |
| prAddKeyDone = (P_EVENT_ADD_KEY_DONE_INFO) (prEvent->aucBuffer); |
| |
| DBGLOG(RSN, EVENT, |
| "EVENT_ID_ADD_PKEY_DONE BSSIDX=%d " MACSTR "\n", |
| prAddKeyDone->ucBSSIndex, MAC2STR(prAddKeyDone->aucStaAddr)); |
| |
| prStaRec = cnmGetStaRecByAddress(prAdapter, prAddKeyDone->ucBSSIndex, prAddKeyDone->aucStaAddr); |
| |
| if (prStaRec) { |
| DBGLOG(RSN, EVENT, "STA " MACSTR " Add Key Done!!\n", MAC2STR(prStaRec->aucMacAddr)); |
| prStaRec->fgIsTxKeyReady = TRUE; |
| qmUpdateStaRec(prAdapter, prStaRec); |
| } |
| } |
| break; |
| case EVENT_ID_ICAP_DONE: |
| { |
| P_EVENT_ICAP_STATUS_T prEventIcapStatus; |
| PARAM_CUSTOM_MEM_DUMP_STRUCT_T rMemDumpInfo; |
| UINT_32 u4QueryInfo; |
| |
| prEventIcapStatus = (P_EVENT_ICAP_STATUS_T) (prEvent->aucBuffer); |
| |
| rMemDumpInfo.u4Address = prEventIcapStatus->u4StartAddress; |
| rMemDumpInfo.u4Length = prEventIcapStatus->u4IcapSieze; |
| #if CFG_SUPPORT_QA_TOOL |
| rMemDumpInfo.u4IcapContent = prEventIcapStatus->u4IcapContent; |
| #endif |
| |
| wlanoidQueryMemDump(prAdapter, &rMemDumpInfo, sizeof(rMemDumpInfo), &u4QueryInfo); |
| |
| } |
| |
| break; |
| case EVENT_ID_DEBUG_MSG: |
| { |
| P_EVENT_DEBUG_MSG_T prEventDebugMsg; |
| UINT_16 u2DebugMsgId; |
| UINT_8 ucMsgType; |
| UINT_8 ucFlags; |
| UINT_32 u4Value; |
| UINT_16 u2MsgSize; |
| P_UINT_8 pucMsg; |
| |
| prEventDebugMsg = (P_EVENT_DEBUG_MSG_T) (prEvent->aucBuffer); |
| |
| u2DebugMsgId = prEventDebugMsg->u2DebugMsgId; |
| ucMsgType = prEventDebugMsg->ucMsgType; |
| ucFlags = prEventDebugMsg->ucFlags; |
| u4Value = prEventDebugMsg->u4Value; |
| u2MsgSize = prEventDebugMsg->u2MsgSize; |
| pucMsg = prEventDebugMsg->aucMsg; |
| |
| DBGLOG(SW4, TRACE, "DEBUG_MSG Id %u Type %u Fg 0x%x Val 0x%x Size %u\n", |
| u2DebugMsgId, ucMsgType, ucFlags, u4Value, u2MsgSize); |
| |
| if (u2MsgSize <= DEBUG_MSG_SIZE_MAX) { |
| if (ucMsgType >= DEBUG_MSG_TYPE_END) |
| ucMsgType = DEBUG_MSG_TYPE_MEM32; |
| |
| if (ucMsgType == DEBUG_MSG_TYPE_ASCII) { |
| PUINT_8 pucChr; |
| |
| pucMsg[u2MsgSize] = '\0'; |
| |
| /* skip newline */ |
| pucChr = kalStrChr(pucMsg, '\0'); |
| if (*(pucChr - 1) == '\n') |
| *(pucChr - 1) = '\0'; |
| |
| DBGLOG(SW4, INFO, "<FW>%s\n", pucMsg); |
| } else if (ucMsgType == DEBUG_MSG_TYPE_MEM8) { |
| DBGLOG(SW4, INFO, "<FW>Dump MEM8\n"); |
| DBGLOG_MEM8(SW4, INFO, pucMsg, u2MsgSize); |
| } else { |
| DBGLOG(SW4, INFO, "<FW>Dump MEM32\n"); |
| DBGLOG_MEM32(SW4, INFO, pucMsg, u2MsgSize); |
| } |
| } /* DEBUG_MSG_SIZE_MAX */ |
| else |
| DBGLOG(SW4, INFO, "Debug msg size %u is too large.\n", u2MsgSize); |
| } |
| break; |
| |
| #if CFG_SUPPORT_BATCH_SCAN |
| case EVENT_ID_BATCH_RESULT: |
| DBGLOG(SCN, TRACE, "Got EVENT_ID_BATCH_RESULT"); |
| |
| /* command response handling */ |
| prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); |
| |
| if (prCmdInfo != NULL) { |
| if (prCmdInfo->pfCmdDoneHandler) |
| prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, prEvent->aucBuffer); |
| else if (prCmdInfo->fgIsOid) |
| kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_SUCCESS); |
| /* return prCmdInfo */ |
| cmdBufFreeCmdInfo(prAdapter, prCmdInfo); |
| } |
| |
| break; |
| #endif /* CFG_SUPPORT_BATCH_SCAN */ |
| |
| #if CFG_SUPPORT_TDLS |
| case EVENT_ID_TDLS: |
| |
| TdlsexEventHandle(prAdapter->prGlueInfo, |
| (UINT_8 *) prEvent->aucBuffer, (UINT_32) (prEvent->u2PacketLength - 8)); |
| break; |
| #endif /* CFG_SUPPORT_TDLS */ |
| |
| case EVENT_ID_DUMP_MEM: |
| DBGLOG(INIT, INFO, "%s: EVENT_ID_DUMP_MEM\n", __func__); |
| |
| prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); |
| |
| if (prCmdInfo != NULL) { |
| DBGLOG(INIT, INFO, ": ==> 1\n"); |
| if (prCmdInfo->pfCmdDoneHandler) |
| prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, prEvent->aucBuffer); |
| else if (prCmdInfo->fgIsOid) |
| kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_SUCCESS); |
| /* return prCmdInfo */ |
| cmdBufFreeCmdInfo(prAdapter, prCmdInfo); |
| } else { |
| /* Burst mode */ |
| DBGLOG(INIT, INFO, ": ==> 2\n"); |
| nicEventQueryMemDump(prAdapter, prEvent->aucBuffer); |
| } |
| break; |
| #if CFG_ASSERT_DUMP |
| case EVENT_ID_ASSERT_DUMP: |
| |
| if (prEvent->ucS2DIndex == S2D_INDEX_EVENT_N2H) { |
| if (!prAdapter->fgN9AssertDumpOngoing) { |
| DBGLOG(INIT, INFO, "%s: EVENT_ID_ASSERT_DUMP\n", __func__); |
| DBGLOG(INIT, INFO, "\n[DUMP_N9]====N9 ASSERT_DUMPSTART====\n"); |
| fgKeepPrintCoreDump = TRUE; |
| if (kalOpenCorDumpFile(TRUE) != WLAN_STATUS_SUCCESS) |
| DBGLOG(INIT, INFO, "kalOpenCorDumpFile fail\n"); |
| else |
| prAdapter->fgN9CorDumpFileOpend = TRUE; |
| |
| prAdapter->fgN9AssertDumpOngoing = TRUE; |
| } else if (prAdapter->fgN9AssertDumpOngoing) { |
| |
| if (fgKeepPrintCoreDump) |
| DBGLOG(INIT, INFO, "[DUMP_N9]%s:\n", prEvent->aucBuffer); |
| if (!kalStrnCmp(prEvent->aucBuffer, ";more log added here", 5) |
| || !kalStrnCmp(prEvent->aucBuffer, ";[core dump start]", 5)) |
| fgKeepPrintCoreDump = FALSE; |
| |
| if (prAdapter->fgN9CorDumpFileOpend) { |
| if (kalWriteCorDumpFile(prEvent->aucBuffer, prEvent->u2PacketLength, TRUE) != |
| WLAN_STATUS_SUCCESS) { |
| DBGLOG(INIT, INFO, "kalWriteN9CorDumpFile fail\n"); |
| } |
| } |
| wlanCorDumpTimerReset(prAdapter, TRUE); |
| } |
| } else { |
| /* prEvent->ucS2DIndex == S2D_INDEX_EVENT_C2H */ |
| if (!prAdapter->fgCr4AssertDumpOngoing) { |
| DBGLOG(INIT, INFO, "%s: EVENT_ID_ASSERT_DUMP\n", __func__); |
| DBGLOG(INIT, INFO, "\n[DUMP_Cr4]====CR4 ASSERT_DUMPSTART====\n"); |
| fgKeepPrintCoreDump = TRUE; |
| if (kalOpenCorDumpFile(FALSE) != WLAN_STATUS_SUCCESS) |
| DBGLOG(INIT, INFO, "kalOpenCorDumpFile fail\n"); |
| else |
| prAdapter->fgCr4CorDumpFileOpend = TRUE; |
| |
| prAdapter->fgCr4AssertDumpOngoing = TRUE; |
| } else if (prAdapter->fgCr4AssertDumpOngoing) { |
| if (fgKeepPrintCoreDump) |
| DBGLOG(INIT, INFO, "[DUMP_CR4]%s:\n", prEvent->aucBuffer); |
| if (!kalStrnCmp(prEvent->aucBuffer, ";more log added here", 5)) |
| fgKeepPrintCoreDump = FALSE; |
| |
| if (prAdapter->fgCr4CorDumpFileOpend) { |
| if (kalWriteCorDumpFile(prEvent->aucBuffer, prEvent->u2PacketLength, FALSE) != |
| WLAN_STATUS_SUCCESS) { |
| DBGLOG(INIT, INFO, "kalWriteN9CorDumpFile fail\n"); |
| } |
| } |
| wlanCorDumpTimerReset(prAdapter, FALSE); |
| } |
| } |
| break; |
| |
| #endif |
| |
| case EVENT_ID_RDD_SEND_PULSE: |
| DBGLOG(INIT, INFO, "%s: EVENT_ID_RDD_SEND_PULSE\n", __func__); |
| |
| nicEventRddPulseDump(prAdapter, prEvent->aucBuffer); |
| break; |
| |
| case EVENT_ID_ACCESS_RX_STAT: |
| case EVENT_ID_ACCESS_REG: |
| case EVENT_ID_NIC_CAPABILITY: |
| /* case EVENT_ID_MAC_MCAST_ADDR: */ |
| case EVENT_ID_ACCESS_EEPROM: |
| case EVENT_ID_TEST_STATUS: |
| default: |
| prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); |
| |
| if (prCmdInfo != NULL) { |
| if (prCmdInfo->pfCmdDoneHandler) |
| prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, prEvent->aucBuffer); |
| else if (prCmdInfo->fgIsOid) |
| kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_SUCCESS); |
| /* return prCmdInfo */ |
| cmdBufFreeCmdInfo(prAdapter, prCmdInfo); |
| } |
| |
| break; |
| } |
| |
| /* Reset Chip NoAck flag */ |
| if (prGlueInfo->prAdapter->fgIsChipNoAck) { |
| DBGLOG(INIT, WARN, "Got response from chip, clear NoAck flag!\n"); |
| WARN_ON(TRUE); |
| } |
| prGlueInfo->prAdapter->ucOidTimeoutCount = 0; |
| prGlueInfo->prAdapter->fgIsChipNoAck = FALSE; |
| |
| nicRxReturnRFB(prAdapter, prSwRfb); |
| } |
| #endif |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief nicRxProcessMgmtPacket is used to dispatch management frames |
| * to corresponding modules |
| * |
| * @param prAdapter Pointer to the Adapter structure. |
| * @param prSWRfb the RFB to receive rx data |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID nicRxProcessMgmtPacket(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb) |
| { |
| UINT_8 ucSubtype; |
| #if CFG_SUPPORT_802_11W |
| /* BOOL fgMfgDrop = FALSE; */ |
| #endif |
| ASSERT(prAdapter); |
| ASSERT(prSwRfb); |
| |
| nicRxFillRFB(prAdapter, prSwRfb); |
| |
| ucSubtype = (*(PUINT_8) (prSwRfb->pvHeader) & MASK_FC_SUBTYPE) >> OFFSET_OF_FC_SUBTYPE; |
| |
| #if CFG_RX_PKTS_DUMP |
| { |
| P_WLAN_MAC_MGMT_HEADER_T prWlanMgmtHeader; |
| UINT_16 u2TxFrameCtrl; |
| |
| u2TxFrameCtrl = (*(PUINT_8) (prSwRfb->pvHeader) & MASK_FRAME_TYPE); |
| if (prAdapter->rRxCtrl.u4RxPktsDumpTypeMask & BIT(HIF_RX_PKT_TYPE_MANAGEMENT)) { |
| if (u2TxFrameCtrl == MAC_FRAME_BEACON || u2TxFrameCtrl == MAC_FRAME_PROBE_RSP) { |
| |
| prWlanMgmtHeader = (P_WLAN_MAC_MGMT_HEADER_T) (prSwRfb->pvHeader); |
| |
| DBGLOG(SW4, INFO, |
| "QM RX MGT: net %u sta idx %u wlan idx %u ssn %u ptype %u subtype %u 11 %u\n", |
| prSwRfb->prStaRec->ucBssIndex, prSwRfb->ucStaRecIdx, |
| prSwRfb->ucWlanIdx, prWlanMgmtHeader->u2SeqCtrl, |
| /* The new SN of the frame */ |
| prSwRfb->ucPacketType, ucSubtype); |
| /* HIF_RX_HDR_GET_80211_FLAG(prHifRxHdr))); */ |
| |
| DBGLOG_MEM8(SW4, TRACE, (PUINT_8) prSwRfb->pvHeader, prSwRfb->u2PacketLen); |
| } |
| } |
| } |
| #endif |
| #if CFG_SUPPORT_802_11W |
| if (HAL_RX_STATUS_IS_ICV_ERROR(prSwRfb->prRxStatus)) { |
| if (HAL_RX_STATUS_GET_SEC_MODE(prSwRfb->prRxStatus) == CIPHER_SUITE_BIP) |
| DBGLOG(RSN, INFO, "[MFP] RX with BIP ICV ERROR\n"); |
| else |
| DBGLOG(RSN, INFO, "[MFP] RX with ICV ERROR\n"); |
| |
| nicRxReturnRFB(prAdapter, prSwRfb); |
| RX_INC_CNT(&prAdapter->rRxCtrl, RX_DROP_TOTAL_COUNT); |
| return; |
| } |
| #endif |
| |
| if (prAdapter->fgTestMode == FALSE) { |
| #if CFG_MGMT_FRAME_HANDLING |
| if (apfnProcessRxMgtFrame[ucSubtype]) { |
| switch (apfnProcessRxMgtFrame[ucSubtype] (prAdapter, prSwRfb)) { |
| case WLAN_STATUS_PENDING: |
| return; |
| case WLAN_STATUS_SUCCESS: |
| case WLAN_STATUS_FAILURE: |
| break; |
| |
| default: |
| DBGLOG(RX, WARN, "Unexpected MMPDU(0x%02X) returned with abnormal status\n", ucSubtype); |
| break; |
| } |
| } |
| #endif |
| } |
| |
| nicRxReturnRFB(prAdapter, prSwRfb); |
| } |
| |
| VOID nicRxProcessMsduReport(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb) |
| { |
| halRxProcessMsduReport(prAdapter, prSwRfb); |
| |
| nicRxReturnRFB(prAdapter, prSwRfb); |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief nicProcessRFBs is used to process RFBs in the rReceivedRFBList queue. |
| * |
| * @param prAdapter Pointer to the Adapter structure. |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID nicRxProcessRFBs(IN P_ADAPTER_T prAdapter) |
| { |
| P_RX_CTRL_T prRxCtrl; |
| P_SW_RFB_T prSwRfb = (P_SW_RFB_T) NULL; |
| QUE_T rTempRfbList; |
| P_QUE_T prTempRfbList = &rTempRfbList; |
| UINT_32 u4RxLoopCount; |
| |
| KAL_SPIN_LOCK_DECLARATION(); |
| |
| DEBUGFUNC("nicRxProcessRFBs"); |
| |
| ASSERT(prAdapter); |
| |
| prRxCtrl = &prAdapter->rRxCtrl; |
| ASSERT(prRxCtrl); |
| |
| prRxCtrl->ucNumIndPacket = 0; |
| prRxCtrl->ucNumRetainedPacket = 0; |
| u4RxLoopCount = prAdapter->rWifiVar.u4TxRxLoopCount; |
| |
| QUEUE_INITIALIZE(prTempRfbList); |
| |
| while (u4RxLoopCount--) { |
| while (QUEUE_IS_NOT_EMPTY(&prRxCtrl->rReceivedRfbList)) { |
| |
| KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); |
| QUEUE_MOVE_ALL(prTempRfbList, &prRxCtrl->rReceivedRfbList); |
| KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); |
| |
| while (QUEUE_IS_NOT_EMPTY(prTempRfbList)) { |
| QUEUE_REMOVE_HEAD(prTempRfbList, prSwRfb, P_SW_RFB_T); |
| |
| switch (prSwRfb->ucPacketType) { |
| case RX_PKT_TYPE_RX_DATA: |
| #if CFG_SUPPORT_SNIFFER |
| if (prAdapter->prGlueInfo->fgIsEnableMon && HAL_IS_RX_DIRECT(prAdapter)) { |
| spin_lock_bh(&prAdapter->prGlueInfo->rSpinLock[SPIN_LOCK_RX_DIRECT]); |
| nicRxProcessMonitorPacket(prAdapter, prSwRfb); |
| spin_unlock_bh(&prAdapter->prGlueInfo->rSpinLock[SPIN_LOCK_RX_DIRECT]); |
| break; |
| } else if (prAdapter->prGlueInfo->fgIsEnableMon) { |
| nicRxProcessMonitorPacket(prAdapter, prSwRfb); |
| break; |
| } |
| #endif |
| if (HAL_IS_RX_DIRECT(prAdapter)) { |
| spin_lock_bh(&prAdapter->prGlueInfo->rSpinLock[SPIN_LOCK_RX_DIRECT]); |
| nicRxProcessDataPacket(prAdapter, prSwRfb); |
| spin_unlock_bh(&prAdapter->prGlueInfo->rSpinLock[SPIN_LOCK_RX_DIRECT]); |
| } else { |
| nicRxProcessDataPacket(prAdapter, prSwRfb); |
| } |
| break; |
| |
| case RX_PKT_TYPE_SW_DEFINED: |
| /* HIF_RX_PKT_TYPE_EVENT */ |
| if ((prSwRfb->prRxStatus->u2PktTYpe & RXM_RXD_PKT_TYPE_SW_BITMAP) == |
| RXM_RXD_PKT_TYPE_SW_EVENT) { |
| nicRxProcessEventPacket(prAdapter, prSwRfb); |
| } |
| /* case HIF_RX_PKT_TYPE_MANAGEMENT: */ |
| else if ((prSwRfb->prRxStatus->u2PktTYpe & RXM_RXD_PKT_TYPE_SW_BITMAP) == |
| RXM_RXD_PKT_TYPE_SW_FRAME) { |
| nicRxProcessMgmtPacket(prAdapter, prSwRfb); |
| } else { |
| DBGLOG(RX, ERROR, "u2PktTYpe(0x%04X) is OUT OF DEF.!!!\n", |
| prSwRfb->prRxStatus->u2PktTYpe); |
| DBGLOG_MEM8(RX, ERROR, (PUINT_8) prSwRfb->pvHeader, |
| prSwRfb->u2PacketLen); |
| |
| /*ASSERT(0);*/ |
| nicRxReturnRFB(prAdapter, prSwRfb); |
| RX_INC_CNT(prRxCtrl, RX_TYPE_ERR_DROP_COUNT); |
| RX_INC_CNT(prRxCtrl, RX_DROP_TOTAL_COUNT); |
| |
| } |
| break; |
| |
| case RX_PKT_TYPE_MSDU_REPORT: |
| nicRxProcessMsduReport(prAdapter, prSwRfb); |
| break; |
| |
| /* case HIF_RX_PKT_TYPE_TX_LOOPBACK: */ |
| /* case HIF_RX_PKT_TYPE_MANAGEMENT: */ |
| case RX_PKT_TYPE_TX_STATUS: |
| case RX_PKT_TYPE_RX_VECTOR: |
| case RX_PKT_TYPE_TM_REPORT: |
| default: |
| nicRxReturnRFB(prAdapter, prSwRfb); |
| RX_INC_CNT(prRxCtrl, RX_TYPE_ERR_DROP_COUNT); |
| RX_INC_CNT(prRxCtrl, RX_DROP_TOTAL_COUNT); |
| DBGLOG(RX, ERROR, "ucPacketType = %d\n", prSwRfb->ucPacketType); |
| break; |
| } |
| |
| } |
| |
| if (prRxCtrl->ucNumIndPacket > 0) { |
| RX_ADD_CNT(prRxCtrl, RX_DATA_INDICATION_COUNT, prRxCtrl->ucNumIndPacket); |
| RX_ADD_CNT(prRxCtrl, RX_DATA_RETAINED_COUNT, prRxCtrl->ucNumRetainedPacket); |
| #if !CFG_SUPPORT_MULTITHREAD |
| /* DBGLOG(RX, INFO, ("%d packets indicated, Retained cnt = %d\n", */ |
| /* prRxCtrl->ucNumIndPacket, prRxCtrl->ucNumRetainedPacket)); */ |
| #if CFG_NATIVE_802_11 |
| kalRxIndicatePkts(prAdapter->prGlueInfo, (UINT_32) prRxCtrl->ucNumIndPacket, |
| (UINT_32) prRxCtrl->ucNumRetainedPacket); |
| #else |
| kalRxIndicatePkts(prAdapter->prGlueInfo, prRxCtrl->apvIndPacket, |
| (UINT_32) prRxCtrl->ucNumIndPacket); |
| #endif |
| #endif |
| } |
| } |
| } |
| } /* end of nicRxProcessRFBs() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Setup a RFB and allocate the os packet to the RFB |
| * |
| * @param prAdapter Pointer to the Adapter structure. |
| * @param prSwRfb Pointer to the RFB |
| * |
| * @retval WLAN_STATUS_SUCCESS |
| * @retval WLAN_STATUS_RESOURCES |
| */ |
| /*----------------------------------------------------------------------------*/ |
| WLAN_STATUS nicRxSetupRFB(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) |
| { |
| PVOID pvPacket; |
| PUINT_8 pucRecvBuff; |
| |
| ASSERT(prAdapter); |
| ASSERT(prSwRfb); |
| |
| if (!prSwRfb->pvPacket) { |
| kalMemZero(prSwRfb, sizeof(SW_RFB_T)); |
| pvPacket = kalPacketAlloc(prAdapter->prGlueInfo, CFG_RX_MAX_PKT_SIZE, &pucRecvBuff); |
| if (pvPacket == NULL) |
| return WLAN_STATUS_RESOURCES; |
| |
| prSwRfb->pvPacket = pvPacket; |
| prSwRfb->pucRecvBuff = (PVOID) pucRecvBuff; |
| } else { |
| kalMemZero(((PUINT_8) prSwRfb + OFFSET_OF(SW_RFB_T, prRxStatus)), |
| (sizeof(SW_RFB_T) - OFFSET_OF(SW_RFB_T, prRxStatus))); |
| } |
| |
| /* ToDo: remove prHifRxHdr */ |
| /* prSwRfb->prHifRxHdr = (P_HIF_RX_HEADER_T)(prSwRfb->pucRecvBuff); */ |
| prSwRfb->prRxStatus = (P_HW_MAC_RX_DESC_T) (prSwRfb->pucRecvBuff); |
| |
| return WLAN_STATUS_SUCCESS; |
| |
| } /* end of nicRxSetupRFB() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This routine is called to put a RFB back onto the "RFB with Buffer" list |
| * or "RFB without buffer" list according to pvPacket. |
| * |
| * @param prAdapter Pointer to the Adapter structure. |
| * @param prSwRfb Pointer to the RFB |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID nicRxReturnRFB(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) |
| { |
| P_RX_CTRL_T prRxCtrl; |
| P_QUE_ENTRY_T prQueEntry; |
| |
| KAL_SPIN_LOCK_DECLARATION(); |
| |
| ASSERT(prAdapter); |
| ASSERT(prSwRfb); |
| prRxCtrl = &prAdapter->rRxCtrl; |
| prQueEntry = &prSwRfb->rQueEntry; |
| |
| ASSERT(prQueEntry); |
| |
| /* The processing on this RFB is done, so put it back on the tail of our list */ |
| KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); |
| |
| if (prSwRfb->pvPacket) { |
| /* QUEUE_INSERT_TAIL */ |
| QUEUE_INSERT_TAIL(&prRxCtrl->rFreeSwRfbList, prQueEntry); |
| } else { |
| /* QUEUE_INSERT_TAIL */ |
| QUEUE_INSERT_TAIL(&prRxCtrl->rIndicatedRfbList, prQueEntry); |
| } |
| KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); |
| |
| /* Trigger Rx if there are free SwRfb */ |
| if (halIsPendingRx(prAdapter) && (prRxCtrl->rFreeSwRfbList.u4NumElem > 0)) |
| kalSetIntEvent(prAdapter->prGlueInfo); |
| } /* end of nicRxReturnRFB() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Process rx interrupt. When the rx |
| * Interrupt is asserted, it means there are frames in queue. |
| * |
| * @param prAdapter Pointer to the Adapter structure. |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID nicProcessRxInterrupt(IN P_ADAPTER_T prAdapter) |
| { |
| ASSERT(prAdapter); |
| |
| /* SER break point */ |
| if (nicSerIsRxStop(prAdapter)) { |
| /* Skip following Rx handling */ |
| return; |
| } |
| |
| halProcessRxInterrupt(prAdapter); |
| |
| #if CFG_SUPPORT_MULTITHREAD |
| set_bit(GLUE_FLAG_RX_BIT, &(prAdapter->prGlueInfo->ulFlag)); |
| wake_up_interruptible(&(prAdapter->prGlueInfo->waitq)); |
| #else |
| nicRxProcessRFBs(prAdapter); |
| #endif |
| |
| return; |
| |
| } /* end of nicProcessRxInterrupt() */ |
| |
| #if CFG_TCP_IP_CHKSUM_OFFLOAD |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Used to update IP/TCP/UDP checksum statistics of RX Module. |
| * |
| * @param prAdapter Pointer to the Adapter structure. |
| * @param aeCSUM The array of checksum result. |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID nicRxUpdateCSUMStatistics(IN P_ADAPTER_T prAdapter, IN const ENUM_CSUM_RESULT_T aeCSUM[]) |
| { |
| P_RX_CTRL_T prRxCtrl; |
| |
| ASSERT(prAdapter); |
| ASSERT(aeCSUM); |
| |
| prRxCtrl = &prAdapter->rRxCtrl; |
| ASSERT(prRxCtrl); |
| |
| if ((aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_SUCCESS) || (aeCSUM[CSUM_TYPE_IPV6] == CSUM_RES_SUCCESS)) { |
| /* count success num */ |
| RX_INC_CNT(prRxCtrl, RX_CSUM_IP_SUCCESS_COUNT); |
| } else if ((aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_FAILED) || (aeCSUM[CSUM_TYPE_IPV6] == CSUM_RES_FAILED)) { |
| RX_INC_CNT(prRxCtrl, RX_CSUM_IP_FAILED_COUNT); |
| } else if ((aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_NONE) && (aeCSUM[CSUM_TYPE_IPV6] == CSUM_RES_NONE)) { |
| RX_INC_CNT(prRxCtrl, RX_CSUM_UNKNOWN_L3_PKT_COUNT); |
| } else { |
| ASSERT(0); |
| } |
| |
| if (aeCSUM[CSUM_TYPE_TCP] == CSUM_RES_SUCCESS) { |
| /* count success num */ |
| RX_INC_CNT(prRxCtrl, RX_CSUM_TCP_SUCCESS_COUNT); |
| } else if (aeCSUM[CSUM_TYPE_TCP] == CSUM_RES_FAILED) { |
| RX_INC_CNT(prRxCtrl, RX_CSUM_TCP_FAILED_COUNT); |
| } else if (aeCSUM[CSUM_TYPE_UDP] == CSUM_RES_SUCCESS) { |
| RX_INC_CNT(prRxCtrl, RX_CSUM_UDP_SUCCESS_COUNT); |
| } else if (aeCSUM[CSUM_TYPE_UDP] == CSUM_RES_FAILED) { |
| RX_INC_CNT(prRxCtrl, RX_CSUM_UDP_FAILED_COUNT); |
| } else if ((aeCSUM[CSUM_TYPE_UDP] == CSUM_RES_NONE) && (aeCSUM[CSUM_TYPE_TCP] == CSUM_RES_NONE)) { |
| RX_INC_CNT(prRxCtrl, RX_CSUM_UNKNOWN_L4_PKT_COUNT); |
| } else { |
| ASSERT(0); |
| } |
| |
| } /* end of nicRxUpdateCSUMStatistics() */ |
| #endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is used to query current status of RX Module. |
| * |
| * @param prAdapter Pointer to the Adapter structure. |
| * @param pucBuffer Pointer to the message buffer. |
| * @param pu4Count Pointer to the buffer of message length count. |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID nicRxQueryStatus(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuffer, OUT PUINT_32 pu4Count) |
| { |
| P_RX_CTRL_T prRxCtrl; |
| PUINT_8 pucCurrBuf = pucBuffer; |
| UINT_32 u4CurrCount; |
| |
| ASSERT(prAdapter); |
| prRxCtrl = &prAdapter->rRxCtrl; |
| ASSERT(prRxCtrl); |
| |
| /* if (pucBuffer) {} *//* For Windows, we'll print directly instead of sprintf() */ |
| ASSERT(pu4Count); |
| |
| #define SPRINTF_RX_QSTATUS(arg) \ |
| { \ |
| u4CurrCount = scnprintf(pucCurrBuf, *pu4Count, PRINTF_ARG arg); \ |
| pucCurrBuf += (UINT_8)u4CurrCount; \ |
| *pu4Count -= u4CurrCount; \ |
| } |
| |
| |
| SPRINTF_RX_QSTATUS(("\n\nRX CTRL STATUS:")); |
| SPRINTF_RX_QSTATUS(("\n===============")); |
| SPRINTF_RX_QSTATUS(("\nFREE RFB w/i BUF LIST :%9ld", prRxCtrl->rFreeSwRfbList.u4NumElem)); |
| SPRINTF_RX_QSTATUS(("\nFREE RFB w/o BUF LIST :%9ld", prRxCtrl->rIndicatedRfbList.u4NumElem)); |
| SPRINTF_RX_QSTATUS(("\nRECEIVED RFB LIST :%9ld", prRxCtrl->rReceivedRfbList.u4NumElem)); |
| |
| SPRINTF_RX_QSTATUS(("\n\n")); |
| |
| /* *pu4Count = (UINT_32)((UINT_32)pucCurrBuf - (UINT_32)pucBuffer); */ |
| |
| } /* end of nicRxQueryStatus() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Clear RX related counters |
| * |
| * @param prAdapter Pointer of Adapter Data Structure |
| * |
| * @return - (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID nicRxClearStatistics(IN P_ADAPTER_T prAdapter) |
| { |
| P_RX_CTRL_T prRxCtrl; |
| |
| ASSERT(prAdapter); |
| prRxCtrl = &prAdapter->rRxCtrl; |
| ASSERT(prRxCtrl); |
| |
| RX_RESET_ALL_CNTS(prRxCtrl); |
| |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is used to query current statistics of RX Module. |
| * |
| * @param prAdapter Pointer to the Adapter structure. |
| * @param pucBuffer Pointer to the message buffer. |
| * @param pu4Count Pointer to the buffer of message length count. |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID nicRxQueryStatistics(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuffer, OUT PUINT_32 pu4Count) |
| { |
| P_RX_CTRL_T prRxCtrl; |
| PUINT_8 pucCurrBuf = pucBuffer; |
| UINT_32 u4CurrCount; |
| |
| ASSERT(prAdapter); |
| prRxCtrl = &prAdapter->rRxCtrl; |
| ASSERT(prRxCtrl); |
| |
| /* if (pucBuffer) {} *//* For Windows, we'll print directly instead of sprintf() */ |
| ASSERT(pu4Count); |
| |
| #define SPRINTF_RX_COUNTER(eCounter) \ |
| { \ |
| u4CurrCount = scnprintf(pucCurrBuf, *pu4Count, "%-30s : %ld\n", \ |
| #eCounter, (UINT_32)prRxCtrl->au8Statistics[eCounter]); \ |
| pucCurrBuf += (UINT_8)u4CurrCount; \ |
| *pu4Count -= u4CurrCount; \ |
| } |
| |
| SPRINTF_RX_COUNTER(RX_MPDU_TOTAL_COUNT); |
| SPRINTF_RX_COUNTER(RX_SIZE_ERR_DROP_COUNT); |
| SPRINTF_RX_COUNTER(RX_DATA_INDICATION_COUNT); |
| SPRINTF_RX_COUNTER(RX_DATA_RETURNED_COUNT); |
| SPRINTF_RX_COUNTER(RX_DATA_RETAINED_COUNT); |
| |
| #if CFG_TCP_IP_CHKSUM_OFFLOAD || CFG_TCP_IP_CHKSUM_OFFLOAD_NDIS_60 |
| SPRINTF_RX_COUNTER(RX_CSUM_TCP_FAILED_COUNT); |
| SPRINTF_RX_COUNTER(RX_CSUM_UDP_FAILED_COUNT); |
| SPRINTF_RX_COUNTER(RX_CSUM_IP_FAILED_COUNT); |
| SPRINTF_RX_COUNTER(RX_CSUM_TCP_SUCCESS_COUNT); |
| SPRINTF_RX_COUNTER(RX_CSUM_UDP_SUCCESS_COUNT); |
| SPRINTF_RX_COUNTER(RX_CSUM_IP_SUCCESS_COUNT); |
| SPRINTF_RX_COUNTER(RX_CSUM_UNKNOWN_L4_PKT_COUNT); |
| SPRINTF_RX_COUNTER(RX_CSUM_UNKNOWN_L3_PKT_COUNT); |
| SPRINTF_RX_COUNTER(RX_IP_V6_PKT_CCOUNT); |
| #endif |
| |
| /* *pu4Count = (UINT_32)(pucCurrBuf - pucBuffer); */ |
| |
| nicRxClearStatistics(prAdapter); |
| |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Read the Response data from data port |
| * |
| * @param prAdapter pointer to the Adapter handler |
| * @param pucRspBuffer pointer to the Response buffer |
| * |
| * @retval WLAN_STATUS_SUCCESS: Response packet has been read |
| * @retval WLAN_STATUS_FAILURE: Read Response packet timeout or error occurred |
| * |
| */ |
| /*----------------------------------------------------------------------------*/ |
| WLAN_STATUS |
| nicRxWaitResponse(IN P_ADAPTER_T prAdapter, |
| IN UINT_8 ucPortIdx, OUT PUINT_8 pucRspBuffer, IN UINT_32 u4MaxRespBufferLen, OUT PUINT_32 pu4Length) |
| { |
| P_WIFI_EVENT_T prEvent; |
| WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; |
| |
| u4Status = halRxWaitResponse(prAdapter, ucPortIdx, pucRspBuffer, u4MaxRespBufferLen, pu4Length); |
| if (u4Status == WLAN_STATUS_SUCCESS) { |
| DBGLOG(RX, TRACE, "Dump Response buffer, length = 0x%lx\n", *pu4Length); |
| DBGLOG_MEM8(RX, TRACE, pucRspBuffer, *pu4Length); |
| |
| prEvent = (P_WIFI_EVENT_T) pucRspBuffer; |
| DBGLOG(INIT, TRACE, "RX EVENT: ID[0x%02X] SEQ[%u] LEN[%u]\n", |
| prEvent->ucEID, prEvent->ucSeqNum, prEvent->u2PacketLength); |
| } else { |
| DBGLOG(RX, ERROR, "halRxWaitResponse fail!\n"); |
| } |
| |
| return u4Status; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Set filter to enable Promiscuous Mode |
| * |
| * @param prAdapter Pointer to the Adapter structure. |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID nicRxEnablePromiscuousMode(IN P_ADAPTER_T prAdapter) |
| { |
| ASSERT(prAdapter); |
| |
| } /* end of nicRxEnablePromiscuousMode() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Set filter to disable Promiscuous Mode |
| * |
| * @param prAdapter Pointer to the Adapter structure. |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID nicRxDisablePromiscuousMode(IN P_ADAPTER_T prAdapter) |
| { |
| ASSERT(prAdapter); |
| |
| } /* end of nicRxDisablePromiscuousMode() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief this function flushes all packets queued in reordering module |
| * |
| * @param prAdapter Pointer to the Adapter structure. |
| * |
| * @retval WLAN_STATUS_SUCCESS Flushed successfully |
| */ |
| /*----------------------------------------------------------------------------*/ |
| WLAN_STATUS nicRxFlush(IN P_ADAPTER_T prAdapter) |
| { |
| P_SW_RFB_T prSwRfb; |
| |
| ASSERT(prAdapter); |
| prSwRfb = qmFlushRxQueues(prAdapter); |
| if (prSwRfb != NULL) { |
| do { |
| P_SW_RFB_T prNextSwRfb; |
| |
| /* save next first */ |
| prNextSwRfb = (P_SW_RFB_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prSwRfb); |
| |
| /* free */ |
| nicRxReturnRFB(prAdapter, prSwRfb); |
| |
| prSwRfb = prNextSwRfb; |
| } while (prSwRfb); |
| } |
| |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief |
| * |
| * @param |
| * |
| * @retval |
| */ |
| /*----------------------------------------------------------------------------*/ |
| WLAN_STATUS nicRxProcessActionFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) |
| { |
| P_WLAN_ACTION_FRAME prActFrame; |
| P_BSS_INFO_T prBssInfo = NULL; |
| #if CFG_SUPPORT_802_11W |
| BOOL fgRobustAction = FALSE; |
| P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; |
| #endif |
| |
| ASSERT(prAdapter); |
| ASSERT(prSwRfb); |
| |
| DBGLOG(RSN, TRACE, "[Rx] nicRxProcessActionFrame\n"); |
| |
| if (prSwRfb->u2PacketLen < sizeof(WLAN_ACTION_FRAME) - 1) |
| return WLAN_STATUS_INVALID_PACKET; |
| prActFrame = (P_WLAN_ACTION_FRAME) prSwRfb->pvHeader; |
| |
| DBGLOG(RSN, INFO, "Action frame category=%d\n", prActFrame->ucCategory); |
| |
| #if CFG_SUPPORT_802_11W |
| if ((prActFrame->ucCategory <= CATEGORY_PROTECTED_DUAL_OF_PUBLIC_ACTION && |
| prActFrame->ucCategory != CATEGORY_PUBLIC_ACTION && |
| prActFrame->ucCategory != CATEGORY_HT_ACTION) /* At 11W spec Code 7 is reserved */ || |
| (prActFrame->ucCategory == CATEGORY_VENDOR_SPECIFIC_ACTION_PROTECTED)) { |
| fgRobustAction = TRUE; |
| } |
| /* DBGLOG(RSN, TRACE, ("[Rx] fgRobustAction=%d\n", fgRobustAction)); */ |
| |
| if (fgRobustAction && prSwRfb->prStaRec && |
| GET_BSS_INFO_BY_INDEX(prAdapter, prSwRfb->prStaRec->ucBssIndex)->eNetworkType == NETWORK_TYPE_AIS) { |
| prAisSpecBssInfo = &(prAdapter->rWifiVar.rAisSpecificBssInfo); |
| |
| DBGLOG(RSN, INFO, |
| "[Rx]RobustAction %x %x %x\n", prSwRfb->prRxStatus->u2StatusFlag, |
| prSwRfb->prRxStatus->ucWlanIdx, prSwRfb->prRxStatus->ucTidSecMode); |
| |
| if (prAisSpecBssInfo->fgMgmtProtection && (!(prActFrame->u2FrameCtrl & MASK_FC_PROTECTED_FRAME) |
| && (HAL_RX_STATUS_GET_SEC_MODE(prSwRfb->prRxStatus) == |
| CIPHER_SUITE_CCMP))) { |
| DBGLOG(RSN, INFO, "[MFP] Not handle and drop un-protected robust action frame!!\n"); |
| return WLAN_STATUS_INVALID_PACKET; |
| } |
| } |
| /* DBGLOG(RSN, INFO, "[Rx] pre check done, handle cateory %d\n", prActFrame->ucCategory); */ |
| #endif |
| |
| if (prSwRfb->prStaRec) |
| prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prSwRfb->prStaRec->ucBssIndex); |
| |
| switch (prActFrame->ucCategory) { |
| #if CFG_M0VE_BA_TO_DRIVER |
| case CATEGORY_BLOCK_ACK_ACTION: |
| DBGLOG(RX, WARN, "[Puff][%s] Rx CATEGORY_BLOCK_ACK_ACTION\n", __func__); |
| |
| if (prSwRfb->prStaRec) |
| mqmHandleBaActionFrame(prAdapter, prSwRfb); |
| |
| break; |
| #endif |
| case CATEGORY_PUBLIC_ACTION: |
| #if 0 /* CFG_SUPPORT_802_11W */ |
| /* Sigma */ |
| #else |
| if (prAdapter->prAisBssInfo && |
| prSwRfb->prStaRec && prSwRfb->prStaRec->ucBssIndex == prAdapter->prAisBssInfo->ucBssIndex) { |
| aisFuncValidateRxActionFrame(prAdapter, prSwRfb); |
| } |
| #endif |
| |
| if (prAdapter->prAisBssInfo && prAdapter->prAisBssInfo->ucBssIndex == KAL_NETWORK_TYPE_AIS_INDEX) |
| aisFuncValidateRxActionFrame(prAdapter, prSwRfb); |
| #if CFG_ENABLE_WIFI_DIRECT |
| if (prAdapter->fgIsP2PRegistered) { |
| rlmProcessPublicAction(prAdapter, prSwRfb); |
| if (prBssInfo) |
| p2pFuncValidateRxActionFrame(prAdapter, prSwRfb, |
| (prBssInfo->ucBssIndex == P2P_DEV_BSS_INDEX), (UINT_8) prBssInfo->u4PrivateData); |
| else |
| p2pFuncValidateRxActionFrame(prAdapter, prSwRfb, TRUE, 0); |
| } |
| #endif |
| break; |
| |
| case CATEGORY_HT_ACTION: |
| rlmProcessHtAction(prAdapter, prSwRfb); |
| break; |
| case CATEGORY_VENDOR_SPECIFIC_ACTION: |
| #if CFG_ENABLE_WIFI_DIRECT |
| if (prAdapter->fgIsP2PRegistered) { |
| if (prBssInfo) |
| p2pFuncValidateRxActionFrame(prAdapter, prSwRfb, |
| (prBssInfo->ucBssIndex == P2P_DEV_BSS_INDEX), (UINT_8) prBssInfo->u4PrivateData); |
| else |
| p2pFuncValidateRxActionFrame(prAdapter, prSwRfb, TRUE, 0); |
| } |
| #endif |
| break; |
| #if CFG_SUPPORT_802_11W |
| case CATEGORY_SA_QUERY_ACTION: |
| { |
| P_BSS_INFO_T prBssInfo; |
| |
| if (prSwRfb->prStaRec) { |
| prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prSwRfb->prStaRec->ucBssIndex); |
| ASSERT(prBssInfo); |
| if ((prBssInfo->eNetworkType == NETWORK_TYPE_AIS) && |
| prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection /* Use MFP */) { |
| /* MFP test plan 5.3.3.4 */ |
| rsnSaQueryAction(prAdapter, prSwRfb); |
| } else if ((prBssInfo->eNetworkType == NETWORK_TYPE_P2P) && |
| (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT)) { |
| /* AP PMF */ |
| DBGLOG(RSN, INFO, "[Rx] nicRx AP PMF SAQ action\n"); |
| if (rsnCheckBipKeyInstalled(prAdapter, prSwRfb->prStaRec)) { |
| /* MFP test plan 4.3.3.4 */ |
| rsnApSaQueryAction(prAdapter, prSwRfb); |
| } |
| } |
| } |
| } |
| break; |
| #endif |
| #if CFG_SUPPORT_802_11V |
| case CATEGORY_WNM_ACTION: |
| { |
| wnmWNMAction(prAdapter, prSwRfb); |
| } |
| break; |
| #endif |
| |
| #if CFG_SUPPORT_DFS |
| case CATEGORY_SPEC_MGT: |
| { |
| if (prAdapter->fgEnable5GBand) { |
| DBGLOG(RLM, INFO, "[Channel Switch]nicRxProcessActionFrame\n"); |
| rlmProcessSpecMgtAction(prAdapter, prSwRfb); |
| } |
| } |
| break; |
| #endif |
| |
| #if CFG_SUPPORT_802_11AC |
| case CATEGORY_VHT_ACTION: |
| rlmProcessVhtAction(prAdapter, prSwRfb); |
| break; |
| #endif |
| |
| default: |
| break; |
| } /* end of switch case */ |
| |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief |
| * |
| * @param |
| * |
| * @retval |
| */ |
| /*----------------------------------------------------------------------------*/ |
| UINT_8 |
| nicRxGetRcpiValueFromRxv(IN UINT_8 ucRcpiMode, IN P_SW_RFB_T prSwRfb) |
| { |
| UINT_8 ucRcpi0, ucRcpi1; |
| UINT_8 ucRcpiValue = 0; |
| UINT_8 ucRxNum; |
| |
| ASSERT(prSwRfb); |
| |
| if (ucRcpiMode >= RCPI_MODE_NUM) { |
| DBGLOG(RX, WARN, "Rcpi Mode = %d is invalid for getting RCPI value from RXV\n", ucRcpiMode); |
| return 0; |
| } |
| |
| ucRcpi0 = HAL_RX_STATUS_GET_RCPI0(prSwRfb->prRxStatusGroup3); |
| ucRcpi1 = HAL_RX_STATUS_GET_RCPI1(prSwRfb->prRxStatusGroup3); |
| ucRxNum = HAL_RX_STATUS_GET_RX_NUM(prSwRfb->prRxStatusGroup3); |
| |
| if (ucRxNum == 0) |
| ucRcpiValue = ucRcpi0; /*0:1R, BBP always report RCPI0 at 1R mode*/ |
| |
| else if (ucRxNum == 1) { |
| switch (ucRcpiMode) { |
| case RCPI_MODE_WF0: |
| ucRcpiValue = ucRcpi0; |
| break; |
| |
| case RCPI_MODE_WF1: |
| ucRcpiValue = ucRcpi1; |
| break; |
| |
| case RCPI_MODE_WF2: |
| case RCPI_MODE_WF3: |
| DBGLOG(RX, WARN, "Rcpi Mode = %d is invalid for device with only 2 antenna\n", ucRcpiMode); |
| break; |
| |
| case RCPI_MODE_AVG: /*Not recommended for CBW80+80*/ |
| ucRcpiValue = (ucRcpi0 + ucRcpi1) / 2; |
| break; |
| |
| case RCPI_MODE_MAX: |
| ucRcpiValue = (ucRcpi0 > ucRcpi1) ? (ucRcpi0) : (ucRcpi1); |
| break; |
| |
| case RCPI_MODE_MIN: |
| ucRcpiValue = (ucRcpi0 < ucRcpi1) ? (ucRcpi0) : (ucRcpi1); |
| break; |
| |
| default: |
| break; |
| } |
| } else { |
| DBGLOG(RX, WARN, "RX_NUM = %d is invalid for getting RCPI value from RXV\n", ucRxNum); |
| return 0; |
| } |
| |
| return ucRcpiValue; |
| } |