Files
Linux_Drivers/osdrv/extdrv/wireless/mediatek/mt7603/ap/ap_data.c
forum_service 213c880673 add driver of tp、wiegand-gpio and wireless
Change-Id: Ie3c11d9d85cf1a05042f5690ac711856fe8b1ad7
2023-12-22 09:56:05 +08:00

4648 lines
132 KiB
C

/*
***************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
*
* (c) Copyright 2002, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************
Module Name:
ap_data.c
Abstract:
Data path subroutines
Revision History:
Who When What
-------- ---------- ----------------------------------------------
*/
#include "rt_config.h"
INT ApAllowToSendPacket(
IN RTMP_ADAPTER *pAd,
IN struct wifi_dev *wdev,
IN PNDIS_PACKET pPacket,
IN UCHAR *pWcid)
{
PACKET_INFO PacketInfo;
UCHAR *pSrcBufVA;
UINT SrcBufLen;
MAC_TABLE_ENTRY *pEntry = NULL;
RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
/* 0 is main BSS, FIRST_MBSSID = 1 */
ASSERT(wdev->func_idx < pAd->ApCfg.BssidNum);
ASSERT (wdev->wdev_type == WDEV_TYPE_AP);
if ((wdev->func_idx < 0) || (wdev->func_idx > pAd->ApCfg.BssidNum) ||
(wdev->func_idx >= ARRAY_SIZE(pAd->ApCfg.MBSSID))) {
DBGPRINT(RT_DEBUG_ERROR, ("%s(): wrong func_idx=%d\n",
__func__, wdev->func_idx));
return FALSE;
}
if (wdev != &pAd->ApCfg.MBSSID[wdev->func_idx].wdev) {
DBGPRINT(RT_DEBUG_ERROR, ("%s(): wdev(0x%p) not equal MBSS(0x%p), func_idx=%d\n",
__FUNCTION__, wdev, &pAd->ApCfg.MBSSID[wdev->func_idx].wdev, wdev->func_idx));
}
#ifdef RT_CFG80211_P2P_SINGLE_DEVICE
//CFG_TODO: POS NO GOOD
if (pAd->cfg80211_ctrl.isCfgInApMode == RT_CMD_80211_IFTYPE_AP)
{
RTMP_SET_PACKET_OPMODE(pPacket, OPMODE_AP);
}
#endif /* RT_CFG80211_P2P_SINGLE_DEVICE */
if (MAC_ADDR_IS_GROUP(pSrcBufVA))
{
*pWcid = wdev->tr_tb_idx;
return TRUE;
}
else
{
pEntry = MacTableLookup(pAd, pSrcBufVA);
if (pEntry && (pEntry->Sst == SST_ASSOC))
{
*pWcid = (UCHAR)pEntry->wcid;
return TRUE;
}
#ifdef CLIENT_WDS
if (pEntry == NULL) {
SST Sst;
USHORT Aid;
UCHAR PsMode, Rate;
PUCHAR pEntryAddr = CliWds_ProxyLookup(pAd, pSrcBufVA);
if (pEntryAddr != NULL) {
pEntry = APSsPsInquiry(pAd, pEntryAddr, &Sst, &Aid, &PsMode, &Rate);
if ((pEntry && (pEntry->Sst == SST_ASSOC)) {
*pWcid = (UCHAR)Aid;
return TRUE;
}
}
}
#endif /* CLIENT_WDS */
}
return FALSE;
}
enum pkt_tx_status{
PKT_SUCCESS = 0,
INVALID_PKT_LEN = 1,
INVALID_TR_WCID = 2,
INVALID_TR_ENTRY = 3,
INVALID_WDEV = 4,
INVALID_ETH_TYPE = 5,
DROP_PORT_SECURE = 6,
DROP_PSQ_FULL = 7,
DROP_TXQ_FULL = 8,
DROP_TX_JAM = 9,
DROP_TXQ_ENQ_FAIL = 10,
};
struct reason_id_str{
INT id;
RTMP_STRING *code_str;
};
/*Nobody uses it currently*/
#if 0
static struct reason_id_str pkt_drop_code[]={
{PKT_SUCCESS, "TxSuccess"},
{INVALID_PKT_LEN, "pkt error"},
{INVALID_TR_WCID, "invalid TR wcid"},
{INVALID_TR_ENTRY, "wrong TR entry type"},
{INVALID_WDEV, "Invalid wdev"},
{INVALID_ETH_TYPE, "ether type check fail"},
{DROP_PORT_SECURE, "port not secure"},
{DROP_PSQ_FULL, "PsQ full"},
{DROP_TXQ_FULL, "TxQ full"},
{DROP_TX_JAM, "Tx jam"},
{DROP_TXQ_ENQ_FAIL, "TxQ EnQ fail"},
};
#endif
/*
========================================================================
Routine Description:
This routine is used to do packet parsing and classification for Tx packet
to AP device, and it will en-queue packets to our TxSwQ depends on AC
class.
Arguments:
pAd Pointer to our adapter
pPacket Pointer to send packet
Return Value:
NDIS_STATUS_SUCCESS If succes to queue the packet into TxSwQ.
NDIS_STATUS_FAILURE If failed to do en-queue.
pre: Before calling this routine, caller should have filled the following fields
pPacket->MiniportReserved[6] - contains packet source
pPacket->MiniportReserved[5] - contains RA's WDS index (if RA on WDS link) or AID
(if RA directly associated to this AP)
post:This routine should decide the remaining pPacket->MiniportReserved[] fields
before calling APHardTransmit(), such as:
pPacket->MiniportReserved[4] - Fragment # and User PRiority
pPacket->MiniportReserved[7] - RTS/CTS-to-self protection method and TX rate
Note:
You only can put OS-indepened & AP related code in here.
========================================================================
*/
INT APSendPacket(RTMP_ADAPTER *pAd, PNDIS_PACKET pPacket)
{
PACKET_INFO PacketInfo;
UCHAR *pSrcBufVA;
UINT SrcBufLen, frag_sz, pkt_len;
UCHAR NumberOfFrag;
UCHAR wcid = RESERVED_WCID, QueIdx = QID_AC_BE, UserPriority;
#ifdef IGMP_SNOOP_SUPPORT
INT InIgmpGroup = IGMP_NONE;
MULTICAST_FILTER_TABLE_ENTRY *pGroupEntry = NULL;
#endif /* IGMP_SNOOP_SUPPORT */
STA_TR_ENTRY *tr_entry = NULL;
struct wifi_dev *wdev;
enum pkt_tx_status drop_reason = PKT_SUCCESS;
INT ret=0;
#ifdef RELEASE_EXCLUDE
DBGPRINT(RT_DEBUG_INFO, ("==>%s()\n", __FUNCTION__));
#endif /* RELEASE_EXCLUDE */
RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
if ((!pSrcBufVA) || (SrcBufLen <= 14)) {
drop_reason = INVALID_PKT_LEN;
goto drop_pkt;
}
wcid = RTMP_GET_PACKET_WCID(pPacket);
DBGPRINT(RT_DEBUG_INFO, ("%s(): wcid=%d\n", __FUNCTION__, wcid));
if (!(VALID_TR_WCID(wcid) && IS_VALID_ENTRY(&pAd->MacTab.tr_entry[wcid]))) {
drop_reason = INVALID_TR_WCID;
goto drop_pkt;
}
tr_entry = &pAd->MacTab.tr_entry[wcid];
if (!tr_entry->wdev) {
drop_reason = INVALID_WDEV;
goto drop_pkt;
}
wdev = tr_entry->wdev;
UserPriority = 0;
QueIdx = QID_AC_BE;
if (RTMPCheckEtherType(pAd, pPacket, tr_entry, wdev, &UserPriority, &QueIdx, &wcid) == FALSE) {
drop_reason = INVALID_ETH_TYPE;
goto drop_pkt;
}
/*add hook point when enqueue*/
RTMP_OS_TXRXHOOK_CALL(WLAN_TX_ENQUEUE,pPacket,QueIdx,pAd);
#ifdef CONFIG_HOTSPOT
/*
Re-check the wcid, it maybe broadcast to unicast by RTMPCheckEtherType.
*/
if (wcid != RTMP_GET_PACKET_WCID(pPacket))
{
wcid = RTMP_GET_PACKET_WCID(pPacket);
//pMacEntry = &pAd->MacTab.Content[wcid];
tr_entry = &pAd->MacTab.tr_entry[wcid];
wdev = tr_entry->wdev;
}
/* Drop broadcast/multicast packet if disable dgaf */
// TODO: shiang-usw, fix me because MCAST_WCID is not used now!
if (IS_ENTRY_CLIENT(tr_entry)) {
BSS_STRUCT *pMbss = (BSS_STRUCT *)wdev->func_dev;
if ((wcid == MCAST_WCID) &&
(pMbss->HotSpotCtrl.HotSpotEnable || pMbss->HotSpotCtrl.bASANEnable) &&
pMbss->HotSpotCtrl.DGAFDisable) {
DBGPRINT(RT_DEBUG_INFO, ("Drop broadcast/multicast packet when dgaf disable\n"));
goto drop_pkt;
}
}
#endif
/* AP does not send packets before port secured */
if (tr_entry->PortSecured == WPA_802_1X_PORT_NOT_SECURED)
{
if (!(((wdev->AuthMode >= Ndis802_11AuthModeWPA) ||
(wdev->AuthMode == Ndis802_11AuthModeOpen) /*for WPS-OPEN connection */
#ifdef DOT1X_SUPPORT
|| (wdev->IEEE8021X == TRUE)
#endif /* DOT1X_SUPPORT */
) && ((RTMP_GET_PACKET_EAPOL(pPacket) ||
RTMP_GET_PACKET_WAI(pPacket))))
)
{
drop_reason = DROP_PORT_SECURE;
goto drop_pkt;
}
}
#ifdef MAC_REPEATER_SUPPORT
if (VALID_WCID(wcid)){
// TODO: shiang-usw, remove pMacEntry here!
MAC_TABLE_ENTRY *pMacEntry = &pAd->MacTab.Content[wcid];
if (pMacEntry->bReptCli)
pMacEntry->ReptCliIdleCount = 0;
}
#endif /* MAC_REPEATER_SUPPORT */
/*
STEP 1. Decide number of fragments required to deliver this MSDU.
The estimation here is not very accurate because difficult to
take encryption overhead into consideration here. The result
"NumberOfFrag" is then just used to pre-check if enough free
TXD are available to hold this MSDU.
The calculated "NumberOfFrag" is a rough estimation because of various
encryption/encapsulation overhead not taken into consideration. This number is just
used to make sure enough free TXD are available before fragmentation takes place.
In case the actual required number of fragments of an NDIS packet
excceeds "NumberOfFrag"caculated here and not enough free TXD available, the
last fragment (i.e. last MPDU) will be dropped in RTMPHardTransmit() due to out of
resource, and the NDIS packet will be indicated NDIS_STATUS_FAILURE. This should
rarely happen and the penalty is just like a TX RETRY fail. Affordable.
exception:
a). fragmentation not allowed on multicast & broadcast
b). Aggregation overwhelms fragmentation (fCLIENT_STATUS_AGGREGATION_CAPABLE)
c). TSO/CSO not do fragmentation
*/
// TODO: shiang-usw. we need to modify the TxPktClassificatio to adjust the NumberOfFrag!
pkt_len = PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H;
frag_sz = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC;
if (pkt_len < frag_sz)
NumberOfFrag = 1;
else
NumberOfFrag = (UCHAR)((pkt_len / frag_sz) + 1);
/* Save fragment number to Ndis packet reserved field */
RTMP_SET_PACKET_FRAGMENTS(pPacket, NumberOfFrag);
#ifdef WMM_ACM_SUPPORT
{
BOOLEAN RTSRequired;
/*
STEP 2. Check the requirement of RTS; decide packet TX rate
If multiple fragment required, RTS is required only for the first fragment
if the fragment size large than RTS threshold
*/
if (NumberOfFrag > 1)
RTSRequired = (pAd->CommonCfg.FragmentThreshold > pAd->CommonCfg.RtsThreshold) ? 1 : 0;
else
RTSRequired = (PacketInfo.TotalPacketLength > pAd->CommonCfg.RtsThreshold) ? 1 : 0;
// TODO: shiang-6590, remove the Rate! For RalinkAgg, we need another way to check it!
{
UCHAR Rate;
if (IS_VALID_ENTRY(tr_entry)) {
Rate = tr_entry->CurrTxRate;
/* RTS/CTS may also be required in order to protect OFDM frame */
if ((Rate >= RATE_FIRST_OFDM_RATE) &&
(Rate <= RATE_LAST_OFDM_RATE) &&
OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
RTSRequired = 1;
RTMP_SET_PACKET_TXRATE(pPacket, Rate);
}
}
// TODO: shiang_dbg, for now only ACM use it!
/* Save RTS requirement to Ndis packet reserved field */
RTMP_SET_PACKET_RTS(pPacket, RTSRequired);
}
#endif /* WMM_ACM_SUPPORT */
/*
3. Put to corrsponding TxSwQ or Power-saving queue
a).WDS/ApClient/Mesh link should never go into power-save mode; just send out the frame
b).multicast packets in IgmpSn table should never send to Power-Saving queue.
c). M/BCAST frames are put to PSQ as long as there's any associated STA in power-save mode
*/
// TODO: shiang-usw, remove "ApCfg.IgmpSnoopEnable" and use "wdev->IgmpSnoopEnable" replace it!
if (tr_entry->EntryType == ENTRY_CAT_MCAST)
{
#ifdef IGMP_SNOOP_SUPPORT
//TODO : check global setting only!
if (pAd->ApCfg.IgmpSnoopEnable /*&& wdev->IgmpSnoopEnable*/)
{
if (IgmpPktInfoQuery(pAd, pSrcBufVA, pPacket, wdev,
&InIgmpGroup, &pGroupEntry) != NDIS_STATUS_SUCCESS)
return NDIS_STATUS_FAILURE;
}
// TODO: shiang-usw, need to revise for Igmp snooping case!!
if (InIgmpGroup)
{
/* if it's a mcast packet in igmp gourp. ucast clone it for all members in the gourp. */
if (((InIgmpGroup == IGMP_IN_GROUP)
&& pGroupEntry
&& (IgmpMemberCnt(&pGroupEntry->MemberList) > 0)
)
|| (InIgmpGroup == IGMP_PKT)
)
{
NDIS_STATUS PktCloneResult = IgmpPktClone(pAd, pPacket, InIgmpGroup, pGroupEntry,
QueIdx, UserPriority, GET_OS_PKT_NETDEV(pPacket));
RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
return PktCloneResult; // need to alway return to prevent skb double free.
}
}
else
#endif /* IGMP_SNOOP_SUPPORT */
{
UserPriority = 0;
QueIdx = QID_AC_BE;
RTMP_SET_PACKET_UP(pPacket, UserPriority);
}
RTMP_SET_PACKET_TXTYPE(pPacket, TX_MCAST_FRAME);
}
else
{
#if defined(RTMP_MAC) || defined(RLT_MAC)
/* detect AC Category of tx packets to tune AC0(BE) TX_OP (MAC reg 0x1300) */
// TODO: shiang-usw, check this for REG access, it should not be here!
if ((pAd->chipCap.hif_type == HIF_RTMP) || (pAd->chipCap.hif_type == HIF_RLT))
detect_wmm_traffic(pAd, UserPriority, 1);
#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */
RTMP_SET_PACKET_UP(pPacket, UserPriority);
#ifdef RTMP_USB_SUPPORT
#ifdef INF_AMAZON_SE
pAd->BulkOutDataSizeCount[QueIdx]+=SrcBufLen;
#endif /* INF_AMAZON_SE */
#endif /* RTMP_USB_SUPPORT */
}
//DBGPRINT(RT_DEBUG_OFF, ("%s(%d): shiang-dbg, QueIdx=%d, tr_entry=%p\n", __FUNCTION__, __LINE__, QueIdx, tr_entry));
if (pAd->TxSwQueue[QueIdx].Number >= pAd->TxSwQMaxLen)
{
#ifdef WMM_ACM_SUPPORT
// TODO: shiang-usw, we need to take care ACM case here!!
/* only for BE traffic & ACM of BE is set */
if (ACMP_BE_IsReallyToReleaseWhenQueFull(
pAd,
pMacEntry,
QueIdx,
pPacket) != ACM_RTN_OK)
{
unsigned long IrqFlags;
/* re-insert to the BE queue */
RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
InsertTailQueue(&tr_entry->tx_queue[QueIdx], PACKET_TO_QUEUE_ENTRY(pPacket));
RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
}
else
#endif /* WMM_ACM_SUPPORT */
{
#ifdef BLOCK_NET_IF
StopNetIfQueue(pAd, QueIdx, pPacket);
#endif /* BLOCK_NET_IF */
drop_reason = DROP_TXQ_FULL;
goto drop_pkt;
}
}
#ifdef WDS_SUPPORT
else if(IS_ENTRY_WDS(tr_entry)) {
/* when WDS Jam happen, drop following 1min to SWQueue Pkts */
ULONG Now32;
NdisGetSystemUpTime(&Now32);
if ((tr_entry->LockEntryTx == TRUE)
&& RTMP_TIME_BEFORE(Now32, tr_entry->TimeStamp_toTxRing + WDS_ENTRY_RETRY_INTERVAL)) {
drop_reason = DROP_TX_JAM;
goto drop_pkt;
} else {
if (rtmp_enq_req(pAd, pPacket, QueIdx, tr_entry, FALSE,NULL) == FALSE) {
drop_reason = DROP_TXQ_ENQ_FAIL;
goto drop_pkt;
}
}
}
#endif /* WDS_SUPPORT */
else
{
#ifdef MT_MAC
if (pAd->chipCap.hif_type == HIF_MT)
{
if ((pAd->MacTab.fAnyStationInPsm == 1) && (tr_entry->EntryType == ENTRY_CAT_MCAST)) {
if (tr_entry->tx_queue[QID_AC_BE].Number > MAX_PACKETS_IN_MCAST_PS_QUEUE) {
DBGPRINT(RT_DEBUG_INFO, ("%s(%d): BSS tx_queue full\n", __FUNCTION__, __LINE__));
drop_reason = DROP_TXQ_ENQ_FAIL;
goto drop_pkt;
}
} else if ((tr_entry->EntryType != ENTRY_CAT_MCAST) && (tr_entry->PsMode == PWR_SAVE)) {
if (tr_entry->tx_queue[QID_AC_BE].Number+tr_entry->tx_queue[QID_AC_BK].Number+tr_entry->tx_queue[QID_AC_VI].Number+tr_entry->tx_queue[QID_AC_VO].Number > MAX_PACKETS_IN_PS_QUEUE) {
DBGPRINT(RT_DEBUG_INFO, ("%s(%d): STA tx_queue full\n", __FUNCTION__, __LINE__));
drop_reason = DROP_TXQ_ENQ_FAIL;
goto drop_pkt;
}
}
}
#endif /* MT_MAC */
#ifdef UAPSD_SUPPORT
if (IS_ENTRY_CLIENT(tr_entry)
&& (tr_entry->PsMode == PWR_SAVE)
&& UAPSD_MR_IS_UAPSD_AC(&pAd->MacTab.Content[wcid], QueIdx))
{
UAPSD_PacketEnqueue(pAd, &pAd->MacTab.Content[wcid], pPacket, QueIdx, FALSE);
}
else
#endif /* UAPSD_SUPPORT */
#ifdef IP_ASSEMBLY
if ((pAd->CommonCfg.BACapability.field.AutoBA == FALSE) && (ret = rtmp_IpAssembleHandle(pAd,tr_entry, pPacket,QueIdx,PacketInfo))!=NDIS_STATUS_INVALID_DATA)
{
if(ret == NDIS_STATUS_FAILURE)
{
goto nofree_drop_pkt;
}
/*else if success do normal path means*/
}else
#endif /* IP_ASSEMBLY */
if (rtmp_enq_req(pAd, pPacket, QueIdx, tr_entry, FALSE,NULL) == FALSE) {
drop_reason = DROP_TXQ_ENQ_FAIL;
goto drop_pkt;
}
/* If the data is broadcast/multicast and any stations are in PWR_SAVE, we set BCAST TIM bit. */
/* If the data is unicast and the station is in PWR_SAVE, we set STA TIM bit */
#if 0
#ifdef MT_MAC
// TODO: shiang-usw, move this to BeaconUpdate!!
if (pAd->chipCap.hif_type == HIF_MT)
{
if (tr_entry->EntryType == ENTRY_CAT_MCAST)
{
if (pAd->MacTab.fAnyStationInPsm == 1)
WLAN_MR_TIM_BCMC_SET(tr_entry->func_tb_idx); /* mark MCAST/BCAST TIM bit */
}
else
{
if (tr_entry->PsMode == PWR_SAVE)
WLAN_MR_TIM_BIT_SET(pAd, tr_entry->func_tb_idx, tr_entry->wcid);
}
}
#endif /* MT_MAC */
#else
if (tr_entry->EntryType == ENTRY_CAT_MCAST)
{
if (pAd->MacTab.fAnyStationInPsm == TRUE)
WLAN_MR_TIM_BCMC_SET(tr_entry->func_tb_idx); /* mark MCAST/BCAST TIM bit */
}
else
{
if (IS_ENTRY_CLIENT(tr_entry) && (tr_entry->PsMode == PWR_SAVE))
{
/* mark corresponding TIM bit in outgoing BEACON frame */
#ifdef UAPSD_SUPPORT
if (UAPSD_MR_IS_NOT_TIM_BIT_NEEDED_HANDLED(&pAd->MacTab.Content[wcid], QueIdx))
{
/*
1. the station is UAPSD station;
2. one of AC is non-UAPSD (legacy) AC;
3. the destinated AC of the packet is UAPSD AC.
*/
/* So we can not set TIM bit due to one of AC is legacy AC */
}
else
#endif /* UAPSD_SUPPORT */
{
WLAN_MR_TIM_BIT_SET(pAd, tr_entry->func_tb_idx, tr_entry->wcid);
}
}
}
#endif
}
//dump_tr_entry(pAd, wcid, __FUNCTION__, __LINE__);
//DBGPRINT(RT_DEBUG_OFF, ("%s(%d): shiang-dbg EnQDone done\n", __FUNCTION__, __LINE__));
// TODO: shiang-usw, backup code here for ACM/WDS->LockTx related functions
#if 0
if (tr_entry->PsMode == PWR_SAVE)
{
UINT max_pkt_cnt;
BOOLEAN mcast = FALSE;
// TODO: shiang-usw, need to unify the MaxPktCnt of ps_queue for MCAST/UCAST
if (tr_entry->EntryType == ENTRY_CAT_MCAST ) {
/*
we don't want too many MCAST/BCAST backlog frames to eat up all buffers.
So in case number of backlog MCAST/BCAST frames exceeds a pre-defined
watermark within a DTIM period, simply drop coming new MCAST/BCAST frames.
This design is similiar to "BROADCAST throttling in most manageable
Ethernet Switch chip.
*/
max_pkt_cnt = MAX_PACKETS_IN_MCAST_PS_QUEUE;
mcast = TRUE;
}
else {
max_pkt_cnt = MAX_PACKETS_IN_PS_QUEUE;
mcast = FALSE;
}
if (mcast == TRUE)
{
if (tr_entry->ps_queue.Number < max_pkt_cnt)
{
RTMP_IRQ_LOCK(&tr_entry->ps_queue_lock, IrqFlags);
InsertHeadQueue(&tr_entry->ps_queue, PACKET_TO_QUEUE_ENTRY(pPacket));
RTMP_IRQ_UNLOCK(&tr_entry->ps_queue_lock, IrqFlags);
WLAN_MR_TIM_BCMC_SET(tr_entry->func_tb_idx); /* mark MCAST/BCAST TIM bit */
#ifdef RELEASE_EXCLUDE
if (tr_entry->func_tb_idx < pAd->ApCfg.BssidNum) {
DBGPRINT(RT_DEBUG_INFO, ("BSS[%d]:at least 1 STA in psm, move M/BCAST to PSQ, TIM bitmap=%08x\n",
tr_entry->func_tb_idx,
pAd->ApCfg.MBSSID[tr_entry->func_tb_idx].TimBitmaps[WLAN_CT_TIM_BCMC_OFFSET]));
}
#endif /* RELEASE_EXCLUDE */
}
else
{
drop_reason = DROP_PSQ_FULL;
goto drop_pkt;
}
}
else
{
/* else if the associted STA in power-save mode, frame also goes to PSQ */
if (APInsertPsQueue(pAd, pPacket, tr_entry, QueIdx) != NDIS_STATUS_SUCCESS)
return NDIS_STATUS_FAILURE;
}
}
else
{
#ifdef DOT11V_WNM_SUPPORT //Haipin:Check this
if (DMSPktInfoQuery(pAd, pSrcBufVA, pPacket, apidx, QueIdx ,UserPriority) != NDIS_STATUS_SUCCESS)
{
return NDIS_STATUS_FAILURE;
}
#endif /* DOT11V_WNM_SUPPORT */
if (pAd->TxSwQueue[QueIdx].Number >= pAd->TxSwQMaxLen)
{
#ifdef WMM_ACM_SUPPORT
/* only for BE traffic & ACM of BE is set */
if (ACMP_BE_IsReallyToReleaseWhenQueFull(
pAd,
pMacEntry,
QueIdx,
pPacket) != ACM_RTN_OK)
{
/* re-insert to the BE queue */
RTMP_IRQ_LOCK(&tr_entry->txq_lock, IrqFlags);
InsertTailQueue(&tr_entry->tx_queue[QueIdx], PACKET_TO_QUEUE_ENTRY(pPacket));
RTMP_IRQ_UNLOCK(&tr_entry->txq_lock, IrqFlags);
}
else
#endif /* WMM_ACM_SUPPORT */
{
#ifdef BLOCK_NET_IF
StopNetIfQueue(pAd, QueIdx, pPacket);
#endif /* BLOCK_NET_IF */
goto drop_pkt;
}
}
#ifdef WDS_SUPPORT
else if(IS_ENTRY_WDS(pMacEntry)) /* when WDS Jam happen, drop following 1min to SWQueue Pkts */
{
ULONG Now32;
NdisGetSystemUpTime(&Now32);
if ((pMacEntry->LockEntryTx == TRUE)
&& RTMP_TIME_BEFORE(Now32, pMacEntry->TimeStamp_toTxRing + WDS_ENTRY_RETRY_INTERVAL)) {
goto drop_pkt;
}
}
#endif /* WDS_SUPPORT */
else
{
RTMP_IRQ_LOCK(&tr_entry->txq_lock, IrqFlags);
InsertTailQueueAc(pAd, pMacEntry, &tr_entry->tx_queue[QueIdx], PACKET_TO_QUEUE_ENTRY(pPacket));
RTMP_IRQ_UNLOCK(&tr_entry->txq_lock, IrqFlags);
rtmp_enq_req(pAd, pPacket, QueIdx, tr_entry->wcid,FALSE,NULL);
}
}
#endif
#ifdef DOT11_N_SUPPORT
RTMP_BASetup(pAd, tr_entry, UserPriority);
#endif /* DOT11_N_SUPPORT */
return NDIS_STATUS_SUCCESS;
drop_pkt:
RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
nofree_drop_pkt:
/*add hook point when drop*/
RTMP_OS_TXRXHOOK_CALL(WLAN_TX_DROP,NULL,QueIdx,pAd);
DBGPRINT(RT_DEBUG_INFO, ("%s():drop pkt, drop_reason=%d!, wcid = %d\n", __FUNCTION__, drop_reason, wcid));
#if 0//def DBG
if (RTDebugFunc & DBG_FUNC_TXQ) {
if ((pSrcBufVA != NULL) && (SrcBufLen > 0)) {
hex_dump("droped_packet", pSrcBufVA, SrcBufLen > 32 ? 32 : SrcBufLen);
}
}
#endif /* DBG */
return NDIS_STATUS_FAILURE;
}
/*
--------------------------------------------------------
FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM
Find the WPA key, either Group or Pairwise Key
LEAP + TKIP also use WPA key.
--------------------------------------------------------
Decide WEP bit and cipher suite to be used.
Same cipher suite should be used for whole fragment burst
In Cisco CCX 2.0 Leap Authentication
WepStatus is Ndis802_11WEPEnabled but the key will use PairwiseKey
Instead of the SharedKey, SharedKey Length may be Zero.
*/
static inline VOID APFindCipherAlgorithm(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk)
{
CIPHER_KEY *pKey = NULL;
UCHAR KeyIdx = 0, CipherAlg = CIPHER_NONE;
UCHAR RAWcid = pTxBlk->Wcid;
MAC_TABLE_ENTRY *pMacEntry = pTxBlk->pMacEntry;
#if defined(APCLI_SUPPORT) && defined(WPA_SUPPLICANT_SUPPORT)
STA_TR_ENTRY *tr_entry = pTxBlk->tr_entry;
#endif /* defined(APCLI_SUPPORT) && defined(WPA_SUPPLICANT_SUPPORT) */
#ifdef WAPI_SUPPORT
BSS_STRUCT *pMbss;
#endif /* WAPI_SUPPORT */
struct wifi_dev *wdev;
ASSERT(pTxBlk->wdev_idx < WDEV_NUM_MAX);
wdev = pAd->wdev_list[pTxBlk->wdev_idx];
ASSERT(wdev->func_idx < pAd->ApCfg.BssidNum);
if ((wdev->func_idx < 0) || (wdev->func_idx >= pAd->ApCfg.BssidNum)) {
DBGPRINT(RT_DEBUG_ERROR, ("%s wrong wdev->func_idx %d BssidNum %u\n",
__func__, wdev->func_idx,
pAd->ApCfg.BssidNum));
return;
}
#ifdef WAPI_SUPPORT
pMbss = &pAd->ApCfg.MBSSID[wdev->func_idx];
#endif /* WAPI_SUPPORT */
// TODO: shiang-usw, we should use this check to replace rest of the codes!
#if 0
if ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame)) ||
(pMacEntry && pMacEntry->current_cipher == NULL))
{
CipherAlg = CIPHER_NONE;
pKey = NULL;
} else {
CipherAlg = pMacEntry->current_cipher->CipherAlg;
pKey = pMacEntry->current_cipher;
}
#endif
/* These EAPoL frames must be clear before 4-way handshaking is completed. */
if ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame)))
{
CipherAlg = CIPHER_NONE;
pKey = NULL;
} else
#ifdef MESH_SUPPORT
if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bMeshEntry)) {
if (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket)) {
if ((pMacEntry->PairwiseKey.CipherAlg) && (pMacEntry->PairwiseKey.KeyLen))
{
CipherAlg = pMacEntry->PairwiseKey.CipherAlg;
pKey = &pMacEntry->PairwiseKey;
} else {
CipherAlg = CIPHER_NONE;
pKey = NULL;
}
} else if (pMacEntry->WepStatus == Ndis802_11WEPEnabled) {
CipherAlg = pAd->MeshTab.SharedKey.CipherAlg;
pKey = &pAd->MeshTab.SharedKey;
} else if (pMacEntry->WepStatus == Ndis802_11TKIPEnable ||
pMacEntry->WepStatus == Ndis802_11AESEnable) {
CipherAlg = pMacEntry->PairwiseKey.CipherAlg;
pKey = &pMacEntry->PairwiseKey;
} else {
CipherAlg = CIPHER_NONE;
pKey = NULL;
}
}
else
#endif /* MESH_SUPPORT */
#ifdef APCLI_SUPPORT
if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bApCliPacket))
{
APCLI_STRUCT *pApCliEntry = pTxBlk->pApCliEntry;
wdev = &pApCliEntry->wdev;
if (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
{
/* These EAPoL frames must be clear before 4-way handshaking is completed. */
if ((pMacEntry->PairwiseKey.CipherAlg) && (pMacEntry->PairwiseKey.KeyLen))
{
CipherAlg = pMacEntry->PairwiseKey.CipherAlg;
pKey = &pMacEntry->PairwiseKey;
}
else
{
CipherAlg = CIPHER_NONE;
pKey = NULL;
}
}
#ifdef WPA_SUPPLICANT_SUPPORT
else if (pApCliEntry->wpa_supplicant_info.WpaSupplicantUP &&
(pMacEntry->WepStatus == Ndis802_11WEPEnabled) &&
(pApCliEntry->wdev.IEEE8021X == TRUE) &&
(tr_entry->PortSecured == WPA_802_1X_PORT_NOT_SECURED))
{
CipherAlg = CIPHER_NONE;
}
#endif /* WPA_SUPPLICANT_SUPPORT */
else if (pMacEntry->WepStatus == Ndis802_11WEPEnabled)
{
CipherAlg = pApCliEntry->SharedKey[wdev->DefaultKeyId].CipherAlg;
pKey = &pApCliEntry->SharedKey[wdev->DefaultKeyId];
}
else if (pMacEntry->WepStatus == Ndis802_11TKIPEnable ||
pMacEntry->WepStatus == Ndis802_11AESEnable)
{
CipherAlg = pMacEntry->PairwiseKey.CipherAlg;
pKey = &pMacEntry->PairwiseKey;
}
else
{
CipherAlg = CIPHER_NONE;
pKey = NULL;
}
}
else
#endif /* APCLI_SUPPORT */
#ifdef WDS_SUPPORT
if (TX_BLK_TEST_FLAG(pTxBlk,fTX_bWDSEntry))
{
wdev = &pAd->WdsTab.WdsEntry[pMacEntry->func_tb_idx].wdev;
if (wdev->WepStatus == Ndis802_11WEPEnabled ||
wdev->WepStatus == Ndis802_11TKIPEnable ||
wdev->WepStatus == Ndis802_11AESEnable)
{
CipherAlg = pAd->WdsTab.WdsEntry[pMacEntry->func_tb_idx].WdsKey.CipherAlg;
pKey = &pAd->WdsTab.WdsEntry[pMacEntry->func_tb_idx].WdsKey;
}
else
{
CipherAlg = CIPHER_NONE;
pKey = NULL;
}
}
else
#endif /* WDS_SUPPORT */
#ifdef WAPI_SUPPORT
if (pMbss->wdev.WepStatus == Ndis802_11EncryptionSMS4Enabled)
{
if (RTMP_GET_PACKET_WAI(pTxBlk->pPacket)) {
/* WAI negotiation packet is always clear. */
CipherAlg = CIPHER_NONE;
pKey = NULL;
}
else if (!pMacEntry)
{
KeyIdx = pMbss->wdev.DefaultKeyId; /* MSK ID */
CipherAlg = pAd->SharedKey[wdev->func_idx][KeyIdx].CipherAlg;
if (CipherAlg == CIPHER_SMS4) {
pKey = &pAd->SharedKey[wdev->func_idx][KeyIdx];
#ifdef SOFT_ENCRYPT
if (pMbss->sw_wpi_encrypt) {
TX_BLK_SET_FLAG(pTxBlk, fTX_bSwEncrypt);
/* TSC increment pre encryption transmittion */
inc_iv_byte(pKey->TxTsc, LEN_WAPI_TSC, 1);
}
#endif /* SOFT_ENCRYPT */
}
}
else
{
KeyIdx = pTxBlk->pMacEntry->usk_id; /* USK ID */
CipherAlg = pAd->MacTab.Content[RAWcid].PairwiseKey.CipherAlg;
if (CipherAlg == CIPHER_SMS4)
{
pKey = &pAd->MacTab.Content[RAWcid].PairwiseKey;
#ifdef SOFT_ENCRYPT
if (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_SOFTWARE_ENCRYPT)) {
TX_BLK_SET_FLAG(pTxBlk, fTX_bSwEncrypt);
/* TSC increment pre encryption transmittion */
inc_iv_byte(pKey->TxTsc, LEN_WAPI_TSC, 2);
}
#endif /* SOFT_ENCRYPT */
}
}
}
else
#endif /* WAPI_SUPPORT */
if ((RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket)) ||
#ifdef DOT1X_SUPPORT
((wdev->WepStatus == Ndis802_11WEPEnabled) && (wdev->IEEE8021X == TRUE)) ||
#endif /* DOT1X_SUPPORT */
(wdev->WepStatus == Ndis802_11TKIPEnable) ||
(wdev->WepStatus == Ndis802_11AESEnable) ||
(wdev->WepStatus == Ndis802_11TKIPAESMix))
{
if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame))
{
DBGPRINT(RT_DEBUG_TRACE,("%s():clear EAP frm\n", __FUNCTION__));
CipherAlg = CIPHER_NONE;
pKey = NULL;
}
else if (!pMacEntry) /* M/BCAST to local BSS, use default key in shared key table */
{
KeyIdx = wdev->DefaultKeyId;
#ifdef P2P_APCLI_SUPPORT
if (P2P_INF_ON(pAd) && P2P_GO_ON(pAd))
CipherAlg = pAd->SharedKey[wdev->func_idx+1][KeyIdx].CipherAlg;
else
#endif /* P2P_APCLI_SUPPORT */
CipherAlg = pAd->SharedKey[wdev->func_idx][KeyIdx].CipherAlg;
pKey = &pAd->SharedKey[wdev->func_idx][KeyIdx];
}
else /* unicast to local BSS */
{
CipherAlg = pAd->MacTab.Content[RAWcid].PairwiseKey.CipherAlg;
pKey = &pAd->MacTab.Content[RAWcid].PairwiseKey;
#ifdef SOFT_ENCRYPT
if (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_SOFTWARE_ENCRYPT))
{
TX_BLK_SET_FLAG(pTxBlk, fTX_bSwEncrypt);
/* TSC increment pre encryption transmittion */
if (pKey == NULL)
DBGPRINT(RT_DEBUG_ERROR, ("%s pKey == NULL!\n", __FUNCTION__));
else
{
INC_TX_TSC(pKey->TxTsc, LEN_WPA_TSC);
}
}
#endif /* SOFT_ENCRYPT */
}
}
else if (wdev->WepStatus == Ndis802_11WEPEnabled) /* WEP always uses shared key table */
{
KeyIdx = wdev->DefaultKeyId;
CipherAlg = pAd->SharedKey[wdev->func_idx][KeyIdx].CipherAlg;
pKey = &pAd->SharedKey[wdev->func_idx][KeyIdx];
}
else
{
CipherAlg = CIPHER_NONE;
pKey = NULL;
}
pTxBlk->CipherAlg = CipherAlg;
if (CipherAlg)
pTxBlk->pKey = pKey;
pTxBlk->KeyIdx = KeyIdx;
}
#ifdef DOT11_N_SUPPORT
static inline VOID APBuildCache802_11Header(
IN RTMP_ADAPTER *pAd,
IN TX_BLK *pTxBlk,
IN UCHAR *pHeader)
{
STA_TR_ENTRY *tr_entry;
HEADER_802_11 *pHeader80211;
#if defined(MESH_SUPPORT) || defined(APCLI_SUPPORT)
MAC_TABLE_ENTRY *pMacEntry = pTxBlk->pMacEntry;
#endif
pHeader80211 = (PHEADER_802_11)pHeader;
tr_entry = pTxBlk->tr_entry;
/*
Update the cached 802.11 HEADER
*/
/* normal wlan header size : 24 octets */
pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
pTxBlk->wifi_hdr_len = sizeof(HEADER_802_11);
/* More Bit */
pHeader80211->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
/* Sequence */
pHeader80211->Sequence = tr_entry->TxSeq[pTxBlk->UserPriority];
tr_entry->TxSeq[pTxBlk->UserPriority] = (tr_entry->TxSeq[pTxBlk->UserPriority] + 1) & MAXSEQ;
/* SA */
#ifdef MESH_SUPPORT
if(IS_ENTRY_MESH(pMacEntry))
{ /* The addr3 of WDS packet is Destination Mac address and Addr4 is the Source Mac address. */
PNDIS_PACKET pPacket = pTxBlk->pPacket;
COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pMeshDA);
if (RTMP_GET_MESH_SOURCE(pPacket) == MESH_PROXY)
COPY_MAC_ADDR(&pHeader80211->Octet[0], pAd->MeshTab.wdev.if_addr);
else
COPY_MAC_ADDR(&pHeader80211->Octet[0], pTxBlk->pSrcBufHeader + MAC_ADDR_LEN);
pTxBlk->MpduHeaderLen += MAC_ADDR_LEN;
pTxBlk->wifi_hdr_len += MAC_ADDR_LEN;
}
else
#endif /* MESH_SUPPORT */
#if defined(WDS_SUPPORT) || defined(CLIENT_WDS)
if (FALSE
#ifdef WDS_SUPPORT
|| TX_BLK_TEST_FLAG(pTxBlk, fTX_bWDSEntry)
#endif /* WDS_SUPPORT */
#ifdef CLIENT_WDS
|| TX_BLK_TEST_FLAG(pTxBlk, fTX_bClientWDSFrame)
#endif /* CLIENT_WDS */
)
{ /* The addr3 of WDS packet is Destination Mac address and Addr4 is the Source Mac address. */
COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pSrcBufHeader);
COPY_MAC_ADDR(pHeader80211->Octet, pTxBlk->pSrcBufHeader + MAC_ADDR_LEN);
pTxBlk->MpduHeaderLen += MAC_ADDR_LEN;
pTxBlk->wifi_hdr_len += MAC_ADDR_LEN;
}
else
#endif /* WDS_SUPPORT || CLIENT_WDS */
#ifdef APCLI_SUPPORT
if(IS_ENTRY_APCLI(pMacEntry))
{ /* The addr3 of Ap-client packet is Destination Mac address. */
COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pSrcBufHeader);
}
else
#endif /* APCLI_SUPPORT */
{ /* The addr3 of normal packet send from DS is Src Mac address. */
COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pSrcBufHeader + MAC_ADDR_LEN);
}
}
#ifdef HDR_TRANS_TX_SUPPORT
static inline VOID APBuildCacheWifiInfo(
IN RTMP_ADAPTER *pAd,
IN TX_BLK *pTxBlk,
IN UCHAR *pWiInfo)
{
STA_TR_ENTRY *tr_entry;
TX_WIFI_INFO *pWI;
pWI = (TX_WIFI_INFO *)pWiInfo;
tr_entry = pTxBlk->tr_entry;
/* WIFI INFO size : 4 octets */
pTxBlk->MpduHeaderLen = TX_WIFI_INFO_SIZE;
/* More Bit */
pWI->field.More_Data = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
/* Sequence */
pWI->field.Seq_Num = tr_entry->TxSeq[pTxBlk->UserPriority];
tr_entry->TxSeq[pTxBlk->UserPriority] = (tr_entry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
}
#endif /* HDR_TRANS_TX_SUPPORT */
#endif /* DOT11_N_SUPPORT */
#ifdef HDR_TRANS_TX_SUPPORT
static inline VOID APBuildWifiInfo(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk)
{
UINT8 TXWISize = pAd->chipCap.TXWISize;
TX_WIFI_INFO *pWI;
STA_TR_ENTRY *tr_entry = pTxBlk->tr_entry;
/* WIFI INFO size : 4 octets */
pTxBlk->MpduHeaderLen = TX_WIFI_INFO_SIZE;
pWI = (TX_WIFI_INFO *)&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWISize];
NdisZeroMemory(pWI, TX_WIFI_INFO_SIZE);
#ifdef APCLI_SUPPORT
if (IS_ENTRY_APCLI(pTxBlk->pMacEntry))
pWI->field.Mode = 2; /* STA */
else
#endif /* APCLI_SUPPORT */
pWI->field.Mode = 1; /* AP */
pWI->field.QoS = (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? 1 : 0;
if (pTxBlk->pMacEntry && tr_entry)
{
if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
{
pWI->field.Seq_Num = tr_entry->TxSeq[pTxBlk->UserPriority];
tr_entry->TxSeq[pTxBlk->UserPriority] = (tr_entry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
} else {
pWI->field.Seq_Num = tr_entry->NonQosDataSeq;
tr_entry->NonQosDataSeq = (tr_entry->NonQosDataSeq+1) & MAXSEQ;
}
pWI->field.BssIdx = pTxBlk->pMacEntry->func_tb_idx;
}
else
{
pWI->field.Seq_Num = pAd->Sequence;
pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; /* next sequence */
}
pWI->field.More_Data = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
#ifdef P2P_SUPPORT
/* To not disturb the Opps test, set psm bit if I use power save mode. */
/* P2P Test case 7.1.3 */
if (P2P_INF_ON(pAd) && P2P_CLI_ON(pAd) &&
(P2P_TEST_BIT(pAd->P2pCfg.CTWindows, P2P_OPPS_BIT ))
&& (pAd->P2pCfg.bP2pCliPmEnable))
pWI->field.PS = 1;
#endif /* P2P_SUPPORT */
if (pTxBlk->CipherAlg != CIPHER_NONE)
pWI->field.WEP = 1;
}
#endif /* HDR_TRANS_TX_SUPPORT */
static inline VOID APBuildCommon802_11Header(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk)
{
HEADER_802_11 *wifi_hdr;
UINT8 tx_hw_hdr_len = pAd->chipCap.tx_hw_hdr_len;
struct wifi_dev *wdev = pAd->wdev_list[pTxBlk->wdev_idx];
STA_TR_ENTRY *tr_entry = pTxBlk->tr_entry;
/*
MAKE A COMMON 802.11 HEADER
*/
/* normal wlan header size : 24 octets */
pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
pTxBlk->wifi_hdr_len = sizeof(HEADER_802_11);
// TODO: shiang-7603
pTxBlk->wifi_hdr = &pTxBlk->HeaderBuf[tx_hw_hdr_len];
wifi_hdr = (HEADER_802_11 *)pTxBlk->wifi_hdr;
NdisZeroMemory(wifi_hdr, sizeof(HEADER_802_11));
wifi_hdr->FC.FrDs = 1;
wifi_hdr->FC.Type = FC_TYPE_DATA;
wifi_hdr->FC.SubType = ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? SUBTYPE_QDATA : SUBTYPE_DATA);
// TODO: shiang-usw, for BCAST/MCAST, original it's sequence assigned by "pAd->Sequence", how about now?
if (tr_entry) {
if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) {
wifi_hdr->Sequence = tr_entry->TxSeq[pTxBlk->UserPriority];
tr_entry->TxSeq[pTxBlk->UserPriority] = (tr_entry->TxSeq[pTxBlk->UserPriority] + 1) & MAXSEQ;
} else {
wifi_hdr->Sequence = tr_entry->NonQosDataSeq;
tr_entry->NonQosDataSeq = (tr_entry->NonQosDataSeq + 1) & MAXSEQ;
}
}
else
{
wifi_hdr->Sequence = pAd->Sequence;
pAd->Sequence = (pAd->Sequence + 1) & MAXSEQ; /* next sequence */
}
wifi_hdr->Frag = 0;
wifi_hdr->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
#ifdef MESH_SUPPORT
if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bMeshEntry))
{
wifi_hdr->FC.ToDs = 1;
COPY_MAC_ADDR(wifi_hdr->Addr1, pTxBlk->pMacEntry->Addr); /* to AP2 */
COPY_MAC_ADDR(wifi_hdr->Addr2, pAd->MeshTab.wdev.if_addr); /* from AP1 */
COPY_MAC_ADDR(wifi_hdr->Addr3, pTxBlk->pMeshDA);
if (RTMP_GET_MESH_SOURCE(pTxBlk->pPacket) == MESH_PROXY)
COPY_MAC_ADDR(&wifi_hdr->Octet[0], pAd->MeshTab.wdev.if_addr);
else
COPY_MAC_ADDR(&wifi_hdr->Octet[0], pTxBlk->pSrcBufHeader + MAC_ADDR_LEN); /* ADDR4 = SA */
pTxBlk->MpduHeaderLen += MAC_ADDR_LEN;
pTxBlk->wifi_hdr_len += MAC_ADDR_LEN;
}
else
#endif /* MESH_SUPPORT */
#ifdef APCLI_SUPPORT
if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bApCliPacket))
{
wifi_hdr->FC.ToDs = 1;
wifi_hdr->FC.FrDs = 0;
COPY_MAC_ADDR(wifi_hdr->Addr1, APCLI_ROOT_BSSID_GET(pAd, pTxBlk->Wcid)); /* to AP2 */
#ifdef MAC_REPEATER_SUPPORT
if (pTxBlk->pMacEntry && (pTxBlk->pMacEntry->bReptCli == TRUE))
COPY_MAC_ADDR(wifi_hdr->Addr2, pTxBlk->pMacEntry->ReptCliAddr);
else
#endif /* MAC_REPEATER_SUPPORT */
COPY_MAC_ADDR(wifi_hdr->Addr2, pTxBlk->pApCliEntry->wdev.if_addr); /* from AP1 */
COPY_MAC_ADDR(wifi_hdr->Addr3, pTxBlk->pSrcBufHeader); /* DA */
}
else
#endif /* APCLI_SUPPORT */
#if defined(WDS_SUPPORT) || defined(CLIENT_WDS)
if (FALSE
#ifdef WDS_SUPPORT
|| TX_BLK_TEST_FLAG(pTxBlk, fTX_bWDSEntry)
#endif /* WDS_SUPPORT */
#ifdef CLIENT_WDS
|| TX_BLK_TEST_FLAG(pTxBlk, fTX_bClientWDSFrame)
#endif /* CLIENT_WDS */
)
{
wifi_hdr->FC.ToDs = 1;
if (pTxBlk->pMacEntry == NULL)
DBGPRINT(RT_DEBUG_ERROR, ("%s pTxBlk->pMacEntry == NULL!\n", __FUNCTION__));
else
COPY_MAC_ADDR(wifi_hdr->Addr1, pTxBlk->pMacEntry->Addr); /* to AP2 */
COPY_MAC_ADDR(wifi_hdr->Addr2, pAd->CurrentAddress); /* from AP1 */
COPY_MAC_ADDR(wifi_hdr->Addr3, pTxBlk->pSrcBufHeader); /* DA */
COPY_MAC_ADDR(&wifi_hdr->Octet[0], pTxBlk->pSrcBufHeader + MAC_ADDR_LEN);/* ADDR4 = SA */
pTxBlk->MpduHeaderLen += MAC_ADDR_LEN;
pTxBlk->wifi_hdr_len += MAC_ADDR_LEN;
}
else
#endif /* WDS_SUPPORT || CLIENT_WDS */
{
/* TODO: how about "MoreData" bit? AP need to set this bit especially for PS-POLL response */
#if defined(IGMP_SNOOP_SUPPORT) || defined(DOT11V_WNM_SUPPORT)
#if 1 //can't check MCAST_WCID to prevent pTxBlk->pMacEntry is NULL
if (pTxBlk->tr_entry->EntryType != ENTRY_CAT_MCAST)
#else
if (pTxBlk->Wcid != MCAST_WCID)
#endif
{
COPY_MAC_ADDR(wifi_hdr->Addr1, pTxBlk->pMacEntry->Addr); /* DA */
}
else
#endif /* defined(IGMP_SNOOP_SUPPORT) || defined(DOT11V_WNM_SUPPORT) */
{
COPY_MAC_ADDR(wifi_hdr->Addr1, pTxBlk->pSrcBufHeader);
}
COPY_MAC_ADDR(wifi_hdr->Addr2, pAd->ApCfg.MBSSID[wdev->func_idx].wdev.bssid); /* BSSID */
COPY_MAC_ADDR(wifi_hdr->Addr3, pTxBlk->pSrcBufHeader + MAC_ADDR_LEN); /* SA */
}
#ifdef P2P_SUPPORT
/* To not disturb the Opps test, set psm bit if I use power save mode. */
/* P2P Test case 7.1.3 */
if (P2P_INF_ON(pAd) && P2P_CLI_ON(pAd) &&
(P2P_TEST_BIT(pAd->P2pCfg.CTWindows, P2P_OPPS_BIT ))
&& (pAd->P2pCfg.bP2pCliPmEnable))
wifi_hdr->FC.PwrMgmt = 1;
#endif /* P2P_SUPPORT */
if (pTxBlk->CipherAlg != CIPHER_NONE)
wifi_hdr->FC.Wep = 1;
}
static inline PUCHAR AP_Build_ARalink_Frame_Header(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk)
{
UCHAR *pHeaderBufPtr, *pTmpHeaderBufPtr;
HEADER_802_11 *wifi_hdr;
PNDIS_PACKET pNextPacket;
UINT32 nextBufLen;
PQUEUE_ENTRY pQEntry;
APFindCipherAlgorithm(pAd, pTxBlk);
APBuildCommon802_11Header(pAd, pTxBlk);
pHeaderBufPtr = pTxBlk->wifi_hdr;
wifi_hdr = (HEADER_802_11 *)pHeaderBufPtr;
/* steal "order" bit to mark "aggregation" */
wifi_hdr->FC.Order = 1;
/* skip common header */
pHeaderBufPtr += pTxBlk->wifi_hdr_len;
if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) {
/* build QOS Control bytes */
*pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
#ifdef UAPSD_SUPPORT
if (CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_APSD_CAPABLE)
#ifdef WDS_SUPPORT
&& (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWDSEntry) == FALSE)
#endif /* WDS_SUPPORT */
)
{
/*
* we can not use bMoreData bit to get EOSP bit because
* maybe bMoreData = 1 & EOSP = 1 when Max SP Length != 0
*/
if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP))
*pHeaderBufPtr |= (1 << 4);
}
#endif /* UAPSD_SUPPORT */
*(pHeaderBufPtr + 1) = 0;
pHeaderBufPtr += 2;
pTxBlk->MpduHeaderLen += 2;
pTxBlk->wifi_hdr_len += 2;
}
/* padding at front of LLC header. LLC header should at 4-bytes aligment. */
pTmpHeaderBufPtr = pHeaderBufPtr;
pHeaderBufPtr = (UCHAR *)ROUND_UP(pHeaderBufPtr, 4);
pTxBlk->HdrPadLen = (UCHAR)(pHeaderBufPtr - pTmpHeaderBufPtr);
/*
For RA Aggregation, put the 2nd MSDU length(extra 2-byte field) after
QOS_CONTROL in little endian format
*/
pQEntry = pTxBlk->TxPacketList.Head;
pNextPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
nextBufLen = GET_OS_PKT_LEN(pNextPacket);
if (RTMP_GET_PACKET_VLAN(pNextPacket))
nextBufLen -= LENGTH_802_1Q;
*pHeaderBufPtr = (UCHAR)nextBufLen & 0xff;
*(pHeaderBufPtr + 1) = (UCHAR)(nextBufLen >> 8);
pHeaderBufPtr += 2;
pTxBlk->MpduHeaderLen += 2;
pTxBlk->wifi_hdr_len += 2;
return pHeaderBufPtr;
}
#ifdef DOT11_N_SUPPORT
static inline BOOLEAN BuildHtcField(
IN RTMP_ADAPTER *pAd,
IN TX_BLK *pTxBlk,
IN MAC_TABLE_ENTRY *pMacEntry,
IN PUCHAR pHeaderBufPtr)
{
BOOLEAN bHTCPlus = FALSE;
#if 0 /* def TXBF_SUPPORT */
HT_CONTROL *pHTCtrlField;
if (pTxBlk->pMacEntry)
{
pTxBlk->TxSndgPkt = SNDG_TYPE_DISABLE;
NdisAcquireSpinLock(&pMacEntry->TxSndgLock);
if (pMacEntry->TxSndgType >= SNDG_TYPE_SOUNDING)
{
NdisZeroMemory(pHeaderBufPtr, 4);
if (pMacEntry->TxSndgType == SNDG_TYPE_SOUNDING)
{
/* Select compress if supported. Otherwise select noncompress */
if (pAd->CommonCfg.ETxBfNoncompress==0 &&
(pMacEntry->HTCapability.TxBFCap.ExpComBF>0) )
*(pHeaderBufPtr+2) |= 0xC0;
else
*(pHeaderBufPtr+2) |= 0x80;
}
else if (pMacEntry->TxSndgType == SNDG_TYPE_NDP)
{
/* Select compress if supported. Otherwise select noncompress */
if (pAd->CommonCfg.ETxBfNoncompress==0 &&
(pMacEntry->HTCapability.TxBFCap.ExpComBF>0) &&
(pMacEntry->HTCapability.TxBFCap.ComSteerBFAntSup >= (pMacEntry->sndgMcs/8))
)
*(pHeaderBufPtr+2) |= 0xC0;
else
*(pHeaderBufPtr+2) |= 0x80;
/* Set NDP Announcement */
*(pHeaderBufPtr+3) |= 0x01;
pTxBlk->TxNDPSndgBW = pMacEntry->sndgBW;
pTxBlk->TxNDPSndgMcs = pMacEntry->sndgMcs;
}
pTxBlk->TxSndgPkt = pMacEntry->TxSndgType;
/* arvin add for julian request send NDP */
pMacEntry->TxSndgType = SNDG_TYPE_DISABLE;
bHTCPlus = TRUE;
}
NdisReleaseSpinLock(&pMacEntry->TxSndgLock);
#ifdef MFB_SUPPORT
#if defined(MRQ_FORCE_TX) /* have to replace this by the correct condition!!! */
pMacEntry->HTCapability.ExtHtCapInfo.MCSFeedback = MCSFBK_MRQ;
#endif
/*
Ignore sounding frame because the signal format of sounding frmae may
be different from normal data frame, which may result in different MFB
*/
if ((pMacEntry->HTCapability.ExtHtCapInfo.MCSFeedback >=MCSFBK_MRQ) &&
(pTxBlk->TxSndgPkt == SNDG_TYPE_DISABLE))
{
if (bHTCPlus == FALSE)
{
bHTCPlus = TRUE;
NdisZeroMemory(pHeaderBufPtr, 4);
}
MFB_PerPareMRQ(pAd, pHeaderBufPtr, pMacEntry);
}
if (pAd->CommonCfg.HtCapability.ExtHtCapInfo.MCSFeedback >=MCSFBK_MRQ && pMacEntry->toTxMfb == 1)
{
if (bHTCPlus == FALSE)
{
NdisZeroMemory(pHeaderBufPtr, 4);
bHTCPlus = TRUE;
}
MFB_PerPareMFB(pAd, pHeaderBufPtr, pMacEntry);/* not complete yet!!! */
pMacEntry->toTxMfb = 0;
}
#endif /* MFB_SUPPORT */
}
#endif /* TXBF_SUPPORT */
return bHTCPlus;
}
static inline PUCHAR AP_Build_AMSDU_Frame_Header(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk)
{
UCHAR *buf_ptr, *tmp_buf_ptr;
HEADER_802_11 *wifi_hdr;
APFindCipherAlgorithm(pAd, pTxBlk);
APBuildCommon802_11Header(pAd, pTxBlk);
buf_ptr = pTxBlk->wifi_hdr;
wifi_hdr = (HEADER_802_11 *)buf_ptr;
if(wifi_hdr == NULL)
DBGPRINT(RT_DEBUG_TRACE, ("wifi_hdr is NULL.\n"));
/* skip common header */
buf_ptr += pTxBlk->wifi_hdr_len;
/* build QOS Control bytes */
*buf_ptr = (pTxBlk->UserPriority & 0x0F);
#ifdef UAPSD_SUPPORT
if (CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_APSD_CAPABLE)
#ifdef WDS_SUPPORT
&& (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWDSEntry) == FALSE)
#endif /* WDS_SUPPORT */
)
{
/*
* we can not use bMoreData bit to get EOSP bit because
* maybe bMoreData = 1 & EOSP = 1 when Max SP Length != 0
*/
if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP))
*buf_ptr |= (1 << 4);
}
#endif /* UAPSD_SUPPORT */
/* A-MSDU packet */
*buf_ptr |= 0x80;
*(buf_ptr + 1) = 0;
buf_ptr += 2;
pTxBlk->MpduHeaderLen += 2;
pTxBlk->wifi_hdr_len += 2;
#ifdef TXBF_SUPPORT
if (pTxBlk->pMacEntry && pAd->chipCap.FlgHwTxBfCap)
{
MAC_TABLE_ENTRY *pMacEntry = pTxBlk->pMacEntry;
BOOLEAN bHTCPlus = FALSE;
pTxBlk->TxSndgPkt = SNDG_TYPE_DISABLE;
// TODO: shiang-lock, fix ME!
NdisAcquireSpinLock(&pMacEntry->TxSndgLock);
if (pMacEntry->TxSndgType >= SNDG_TYPE_SOUNDING)
{
NdisZeroMemory(buf_ptr, sizeof(HT_CONTROL));
if (pMacEntry->TxSndgType == SNDG_TYPE_SOUNDING)
{
/* Select compress if supported. Otherwise select noncompress */
if ((pAd->CommonCfg.ETxBfNoncompress == 0) &&
(pMacEntry->HTCapability.TxBFCap.ExpComBF > 0))
((PHT_CONTROL)buf_ptr)->CSISTEERING = 3;
else
((PHT_CONTROL)buf_ptr)->CSISTEERING = 2;
/* Clear NDP Announcement */
((PHT_CONTROL)pHeaderBufPtr)->NDPAnnounce = 0;
}
else if (pMacEntry->TxSndgType == SNDG_TYPE_NDP)
{
/* Select compress if supported. Otherwise select noncompress */
if ((pAd->CommonCfg.ETxBfNoncompress == 0) &&
(pMacEntry->HTCapability.TxBFCap.ExpComBF > 0) &&
(pMacEntry->HTCapability.TxBFCap.ComSteerBFAntSup >= (pMacEntry->sndgMcs / 8))
)
((PHT_CONTROL)buf_ptr)->CSISTEERING = 3;
else
((PHT_CONTROL)buf_ptr)->CSISTEERING = 2;
/* Set NDP Announcement */
((PHT_CONTROL)buf_ptr)->NDPAnnounce = 1;
pTxBlk->TxNDPSndgBW = pMacEntry->sndgBW;
pTxBlk->TxNDPSndgMcs = pMacEntry->sndgMcs;
}
pTxBlk->TxSndgPkt = pMacEntry->TxSndgType;
/* arvin add for julian request send NDP */
pMacEntry->TxSndgType = SNDG_TYPE_DISABLE;
bHTCPlus = TRUE;
}
NdisReleaseSpinLock(&pMacEntry->TxSndgLock);
#ifdef MFB_SUPPORT
#if defined(MRQ_FORCE_TX) /* have to replace this by the correct condition!!! */
pMacEntry->HTCapability.ExtHtCapInfo.MCSFeedback = MCSFBK_MRQ;
#endif
/*
Ignore sounding frame because the signal format of sounding frmae may
be different from normal data frame, which may result in different MFB
*/
if ((pMacEntry->HTCapability.ExtHtCapInfo.MCSFeedback >=MCSFBK_MRQ) &&
(pTxBlk->TxSndgPkt == SNDG_TYPE_DISABLE))
{
if (bHTCPlus == FALSE)
{
bHTCPlus = TRUE;
NdisZeroMemory(buf_ptr, sizeof(HT_CONTROL));
}
MFB_PerPareMRQ(pAd, buf_ptr, pMacEntry);
}
if (pAd->CommonCfg.HtCapability.ExtHtCapInfo.MCSFeedback >=MCSFBK_MRQ && pMacEntry->toTxMfb == 1)
{
if (bHTCPlus == FALSE)
{
NdisZeroMemory(buf_ptr, sizeof(HT_CONTROL));
bHTCPlus = TRUE;
}
MFB_PerPareMFB(pAd, buf_ptr, pMacEntry); /* not complete yet!!! */
pMacEntry->toTxMfb = 0;
}
#endif /* MFB_SUPPORT */
if (bHTCPlus == TRUE)
{
wifi_hdr->FC.Order = 1;
buf_ptr += 4;
pTxBlk->MpduHeaderLen += 4;
pTxBlk->wifi_hdr_len += 4;
}
}
#endif /* TXBF_SUPPORT */
/*
padding at front of LLC header
LLC header should locate at 4-octets aligment
@@@ MpduHeaderLen excluding padding @@@
*/
tmp_buf_ptr = buf_ptr;
buf_ptr = (UCHAR *)(ROUND_UP(buf_ptr, 4));
pTxBlk->HdrPadLen = (UCHAR)(buf_ptr - tmp_buf_ptr);
return buf_ptr;
}
VOID AP_AMPDU_Frame_Tx(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk)
{
HEADER_802_11 *wifi_hdr;
UCHAR *pHeaderBufPtr, *src_ptr, *pTmpHeaderBufPtr;
USHORT freeCnt = 1;
BOOLEAN bVLANPkt;
MAC_TABLE_ENTRY *pMacEntry;
STA_TR_ENTRY *tr_entry;
PQUEUE_ENTRY pQEntry;
BOOLEAN bHTCPlus = FALSE;
UINT hdr_offset, cache_sz;
ASSERT(pTxBlk);
pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) {
#ifdef STATS_COUNT_SUPPORT
BSS_STRUCT *pMbss = pTxBlk->pMbss;
if (pMbss != NULL)
pMbss->TxDropCount++;
#endif /* STATS_COUNT_SUPPORT */
RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
return;
}
#if defined(MT7603) || defined(MT7628)
// TODO: shiang-7603
hdr_offset = pAd->chipCap.tx_hw_hdr_len;
#else
hdr_offset = TXINFO_SIZE + pAd->chipCap.TXWISize + TSO_SIZE;
#endif /* defined(MT7603) || defined(MT7628) */
pMacEntry = pTxBlk->pMacEntry;
tr_entry = pTxBlk->tr_entry;
if ((tr_entry->isCached)
#ifdef TXBF_SUPPORT
&& (pMacEntry->TxSndgType == SNDG_TYPE_DISABLE)
#endif /* TXBF_SUPPORT */
)
{
#if defined(MT7603) || defined(MT7628)
#ifndef VENDOR_FEATURE1_SUPPORT
NdisMoveMemory((UCHAR *)(&pTxBlk->HeaderBuf[0]),
(UCHAR *)(&tr_entry->CachedBuf[0]),
pAd->chipCap.tx_hw_hdr_len + sizeof(HEADER_802_11));
#else
pTxBlk->HeaderBuf = (UCHAR *)(tr_entry->HeaderBuf);
#endif /* VENDOR_FEATURE1_SUPPORT */
#else
#ifndef VENDOR_FEATURE1_SUPPORT
NdisMoveMemory((UCHAR *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]),
(UCHAR *)(&tr_entry->CachedBuf[0]),
pAd->chipCap.TXWISize + sizeof(HEADER_802_11));
#else
pTxBlk->HeaderBuf = (UCHAR *)(tr_entry->HeaderBuf);
#endif /* VENDOR_FEATURE1_SUPPORT */
#endif /* defined(MT7603) || defined(MT7628) */
pHeaderBufPtr = (UCHAR *)(&pTxBlk->HeaderBuf[hdr_offset]);
APBuildCache802_11Header(pAd, pTxBlk, pHeaderBufPtr);
#ifdef SOFT_ENCRYPT
RTMPUpdateSwCacheCipherInfo(pAd, pTxBlk, pHeaderBufPtr);
#endif /* SOFT_ENCRYPT */
}
else
{
APFindCipherAlgorithm(pAd, pTxBlk);
APBuildCommon802_11Header(pAd, pTxBlk);
pHeaderBufPtr = &pTxBlk->HeaderBuf[hdr_offset];
}
#ifdef SOFT_ENCRYPT
if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt)) {
if (RTMPExpandPacketForSwEncrypt(pAd, pTxBlk) == FALSE) {
RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
return;
}
}
#endif /* SOFT_ENCRYPT */
wifi_hdr = (HEADER_802_11 *)pHeaderBufPtr;
//+++Add by shiang for debug
#if 0
DBGPRINT(RT_DEBUG_OFF, ("%s():wifi_hdr=%p, tr_entry->isCached=%d, hdr_offset=%d\n",
__FUNCTION__, pTxBlk->wifi_hdr, tr_entry->isCached, hdr_offset));
hex_dump("AMPDU HeaderBufPtr", pHeaderBufPtr, pTxBlk->wifi_hdr_len);
#endif
//---Add by shiang for debug
/* skip common header */
pHeaderBufPtr += pTxBlk->MpduHeaderLen;
#ifdef VENDOR_FEATURE1_SUPPORT
if (tr_entry->isCached
&& (tr_entry->Protocol == (RTMP_GET_PACKET_PROTOCOL(pTxBlk->pPacket)))
#ifdef MESH_SUPPORT
&& !TX_BLK_TEST_FLAG(pTxBlk, fTX_bMeshEntry)
#endif /* MESH_SUPPORT */
#ifdef SOFT_ENCRYPT
&& !TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt)
#endif /* SOFT_ENCRYPT */
#ifdef TXBF_SUPPORT
&& (pMacEntry->TxSndgType == SNDG_TYPE_DISABLE)
#endif /* TXBF_SUPPORT */
)
{
/* build QOS Control bytes */
*pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
#ifdef UAPSD_SUPPORT
if (CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_APSD_CAPABLE)
#ifdef WDS_SUPPORT
&& (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWDSEntry) == FALSE)
#endif /* WDS_SUPPORT */
#ifdef MESH_SUPPORT
&& (TX_BLK_TEST_FLAG(pTxBlk, fTX_bMeshEntry) == FALSE)
#endif /* MESH_SUPPORT */
)
{
/*
* we can not use bMoreData bit to get EOSP bit because
* maybe bMoreData = 1 & EOSP = 1 when Max SP Length != 0
*/
if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP))
*pHeaderBufPtr |= (1 << 4);
}
#endif /* UAPSD_SUPPORT */
pTxBlk->MpduHeaderLen = tr_entry->MpduHeaderLen;
pTxBlk->wifi_hdr_len = tr_entry->wifi_hdr_len;
pHeaderBufPtr = ((UCHAR *)wifi_hdr) + pTxBlk->MpduHeaderLen;
pTxBlk->HdrPadLen = tr_entry->HdrPadLen;
/* skip 802.3 header */
pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
pTxBlk->SrcBufLen -= LENGTH_802_3;
/* skip vlan tag */
bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
if (bVLANPkt) {
pTxBlk->pSrcBufData += LENGTH_802_1Q;
pTxBlk->SrcBufLen -= LENGTH_802_1Q;
}
}
else
#endif /* VENDOR_FEATURE1_SUPPORT */
{
/* build QOS Control bytes */
*pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
#ifdef UAPSD_SUPPORT
if (CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_APSD_CAPABLE)
#ifdef WDS_SUPPORT
&& (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWDSEntry) == FALSE)
#endif /* WDS_SUPPORT */
#ifdef MESH_SUPPORT
&& (TX_BLK_TEST_FLAG(pTxBlk, fTX_bMeshEntry) == FALSE)
#endif /* MESH_SUPPORT */
)
{
/*
* we can not use bMoreData bit to get EOSP bit because
* maybe bMoreData = 1 & EOSP = 1 when Max SP Length != 0
*/
if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP))
*pHeaderBufPtr |= (1 << 4);
}
#endif /* UAPSD_SUPPORT */
*(pHeaderBufPtr + 1) = 0;
pHeaderBufPtr += 2;
pTxBlk->MpduHeaderLen += 2;
pTxBlk->wifi_hdr_len += 2;
#ifndef MT_MAC
// TODO: Shiang-usw, we need a more proper way to handle this instead of ifndef MT_MAC !
/* For MT_MAC, SW not to prepare the HTC field for RDG enable */
/* build HTC control field after QoS field */
if ((pAd->CommonCfg.bRdg == TRUE)
&& (CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_RDG_CAPABLE))
#ifdef TXBF_SUPPORT
&& (pMacEntry->TxSndgType != SNDG_TYPE_NDP)
#endif /* TXBF_SUPPORT */
)
{
NdisZeroMemory(pHeaderBufPtr, sizeof(HT_CONTROL));
((PHT_CONTROL)pHeaderBufPtr)->RDG = 1;
bHTCPlus = TRUE;
}
#endif /* MT_MAC */
#ifdef TXBF_SUPPORT
if (pAd->chipCap.FlgHwTxBfCap)
{
pTxBlk->TxSndgPkt = SNDG_TYPE_DISABLE;
// TODO: shiang-lock, fix ME!!
NdisAcquireSpinLock(&pMacEntry->TxSndgLock);
if (pMacEntry->TxSndgType >= SNDG_TYPE_SOUNDING)
{
if (bHTCPlus == FALSE)
{
NdisZeroMemory(pHeaderBufPtr, sizeof(HT_CONTROL));
bHTCPlus = TRUE;
}
if (pMacEntry->TxSndgType == SNDG_TYPE_SOUNDING)
{
/* Select compress if supported. Otherwise select noncompress */
if ((pAd->CommonCfg.ETxBfNoncompress==0) &&
(pMacEntry->HTCapability.TxBFCap.ExpComBF>0))
((PHT_CONTROL)pHeaderBufPtr)->CSISTEERING = 3;
else
((PHT_CONTROL)pHeaderBufPtr)->CSISTEERING = 2;
/* Clear NDP Announcement */
((PHT_CONTROL)pHeaderBufPtr)->NDPAnnounce = 0;
}
else if (pMacEntry->TxSndgType == SNDG_TYPE_NDP)
{
/* Select compress if supported. Otherwise select noncompress */
if ((pAd->CommonCfg.ETxBfNoncompress == 0) &&
(pMacEntry->HTCapability.TxBFCap.ExpComBF>0) &&
(pMacEntry->HTCapability.TxBFCap.ComSteerBFAntSup >= (pMacEntry->sndgMcs/8))
)
((PHT_CONTROL)pHeaderBufPtr)->CSISTEERING = 3;
else
((PHT_CONTROL)pHeaderBufPtr)->CSISTEERING = 2;
/* Set NDP Announcement */
((PHT_CONTROL)pHeaderBufPtr)->NDPAnnounce = 1;
pTxBlk->TxNDPSndgBW = pMacEntry->sndgBW;
pTxBlk->TxNDPSndgMcs = pMacEntry->sndgMcs;
}
pTxBlk->TxSndgPkt = pMacEntry->TxSndgType;
pMacEntry->TxSndgType = SNDG_TYPE_DISABLE;
}
NdisReleaseSpinLock(&pMacEntry->TxSndgLock);
#ifdef MFB_SUPPORT
#if defined(MRQ_FORCE_TX)
/* have to replace this by the correct condition!!! */
pMacEntry->HTCapability.ExtHtCapInfo.MCSFeedback = MCSFBK_MRQ;
#endif
/*
Ignore sounding frame because the signal format of sounding frmae may
be different from normal data frame, which may result in different MFB
*/
if ((pMacEntry->HTCapability.ExtHtCapInfo.MCSFeedback >=MCSFBK_MRQ) &&
(pTxBlk->TxSndgPkt == SNDG_TYPE_DISABLE))
{
if (bHTCPlus == FALSE)
{
NdisZeroMemory(pHeaderBufPtr, sizeof(HT_CONTROL));
bHTCPlus = TRUE;
}
MFB_PerPareMRQ(pAd, pHeaderBufPtr, pMacEntry);
}
if (pAd->CommonCfg.HtCapability.ExtHtCapInfo.MCSFeedback >=MCSFBK_MRQ &&
pMacEntry->toTxMfb == 1)
{
if (bHTCPlus == FALSE)
{
NdisZeroMemory(pHeaderBufPtr, sizeof(HT_CONTROL));
bHTCPlus = TRUE;
}
MFB_PerPareMFB(pAd, pHeaderBufPtr, pMacEntry);/* not complete yet!!! */
pMacEntry->toTxMfb = 0;
}
#endif /* MFB_SUPPORT */
}
#endif /* TXBF_SUPPORT */
if (bHTCPlus == TRUE)
{
wifi_hdr->FC.Order = 1;
pHeaderBufPtr += 4;
pTxBlk->MpduHeaderLen += 4;
pTxBlk->wifi_hdr_len += 4;
}
/*pTxBlk->MpduHeaderLen = pHeaderBufPtr - pTxBlk->HeaderBuf - TXWI_SIZE - TXINFO_SIZE; */
ASSERT(pTxBlk->MpduHeaderLen >= 24);
/* skip 802.3 header */
pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
pTxBlk->SrcBufLen -= LENGTH_802_3;
/* skip vlan tag */
if (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket))
{
pTxBlk->pSrcBufData += LENGTH_802_1Q;
pTxBlk->SrcBufLen -= LENGTH_802_1Q;
}
/*
padding at front of LLC header
LLC header should locate at 4-octets aligment
@@@ MpduHeaderLen excluding padding @@@
*/
pTmpHeaderBufPtr = pHeaderBufPtr;
pHeaderBufPtr = (UCHAR *)ROUND_UP(pHeaderBufPtr, 4);
pTxBlk->HdrPadLen = (UCHAR)(pHeaderBufPtr - pTmpHeaderBufPtr);
#ifdef VENDOR_FEATURE1_SUPPORT
tr_entry->HdrPadLen = pTxBlk->HdrPadLen;
#endif /* VENDOR_FEATURE1_SUPPORT */
#ifdef SOFT_ENCRYPT
if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt)) {
tx_sw_encrypt(pAd, pTxBlk, pHeaderBufPtr, wifi_hdr);
}
else
#endif /* SOFT_ENCRYPT */
{
#ifdef MESH_SUPPORT
if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bMeshEntry))
InsertPktMeshHeader(pAd, pTxBlk, &pHeaderBufPtr);
#endif /* MESH_SUPPORT */
/*
Insert LLC-SNAP encapsulation - 8 octets
if original Ethernet frame contains no LLC/SNAP,
then an extra LLC/SNAP encap is required
*/
EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData - 2, pTxBlk->pExtraLlcSnapEncap);
if (pTxBlk->pExtraLlcSnapEncap) {
NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
pHeaderBufPtr += 6;
/* get 2 octets (TypeofLen) */
NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData - 2, 2);
pHeaderBufPtr += 2;
pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
}
}
#ifdef VENDOR_FEATURE1_SUPPORT
tr_entry->Protocol = RTMP_GET_PACKET_PROTOCOL(pTxBlk->pPacket);
tr_entry->MpduHeaderLen = pTxBlk->MpduHeaderLen;
tr_entry->wifi_hdr_len = pTxBlk->wifi_hdr_len;
#endif /* VENDOR_FEATURE1_SUPPORT */
}
if ((tr_entry->isCached)
#ifdef TXBF_SUPPORT
&& (pTxBlk->TxSndgPkt == SNDG_TYPE_DISABLE)
#endif /* TXBF_SUPPORT */
)
{
write_tmac_info_Cache(pAd, &pTxBlk->HeaderBuf[0], pTxBlk);
}
else
{
write_tmac_info_Data(pAd, &pTxBlk->HeaderBuf[0], pTxBlk);
if (RTMP_GET_PACKET_LOWRATE(pTxBlk->pPacket))
tr_entry->isCached = FALSE;
#ifdef CONFIG_TSO_SUPPORT
// TODO: shiang-6590, the pTxBlk->MpduHeaderLen is not correct for tso_info
rlt_tso_info_write(pAd, (TSO_INFO *)(&pTxBlk->HeaderBuf[TXINFO_SIZE + pAd->chipCap.TXWISize]), pTxBlk, pTxBlk->MpduHeaderLen);
#endif /* CONFIG_TSO_SUPPORT */
NdisZeroMemory((UCHAR *)(&tr_entry->CachedBuf[0]), sizeof(tr_entry->CachedBuf));
#if defined(MT7603) || defined(MT7628)
cache_sz = (pHeaderBufPtr - (UCHAR *)(&pTxBlk->HeaderBuf[0]));
src_ptr = (UCHAR *)&pTxBlk->HeaderBuf[0];
#else
cache_sz = (pHeaderBufPtr - (UCHAR *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]));
src_ptr = (UCHAR *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]);
#endif /* defined(MT7603) || defined(MT7628) */
NdisMoveMemory((UCHAR *)(&tr_entry->CachedBuf[0]), src_ptr, cache_sz);
#ifdef VENDOR_FEATURE1_SUPPORT
/* use space to get performance enhancement */
NdisZeroMemory((UCHAR *)(&tr_entry->HeaderBuf[0]), sizeof(tr_entry->HeaderBuf));
#if defined(MT7603) || defined(MT7628)
NdisMoveMemory((UCHAR *)(&tr_entry->HeaderBuf[0]),
(UCHAR *)(&pTxBlk->HeaderBuf[0]), cache_sz);
#else
NdisMoveMemory((UCHAR *)(&tr_entry->HeaderBuf[0]),
(UCHAR *)(&pTxBlk->HeaderBuf[0]),
(pHeaderBufPtr - (UCHAR *)(&pTxBlk->HeaderBuf[0])));
#endif /* defined(MT7603) || defined(MT7628) */
#endif /* VENDOR_FEATURE1_SUPPORT */
//+++Mark by shiang test
// tr_entry->isCached = TRUE;
//---Mark by shiang for test
}
//+++Add by shiang for debug
#if defined(MT7603) || defined(MT7628)
#if 0
hex_dump("AMPDU_Frame-FirstBufContent", pTxBlk->HeaderBuf, 128);
hex_dump("AMPDU_Frame-FirstBufContent - WiFi Hdr Segment", pTxBlk->wifi_hdr, pTxBlk->wifi_hdr_len);
DBGPRINT(RT_DEBUG_OFF, ("%s(): pTxBlk->MpduHeaderLen=%d, wifi_hdr_len=%d, HdrPadLen=%d, hw_rsv_len=%d\n",
__FUNCTION__, pTxBlk->MpduHeaderLen, pTxBlk->wifi_hdr_len, pTxBlk->HdrPadLen, pTxBlk->hw_rsv_len));
dump_tmac_info(pAd, &pTxBlk->HeaderBuf[pTxBlk->hw_rsv_len]);
#endif
#endif /* MT7603 */
//---Add by shiang for debug
#ifdef TXBF_SUPPORT
if (pTxBlk->TxSndgPkt != SNDG_TYPE_DISABLE)
tr_entry->isCached = FALSE;
#endif /* TXBF_SUPPORT */
#ifdef STATS_COUNT_SUPPORT
pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.LowPart++;
pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.QuadPart += pTxBlk->SrcBufLen;
/* calculate Tx count and ByteCount per BSS */
#ifdef WAPI_SUPPORT
if (IS_ENTRY_CLIENT(pMacEntry))
#endif /* WAPI_SUPPORT */
{
BSS_STRUCT *pMbss = pTxBlk->pMbss;
#ifdef WAPI_SUPPORT
if (pMacEntry->WapiUskRekeyTimerRunning &&
pAd->CommonCfg.wapi_usk_rekey_method == REKEY_METHOD_PKT)
pMacEntry->wapi_usk_rekey_cnt += pTxBlk->SrcBufLen;
#endif /* WAPI_SUPPORT */
if (pMbss != NULL)
{
pMbss->TransmittedByteCount += pTxBlk->SrcBufLen;
pMbss->TxCount ++;
#ifdef STATS_COUNT_SUPPORT
if(IS_MULTICAST_MAC_ADDR(pTxBlk->pSrcBufHeader))
pMbss->mcPktsTx++;
else if(IS_BROADCAST_MAC_ADDR(pTxBlk->pSrcBufHeader))
pMbss->bcPktsTx++;
else
pMbss->ucPktsTx++;
#endif /* STATS_COUNT_SUPPORT */
}
if(pMacEntry->Sst == SST_ASSOC)
{
INC_COUNTER64(pMacEntry->TxPackets);
pMacEntry->TxBytes+=pTxBlk->SrcBufLen;
pAd->TxTotalByteCnt += pTxBlk->SrcBufLen;
}
}
#ifdef WDS_SUPPORT
if (pMacEntry && IS_ENTRY_WDS(pMacEntry))
{
INC_COUNTER64(pAd->WdsTab.WdsEntry[pMacEntry->func_tb_idx].WdsCounter.TransmittedFragmentCount);
pAd->WdsTab.WdsEntry[pMacEntry->func_tb_idx].WdsCounter.TransmittedByteCount+= pTxBlk->SrcBufLen;
}
#endif /* WDS_SUPPORT */
#endif /* STATS_COUNT_SUPPORT */
HAL_WriteTxResource(pAd, pTxBlk, TRUE, &freeCnt);
#ifdef SMART_ANTENNA
if (pMacEntry)
pMacEntry->saTxCnt++;
#endif /* SMART_ANTENNA */
#ifdef DBG_CTRL_SUPPORT
#ifdef INCLUDE_DEBUG_QUEUE
if (pAd->CommonCfg.DebugFlags & DBF_DBQ_TXFRAME)
dbQueueEnqueueTxFrame((UCHAR *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (UCHAR *)wifi_hdr);
#endif /* INCLUDE_DEBUG_QUEUE */
#endif /* DBG_CTRL_SUPPORT */
/*
Kick out Tx
*/
HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
pAd->RalinkCounters.KickTxCount++;
pAd->RalinkCounters.OneSecTxDoneCount++;
}
#ifdef HDR_TRANS_TX_SUPPORT
VOID AP_AMPDU_Frame_Tx_Hdr_Trns(
IN PRTMP_ADAPTER pAd,
IN TX_BLK *pTxBlk)
{
PUCHAR pWiBufPtr;
USHORT FreeNumber = 1; /* no use */
MAC_TABLE_ENTRY *pMacEntry;
STA_TR_ENTRY *tr_entry;
PQUEUE_ENTRY pQEntry;
UINT8 TXWISize = pAd->chipCap.TXWISize;
TX_WIFI_INFO *pWI;
ASSERT(pTxBlk);
pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
{
#ifdef STATS_COUNT_SUPPORT
BSS_STRUCT *pMbss = pTxBlk->pMbss;
if (pMbss != NULL)
pMbss->TxDropCount ++;
#endif /* STATS_COUNT_SUPPORT */
RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
return;
}
/*
if ( pAd->debug_on )
{
UCHAR index = RTMP_GET_DEBUG_INDEX(pTxBlk->pPacket);
do_gettimeofday(&(pAd->debug_time_2[index]));
}
*/
pMacEntry = pTxBlk->pMacEntry;
tr_entry = pTxBlk->tr_entry;
if ((tr_entry->isCached)
)
{
/* It should be cleared!!! */
/*NdisZeroMemory((PUCHAR)(&pTxBlk->HeaderBuf[0]), sizeof(pTxBlk->HeaderBuf)); */
NdisMoveMemory((PUCHAR)
(&pTxBlk->HeaderBuf[TXINFO_SIZE]),
(PUCHAR) (&tr_entry->CachedBuf[0]),
TXWISize + TX_WIFI_INFO_SIZE);
pWiBufPtr = (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWISize]);
APBuildCacheWifiInfo(pAd, pTxBlk, pWiBufPtr);
}
else
{
APFindCipherAlgorithm(pAd, pTxBlk);
APBuildWifiInfo(pAd, pTxBlk);
pWiBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWISize];
}
pWI = (TX_WIFI_INFO *)pWiBufPtr;
pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader;
if (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket))
pWI->field.VLAN = TRUE;
pWI->field.TID = (pTxBlk->UserPriority & 0x0F);
#ifdef UAPSD_SUPPORT
if (CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_APSD_CAPABLE)
&& TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP))
pWI->field.EOSP = TRUE;
#endif /* UAPSD_SUPPORT */
{
/*
build HTC+
HTC control filed following QoS field
*/
if ((pAd->CommonCfg.bRdg == TRUE)
&& (CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_RDG_CAPABLE))
)
{
pWI->field.RDG = 1;
}
}
/*
if ( pAd->debug_on )
{
UCHAR index = RTMP_GET_DEBUG_INDEX(pTxBlk->pPacket);
do_gettimeofday(&(pAd->debug_time_3[index]));
}
*/
if ((tr_entry->isCached)
)
{
write_tmac_info_Cache(pAd, &pTxBlk->HeaderBuf[0], pTxBlk);
}
else
{
write_tmac_info_Data(pAd, &pTxBlk->HeaderBuf[0], pTxBlk);
NdisZeroMemory((PUCHAR)(&tr_entry->CachedBuf[0]), sizeof(tr_entry->CachedBuf));
NdisMoveMemory((PUCHAR)(&tr_entry->CachedBuf[0]),
(PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE]),
TXWISize + TX_WIFI_INFO_SIZE);
tr_entry->isCached = TRUE;
}
#ifdef STATS_COUNT_SUPPORT
pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.LowPart ++;
pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.QuadPart += pTxBlk->SrcBufLen;
/* calculate Tx count and ByteCount per BSS */
#ifdef WAPI_SUPPORT
if (IS_ENTRY_CLIENT(pMacEntry))
#endif /* WAPI_SUPPORT */
{
BSS_STRUCT *pMbss = pTxBlk->pMbss;
#ifdef WAPI_SUPPORT
if (pMacEntry->WapiUskRekeyTimerRunning &&
pAd->CommonCfg.wapi_usk_rekey_method == REKEY_METHOD_PKT)
pMacEntry->wapi_usk_rekey_cnt += pTxBlk->SrcBufLen;
#endif /* WAPI_SUPPORT */
if (pMbss != NULL)
{
pMbss->TransmittedByteCount += pTxBlk->SrcBufLen;
pMbss->TxCount ++;
#ifdef STATS_COUNT_SUPPORT
if(IS_MULTICAST_MAC_ADDR(pTxBlk->pSrcBufHeader))
pMbss->mcPktsTx++;
else if(IS_BROADCAST_MAC_ADDR(pTxBlk->pSrcBufHeader))
pMbss->bcPktsTx++;
else
pMbss->ucPktsTx++;
#endif /* STATS_COUNT_SUPPORT */
}
if(pMacEntry->Sst == SST_ASSOC)
{
INC_COUNTER64(pMacEntry->TxPackets);
pMacEntry->TxBytes+=pTxBlk->SrcBufLen;
}
}
#endif /* STATS_COUNT_SUPPORT */
/*FreeNumber = GET_TXRING_FREENO(pAd, QueIdx); */
HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
#ifdef SMART_ANTENNA
if (pMacEntry)
pMacEntry->saTxCnt++;
#endif /* SMART_ANTENNA */
/*
if ( pAd->debug_on )
{
UCHAR index = RTMP_GET_DEBUG_INDEX(pTxBlk->pPacket);
do_gettimeofday(&(pAd->debug_time_4[index]));
}
*/
/*
Kick out Tx
*/
HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
pAd->RalinkCounters.KickTxCount++;
pAd->RalinkCounters.OneSecTxDoneCount++;
/*
if ( pAd->debug_on )
{
UCHAR index = RTMP_GET_DEBUG_INDEX(pTxBlk->pPacket);
do_gettimeofday(&(pAd->debug_time_5[index]));
if ( pAd->debug_index < 201 )
{
pAd->debug_index ++;
} else {
pAd->debug_on = 0;
}
}
*/
}
#endif /* HDR_TRANS_TX_SUPPORT */
VOID AP_AMSDU_Frame_Tx(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk)
{
UCHAR *pHeaderBufPtr, *subFrameHeader;
USHORT freeCnt = 1; /* no use */
USHORT subFramePayloadLen = 0; /* AMSDU Subframe length without AMSDU-Header / Padding */
USHORT totalMPDUSize = 0;
UCHAR padding = 0;
USHORT FirstTx = 0/*, LastTxIdx = 0*/;
int frameNum = 0;
PQUEUE_ENTRY pQEntry;
//STA_TR_ENTRY *tr_entry;
#ifdef CONFIG_AP_SUPPORT
#ifdef APCLI_SUPPORT
PAPCLI_STRUCT pApCliEntry = NULL;
#endif /* APCLI_SUPPORT */
#ifdef MAC_REPEATER_SUPPORT
REPEATER_CLIENT_ENTRY *pReptEntry = NULL;
#endif /* MAC_REPEATER_SUPPORT */
#endif /* CONFIG_AP_SUPPORT */
#ifdef WFA_VHT_PF
MAC_TABLE_ENTRY *pMacEntry = pTxBlk->pMacEntry;
#endif /* WFA_VHT_PF */
ASSERT((pTxBlk->TxPacketList.Number > 1));
while (pTxBlk->TxPacketList.Head)
{
pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) {
#ifdef STATS_COUNT_SUPPORT
BSS_STRUCT *pMbss = pTxBlk->pMbss;
if (pMbss != NULL)
pMbss->TxDropCount++;
#endif /* STATS_COUNT_SUPPORT */
RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
continue;
}
/* skip 802.3 header */
pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
pTxBlk->SrcBufLen -= LENGTH_802_3;
/* skip vlan tag */
if (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket)) {
pTxBlk->pSrcBufData += LENGTH_802_1Q;
pTxBlk->SrcBufLen -= LENGTH_802_1Q;
}
if (frameNum == 0)
{
pHeaderBufPtr = AP_Build_AMSDU_Frame_Header(pAd, pTxBlk);
/* NOTE: TxWI->TxWIMPDUByteCnt will be updated after final frame was handled. */
#ifdef WFA_VHT_PF
if (pAd->force_amsdu)
{
UCHAR RABAOriIdx;
if (pMacEntry) {
RABAOriIdx = pMacEntry->BAOriWcidArray[pTxBlk->UserPriority];
if (((pMacEntry->TXBAbitmap & (1<<pTxBlk->UserPriority)) != 0) &&
(pAd->BATable.BAOriEntry[RABAOriIdx].amsdu_cap == TRUE))
TX_BLK_SET_FLAG (pTxBlk, fTX_AmsduInAmpdu);
}
}
#endif /* WFA_VHT_PF */
write_tmac_info_Data(pAd, &pTxBlk->HeaderBuf[0], pTxBlk);
#if 0
DBGPRINT(RT_DEBUG_OFF, ("%s(): frameNum=%d, pHeaderBufPtr=%p\n", __FUNCTION__, frameNum, pHeaderBufPtr));
hex_dump("AMSDU_Frame-FirstBufContent", pTxBlk->HeaderBuf, 128);
hex_dump("AMSDU_Frame-FirstBufContent - WiFi Hdr Segment", pTxBlk->wifi_hdr, pTxBlk->wifi_hdr_len);
DBGPRINT(RT_DEBUG_OFF, ("%s(): pTxBlk->MpduHeaderLen=%d, wifi_hdr_len=%d, HdrPadLen=%d, hw_rsv_len=%d\n",
__FUNCTION__, pTxBlk->MpduHeaderLen, pTxBlk->wifi_hdr_len, pTxBlk->HdrPadLen, pTxBlk->hw_rsv_len));
dump_tmac_info(pAd, &pTxBlk->HeaderBuf[pTxBlk->hw_rsv_len]);
#endif
if (RTMP_GET_PACKET_LOWRATE(pTxBlk->pPacket))
if (pTxBlk->tr_entry)
pTxBlk->tr_entry->isCached = FALSE;
}
else
{
#if defined(MT7603) || defined(MT7628)
pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
#else
// TODO: shiang-usw, check this, original code is use pTxBlk->HeaderBuf[0]
pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE];
#endif /* defined(MT7603) || defined(MT7628) */
padding = (UCHAR)(ROUND_UP(AMSDU_SUBHEAD_LEN + subFramePayloadLen, 4)
- (AMSDU_SUBHEAD_LEN + subFramePayloadLen));
NdisZeroMemory(pHeaderBufPtr, padding + AMSDU_SUBHEAD_LEN);
pHeaderBufPtr += padding;
pTxBlk->MpduHeaderLen = padding;
}
/*
A-MSDU subframe
DA(6)+SA(6)+Length(2) + LLC/SNAP Encap
*/
subFrameHeader = pHeaderBufPtr;
subFramePayloadLen = (USHORT)pTxBlk->SrcBufLen;
NdisMoveMemory(subFrameHeader, pTxBlk->pSrcBufHeader, 12);
#ifdef APCLI_SUPPORT
if(TX_BLK_TEST_FLAG(pTxBlk, fTX_bApCliPacket))
{
#ifdef MAC_REPEATER_SUPPORT
if (pTxBlk->pMacEntry->bReptCli)
{
pReptEntry = &pAd->ApCfg.ApCliTab[pTxBlk->pMacEntry->func_tb_idx].RepeaterCli[pTxBlk->pMacEntry->MatchReptCliIdx];
if (pReptEntry->CliValid)
NdisMoveMemory(&subFrameHeader[6] , pReptEntry->CurrentAddress, 6);
}
else
#endif /* MAC_REPEATER_SUPPORT */
{
pApCliEntry = &pAd->ApCfg.ApCliTab[pTxBlk->pMacEntry->func_tb_idx];
if (pApCliEntry->Valid)
NdisMoveMemory(&subFrameHeader[6] , pApCliEntry->wdev.if_addr, 6);
}
}
#endif /* APCLI_SUPPORT */
#ifdef MESH_SUPPORT
if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bMeshEntry))
{
if (RTMP_GET_MESH_SOURCE(pTxBlk->pPacket) == MESH_PROXY)
COPY_MAC_ADDR(&subFrameHeader[6], pAd->MeshTab.wdev.if_addr);
else
COPY_MAC_ADDR(&subFrameHeader[6], pTxBlk->pSrcBufHeader + MAC_ADDR_LEN); /* ADDR4 = SA */
}
#endif /* MESH_SUPPORT */
pHeaderBufPtr += AMSDU_SUBHEAD_LEN;
pTxBlk->MpduHeaderLen += AMSDU_SUBHEAD_LEN;
#ifdef MESH_SUPPORT
if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bMeshEntry))
subFramePayloadLen += InsertPktMeshHeader(pAd, pTxBlk, &pHeaderBufPtr);
#endif /* MESH_SUPPORT */
/* Insert LLC-SNAP encapsulation - 8 octets */
EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData - 2, pTxBlk->pExtraLlcSnapEncap);
subFramePayloadLen = (USHORT)pTxBlk->SrcBufLen;
if (pTxBlk->pExtraLlcSnapEncap) {
NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
pHeaderBufPtr += 6;
/* get 2 octets (TypeofLen) */
NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData - 2, 2);
pHeaderBufPtr += 2;
pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
subFramePayloadLen += LENGTH_802_1_H;
}
/* update subFrame Length field */
subFrameHeader[12] = (UCHAR)((subFramePayloadLen & 0xFF00) >> 8);
subFrameHeader[13] = subFramePayloadLen & 0xFF;
#if defined(MT7603) || defined(MT7628)
if (frameNum == 0)
totalMPDUSize += pAd->chipCap.tx_hw_hdr_len - pTxBlk->hw_rsv_len + pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen + pTxBlk->SrcBufLen;
else
totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
#else
totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
#endif /* MT7603 */
if (frameNum == 0)
FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, (UCHAR)frameNum, &freeCnt);
else
/*LastTxIdx = */HAL_WriteMultiTxResource(pAd, pTxBlk
, (UCHAR)frameNum, &freeCnt);
#ifdef DBG_CTRL_SUPPORT
#ifdef INCLUDE_DEBUG_QUEUE
if (pAd->CommonCfg.DebugFlags & DBF_DBQ_TXFRAME)
dbQueueEnqueueTxFrame((UCHAR *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), NULL);
#endif /* INCLUDE_DEBUG_QUEUE */
#endif /* DBG_CTRL_SUPPORT */
frameNum++;
#ifdef SMART_ANTENNA
if (pTxBlk->pMacEntry)
pTxBlk->pMacEntry->saTxCnt++;
#endif /* SMART_ANTENNA */
pAd->RalinkCounters.KickTxCount++;
pAd->RalinkCounters.OneSecTxDoneCount++;
#ifdef STATS_COUNT_SUPPORT
{
/* calculate Transmitted AMSDU Count and ByteCount */
pAd->RalinkCounters.TxAMSDUCount.u.LowPart++;
}
/* calculate Tx count and ByteCount per BSS */
#ifdef WAPI_SUPPORT
if (IS_ENTRY_CLIENT(pTxBlk->pMacEntry))
#endif /* WAPI_SUPPORT */
{
BSS_STRUCT *pMbss = pTxBlk->pMbss;
MAC_TABLE_ENTRY *pMacEntry = pTxBlk->pMacEntry;
#ifdef WAPI_SUPPORT
if (pTxBlk->pMacEntry->WapiUskRekeyTimerRunning && pAd->CommonCfg.wapi_usk_rekey_method == REKEY_METHOD_PKT)
pTxBlk->pMacEntry->wapi_usk_rekey_cnt += totalMPDUSize;
#endif /* WAPI_SUPPORT */
if (pMbss != NULL)
{
pMbss->TransmittedByteCount += totalMPDUSize;
pMbss->TxCount ++;
#ifdef STATS_COUNT_SUPPORT
if(IS_MULTICAST_MAC_ADDR(pTxBlk->pSrcBufHeader))
pMbss->mcPktsTx++;
else if(IS_BROADCAST_MAC_ADDR(pTxBlk->pSrcBufHeader))
pMbss->bcPktsTx++;
else
pMbss->ucPktsTx++;
#endif /* STATS_COUNT_SUPPORT */
}
if(pMacEntry->Sst == SST_ASSOC)
{
INC_COUNTER64(pMacEntry->TxPackets);
pMacEntry->TxBytes+=pTxBlk->SrcBufLen;
pAd->TxTotalByteCnt += pTxBlk->SrcBufLen;
}
}
#ifdef WDS_SUPPORT
if (pTxBlk->pMacEntry && IS_ENTRY_WDS(pTxBlk->pMacEntry))
{
INC_COUNTER64(pAd->WdsTab.WdsEntry[pTxBlk->pMacEntry->func_tb_idx].WdsCounter.TransmittedFragmentCount);
pAd->WdsTab.WdsEntry[pTxBlk->pMacEntry->func_tb_idx].WdsCounter.TransmittedByteCount+= pTxBlk->SrcBufLen;
}
#endif /* WDS_SUPPORT */
#endif /* STATS_COUNT_SUPPORT */
}
HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
HAL_LastTxIdx(pAd, pTxBlk->QueIdx, 0/*LastTxIdx*/);
/*
Kick out Tx
*/
HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
}
#endif /* DOT11_N_SUPPORT */
VOID AP_Legacy_Frame_Tx(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk)
{
HEADER_802_11 *wifi_hdr;
UCHAR *pHeaderBufPtr, *pTmpHeaderBufPtr;
USHORT freeCnt = 1;
BOOLEAN bVLANPkt;
QUEUE_ENTRY *pQEntry;
//UINT8 TXWISize = pAd->chipCap.TXWISize;
ASSERT(pTxBlk);
pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) {
#ifdef STATS_COUNT_SUPPORT
BSS_STRUCT *pMbss = pTxBlk->pMbss;
if (pMbss != NULL)
pMbss->TxDropCount++;
#endif /* STATS_COUNT_SUPPORT */
RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
DBGPRINT(RT_DEBUG_TRACE, ("<--%s(%d): ##########Fail#########\n", __FUNCTION__, __LINE__));
return;
}
APFindCipherAlgorithm(pAd, pTxBlk);
APBuildCommon802_11Header(pAd, pTxBlk);
#ifdef SOFT_ENCRYPT
if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt)) {
if (RTMPExpandPacketForSwEncrypt(pAd, pTxBlk) == FALSE) {
RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
return;
}
}
#endif /* SOFT_ENCRYPT */
/* skip 802.3 header */
pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
pTxBlk->SrcBufLen -= LENGTH_802_3;
/* skip vlan tag */
bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
if (bVLANPkt) {
pTxBlk->pSrcBufData += LENGTH_802_1Q;
pTxBlk->SrcBufLen -= LENGTH_802_1Q;
}
/* record these MCAST_TX frames for group key rekey */
if (pTxBlk->TxFrameType == TX_MCAST_FRAME)
{
INT idx;
#ifdef STATS_COUNT_SUPPORT
INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount);
#endif /* STATS_COUNT_SUPPORT */
for (idx = 0; idx < pAd->ApCfg.BssidNum; idx++)
{
if (pAd->ApCfg.MBSSID[idx].REKEYTimerRunning &&
pAd->ApCfg.MBSSID[idx].WPAREKEY.ReKeyMethod == PKT_REKEY)
{
pAd->ApCfg.MBSSID[idx].REKEYCOUNTER += (pTxBlk->SrcBufLen);
}
}
#ifdef WAPI_SUPPORT
if (pAd->CommonCfg.WapiMskRekeyTimerRunning &&
pAd->CommonCfg.wapi_msk_rekey_method == REKEY_METHOD_PKT)
{
pAd->CommonCfg.wapi_msk_rekey_cnt += (pTxBlk->SrcBufLen);
}
#endif /* WAPI_SUPPORT */
}
else
{
/* Unicast */
if (pTxBlk->tr_entry && pTxBlk->tr_entry->PsDeQWaitCnt)
pTxBlk->Pid = PID_PS_DATA;
}
pHeaderBufPtr = pTxBlk->wifi_hdr;
wifi_hdr = (HEADER_802_11 *)pHeaderBufPtr;
if(wifi_hdr == NULL)
DBGPRINT(RT_DEBUG_TRACE, ("wifi_hdr is NULL.\n"));
/* skip common header */
pHeaderBufPtr += pTxBlk->wifi_hdr_len;
if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) {
/* build QOS Control bytes */
*pHeaderBufPtr = ((pTxBlk->UserPriority & 0x0F) | (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx] << 5));
#ifdef WFA_VHT_PF
if (pAd->force_noack)
*pHeaderBufPtr |= (1 << 5);
#endif /* WFA_VHT_PF */
#ifdef UAPSD_SUPPORT
if (CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_APSD_CAPABLE)
#ifdef WDS_SUPPORT
&& (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWDSEntry) == FALSE)
#endif /* WDS_SUPPORT */
#ifdef MESH_SUPPORT
&& (TX_BLK_TEST_FLAG(pTxBlk, fTX_bMeshEntry) == FALSE)
#endif /* MESH_SUPPORT */
)
{
/*
we can not use bMoreData bit to get EOSP bit because
maybe bMoreData = 1 & EOSP = 1 when Max SP Length != 0
*/
if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP))
*pHeaderBufPtr |= (1 << 4);
}
#endif /* UAPSD_SUPPORT */
*(pHeaderBufPtr + 1) = 0;
pHeaderBufPtr += 2;
pTxBlk->MpduHeaderLen += 2;
pTxBlk->wifi_hdr_len += 2;
#ifdef TXBF_SUPPORT
if (pAd->chipCap.FlgHwTxBfCap &&
(pTxBlk->pMacEntry) &&
(pTxBlk->pTransmit->field.MODE >= MODE_HTMIX))
{
MAC_TABLE_ENTRY *pMacEntry = pTxBlk->pMacEntry;
BOOLEAN bHTCPlus = FALSE;
pTxBlk->TxSndgPkt = SNDG_TYPE_DISABLE;
// TODO: shiang-usw, fix ME!!
NdisAcquireSpinLock(&pMacEntry->TxSndgLock);
if (pMacEntry->TxSndgType >= SNDG_TYPE_SOUNDING)
{
NdisZeroMemory(pHeaderBufPtr, sizeof(HT_CONTROL));
if (pMacEntry->TxSndgType == SNDG_TYPE_SOUNDING)
{
/* Select compress if supported. Otherwise select noncompress */
if ((pAd->CommonCfg.ETxBfNoncompress==0) &&
(pMacEntry->HTCapability.TxBFCap.ExpComBF>0))
((PHT_CONTROL)pHeaderBufPtr)->CSISTEERING = 3;
else
((PHT_CONTROL)pHeaderBufPtr)->CSISTEERING = 2;
/* Clear NDP Announcement */
((PHT_CONTROL)pHeaderBufPtr)->NDPAnnounce = 0;
}
else if (pMacEntry->TxSndgType == SNDG_TYPE_NDP)
{
/* Select compress if supported. Otherwise select noncompress */
if ((pAd->CommonCfg.ETxBfNoncompress == 0) &&
(pMacEntry->HTCapability.TxBFCap.ExpComBF>0) &&
(pMacEntry->HTCapability.TxBFCap.ComSteerBFAntSup >= (pMacEntry->sndgMcs/8))
)
((PHT_CONTROL)pHeaderBufPtr)->CSISTEERING = 3;
else
((PHT_CONTROL)pHeaderBufPtr)->CSISTEERING = 2;
/* Set NDP Announcement */
((PHT_CONTROL)pHeaderBufPtr)->NDPAnnounce = 1;
pTxBlk->TxNDPSndgBW = pMacEntry->sndgBW;
pTxBlk->TxNDPSndgMcs = pMacEntry->sndgMcs;
}
pTxBlk->TxSndgPkt = pMacEntry->TxSndgType;
pMacEntry->TxSndgType = SNDG_TYPE_DISABLE;
bHTCPlus = TRUE;
}
NdisReleaseSpinLock(&pMacEntry->TxSndgLock);
#ifdef MFB_SUPPORT
#if defined(MRQ_FORCE_TX)
/* have to replace this by the correct condition!!! */
pMacEntry->HTCapability.ExtHtCapInfo.MCSFeedback = MCSFBK_MRQ;
#endif
/*
Ignore sounding frame because the signal format of sounding frmae may
be different from normal data frame, which may result in different MFB
*/
if ((pMacEntry->HTCapability.ExtHtCapInfo.MCSFeedback >=MCSFBK_MRQ) &&
(pTxBlk->TxSndgPkt == SNDG_TYPE_DISABLE))
{
if (bHTCPlus == FALSE)
{
NdisZeroMemory(pHeaderBufPtr, sizeof(HT_CONTROL));
bHTCPlus = TRUE;
}
MFB_PerPareMRQ(pAd, pHeaderBufPtr, pMacEntry);
}
if (pAd->CommonCfg.HtCapability.ExtHtCapInfo.MCSFeedback >=MCSFBK_MRQ &&
pMacEntry->toTxMfb == 1)
{
if (bHTCPlus == FALSE)
{
NdisZeroMemory(pHeaderBufPtr, sizeof(HT_CONTROL));
bHTCPlus = TRUE;
}
MFB_PerPareMFB(pAd, pHeaderBufPtr, pMacEntry);/* not complete yet!!! */
pMacEntry->toTxMfb = 0;
}
#endif /* MFB_SUPPORT */
if (bHTCPlus == TRUE)
{
/* mark HTC bit */
wifi_hdr->FC.Order = 1;
pHeaderBufPtr += 4;
pTxBlk->wifi_hdr_len += 4;
}
}
#endif /* TXBF_SUPPORT */
}
/* The remaining content of MPDU header should locate at 4-octets aligment */
pTmpHeaderBufPtr = pHeaderBufPtr;
pHeaderBufPtr = (UCHAR *)ROUND_UP(pHeaderBufPtr, 4);
pTxBlk->HdrPadLen = (UCHAR)(pHeaderBufPtr - pTmpHeaderBufPtr);
pTxBlk->MpduHeaderLen = pTxBlk->wifi_hdr_len;
#ifdef SOFT_ENCRYPT
if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt)) {
tx_sw_encrypt(pAd, pTxBlk, pHeaderBufPtr, wifi_hdr);
}
else
#endif /* SOFT_ENCRYPT */
{
#ifdef MESH_SUPPORT
if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bMeshEntry))
InsertPktMeshHeader(pAd, pTxBlk, &pHeaderBufPtr);
#endif /* MESH_SUPPORT */
/*
Insert LLC-SNAP encapsulation - 8 octets
if original Ethernet frame contains no LLC/SNAP,
then an extra LLC/SNAP encap is required
*/
EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader,
pTxBlk->pExtraLlcSnapEncap);
if (pTxBlk->pExtraLlcSnapEncap) {
UCHAR vlan_size;
NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
pHeaderBufPtr += 6;
/* skip vlan tag */
vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
/* get 2 octets (TypeofLen) */
NdisMoveMemory(pHeaderBufPtr,
pTxBlk->pSrcBufHeader + 12 + vlan_size,
2);
pHeaderBufPtr += 2;
pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
}
}
#ifdef STATS_COUNT_SUPPORT
/* calculate Tx count and ByteCount per BSS */
#ifdef WAPI_SUPPORT
if (pTxBlk->pMacEntry && IS_ENTRY_CLIENT(pTxBlk->pMacEntry))
#endif /* WAPI_SUPPORT */
{
BSS_STRUCT *pMbss = pTxBlk->pMbss;
MAC_TABLE_ENTRY *pMacEntry=pTxBlk->pMacEntry;
#ifdef WAPI_SUPPORT
if (pTxBlk->pMacEntry->WapiUskRekeyTimerRunning && pAd->CommonCfg.wapi_usk_rekey_method == REKEY_METHOD_PKT)
pTxBlk->pMacEntry->wapi_usk_rekey_cnt += pTxBlk->SrcBufLen;
#endif /* WAPI_SUPPORT */
if (pMbss != NULL)
{
pMbss->TransmittedByteCount += pTxBlk->SrcBufLen;
pMbss->TxCount ++;
#ifdef STATS_COUNT_SUPPORT
if(IS_MULTICAST_MAC_ADDR(pTxBlk->pSrcBufHeader))
pMbss->mcPktsTx++;
else if(IS_BROADCAST_MAC_ADDR(pTxBlk->pSrcBufHeader))
pMbss->bcPktsTx++;
else
pMbss->ucPktsTx++;
#endif /* STATS_COUNT_SUPPORT */
}
if(pMacEntry && pMacEntry->Sst == SST_ASSOC)
{
INC_COUNTER64(pMacEntry->TxPackets);
pMacEntry->TxBytes+=pTxBlk->SrcBufLen;
pAd->TxTotalByteCnt += pTxBlk->SrcBufLen;
}
}
#ifdef WDS_SUPPORT
if (pTxBlk->pMacEntry && IS_ENTRY_WDS(pTxBlk->pMacEntry))
{
INC_COUNTER64(pAd->WdsTab.WdsEntry[pTxBlk->pMacEntry->func_tb_idx].WdsCounter.TransmittedFragmentCount);
pAd->WdsTab.WdsEntry[pTxBlk->pMacEntry->func_tb_idx].WdsCounter.TransmittedByteCount+= pTxBlk->SrcBufLen;
}
#endif /* WDS_SUPPORT */
#endif /* STATS_COUNT_SUPPORT */
/*
prepare for TXWI
use Wcid as Hardware Key Index
*/
/* update Hardware Group Key Index */
if (!pTxBlk->pMacEntry) {
struct wifi_dev *wdev = pAd->wdev_list[pTxBlk->wdev_idx];
ASSERT(wdev != NULL);
if(wdev != NULL)
{
GET_GroupKey_WCID(pAd, pTxBlk->Wcid, wdev->func_idx);
}
}
write_tmac_info_Data(pAd, &pTxBlk->HeaderBuf[0], pTxBlk);
//hex_dump("Legacy_Frame-FirstBufContent", pTxBlk->HeaderBuf, 128);
//hex_dump("Legacy_Frame-FirstBufContent - WiFi Hdr Segment", pTxBlk->wifi_hdr, pTxBlk->wifi_hdr_len);
//DBGPRINT(RT_DEBUG_OFF, ("%s(): pTxBlk->MpduHeaderLen=%d, wifi_hdr_len=%d, HdrPadLen=%d, hw_rsv_len=%d\n",
// __FUNCTION__, pTxBlk->MpduHeaderLen, pTxBlk->wifi_hdr_len, pTxBlk->HdrPadLen, pTxBlk->hw_rsv_len));
//dump_tmac_info(pAd, &pTxBlk->HeaderBuf[pTxBlk->hw_rsv_len]);
if (RTMP_GET_PACKET_LOWRATE(pTxBlk->pPacket))
if (pTxBlk->tr_entry)
pTxBlk->tr_entry->isCached = FALSE;
HAL_WriteTxResource(pAd, pTxBlk, TRUE, &freeCnt);
#ifdef SMART_ANTENNA
if (pTxBlk->pMacEntry)
pTxBlk->pMacEntry->saTxCnt++;
#endif /* SMART_ANTENNA */
#ifdef DBG_CTRL_SUPPORT
#ifdef INCLUDE_DEBUG_QUEUE
if (pAd->CommonCfg.DebugFlags & DBF_DBQ_TXFRAME)
dbQueueEnqueueTxFrame((UCHAR *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (UCHAR *)wifi_hdr);
#endif /* INCLUDE_DEBUG_QUEUE */
#endif /* DBG_CTRL_SUPPORT */
/*
Kick out Tx
*/
HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
pAd->RalinkCounters.KickTxCount++;
pAd->RalinkCounters.OneSecTxDoneCount++;
//DBGPRINT(RT_DEBUG_TRACE, ("<--%s(%d):Success\n", __FUNCTION__, __LINE__));
}
#ifdef HDR_TRANS_TX_SUPPORT
VOID AP_Legacy_Frame_Tx_Hdr_Trns(
IN PRTMP_ADAPTER pAd,
IN TX_BLK *pTxBlk)
{
/* UCHAR QueIdx = pTxBlk->QueIdx; */
USHORT FreeNumber = 1; /* no use */
BOOLEAN bVLANPkt;
PQUEUE_ENTRY pQEntry;
UINT8 TXWISize = pAd->chipCap.TXWISize;
TX_WIFI_INFO *pWI;
ASSERT(pTxBlk);
pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
{
#ifdef STATS_COUNT_SUPPORT
BSS_STRUCT *pMbss = pTxBlk->pMbss;
if (pMbss != NULL)
pMbss->TxDropCount++;
#endif /* STATS_COUNT_SUPPORT */
RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
return;
}
#ifdef STATS_COUNT_SUPPORT
if (pTxBlk->TxFrameType == TX_MCAST_FRAME)
{
INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount);
}
#endif /* STATS_COUNT_SUPPORT */
bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
APFindCipherAlgorithm(pAd, pTxBlk);
/*
if ( pAd->debug_on )
{
UCHAR index = RTMP_GET_DEBUG_INDEX(pTxBlk->pPacket);
do_gettimeofday(&(pAd->debug_time_2[index]));
}
*/
APBuildWifiInfo(pAd, pTxBlk);
pWI = (TX_WIFI_INFO *)&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWISize];
pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader;
if (bVLANPkt)
pWI->field.VLAN = TRUE;
pWI->field.TID = (pTxBlk->UserPriority & 0x0F);
#ifdef UAPSD_SUPPORT
if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)
&& CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_APSD_CAPABLE)
&& TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP))
pWI->field.EOSP = TRUE;
#endif /* UAPSD_SUPPORT */
#ifdef STATS_COUNT_SUPPORT
/* calculate Tx count and ByteCount per BSS */
#ifdef WAPI_SUPPORT
if (pTxBlk->pMacEntry && IS_ENTRY_CLIENT(pTxBlk->pMacEntry))
#endif /* WAPI_SUPPORT */
{
BSS_STRUCT *pMbss = pTxBlk->pMbss;
MAC_TABLE_ENTRY *pMacEntry=pTxBlk->pMacEntry;
#ifdef WAPI_SUPPORT
if (pTxBlk->pMacEntry->WapiUskRekeyTimerRunning && pAd->CommonCfg.wapi_usk_rekey_method == REKEY_METHOD_PKT)
pTxBlk->pMacEntry->wapi_usk_rekey_cnt += pTxBlk->SrcBufLen;
#endif /* WAPI_SUPPORT */
if (pMbss != NULL)
{
pMbss->TransmittedByteCount += pTxBlk->SrcBufLen;
pMbss->TxCount ++;
#ifdef STATS_COUNT_SUPPORT
if(IS_MULTICAST_MAC_ADDR(pTxBlk->pSrcBufHeader))
pMbss->mcPktsTx++;
else if(IS_BROADCAST_MAC_ADDR(pTxBlk->pSrcBufHeader))
pMbss->bcPktsTx++;
else
pMbss->ucPktsTx++;
#endif /* STATS_COUNT_SUPPORT */
}
if(pMacEntry && pMacEntry->Sst == SST_ASSOC)
{
INC_COUNTER64(pMacEntry->TxPackets);
pMacEntry->TxBytes+=pTxBlk->SrcBufLen;
}
}
#endif /* STATS_COUNT_SUPPORT */
/*
if ( pAd->debug_on )
{
UCHAR index = RTMP_GET_DEBUG_INDEX(pTxBlk->pPacket);
do_gettimeofday(&(pAd->debug_time_3[index]));
}
*/
/*
prepare for TXWI
*/
/* update Hardware Group Key Index */
if (!pTxBlk->pMacEntry)
{
/* use Wcid as Hardware Key Index */
struct wifi_dev *wdev = pAd->wdev_list[pTxBlk->wdev_idx];
ASSERT(wdev != NULL);
GET_GroupKey_WCID(pAd, pTxBlk->Wcid, wdev->func_idx);
}
write_tmac_info_Data(pAd, &pTxBlk->HeaderBuf[0], pTxBlk);
/*FreeNumber = GET_TXRING_FREENO(pAd, QueIdx); */
HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
#ifdef SMART_ANTENNA
if (pTxBlk->pMacEntry)
pTxBlk->pMacEntry->saTxCnt++;
#endif /* SMART_ANTENNA */
#ifdef DBG_CTRL_SUPPORT
#ifdef INCLUDE_DEBUG_QUEUE
if (pAd->CommonCfg.DebugFlags & DBF_DBQ_TXFRAME)
dbQueueEnqueueTxFrame((UCHAR *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (UCHAR *)pHeader_802_11);
#endif /* INCLUDE_DEBUG_QUEUE */
#endif /* DBG_CTRL_SUPPORT */
pAd->RalinkCounters.KickTxCount++;
pAd->RalinkCounters.OneSecTxDoneCount++;
/*
if (pAd->debug_on)
{
UCHAR index = RTMP_GET_DEBUG_INDEX(pTxBlk->pPacket);
do_gettimeofday(&(pAd->debug_time_4[index]));
}
*/
/*
Kick out Tx
*/
HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
/*
if ( pAd->debug_on )
{
UCHAR index = RTMP_GET_DEBUG_INDEX(pTxBlk->pPacket);
do_gettimeofday(&(pAd->debug_time_5[index]));
if ( pAd->debug_index < 201 )
{
pAd->debug_index ++;
} else {
pAd->debug_on = 0;
}
}
*/
}
#endif /* HDR_TRANS_TX_SUPPORT */
VOID AP_Fragment_Frame_Tx(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk)
{
HEADER_802_11 *wifi_hdr;
UCHAR *pHeaderBufPtr, *pTmpHeaderBufPtr;
USHORT freeCnt = 1;
BOOLEAN bVLANPkt;
QUEUE_ENTRY *pQEntry;
//UINT8 TXWISize = pAd->chipCap.TXWISize;
PACKET_INFO PacketInfo;
#ifdef SOFT_ENCRYPT
UCHAR *tmp_ptr = NULL;
UINT32 buf_offset = 0;
#endif /* SOFT_ENCRYPT */
HTTRANSMIT_SETTING *pTransmit;
UCHAR fragNum = 0;
USHORT EncryptionOverhead = 0;
UINT32 FreeMpduSize, SrcRemainingBytes;
USHORT AckDuration;
UINT NextMpduSize;
//UINT8 tx_hw_hdr_len = pAd->chipCap.tx_hw_hdr_len;
ASSERT(pTxBlk);
ASSERT(TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag));
//DBGPRINT(RT_DEBUG_TRACE, ("%s()-->\n", __FUNCTION__));
pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) {
#ifdef STATS_COUNT_SUPPORT
BSS_STRUCT *pMbss = pTxBlk->pMbss;
if (pMbss != NULL)
pMbss->TxDropCount++;
#endif /* STATS_COUNT_SUPPORT */
RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
DBGPRINT(RT_DEBUG_TRACE, ("<--%s(%d): ##########Fail#########\n", __FUNCTION__, __LINE__));
return;
}
APFindCipherAlgorithm(pAd, pTxBlk);
APBuildCommon802_11Header(pAd, pTxBlk);
#ifdef SOFT_ENCRYPT
if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt)) {
if (RTMPExpandPacketForSwEncrypt(pAd, pTxBlk) == FALSE) {
RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
return;
}
}
#endif /* SOFT_ENCRYPT */
if (pTxBlk->CipherAlg == CIPHER_TKIP) {
pTxBlk->pPacket = duplicate_pkt_with_TKIP_MIC(pAd, pTxBlk->pPacket);
if (pTxBlk->pPacket == NULL)
return;
RTMP_QueryPacketInfo(pTxBlk->pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
}
/* skip 802.3 header */
pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
pTxBlk->SrcBufLen -= LENGTH_802_3;
/* skip vlan tag */
bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
if (bVLANPkt) {
pTxBlk->pSrcBufData += LENGTH_802_1Q;
pTxBlk->SrcBufLen -= LENGTH_802_1Q;
}
pHeaderBufPtr = pTxBlk->wifi_hdr;
wifi_hdr = (HEADER_802_11 *)pHeaderBufPtr;
DBGPRINT(RT_DEBUG_TRACE, ("%s(): Before Frag, pTxBlk->MpduHeaderLen=%d, wifi_hdr_len=%d, HdrPadLen=%d, hw_rsv_len=%d\n",
__FUNCTION__, pTxBlk->MpduHeaderLen, pTxBlk->wifi_hdr_len, pTxBlk->HdrPadLen, pTxBlk->hw_rsv_len));
/* skip common header */
pHeaderBufPtr += pTxBlk->wifi_hdr_len;
if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) {
/* build QOS Control bytes */
*pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
#ifdef UAPSD_SUPPORT
if (pTxBlk->pMacEntry &&
CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_APSD_CAPABLE)
#ifdef WDS_SUPPORT
&& (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWDSEntry) == FALSE)
#endif /* WDS_SUPPORT */
)
{
/*
we can not use bMoreData bit to get EOSP bit because
maybe bMoreData = 1 & EOSP = 1 when Max SP Length != 0
*/
if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP))
*pHeaderBufPtr |= (1 << 4);
}
#endif /* UAPSD_SUPPORT */
*(pHeaderBufPtr + 1) = 0;
pHeaderBufPtr += 2;
pTxBlk->MpduHeaderLen += 2;
pTxBlk->wifi_hdr_len += 2;
}
/* The remaining content of MPDU header should locate at 4-octets aligment */
pTmpHeaderBufPtr = pHeaderBufPtr;
pHeaderBufPtr = (UCHAR *)ROUND_UP(pHeaderBufPtr, 4);
pTxBlk->HdrPadLen = (UCHAR)(pHeaderBufPtr - pTmpHeaderBufPtr);
pTxBlk->MpduHeaderLen = pTxBlk->wifi_hdr_len;
#ifdef SOFT_ENCRYPT
if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt)) {
UCHAR iv_offset = 0;
/*
If original Ethernet frame contains no LLC/SNAP,
then an extra LLC/SNAP encap is required
*/
EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData - 2,
pTxBlk->pExtraLlcSnapEncap);
/* Insert LLC-SNAP encapsulation (8 octets) to MPDU data buffer */
if (pTxBlk->pExtraLlcSnapEncap) {
/* Reserve the front 8 bytes of data for LLC header */
pTxBlk->pSrcBufData -= LENGTH_802_1_H;
pTxBlk->SrcBufLen += LENGTH_802_1_H;
NdisMoveMemory(pTxBlk->pSrcBufData, pTxBlk->pExtraLlcSnapEncap, 6);
}
/* Construct and insert specific IV header to MPDU header */
RTMPSoftConstructIVHdr(pTxBlk->CipherAlg,
pTxBlk->KeyIdx,
pTxBlk->pKey->TxTsc,
pHeaderBufPtr, &iv_offset);
pHeaderBufPtr += iv_offset;
pTxBlk->MpduHeaderLen += iv_offset;
}
else
#endif /* SOFT_ENCRYPT */
{
#ifdef MESH_SUPPORT
if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bMeshEntry))
InsertPktMeshHeader(pAd, pTxBlk, &pHeaderBufPtr);
#endif /* MESH_SUPPORT */
/*
Insert LLC-SNAP encapsulation - 8 octets
if original Ethernet frame contains no LLC/SNAP,
then an extra LLC/SNAP encap is required
*/
EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader,
pTxBlk->pExtraLlcSnapEncap);
if (pTxBlk->pExtraLlcSnapEncap) {
UCHAR vlan_size;
NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
pHeaderBufPtr += 6;
/* skip vlan tag */
vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
/* get 2 octets (TypeofLen) */
NdisMoveMemory(pHeaderBufPtr,
pTxBlk->pSrcBufHeader + 12 + vlan_size,
2);
pHeaderBufPtr += 2;
pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
}
}
/* 1. If TKIP is used and fragmentation is required. Driver has to
append TKIP MIC at tail of the scatter buffer
2. When TXWI->FRAG is set as 1 in TKIP mode,
MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC */
/* TKIP appends the computed MIC to the MSDU data prior to fragmentation into MPDUs. */
if (pTxBlk->CipherAlg == CIPHER_TKIP) {
struct wifi_dev *wdev = pAd->wdev_list[pTxBlk->wdev_idx];
ASSERT(wdev != NULL);
if(wdev != NULL)
{
RTMPCalculateMICValue(pAd, pTxBlk->pPacket, pTxBlk->pExtraLlcSnapEncap, pTxBlk->pKey, wdev->func_idx);
}
/*
NOTE: DON'T refer the skb->len directly after following copy. Becasue the length is not adjust
to correct lenght, refer to pTxBlk->SrcBufLen for the packet length in following progress.
*/
NdisMoveMemory(pTxBlk->pSrcBufData + pTxBlk->SrcBufLen, &pAd->PrivateInfo.Tx.MIC[0], 8);
pTxBlk->SrcBufLen += 8;
pTxBlk->TotalFrameLen += 8;
}
#ifdef STATS_COUNT_SUPPORT
/* calculate Tx count and ByteCount per BSS */
#ifdef WAPI_SUPPORT
if (pTxBlk->pMacEntry && IS_ENTRY_CLIENT(pTxBlk->pMacEntry))
#endif /* WAPI_SUPPORT */
{
BSS_STRUCT *pMbss = pTxBlk->pMbss;
MAC_TABLE_ENTRY *pMacEntry=pTxBlk->pMacEntry;
#ifdef WAPI_SUPPORT
if (pTxBlk->pMacEntry->WapiUskRekeyTimerRunning && pAd->CommonCfg.wapi_usk_rekey_method == REKEY_METHOD_PKT)
pTxBlk->pMacEntry->wapi_usk_rekey_cnt += pTxBlk->SrcBufLen;
#endif /* WAPI_SUPPORT */
if (pMbss != NULL)
{
pMbss->TransmittedByteCount += pTxBlk->SrcBufLen;
pMbss->TxCount ++;
#ifdef STATS_COUNT_SUPPORT
if(IS_MULTICAST_MAC_ADDR(pTxBlk->pSrcBufHeader))
pMbss->mcPktsTx++;
else if(IS_BROADCAST_MAC_ADDR(pTxBlk->pSrcBufHeader))
pMbss->bcPktsTx++;
else
pMbss->ucPktsTx++;
#endif /* STATS_COUNT_SUPPORT */
}
if(pMacEntry && pMacEntry->Sst == SST_ASSOC)
{
INC_COUNTER64(pMacEntry->TxPackets);
pMacEntry->TxBytes+=pTxBlk->SrcBufLen;
pAd->TxTotalByteCnt += pTxBlk->SrcBufLen;
}
}
#ifdef WDS_SUPPORT
if (pTxBlk->pMacEntry && IS_ENTRY_WDS(pTxBlk->pMacEntry))
{
INC_COUNTER64(pAd->WdsTab.WdsEntry[pTxBlk->pMacEntry->func_tb_idx].WdsCounter.TransmittedFragmentCount);
pAd->WdsTab.WdsEntry[pTxBlk->pMacEntry->func_tb_idx].WdsCounter.TransmittedByteCount+= pTxBlk->SrcBufLen;
}
#endif /* WDS_SUPPORT */
#endif /* STATS_COUNT_SUPPORT */
/*
calcuate the overhead bytes that encryption algorithm may add. This
affects the calculate of "duration" field
*/
if ((pTxBlk->CipherAlg == CIPHER_WEP64) || (pTxBlk->CipherAlg == CIPHER_WEP128) || (pTxBlk->CipherAlg == CIPHER_WEP152))
EncryptionOverhead = 8; /* WEP: IV[4] + ICV[4]; */
else if (pTxBlk->CipherAlg == CIPHER_TKIP)
EncryptionOverhead = 12; /* TKIP: IV[4] + EIV[4] + ICV[4], MIC will be added to TotalPacketLength */
else if (pTxBlk->CipherAlg == CIPHER_AES)
EncryptionOverhead = 16; /* AES: IV[4] + EIV[4] + MIC[8] */
#ifdef WAPI_SUPPORT
else if (pTxBlk->CipherAlg == CIPHER_SMS4)
EncryptionOverhead = 16; /* SMS4: MIC[16] */
#endif /* WAPI_SUPPORT */
else
EncryptionOverhead = 0;
pTransmit = pTxBlk->pTransmit;
/* Decide the TX rate */
if (pTransmit->field.MODE == MODE_CCK)
pTxBlk->TxRate = (UCHAR)pTransmit->field.MCS;
else if (pTransmit->field.MODE == MODE_OFDM)
pTxBlk->TxRate = (UCHAR)(pTransmit->field.MCS + RATE_FIRST_OFDM_RATE);
else
pTxBlk->TxRate = RATE_6_5;
/* decide how much time an ACK/CTS frame will consume in the air */
if (pTxBlk->TxRate <= RATE_LAST_OFDM_RATE)
AckDuration = RTMPCalcDuration(pAd, pAd->CommonCfg.ExpectedACKRate[pTxBlk->TxRate], 14);
else
AckDuration = RTMPCalcDuration(pAd, RATE_6_5, 14);
/*DBGPRINT(RT_DEBUG_INFO, ("!!!Fragment AckDuration(%d), TxRate(%d)!!!\n", AckDuration, pTxBlk->TxRate)); */
#ifdef SOFT_ENCRYPT
if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt)) {
/* store the outgoing frame for calculating MIC per fragmented frame */
os_alloc_mem(pAd, (PUCHAR *)&tmp_ptr, pTxBlk->SrcBufLen);
if (tmp_ptr == NULL) {
DBGPRINT(RT_DEBUG_ERROR, ("%s():no memory for MIC calculation!\n",
__FUNCTION__));
RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
return;
}
NdisMoveMemory(tmp_ptr, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen);
}
#endif /* SOFT_ENCRYPT */
/* Init the total payload length of this frame. */
SrcRemainingBytes = pTxBlk->SrcBufLen;
pTxBlk->TotalFragNum = 0xff;
do {
FreeMpduSize = pAd->CommonCfg.FragmentThreshold - LENGTH_CRC;
FreeMpduSize -= pTxBlk->MpduHeaderLen;
if (SrcRemainingBytes <= FreeMpduSize)
{
/* This is the last or only fragment */
pTxBlk->SrcBufLen = SrcRemainingBytes;
wifi_hdr->FC.MoreFrag = 0;
wifi_hdr->Duration = pAd->CommonCfg.Dsifs + AckDuration;
/* Indicate the lower layer that this's the last fragment. */
pTxBlk->TotalFragNum = fragNum;
#ifdef MT_MAC
pTxBlk->FragIdx = ((fragNum == 0) ? TX_FRAG_ID_NO : TX_FRAG_ID_LAST);
#endif /* MT_MAC */
}
else
{ /* more fragment is required */
pTxBlk->SrcBufLen = FreeMpduSize;
NextMpduSize = min(((UINT)SrcRemainingBytes - pTxBlk->SrcBufLen),
((UINT)pAd->CommonCfg.FragmentThreshold));
wifi_hdr->FC.MoreFrag = 1;
wifi_hdr->Duration = (3 * pAd->CommonCfg.Dsifs) + (2 * AckDuration) +
RTMPCalcDuration(pAd, pTxBlk->TxRate, NextMpduSize + EncryptionOverhead);
#ifdef MT_MAC
pTxBlk->FragIdx = ((fragNum == 0) ? TX_FRAG_ID_FIRST : TX_FRAG_ID_MIDDLE);
#endif /* MT_MAC */
}
SrcRemainingBytes -= pTxBlk->SrcBufLen;
if (fragNum == 0)
pTxBlk->FrameGap = IFS_HTTXOP;
else
pTxBlk->FrameGap = IFS_SIFS;
#ifdef SOFT_ENCRYPT
if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt))
{
UCHAR ext_offset = 0;
NdisMoveMemory(pTxBlk->pSrcBufData, tmp_ptr + buf_offset, pTxBlk->SrcBufLen);
buf_offset += pTxBlk->SrcBufLen;
/* Encrypt the MPDU data by software */
RTMPSoftEncryptionAction(pAd,
pTxBlk->CipherAlg,
(UCHAR *)wifi_hdr,
pTxBlk->pSrcBufData,
pTxBlk->SrcBufLen,
pTxBlk->KeyIdx,
pTxBlk->pKey,
&ext_offset);
pTxBlk->SrcBufLen += ext_offset;
pTxBlk->TotalFrameLen += ext_offset;
}
#endif /* SOFT_ENCRYPT */
write_tmac_info_Data(pAd, &pTxBlk->HeaderBuf[0], pTxBlk);
#if 0
DBGPRINT(RT_DEBUG_OFF, ("%s(): FRagNum=%d, FragIdx=%d\n",
__FUNCTION__, fragNum, pTxBlk->FragIdx));
hex_dump("Frag_Frame-FirstBufContent", pTxBlk->HeaderBuf, 128);
hex_dump("Frag_Frame-FirstBufContent - WiFi Hdr Segment", pTxBlk->wifi_hdr, pTxBlk->wifi_hdr_len);
DBGPRINT(RT_DEBUG_OFF, ("%s(): pTxBlk->MpduHeaderLen=%d, wifi_hdr_len=%d, HdrPadLen=%d, hw_rsv_len=%d\n",
__FUNCTION__, pTxBlk->MpduHeaderLen, pTxBlk->wifi_hdr_len, pTxBlk->HdrPadLen, pTxBlk->hw_rsv_len));
dump_tmac_info(pAd, &pTxBlk->HeaderBuf[pTxBlk->hw_rsv_len]);
#endif
HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, &freeCnt);
#ifdef SMART_ANTENNA
if (pTxBlk->pMacEntry)
pTxBlk->pMacEntry->saTxCnt++;
#endif /* SMART_ANTENNA */
#ifdef DBG_CTRL_SUPPORT
#ifdef INCLUDE_DEBUG_QUEUE
if (pAd->CommonCfg.DebugFlags & DBF_DBQ_TXFRAME)
dbQueueEnqueueTxFrame((UCHAR *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (UCHAR *)wifi_hdr);
#endif /* INCLUDE_DEBUG_QUEUE */
#endif /* DBG_CTRL_SUPPORT */
pAd->RalinkCounters.KickTxCount++;
pAd->RalinkCounters.OneSecTxDoneCount++;
#ifdef SOFT_ENCRYPT
if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt))
{
#ifdef WAPI_SUPPORT
if (pTxBlk->CipherAlg == CIPHER_SMS4)
{
/* incease WPI IV for next MPDU */
inc_iv_byte(pTxBlk->pKey->TxTsc, LEN_WAPI_TSC, 2);
/* Construct and insert WPI-SMS4 IV header to MPDU header */
RTMPConstructWPIIVHdr(pTxBlk->KeyIdx, pTxBlk->pKey->TxTsc,
pHeaderBufPtr - (LEN_WPI_IV_HDR));
}
else
#endif /* WAPI_SUPPORT */
if ((pTxBlk->CipherAlg == CIPHER_WEP64) || (pTxBlk->CipherAlg == CIPHER_WEP128))
{
inc_iv_byte(pTxBlk->pKey->TxTsc, LEN_WEP_TSC, 1);
/* Construct and insert 4-bytes WEP IV header to MPDU header */
RTMPConstructWEPIVHdr(pTxBlk->KeyIdx, pTxBlk->pKey->TxTsc,
pHeaderBufPtr - (LEN_WEP_IV_HDR));
}
else if (pTxBlk->CipherAlg == CIPHER_TKIP)
;
else if (pTxBlk->CipherAlg == CIPHER_AES)
{
inc_iv_byte(pTxBlk->pKey->TxTsc, LEN_WPA_TSC, 1);
/* Construct and insert 8-bytes CCMP header to MPDU header */
RTMPConstructCCMPHdr(pTxBlk->KeyIdx, pTxBlk->pKey->TxTsc,
pHeaderBufPtr - (LEN_CCMP_HDR));
}
}
else
#endif /* SOFT_ENCRYPT */
{
/* Update the frame number, remaining size of the NDIS packet payload. */
if (fragNum == 0 && pTxBlk->pExtraLlcSnapEncap)
pTxBlk->MpduHeaderLen -= LENGTH_802_1_H; /* space for 802.11 header. */
}
fragNum++;
/* SrcRemainingBytes -= pTxBlk->SrcBufLen; */
pTxBlk->pSrcBufData += pTxBlk->SrcBufLen;
wifi_hdr->Frag++; /* increase Frag # */
} while (SrcRemainingBytes > 0);
#ifdef SOFT_ENCRYPT
if (tmp_ptr != NULL)
os_free_mem(pAd, tmp_ptr);
#endif /* SOFT_ENCRYPT */
/*
Kick out Tx
*/
HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
//DBGPRINT(RT_DEBUG_TRACE, ("<--%s(%d):Success\n", __FUNCTION__, __LINE__));
}
VOID AP_ARalink_Frame_Tx(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk)
{
UCHAR *buf_ptr;
USHORT freeCnt = 1;
USHORT totalMPDUSize = 0;
USHORT FirstTx, LastTxIdx;
int frameNum = 0;
BOOLEAN bVLANPkt;
PQUEUE_ENTRY pQEntry;
ASSERT(pTxBlk);
ASSERT((pTxBlk->TxPacketList.Number == 2));
FirstTx = LastTxIdx = 0; /* Is it ok init they as 0? */
while (pTxBlk->TxPacketList.Head)
{
pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) {
#ifdef STATS_COUNT_SUPPORT
BSS_STRUCT *pMbss = pTxBlk->pMbss;
if (pMbss != NULL)
pMbss->TxDropCount++;
#endif /* STATS_COUNT_SUPPORT */
RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
continue;
}
/* skip 802.3 header */
pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
pTxBlk->SrcBufLen -= LENGTH_802_3;
/* skip vlan tag */
bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
if (bVLANPkt) {
pTxBlk->pSrcBufData += LENGTH_802_1Q;
pTxBlk->SrcBufLen -= LENGTH_802_1Q;
}
/*
For first frame, we need to create:
802.11 header + padding(optional) + RA-AGG-LEN + SNAP Header
For second aggregated frame, we need create:
the 802.3 header to headerBuf, because PCI will copy it to SDPtr0
*/
if (frameNum == 0)
{
buf_ptr = AP_Build_ARalink_Frame_Header(pAd, pTxBlk);
/*
It's ok write the TxWI here, because the TxWI->TxWIMPDUByteCnt
will be updated after final frame was handled.
*/
write_tmac_info_Data(pAd, &pTxBlk->HeaderBuf[0], pTxBlk);
#if 0
DBGPRINT(RT_DEBUG_OFF, ("%s(): frameNum=%d, pHeaderBufPtr=%p\n", __FUNCTION__, frameNum, pHeaderBufPtr));
hex_dump("ARalink_Frame-FirstBufContent", pTxBlk->HeaderBuf, 128);
hex_dump("ARalink_Frame-FirstBufContent - WiFi Hdr Segment", pTxBlk->wifi_hdr, pTxBlk->wifi_hdr_len);
DBGPRINT(RT_DEBUG_OFF, ("%s(): pTxBlk->MpduHeaderLen=%d, wifi_hdr_len=%d, HdrPadLen=%d, hw_rsv_len=%d\n",
__FUNCTION__, pTxBlk->MpduHeaderLen, pTxBlk->wifi_hdr_len, pTxBlk->HdrPadLen, pTxBlk->hw_rsv_len));
dump_tmac_info(pAd, &pTxBlk->HeaderBuf[pTxBlk->hw_rsv_len]);
#endif
#ifdef MESH_SUPPORT
if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bMeshEntry))
InsertPktMeshHeader(pAd, pTxBlk, &buf_ptr);
#endif /* MESH_SUPPORT */
/* Insert LLC-SNAP encapsulation - 8 octets */
EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData - 2,
pTxBlk->pExtraLlcSnapEncap);
if (pTxBlk->pExtraLlcSnapEncap) {
NdisMoveMemory(buf_ptr, pTxBlk->pExtraLlcSnapEncap, 6);
buf_ptr += 6;
/* get 2 octets (TypeofLen) */
NdisMoveMemory(buf_ptr, pTxBlk->pSrcBufData - 2, 2);
/* buf_ptr += 2; */
pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
}
}
else
{
buf_ptr = &pTxBlk->HeaderBuf[0];
pTxBlk->MpduHeaderLen = 0;
/*
A-Ralink sub-sequent frame header is the same as 802.3 header.
DA(6)+SA(6)+FrameType(2)
*/
NdisMoveMemory(buf_ptr, pTxBlk->pSrcBufHeader, 12);
buf_ptr += 12;
/* get 2 octets (TypeofLen) */
NdisMoveMemory(buf_ptr, pTxBlk->pSrcBufData - 2, 2);
buf_ptr += 2;
pTxBlk->MpduHeaderLen = ARALINK_SUBHEAD_LEN;
}
#if defined(MT7603) || defined(MT7628)
if (frameNum == 0)
totalMPDUSize += pAd->chipCap.tx_hw_hdr_len - pTxBlk->hw_rsv_len + pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen + pTxBlk->SrcBufLen;
else
totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
#else
totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
#endif /* defined(MT7603) || defined(MT7628) */
if (frameNum == 0)
FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, (UCHAR)frameNum, &freeCnt);
else
LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk
, (UCHAR)frameNum, &freeCnt);
#ifdef SMART_ANTENNA
if (pTxBlk->pMacEntry)
pTxBlk->pMacEntry->saTxCnt++;
#endif /* SMART_ANTENNA */
#ifdef DBG_CTRL_SUPPORT
#ifdef INCLUDE_DEBUG_QUEUE
if (pAd->CommonCfg.DebugFlags & DBF_DBQ_TXFRAME)
dbQueueEnqueueTxFrame((UCHAR *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), NULL);
#endif /* INCLUDE_DEBUG_QUEUE */
#endif /* DBG_CTRL_SUPPORT */
frameNum++;
pAd->RalinkCounters.OneSecTxARalinkCnt++;
pAd->RalinkCounters.KickTxCount++;
pAd->RalinkCounters.OneSecTxDoneCount++;
#ifdef STATS_COUNT_SUPPORT
/* calculate Tx count and ByteCount per BSS */
#ifdef WAPI_SUPPORT
if (pTxBlk->pMacEntry && IS_ENTRY_CLIENT(pTxBlk->pMacEntry))
#endif /* WAPI_SUPPORT */
{
BSS_STRUCT *pMbss = pTxBlk->pMbss;
MAC_TABLE_ENTRY *pMacEntry=pTxBlk->pMacEntry;
#ifdef WAPI_SUPPORT
if (pTxBlk->pMacEntry->WapiUskRekeyTimerRunning && pAd->CommonCfg.wapi_usk_rekey_method == REKEY_METHOD_PKT)
pTxBlk->pMacEntry->wapi_usk_rekey_cnt += totalMPDUSize;
#endif /* WAPI_SUPPORT */
if (pMbss != NULL)
{
pMbss->TransmittedByteCount += totalMPDUSize;
pMbss->TxCount ++;
#ifdef STATS_COUNT_SUPPORT
if(IS_MULTICAST_MAC_ADDR(pTxBlk->pSrcBufHeader))
pMbss->mcPktsTx++;
else if(IS_BROADCAST_MAC_ADDR(pTxBlk->pSrcBufHeader))
pMbss->bcPktsTx++;
else
pMbss->ucPktsTx++;
#endif /* STATS_COUNT_SUPPORT */
}
if(pMacEntry && pMacEntry->Sst == SST_ASSOC)
{
INC_COUNTER64(pMacEntry->TxPackets);
pMacEntry->TxBytes+=pTxBlk->SrcBufLen;
pAd->TxTotalByteCnt += pTxBlk->SrcBufLen;
}
}
#ifdef WDS_SUPPORT
if (pTxBlk->pMacEntry && IS_ENTRY_WDS(pTxBlk->pMacEntry))
{
INC_COUNTER64(pAd->WdsTab.WdsEntry[pTxBlk->pMacEntry->func_tb_idx].WdsCounter.TransmittedFragmentCount);
pAd->WdsTab.WdsEntry[pTxBlk->pMacEntry->func_tb_idx].WdsCounter.TransmittedByteCount+= pTxBlk->SrcBufLen;
}
#endif /* WDS_SUPPORT */
#endif /* STATS_COUNT_SUPPORT */
}
HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
/*
Kick out Tx
*/
HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
}
#ifdef VHT_TXBF_SUPPORT
VOID AP_NDPA_Frame_Tx(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk)
{
UCHAR *buf;
VHT_NDPA_FRAME *vht_ndpa;
struct wifi_dev *wdev;
UINT frm_len, sta_cnt;
SNDING_STA_INFO *sta_info;
MAC_TABLE_ENTRY *pMacEntry;
pTxBlk->Wcid = RTMP_GET_PACKET_WCID(pTxBlk->pPacket);
pTxBlk->pMacEntry = &pAd->MacTab.Content[pTxBlk->Wcid];
pMacEntry = pTxBlk->pMacEntry;
if (pMacEntry)
{
wdev = pMacEntry->wdev;
if (MlmeAllocateMemory(pAd, &buf) != NDIS_STATUS_SUCCESS)
return;
NdisZeroMemory(buf, MGMT_DMA_BUFFER_SIZE);
vht_ndpa = (VHT_NDPA_FRAME *)buf;
frm_len = sizeof(VHT_NDPA_FRAME);
vht_ndpa->fc.Type = FC_TYPE_CNTL;
vht_ndpa->fc.SubType = SUBTYPE_VHT_NDPA;
COPY_MAC_ADDR(vht_ndpa->ra, pMacEntry->Addr);
COPY_MAC_ADDR(vht_ndpa->ta, wdev->if_addr);
/* Currnetly we only support 1 STA for a VHT DNPA */
sta_info = vht_ndpa->sta_info;
for (sta_cnt = 0; sta_cnt < 1; sta_cnt++) {
sta_info->aid12 = pMacEntry->Aid;
sta_info->fb_type = SNDING_FB_SU;
sta_info->nc_idx = 0;
vht_ndpa->token.token_num = pMacEntry->snd_dialog_token;
frm_len += sizeof(SNDING_STA_INFO);
sta_info++;
if (frm_len >= (MGMT_DMA_BUFFER_SIZE - sizeof(SNDING_STA_INFO))) {
DBGPRINT(RT_DEBUG_ERROR, ("%s(): len(%d) too large!cnt=%d\n",
__FUNCTION__, frm_len, sta_cnt));
break;
}
}
if (pMacEntry->snd_dialog_token & 0xc0)
pMacEntry->snd_dialog_token = 0;
else
pMacEntry->snd_dialog_token++;
#if 0 // Jason's suggestion
vht_ndpa->duration = pAd->CommonCfg.Dsifs +
RTMPCalcDuration(pAd, pAd->CommonCfg.MlmeRate, frm_len);
#else
vht_ndpa->duration = 100;
#endif
//DBGPRINT(RT_DEBUG_OFF, ("Send VHT NDPA Frame to STA(%02x:%02x:%02x:%02x:%02x:%02x)\n",
// PRINT_MAC(pMacEntry->Addr)));
//hex_dump("VHT NDPA Frame", buf, frm_len);
// NDPA's BW needs to sync with Tx BW
pAd->CommonCfg.MlmeTransmit.field.BW = pMacEntry->HTPhyMode.field.BW;
pTxBlk->Flags = FALSE; // No Acq Request
// TODO: shiang-lock, fix ME!!
MiniportMMRequest(pAd, 0, buf, frm_len);
MlmeFreeMemory(pAd, buf);
}
pMacEntry->TxSndgType = SNDG_TYPE_DISABLE;
}
#endif /* VHT_TXBF_SUPPORT */
/*
========================================================================
Routine Description:
Copy frame from waiting queue into relative ring buffer and set
appropriate ASIC register to kick hardware encryption before really
sent out to air.
Arguments:
pAd Pointer to our adapter
pTxBlk Pointer to outgoing TxBlk structure.
QueIdx Queue index for processing
Return Value:
None
========================================================================
*/
NDIS_STATUS APHardTransmit(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk)
{
PQUEUE_ENTRY pQEntry;
PNDIS_PACKET pPacket = NULL;
DBGPRINT(RT_DEBUG_INFO, ("%s(%d)-->\n", __FUNCTION__, __LINE__));
if ((pAd->Dot11_H.RDMode != RD_NORMAL_MODE)
#ifdef CARRIER_DETECTION_SUPPORT
||(isCarrierDetectExist(pAd) == TRUE)
#endif /* CARRIER_DETECTION_SUPPORT */
)
{
while(pTxBlk->TxPacketList.Head)
{
pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
if (pPacket)
RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
}
DBGPRINT(RT_DEBUG_INFO, ("<--%s(%d)\n", __FUNCTION__, __LINE__));
return NDIS_STATUS_FAILURE;
}
/*DTV00663496*/
/* if device is not in AP MODE, and the p2p GO interface is down, release the packet form TX queue avoid crash issue.*/
if ((pAd->cfg80211_ctrl.isCfgInApMode != RT_CMD_80211_IFTYPE_AP)
&& (!RTMP_CFG80211_VIF_P2P_GO_ON(pAd)) && (!RTMP_CFG80211_VIF_P2P_CLI_ON(pAd)))
{
DBGPRINT(RT_DEBUG_TRACE, ("%s(%d) device is not in AP MODE,and the p2p GO interface is down, release the packet!\n", __FUNCTION__, __LINE__));
if (pPacket)
RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
return NDIS_STATUS_FAILURE;
}
if (pTxBlk->wdev->bVLAN_Tag == TRUE)
{
RTMP_SET_PACKET_VLAN(pTxBlk->pPacket, FALSE);
}
/*add hook point when dequeue*/
RTMP_OS_TXRXHOOK_CALL(WLAN_TX_DEQUEUE,pPacket,pTxBlk->QueIdx,pAd);
#ifdef DOT11K_RRM_SUPPORT
#ifdef QUIET_SUPPORT
{
struct wifi_dev *wdev = pAd->wdev_list[pTxBlk->wdev_idx];
if ((wdev->func_idx < pAd->ApCfg.BssidNum)
&& IS_RRM_QUIET(pAd, wdev->func_idx))
{
RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
return NDIS_STATUS_FAILURE;
}
}
#endif /* QUIET_SUPPORT */
#endif /* DOT11K_RRM_SUPPORT */
#ifdef HDR_TRANS_TX_SUPPORT
#ifdef MESH_SUPPORT
if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bMeshEntry))
pTxBlk->NeedTrans = FALSE;
else
#endif /* MESH_SUPPORT */
#ifdef SOFT_ENCRYPT
if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt)) /* need LLC, not yet generated */
pTxBlk->NeedTrans = FALSE;
else
#endif /* SOFT_ENCRYPT */
#ifdef WDS_SUPPORT
if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWDSEntry))
pTxBlk->NeedTrans = FALSE;
else
#endif /* WDS_SUPPORT */
{
pTxBlk->NeedTrans = TRUE;
#ifdef TXBF_SUPPORT
pTxBlk->NeedTrans = FALSE;
#endif // TXBF_SUPPORT //
}
#endif /* HDR_TRANS_TX_SUPPORT */
#ifdef VHT_TXBF_SUPPORT
if ((pTxBlk->TxFrameType & TX_NDPA_FRAME) > 0)
{
UCHAR mlmeMCS, mlmeBW, mlmeMode;
mlmeMCS = pAd->CommonCfg.MlmeTransmit.field.MCS;
mlmeBW = pAd->CommonCfg.MlmeTransmit.field.BW;
mlmeMode = pAd->CommonCfg.MlmeTransmit.field.MODE;
pAd->NDPA_Request = TRUE;
AP_NDPA_Frame_Tx(pAd, pTxBlk);
pAd->NDPA_Request = FALSE;
pTxBlk->TxFrameType &= ~TX_NDPA_FRAME;
// Finish NDPA and then recover to mlme's own setting
pAd->CommonCfg.MlmeTransmit.field.MCS = mlmeMCS;
pAd->CommonCfg.MlmeTransmit.field.BW = mlmeBW;
pAd->CommonCfg.MlmeTransmit.field.MODE = mlmeMode;
}
#endif
switch (pTxBlk->TxFrameType)
{
#ifdef DOT11_N_SUPPORT
case TX_AMPDU_FRAME:
#ifdef HDR_TRANS_TX_SUPPORT
if (pTxBlk->NeedTrans)
AP_AMPDU_Frame_Tx_Hdr_Trns(pAd, pTxBlk);
else
#endif /* HDR_TRANS_TX_SUPPORT */
AP_AMPDU_Frame_Tx(pAd, pTxBlk);
break;
#endif /* DOT11_N_SUPPORT */
case TX_LEGACY_FRAME:
#ifdef HDR_TRANS_TX_SUPPORT
if (pTxBlk->NeedTrans)
AP_Legacy_Frame_Tx_Hdr_Trns(pAd, pTxBlk);
else
#endif /* HDR_TRANS_TX_SUPPORT */
AP_Legacy_Frame_Tx(pAd, pTxBlk);
break;
case TX_MCAST_FRAME:
#ifdef HDR_TRANS_TX_SUPPORT
pTxBlk->NeedTrans = FALSE;
#endif /* HDR_TRANS_TX_SUPPORT */
AP_Legacy_Frame_Tx(pAd, pTxBlk);
break;
#ifdef DOT11_N_SUPPORT
case TX_AMSDU_FRAME:
AP_AMSDU_Frame_Tx(pAd, pTxBlk);
break;
#endif /* DOT11_N_SUPPORT */
case TX_RALINK_FRAME:
AP_ARalink_Frame_Tx(pAd, pTxBlk);
break;
case TX_FRAG_FRAME:
AP_Fragment_Frame_Tx(pAd, pTxBlk);
break;
default:
{
/* It should not happened! */
DBGPRINT(RT_DEBUG_ERROR, ("Send a pacekt was not classified!!\n"));
while (pTxBlk->TxPacketList.Head) {
pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
if (pPacket)
RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
}
}
break;
}
DBGPRINT(RT_DEBUG_INFO, ("<--%s(%d)\n", __FUNCTION__, __LINE__));
return (NDIS_STATUS_SUCCESS);
}
/*
========================================================================
Description:
This routine checks if a received frame causes class 2 or class 3
error, and perform error action (DEAUTH or DISASSOC) accordingly
========================================================================
*/
BOOLEAN APChkCls2Cls3Err(RTMP_ADAPTER *pAd, UCHAR wcid, HEADER_802_11 *hdr)
{
/* software MAC table might be smaller than ASIC on-chip total size. */
/* If no mathed wcid index in ASIC on chip, do we need more check??? need to check again. 06-06-2006 */
if (wcid >= MAX_LEN_OF_MAC_TABLE)
{
MAC_TABLE_ENTRY *pEntry;
DBGPRINT(RT_DEBUG_WARN, ("%s():Rx a frame from %02x:%02x:%02x:%02x:%02x:%02x with WCID(%d) > %d\n",
__FUNCTION__, PRINT_MAC(hdr->Addr2),
wcid, MAX_LEN_OF_MAC_TABLE));
//+++Add by shiang for debug
pEntry = MacTableLookup(pAd, hdr->Addr2);
if (pEntry)
return FALSE;
//---Add by shiang for debug
APCls2errAction(pAd, MAX_LEN_OF_MAC_TABLE, hdr);
return TRUE;
}
if (pAd->MacTab.Content[wcid].Sst == SST_ASSOC)
; /* okay to receive this DATA frame */
else if (pAd->MacTab.Content[wcid].Sst == SST_AUTH)
{
APCls3errAction(pAd, wcid, hdr);
return TRUE;
}
else
{
APCls2errAction(pAd, wcid, hdr);
return TRUE;
}
return FALSE;
}
/*
detect AC Category of trasmitting packets
to turn AC0(BE) TX_OP (MAC reg 0x1300)
*/
// TODO: shiang-usw, this function should move to other place!!
VOID detect_wmm_traffic(
IN RTMP_ADAPTER *pAd,
IN UCHAR UserPriority,
IN UCHAR FlgIsOutput)
{
/* For BE & BK case and TxBurst function is disabled */
if ((pAd->CommonCfg.bEnableTxBurst == FALSE)
#ifdef DOT11_N_SUPPORT
&& (pAd->CommonCfg.bRdg == FALSE)
&& (pAd->CommonCfg.bRalinkBurstMode == FALSE)
#endif /* DOT11_N_SUPPORT */
&& (FlgIsOutput == 1)
)
{
if (WMM_UP2AC_MAP[UserPriority] == QID_AC_BK)
{
/* has any BK traffic */
if (pAd->flg_be_adjust == 0)
{
/* yet adjust */
#ifdef RTMP_MAC_PCI
AsicSetWmmParam(pAd, WMM_PARAM_AC_0, WMM_PARAM_TXOP, 0x20);
#endif /* RTMP_MAC_PCI */
#ifdef RTMP_MAC_USB
RTEnqueueInternalCmd(pAd, CMDTHREAD_AP_ENABLE_TX_BURST, NULL, 0);
#endif /* RTMP_MAC_USB */
pAd->flg_be_adjust = 1;
NdisGetSystemUpTime(&pAd->be_adjust_last_time);
DBGPRINT(RT_DEBUG_TRACE, ("wmm> adjust be!\n"));
}
}
else
{
if (pAd->flg_be_adjust != 0)
{
QUEUE_HEADER *pQueue;
/* has adjusted */
pQueue = &pAd->TxSwQueue[QID_AC_BK];
if ((pQueue == NULL) ||
((pQueue != NULL) && (pQueue->Head == NULL)))
{
ULONG now;
NdisGetSystemUpTime(&now);
if ((now - pAd->be_adjust_last_time) > TIME_ONE_SECOND)
{
/* no any BK traffic */
#ifdef RTMP_MAC_PCI
// TODO: shiang-7603
AsicSetWmmParam(pAd, WMM_PARAM_AC_0, WMM_PARAM_TXOP, 0x0);
#endif /* RTMP_MAC_PCI */
#ifdef RTMP_MAC_USB
RTEnqueueInternalCmd(pAd, CMDTHREAD_AP_DISABLE_TX_BURST, NULL, 0);
#endif /* RTMP_MAC_USB */
pAd->flg_be_adjust = 0;
DBGPRINT(RT_DEBUG_TRACE, ("wmm> recover be!\n"));
}
}
else
NdisGetSystemUpTime(&pAd->be_adjust_last_time);
}
}
}
/* count packets which priority is more than BE */
if (UserPriority > 3)
{
pAd->OneSecondnonBEpackets++;
if (pAd->OneSecondnonBEpackets > 100
#ifdef DOT11_N_SUPPORT
&& pAd->MacTab.fAnyStationMIMOPSDynamic
#endif /* DOT11_N_SUPPORT */
)
{
if (!pAd->is_on)
{
#ifdef RTMP_MAC_PCI
// TODO: shiang-7603
RTMP_IO_WRITE32(pAd, EXP_ACK_TIME, 0x005400ca );
#endif /* RTMP_MAC_PCI */
#ifdef RTMP_MAC_USB
RTEnqueueInternalCmd(pAd, CMDTHREAD_AP_ADJUST_EXP_ACK_TIME, NULL, 0);
#endif /* RTMP_MAC_USB */
pAd->is_on = 1;
}
}
else
{
if (pAd->is_on)
{
#ifdef RTMP_MAC_PCI
// TODO: shiang-7603
RTMP_IO_WRITE32(pAd, EXP_ACK_TIME, 0x002400ca );
#endif /* RTMP_MAC_PCI */
#ifdef RTMP_MAC_USB
RTEnqueueInternalCmd(pAd, CMDTHREAD_AP_RECOVER_EXP_ACK_TIME, NULL, 0);
#endif /* RTMP_MAC_USB */
pAd->is_on = 0;
}
}
}
}
VOID APRxErrorHandle(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk)
{
MAC_TABLE_ENTRY *pEntry = NULL;
RXINFO_STRUC *pRxInfo = pRxBlk->pRxInfo;
if (pRxInfo->CipherErr)
INC_COUNTER64(pAd->WlanCounters.WEPUndecryptableCount);
if (pRxInfo->U2M && pRxInfo->CipherErr)
{
if (pRxBlk->wcid < MAX_LEN_OF_MAC_TABLE)
{
#ifdef APCLI_SUPPORT
#ifdef WPA_SUPPLICANT_SUPPORT
PCIPHER_KEY pWpaKey;
//UCHAR bss_idx = BSS0;
UCHAR Wcid;
PHEADER_802_11 pHeader = pRxBlk->pHeader;
Wcid = pRxBlk->wcid;
if (VALID_WCID(Wcid))
pEntry = ApCliTableLookUpByWcid(pAd, Wcid, pHeader->Addr2);
else
pEntry = MacTableLookup(pAd, pHeader->Addr2);
if (pEntry && IS_ENTRY_APCLI(pEntry))
{
if (pRxInfo->CipherErr == 2)
{
pWpaKey = &pEntry->PairwiseKey;
if (pAd->ApCfg.ApCliTab[pEntry->func_tb_idx].wpa_supplicant_info.WpaSupplicantUP)
{
WpaSendMicFailureToWpaSupplicant(pAd->net_dev, pHeader->Addr2,
(pWpaKey->Type == PAIRWISEKEY) ? TRUE : FALSE,
(INT)pRxBlk->key_idx, NULL);
}
if (((pRxInfo->CipherErr & 2) == 2) && INFRA_ON(pAd))
RTMPSendWirelessEvent(pAd, IW_MIC_ERROR_EVENT_FLAG, pEntry->Addr, pEntry->wdev->wdev_idx, 0);
DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error\n"));
}
}
else
#endif /* WPA_SUPPLICANT_SUPPORT */
#endif /* APCLI_SUPPORT */
{
pEntry = &pAd->MacTab.Content[pRxBlk->wcid];
/*
MIC error
Before verifying the MIC, the receiver shall check FCS, ICV and TSC.
This avoids unnecessary MIC failure events.
*/
if ((pEntry->WepStatus == Ndis802_11TKIPEnable)
&& (pRxInfo->CipherErr == 2))
{
#ifdef HOSTAPD_SUPPORT
if(pAd->ApCfg.MBSSID[pEntry->func_tb_idx].Hostapd == Hostapd_EXT)
ieee80211_notify_michael_failure(pAd, pRxBlk->pHeader, (UINT32)pRxBlk->key_idx, 0);
else
#endif/*HOSTAPD_SUPPORT*/
{
RTMP_HANDLE_COUNTER_MEASURE(pAd, pEntry);
}
}
/* send wireless event - for icv error */
if ((pRxInfo->CipherErr & 1) == 1)
RTMPSendWirelessEvent(pAd, IW_ICV_ERROR_EVENT_FLAG, pEntry->Addr, 0, 0);
}
}
DBGPRINT(RT_DEBUG_TRACE, ("Rx u2me Cipher Err(MPDUsize=%d, WCID=%d, CipherErr=%d)\n",
pRxBlk->MPDUtotalByteCnt, pRxBlk->wcid, pRxInfo->CipherErr));
}
}
#ifdef RLT_MAC_DBG
static int dump_next_valid = 0;
#endif
BOOLEAN APCheckVaildDataFrame(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk)
{
HEADER_802_11 *pHeader = pRxBlk->pHeader;
BOOLEAN isVaild = FALSE;
do
{
if (pHeader->FC.ToDs == 0)
break;
#ifdef IDS_SUPPORT
if ((pHeader->FC.FrDs == 0) && (pRxBlk->wcid == RESERVED_WCID)) /* not in RX WCID MAC table */
{
if (++pAd->ApCfg.RcvdMaliciousDataCount > pAd->ApCfg.DataFloodThreshold)
break;
}
#endif /* IDS_SUPPORT */
/* check if Class2 or 3 error */
if ((pHeader->FC.FrDs == 0) && (APChkCls2Cls3Err(pAd, pRxBlk->wcid, pHeader)))
break;
//+++Add by shiang for debug
#ifdef RLT_MAC_DBG
if (pAd->chipCap.hif_type == HIF_RLT) {
if (pRxBlk->wcid >= MAX_LEN_OF_MAC_TABLE) {
MAC_TABLE_ENTRY *pEntry = NULL;
DBGPRINT(RT_DEBUG_WARN, ("ErrWcidPkt: seq=%d\n", pHeader->Sequence));
pEntry = MacTableLookup(pAd, pHeader->Addr2);
if (pEntry && (pEntry->Sst == SST_ASSOC) && IS_ENTRY_CLIENT(pEntry))
pRxBlk->wcid = pEntry->wcid;
dump_next_valid = 1;
}
else if (dump_next_valid)
{
DBGPRINT(RT_DEBUG_WARN, ("NextValidWcidPkt: seq=%d\n", pHeader->Sequence));
dump_next_valid = 0;
}
}
#endif /* RLT_MAC_DBG */
//---Add by shiang for debug
if(pAd->ApCfg.BANClass3Data == TRUE)
break;
isVaild = TRUE;
} while (0);
return isVaild;
}
INT ap_rx_pkt_allow(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk)
{
RXINFO_STRUC *pRxInfo = pRxBlk->pRxInfo;
HEADER_802_11 *pHeader = pRxBlk->pHeader;
#if defined(WDS_SUPPORT) || defined(CLIENT_WDS) || defined(IDS_SUPPORT)
FRAME_CONTROL *pFmeCtrl = &pHeader->FC;
#endif
MAC_TABLE_ENTRY *pEntry = NULL;
INT hdr_len = 0;
pEntry = PACInquiry(pAd, pRxBlk->wcid);
#if defined(WDS_SUPPORT) || defined(CLIENT_WDS)
if ((pFmeCtrl->FrDs == 1) && (pFmeCtrl->ToDs == 1))
{
#ifdef CLIENT_WDS
if (pEntry) {
/* The CLIENT WDS must be a associated STA */
if (IS_ENTRY_CLIWDS(pEntry))
;
else if (IS_ENTRY_CLIENT(pEntry) && (pEntry->Sst == SST_ASSOC))
SET_ENTRY_CLIWDS(pEntry);
else
return FALSE;
CliWds_ProxyTabUpdate(pAd, pEntry->Aid, pHeader->Octet);
}
#endif /* CLIENT_WDS */
#ifdef WDS_SUPPORT
if (!pEntry)
{
/*
The WDS frame only can go here when in auto learning mode and
this is the first trigger frame from peer
So we check if this is un-registered WDS entry by call function
"FindWdsEntry()"
*/
if (MAC_ADDR_EQUAL(pHeader->Addr1, pAd->CurrentAddress))
pEntry = FindWdsEntry(pAd, pRxBlk->wcid, pHeader->Addr2, pRxBlk->rx_rate.field.MODE);
/* have no valid wds entry exist, then discard the incoming packet.*/
if (!(pEntry && WDS_IF_UP_CHECK(pAd, pEntry->func_tb_idx)))
return FALSE;
/*receive corresponding WDS packet, disable TX lock state (fix WDS jam issue) */
if(pEntry && (pEntry->LockEntryTx == TRUE))
{
DBGPRINT(RT_DEBUG_TRACE, ("Receive WDS packet, disable TX lock state!\n"));
pEntry->ContinueTxFailCnt = 0;
pEntry->LockEntryTx = FALSE;
// TODO: shiang-usw, remove upper setting because we need to mirgate to tr_entry!
pAd->MacTab.tr_entry[pEntry->wcid].ContinueTxFailCnt = 0;
pAd->MacTab.tr_entry[pEntry->wcid].LockEntryTx = FALSE;
}
}
#endif /* WDS_SUPPORT */
if (pEntry)
{
#ifdef STATS_COUNT_SUPPORT
RT_802_11_WDS_ENTRY *pWdsEntry = &pAd->WdsTab.WdsEntry[pEntry->func_tb_idx];
pWdsEntry->WdsCounter.ReceivedByteCount += pRxBlk->MPDUtotalByteCnt;
INC_COUNTER64(pWdsEntry->WdsCounter.ReceivedFragmentCount);
if(IS_MULTICAST_MAC_ADDR(pHeader->Addr3))
INC_COUNTER64(pWdsEntry->WdsCounter.MulticastReceivedFrameCount);
#endif /* STATS_COUNT_SUPPORT */
RX_BLK_SET_FLAG(pRxBlk, fRX_WDS);
hdr_len = LENGTH_802_11_WITH_ADDR4;
return hdr_len;
}
return FALSE;
}
#endif /* defined(WDS_SUPPORT) || defined(CLIENT_WDS) */
if (!pEntry) {
#ifdef IDS_SUPPORT
if ((pHeader->FC.FrDs == 0) && (pRxBlk->wcid == RESERVED_WCID)) /* not in RX WCID MAC table */
pAd->ApCfg.RcvdMaliciousDataCount++;
#endif /* IDS_SUPPORT */
return FALSE;
}
if (!((pHeader->FC.FrDs == 0) && (pHeader->FC.ToDs == 1))) {
#ifdef IDS_SUPPORT
/*
Replay attack detection,
drop it if detect a spoofed data frame from a rogue AP
*/
if (pFmeCtrl->FrDs == 1)
RTMPReplayAttackDetection(pAd, pHeader->Addr2, pRxBlk);
#endif /* IDS_SUPPORT */
return FALSE;
}
/* check if Class2 or 3 error */
if (APChkCls2Cls3Err(pAd, pRxBlk->wcid, pHeader))
return FALSE;
//+++Add by shiang for debug
#ifdef RLT_MAC_DBG
if (pAd->chipCap.hif_type == HIF_RLT) {
if (pRxBlk->wcid >= MAX_LEN_OF_MAC_TABLE) {
MAC_TABLE_ENTRY *pEntry = NULL;
DBGPRINT(RT_DEBUG_WARN, ("ErrWcidPkt: seq=%d\n", pHeader->Sequence));
pEntry = MacTableLookup(pAd, pHeader->Addr2);
if (pEntry && (pEntry->Sst == SST_ASSOC) && IS_ENTRY_CLIENT(pEntry))
pRxBlk->wcid = pEntry->wcid;
dump_next_valid = 1;
}
else if (dump_next_valid)
{
DBGPRINT(RT_DEBUG_WARN, ("NextValidWcidPkt: seq=%d\n", pHeader->Sequence));
dump_next_valid = 0;
}
}
#endif /* RLT_MAC_DBG */
//---Add by shiang for debug
if(pAd->ApCfg.BANClass3Data == TRUE)
return FALSE;
#ifdef STATS_COUNT_SUPPORT
/* Increase received byte counter per BSS */
if (pHeader->FC.FrDs == 0 && pRxInfo->U2M)
{
BSS_STRUCT *pMbss = pEntry->pMbss;
if (pMbss != NULL)
{
pMbss->ReceivedByteCount += pRxBlk->MPDUtotalByteCnt;
pMbss->RxCount ++;
}
}
/* update multicast counter */
if (IS_MULTICAST_MAC_ADDR(pHeader->Addr3))
INC_COUNTER64(pAd->WlanCounters.MulticastReceivedFrameCount);
#endif /* STATS_COUNT_SUPPORT */
hdr_len = LENGTH_802_11;
RX_BLK_SET_FLAG(pRxBlk, fRX_STA);
ASSERT(pEntry->Aid == pRxBlk->wcid);
return hdr_len;
}
INT ap_rx_ps_handle(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk)
{
MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[pRxBlk->wcid];
HEADER_802_11 *pHeader = pRxBlk->pHeader;
UCHAR OldPwrMgmt = PWR_ACTIVE; /* 1: PWR_SAVE, 0: PWR_ACTIVE */
#ifdef UAPSD_SUPPORT
UCHAR *pData = pRxBlk->pData;
#endif /* UAPSD_SUPPORT */
/* 1: PWR_SAVE, 0: PWR_ACTIVE */
OldPwrMgmt = RtmpPsIndicate(pAd, pHeader->Addr2, pEntry->wcid, (UCHAR)pHeader->FC.PwrMgmt);
if(OldPwrMgmt > 2)
DBGPRINT(RT_DEBUG_TRACE, ("OldPwrMgmt is %d\n", OldPwrMgmt));
#ifdef UAPSD_SUPPORT
if ((pHeader->FC.PwrMgmt == PWR_SAVE) &&
(OldPwrMgmt == PWR_SAVE) &&
(CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_APSD_CAPABLE)) &&
(pHeader->FC.SubType & 0x08))
{
/*
In IEEE802.11e, 11.2.1.4 Power management with APSD,
If there is no unscheduled SP in progress, the unscheduled SP begins
when the QAP receives a trigger frame from a non-AP QSTA, which is a
QoS data or QoS Null frame associated with an AC the STA has
configured to be trigger-enabled.
In WMM v1.1, A QoS Data or QoS Null frame that indicates transition
to/from Power Save Mode is not considered to be a Trigger Frame and
the AP shall not respond with a QoS Null frame.
*/
/* Trigger frame must be QoS data or QoS Null frame */
UCHAR OldUP;
// TODO: shiang-usw, check this!!!
#ifdef HDR_TRANS_SUPPORT
if (pRxBlk->bHdrRxTrans) {
#if 0
MT7650E4 - QoS control field would be put in the last DWORD of wifi info.
#endif
// TODO: different chip has different position @20130129. (+32 is for MT7650)
OldUP = (*(pData+32) & 0x07);
}
else
#endif /* HDR_TRANS_SUPPORT */
OldUP = (*(pData+LENGTH_802_11) & 0x07);
#ifdef MT_PS
if (pEntry->i_psm == I_PSM_DISABLE)
{
MT_SET_IGNORE_PSM(pAd, pEntry, I_PSM_ENABLE);
}
#endif /* MT_PS */
UAPSD_TriggerFrameHandle(pAd, pEntry, OldUP);
}
#endif /* UAPSD_SUPPORT */
return TRUE;
}
INT ap_rx_foward_handle(RTMP_ADAPTER *pAd, struct wifi_dev *wdev, PNDIS_PACKET pPacket)
{
MAC_TABLE_ENTRY *pEntry = NULL;
MAC_TABLE_ENTRY *pSrcEntry = NULL;
BOOLEAN to_os, to_air;
UCHAR *pHeader802_3;
PNDIS_PACKET pForwardPacket;
BSS_STRUCT *pMbss;
struct wifi_dev *dst_wdev = NULL;
PHEADER_802_3 pHDR = NULL;
if ((wdev->func_idx < 0) || (wdev->func_idx >= MAX_MBSSID_NUM(pAd)) ||
(wdev->func_idx >= HW_BEACON_MAX_NUM)) {
DBGPRINT(RT_DEBUG_ERROR, ("%s():Invalid func_idx(%d), type(%d)!\n",
__FUNCTION__, wdev->func_idx, wdev->wdev_type));
return FALSE;
}
/* only one connected sta, directly to upper layer */
if (pAd->MacTab.Size <= 1)
return TRUE;
// TODO: shiang-usw, remove pMbss structure here to make it more generic!
pMbss = &pAd->ApCfg.MBSSID[wdev->func_idx];
pHeader802_3 = GET_OS_PKT_DATAPTR(pPacket);
pHDR = (PHEADER_802_3)pHeader802_3;
/* by default, announce this pkt to upper layer (bridge) and not to air */
to_os = TRUE;
to_air = FALSE;
if (pHeader802_3[0] & 0x01)
{
if ((pMbss->StaCount > 1)
#ifdef P2P_SUPPORT
|| (pAd->P2pCfg.bSigmaEnabled == TRUE)
#endif /* P2P_SUPPORT */
) {
/* forward the M/Bcast packet back to air if connected STA > 1 */
to_air = TRUE;
}
}
else
{
/* if destinated STA is a associated wireless STA */
pEntry = MacTableLookup(pAd, pHeader802_3);
if (pEntry && pEntry->Sst == SST_ASSOC && pEntry->wdev)
{
dst_wdev = pEntry->wdev;
if (wdev == dst_wdev)
{
/*
STAs in same SSID, default send to air and not to os,
but not to air if match following case:
a). pMbss->IsolateInterStaTraffic == TRUE
*/
to_air = TRUE;
to_os = FALSE;
if (pMbss->IsolateInterStaTraffic == 1)
to_air = FALSE;
}
else
{
/*
STAs in different SSID, default send to os and not to air
but not to os if match any of following cases:
a). destination VLAN ID != source VLAN ID
b). pAd->ApCfg.IsolateInterStaTrafficBTNBSSID
*/
to_os = TRUE;
to_air = FALSE;
if (pAd->ApCfg.IsolateInterStaTrafficBTNBSSID == 1 ||
(wdev->VLAN_VID != dst_wdev->VLAN_VID))
to_os = FALSE;
/* Check Source STA is in PortSecured then do FWD packet */
pSrcEntry = MacTableLookup(pAd, pHDR->SAAddr2);
if (pSrcEntry) {
STA_TR_ENTRY *tr_entry = &pAd->MacTab.tr_entry[pSrcEntry->tr_tb_idx];
if (tr_entry && (tr_entry->PortSecured != WPA_802_1X_PORT_SECURED)) {
DBGPRINT(RT_DEBUG_OFF,
("%s(): Not PortSecured Pkt FWD to STAs from wcid(%d) to wcid(%d)!\n",
__func__, pSrcEntry->wcid, pEntry->wcid));
to_os = FALSE;
to_air = FALSE;
}
}
}
}
}
if (to_air)
{
#ifdef INF_AMAZON_SE
/*Iverson patch for WMM A5-T07 ,WirelessStaToWirelessSta do not bulk out aggregate */
RTMP_SET_PACKET_NOBULKOUT(pPacket, FALSE);
#endif /* INF_AMAZON_SE */
pForwardPacket = DuplicatePacket(wdev->if_dev, pPacket);
if (pForwardPacket == NULL)
return to_os;
/* 1.1 apidx != 0, then we need set packet mbssid attribute. */
if (pEntry) {
RTMP_SET_PACKET_WDEV(pForwardPacket, dst_wdev->wdev_idx);
RTMP_SET_PACKET_WCID(pForwardPacket, pEntry->wcid);
}
else /* send bc/mc frame back to the same bss */
{
RTMP_SET_PACKET_WDEV(pForwardPacket, wdev->wdev_idx);
RTMP_SET_PACKET_WCID(pForwardPacket, wdev->tr_tb_idx);
}
RTMP_SET_PACKET_MOREDATA(pForwardPacket, FALSE);
#ifdef INF_AMAZON_SE
/*Iverson patch for WMM A5-T07 ,WirelessStaToWirelessSta do not bulk out aggregate */
RTMP_SET_PACKET_NOBULKOUT(pForwardPacket, TRUE);
#endif /* INF_AMAZON_SE */
APSendPacket(pAd, pForwardPacket);
RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, WCID_ALL, MAX_TX_PROCESS);
}
return to_os;
}
/*
========================================================================
Routine Description:
This routine is used to do insert packet into power-saveing queue.
Arguments:
pAd: Pointer to our adapter
pPacket: Pointer to send packet
pMacEntry: portint to entry of MacTab. the pMacEntry store attribute of client (STA).
QueIdx: Priority queue idex.
Return Value:
NDIS_STATUS_SUCCESS:If succes to queue the packet into TxSwQ.
NDIS_STATUS_FAILURE: If failed to do en-queue.
========================================================================
*/
NDIS_STATUS APInsertPsQueue(
IN PRTMP_ADAPTER pAd,
IN PNDIS_PACKET pPacket,
IN STA_TR_ENTRY *tr_entry,
IN UCHAR QueIdx)
{
#if 0
ULONG IrqFlags;
MAC_TABLE_ENTRY *pMacEntry = &pAd->MacTab.Content[tr_entry->wcid];
#ifdef UAPSD_SUPPORT
/* put the U-APSD packet to its U-APSD queue by AC ID */
UINT32 ac_id = QueIdx - QID_AC_BE; /* should be >= 0 */
if (UAPSD_MR_IS_UAPSD_AC(pMacEntry, ac_id))
UAPSD_PacketEnqueue(pAd, pMacEntry, pPacket, ac_id);
else
#endif /* UAPSD_SUPPORT */
{
if (tr_entry->ps_queue.Number >= MAX_PACKETS_IN_PS_QUEUE)
{
#ifdef RELEASE_EXCLUDE
DBGPRINT(RT_DEBUG_INFO, ("UCAST PSQ full, drop it!\n"));
#endif /* RELEASE_EXCLUDE */
RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
return NDIS_STATUS_FAILURE;
}
else
{
RTMP_IRQ_LOCK(&pAd->irq_lock /* &tr_entry->ps_queue_lock */, IrqFlags);
InsertTailQueue(&tr_entry->ps_queue, PACKET_TO_QUEUE_ENTRY(pPacket));
RTMP_IRQ_UNLOCK(&pAd->irq_lock /*&tr_entry->ps_queue_lock */, IrqFlags);
}
}
/* mark corresponding TIM bit in outgoing BEACON frame */
#ifdef UAPSD_SUPPORT
if (UAPSD_MR_IS_NOT_TIM_BIT_NEEDED_HANDLED(pMacEntry, QueIdx))
{
/*
1. the station is UAPSD station;
2. one of AC is non-UAPSD (legacy) AC;
3. the destinated AC of the packet is UAPSD AC.
So we can not set TIM bit due to one of AC is legacy AC
*/
}
else
#endif /* UAPSD_SUPPORT */
{
WLAN_MR_TIM_BIT_SET(pAd, pMacEntry->func_tb_idx, pMacEntry->Aid);
#ifdef RELEASE_EXCLUDE
DBGPRINT(RT_DEBUG_INFO,
("STA (AID=%d) in PSM, move to PSQ, Psqueue #=%d\n",
pMacEntry->Aid, tr_entry->ps_queue.Number));
#endif /* RELEASE_EXCLUDE */
}
#endif
return NDIS_STATUS_SUCCESS;
}