MT7601u/src/ap/ap_mlme.c
Murat Demirtas 612db32659 FIXED
2016-10-30 14:40:00 +00:00

616 lines
16 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:
mlme.c
Abstract:
Major MLME state machiones here
Revision History:
Who When What
-------- ---------- ----------------------------------------------
John Chang 08-04-2003 created for 11g soft-AP
*/
#include "rt_config.h"
#include <stdarg.h>
#ifdef DOT11_N_SUPPORT
int DetectOverlappingPeriodicRound;
#ifdef DOT11N_DRAFT3
VOID Bss2040CoexistTimeOut(
IN PVOID SystemSpecific1,
IN PVOID FunctionContext,
IN PVOID SystemSpecific2,
IN PVOID SystemSpecific3)
{
int apidx;
PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext;
DBGPRINT(RT_DEBUG_TRACE, ("Bss2040CoexistTimeOut(): Recovery to original setting!\n"));
/* Recovery to original setting when next DTIM Interval. */
pAd->CommonCfg.Bss2040CoexistFlag &= (~BSS_2040_COEXIST_TIMER_FIRED);
NdisZeroMemory(&pAd->CommonCfg.LastBSSCoexist2040, sizeof(BSS_2040_COEXIST_IE));
pAd->CommonCfg.Bss2040CoexistFlag |= BSS_2040_COEXIST_INFO_SYNC;
if (pAd->CommonCfg.bBssCoexEnable == FALSE)
{
/* TODO: Find a better way to handle this when the timer is fired and we disable the bBssCoexEable support!! */
DBGPRINT(RT_DEBUG_TRACE, ("Bss2040CoexistTimeOut(): bBssCoexEnable is FALSE, return directly!\n"));
return;
}
for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++)
SendBSS2040CoexistMgmtAction(pAd, MCAST_WCID, apidx, 0);
}
#endif /* DOT11N_DRAFT3 */
#endif /* DOT11_N_SUPPORT */
VOID APDetectOverlappingExec(
IN PVOID SystemSpecific1,
IN PVOID FunctionContext,
IN PVOID SystemSpecific2,
IN PVOID SystemSpecific3)
{
#ifdef DOT11_N_SUPPORT
PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext;
if (DetectOverlappingPeriodicRound == 0)
{
/* switch back 20/40 */
if ((pAd->CommonCfg.Channel <=14) && (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40))
{
pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 1;
pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = pAd->CommonCfg.RegTransmitSetting.field.EXTCHA;
}
}
else
{
if ((DetectOverlappingPeriodicRound == 25) || (DetectOverlappingPeriodicRound == 1))
{
if ((pAd->CommonCfg.Channel <=14) && (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth==BW_40))
{
SendBeaconRequest(pAd, 1);
SendBeaconRequest(pAd, 2);
SendBeaconRequest(pAd, 3);
}
}
DetectOverlappingPeriodicRound--;
}
#endif /* DOT11_N_SUPPORT */
}
/*
==========================================================================
Description:
This routine is executed every second -
1. Decide the overall channel quality
2. Check if need to upgrade the TX rate to any client
3. perform MAC table maintenance, including ageout no-traffic clients,
and release packet buffer in PSQ is fail to TX in time.
==========================================================================
*/
VOID APMlmePeriodicExec(
PRTMP_ADAPTER pAd)
{
/*
Reqeust by David 2005/05/12
It make sense to disable Adjust Tx Power on AP mode, since we can't
take care all of the client's situation
ToDo: need to verify compatibility issue with WiFi product.
*/
#ifdef CARRIER_DETECTION_SUPPORT
if (isCarrierDetectExist(pAd) == TRUE)
{
PCARRIER_DETECTION_STRUCT pCarrierDetect = &pAd->CommonCfg.CarrierDetect;
if (pCarrierDetect->OneSecIntCount < pCarrierDetect->CarrierGoneThreshold)
{
pCarrierDetect->CD_State = CD_NORMAL;
pCarrierDetect->recheck = pCarrierDetect->recheck1;
if (pCarrierDetect->Debug != RT_DEBUG_TRACE)
{
DBGPRINT(RT_DEBUG_TRACE, ("Carrier gone\n"));
/* start all TX actions. */
APMakeAllBssBeacon(pAd);
APUpdateAllBeaconFrame(pAd);
AsicEnableBssSync(pAd);
}
else
{
printk("Carrier gone\n");
}
}
pCarrierDetect->OneSecIntCount = 0;
}
#endif /* CARRIER_DETECTION_SUPPORT */
RTMP_CHIP_HIGH_POWER_TUNING(pAd, &pAd->ApCfg.RssiSample);
/* Disable Adjust Tx Power for WPA WiFi-test. */
/* Because high TX power results in the abnormal disconnection of Intel BG-STA. */
/*#ifndef WIFI_TEST */
/* if (pAd->CommonCfg.bWiFiTest == FALSE) */
/* for SmartBit 64-byte stream test */
/* removed based on the decision of Ralink congress at 2011/7/06 */
/* if (pAd->MacTab.Size > 0) */
AsicAdjustTxPower(pAd);
/*#endif // WIFI_TEST */
RTMP_CHIP_ASIC_TEMPERATURE_COMPENSATION(pAd);
/* BBP TUNING: dynamic tune BBP R66 to find a balance between sensibility
and noise isolation */
/* AsicBbpTuning2(pAd); */
/* walk through MAC table, see if switching TX rate is required */
/* MAC table maintenance */
if (pAd->Mlme.PeriodicRound % MLME_TASK_EXEC_MULTIPLE == 0)
{
/* one second timer */
MacTableMaintenance(pAd);
RTMPMaintainPMKIDCache(pAd);
#ifdef CLIENT_WDS
CliWds_ProxyTabMaintain(pAd);
#endif /* CLIENT_WDS */
}
APUpdateCapabilityAndErpIe(pAd);
#ifdef APCLI_SUPPORT
if (pAd->Mlme.OneSecPeriodicRound % 2 == 0)
ApCliIfMonitor(pAd);
if (pAd->Mlme.OneSecPeriodicRound % 2 == 1)
ApCliIfUp(pAd);
{
INT loop;
ULONG Now32;
NdisGetSystemUpTime(&Now32);
for (loop = 0; loop < MAX_APCLI_NUM; loop++)
{
PAPCLI_STRUCT pApCliEntry = &pAd->ApCfg.ApCliTab[loop];
if ((pApCliEntry->Valid == TRUE)
&& (pApCliEntry->MacTabWCID < MAX_LEN_OF_MAC_TABLE))
{
/* update channel quality for Roaming and UI LinkQuality display */
MlmeCalculateChannelQuality(pAd,
&pAd->MacTab.Content[pApCliEntry->MacTabWCID], Now32);
}
}
}
#endif /* APCLI_SUPPORT */
#ifdef DOT11_N_SUPPORT
if (pAd->CommonCfg.bHTProtect)
{
/*APUpdateCapabilityAndErpIe(pAd); */
APUpdateOperationMode(pAd);
if (pAd->CommonCfg.IOTestParm.bRTSLongProtOn == FALSE)
{
AsicUpdateProtect(pAd, (USHORT)pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, pAd->MacTab.fAnyStationNonGF);
}
}
#endif /* DOT11_N_SUPPORT */
#ifdef A_BAND_SUPPORT
if ( (pAd->CommonCfg.Channel > 14)
&& (pAd->CommonCfg.bIEEE80211H == 1)
)
{
#ifdef DFS_SUPPORT
ApRadarDetectPeriodic(pAd);
#else
pAd->Dot11_H.InServiceMonitorCount++;
if (pAd->Dot11_H.RDMode == RD_SILENCE_MODE)
{
if (pAd->Dot11_H.RDCount++ > pAd->Dot11_H.ChMovingTime)
{
AsicEnableBssSync(pAd);
pAd->Dot11_H.RDMode = RD_NORMAL_MODE;
}
}
#endif /* !DFS_SUPPORT */
}
#endif /* A_BAND_SUPPORT */
}
/*! \brief To substitute the message type if the message is coming from external
* \param *Fr The frame received
* \param *Machine The state machine
* \param *MsgType the message type for the state machine
* \return TRUE if the substitution is successful, FALSE otherwise
* \pre
* \post
*/
BOOLEAN APMsgTypeSubst(
IN PRTMP_ADAPTER pAd,
IN PFRAME_802_11 pFrame,
OUT INT *Machine,
OUT INT *MsgType)
{
USHORT Seq;
UCHAR EAPType;
BOOLEAN Return = FALSE;
#ifdef WSC_AP_SUPPORT
UCHAR EAPCode;
PMAC_TABLE_ENTRY pEntry;
#endif /* WSC_AP_SUPPORT */
/*
TODO:
only PROBE_REQ can be broadcast, all others must be unicast-to-me && is_mybssid; otherwise,
ignore this frame
*/
/* wpa EAPOL PACKET */
if (pFrame->Hdr.FC.Type == BTYPE_DATA)
{
#ifdef WSC_AP_SUPPORT
/*WSC EAPOL PACKET */
pEntry = MacTableLookup(pAd, pFrame->Hdr.Addr2);
if (pEntry &&
((pEntry->bWscCapable) ||
(pAd->ApCfg.MBSSID[pEntry->apidx].AuthMode < Ndis802_11AuthModeWPA)))
{
if ((MAC_ADDR_EQUAL(pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.EntryAddr, pEntry->Addr) ||
MAC_ADDR_EQUAL(pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.EntryAddr, ZERO_MAC_ADDR)) &&
IS_ENTRY_CLIENT(pEntry) &&
(pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.WscConfMode != WSC_DISABLE))
{
*Machine = WSC_STATE_MACHINE;
EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
EAPCode = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 4);
Return = WscMsgTypeSubst(EAPType, EAPCode, MsgType);
}
}
#endif /* WSC_AP_SUPPORT */
if (!Return)
{
*Machine = WPA_STATE_MACHINE;
EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
Return = WpaMsgTypeSubst(EAPType, (INT *) MsgType);
}
return Return;
}
if (pFrame->Hdr.FC.Type != BTYPE_MGMT)
return FALSE;
switch (pFrame->Hdr.FC.SubType)
{
case SUBTYPE_ASSOC_REQ:
*Machine = AP_ASSOC_STATE_MACHINE;
*MsgType = APMT2_PEER_ASSOC_REQ;
break;
/*
case SUBTYPE_ASSOC_RSP:
*Machine = AP_ASSOC_STATE_MACHINE;
*MsgType = APMT2_PEER_ASSOC_RSP;
break;
*/
case SUBTYPE_REASSOC_REQ:
*Machine = AP_ASSOC_STATE_MACHINE;
*MsgType = APMT2_PEER_REASSOC_REQ;
break;
/*
case SUBTYPE_REASSOC_RSP:
*Machine = AP_ASSOC_STATE_MACHINE;
*MsgType = APMT2_PEER_REASSOC_RSP;
break;
*/
case SUBTYPE_PROBE_REQ:
*Machine = AP_SYNC_STATE_MACHINE;
*MsgType = APMT2_PEER_PROBE_REQ;
break;
/* test for 40Mhz intolerant */
/*
For Active Scan
*/
case SUBTYPE_PROBE_RSP:
*Machine = AP_SYNC_STATE_MACHINE;
*MsgType = APMT2_PEER_PROBE_RSP;
break;
case SUBTYPE_BEACON:
*Machine = AP_SYNC_STATE_MACHINE;
*MsgType = APMT2_PEER_BEACON;
break;
/*
case SUBTYPE_ATIM:
*Machine = AP_SYNC_STATE_MACHINE;
*MsgType = APMT2_PEER_ATIM;
break;
*/
case SUBTYPE_DISASSOC:
*Machine = AP_ASSOC_STATE_MACHINE;
*MsgType = APMT2_PEER_DISASSOC_REQ;
break;
case SUBTYPE_AUTH:
/* get the sequence number from payload 24 Mac Header + 2 bytes algorithm */
NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
*Machine = AP_AUTH_STATE_MACHINE;
if (Seq == 1)
*MsgType = APMT2_PEER_AUTH_REQ;
else if (Seq == 3)
*MsgType = APMT2_PEER_AUTH_CONFIRM;
else
{
DBGPRINT(RT_DEBUG_TRACE,("wrong AUTH seq=%d Octet=%02x %02x %02x %02x %02x %02x %02x %02x\n", Seq,
pFrame->Octet[0], pFrame->Octet[1], pFrame->Octet[2], pFrame->Octet[3],
pFrame->Octet[4], pFrame->Octet[5], pFrame->Octet[6], pFrame->Octet[7]));
return FALSE;
}
break;
case SUBTYPE_DEAUTH:
*Machine = AP_AUTH_STATE_MACHINE; /*AP_AUTH_RSP_STATE_MACHINE;*/
*MsgType = APMT2_PEER_DEAUTH;
break;
case SUBTYPE_ACTION:
case SUBTYPE_ACTION_NO_ACK:
*Machine = ACTION_STATE_MACHINE;
/* Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support */
#ifdef P2P_SUPPORT
/* Vendor specific usage. */
if ((pFrame->Octet[0] & 0x7F) == MT2_ACT_VENDOR) /* Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support */
{
UCHAR P2POUIBYTE[4] = {0x50, 0x6f, 0x9a, 0x9};
DBGPRINT(RT_DEBUG_ERROR, ("Vendor Action frame OUI= 0x%x\n", *(PULONG)&pFrame->Octet[1]));
/* Now support WFA P2P */
if (RTMPEqualMemory(&pFrame->Octet[1], P2POUIBYTE, 4) && (P2P_INF_ON(pAd)))
{
DBGPRINT(RT_DEBUG_TRACE, ("Vendor Action frame P2P OUI= 0x%x\n", *(PULONG)&pFrame->Octet[1]));
*Machine = P2P_ACTION_STATE_MACHINE;
if (pFrame->Octet[5] <= MT2_MAX_PEER_SUPPORT)
{
*MsgType = pFrame->Octet[5]; /* subtype. */
}
else
return FALSE;
}
else
{
return FALSE;
}
}
else
#endif /* P2P_SUPPORT */
if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
{
*MsgType = MT2_ACT_INVALID;
}
else
{
*MsgType = (pFrame->Octet[0]&0x7F);
}
break;
default:
return FALSE;
break;
}
return TRUE;
}
/*
========================================================================
Routine Description:
Periodic evaluate antenna link status
Arguments:
pAd - Adapter pointer
Return Value:
None
========================================================================
*/
VOID APAsicEvaluateRxAnt(
IN PRTMP_ADAPTER pAd)
{
ULONG TxTotalCnt;
#ifdef RALINK_ATE
if (ATE_ON(pAd))
return;
#endif /* RALINK_ATE */
#ifdef CARRIER_DETECTION_SUPPORT
if(pAd->CommonCfg.CarrierDetect.CD_State == CD_SILENCE)
return;
#endif /* CARRIER_DETECTION_SUPPORT */
#ifdef RT8592
// TODO: shiang-6590, for 8592, this EvaaluateRxAnt still need??
if (IS_RT8592(pAd))
return;
#endif /* RT8592 */
#ifdef RT65xx //snowpin test
if (IS_RT6590(pAd))
return;
#endif /* RT65xx */
#ifdef MT7601
if ( IS_MT7601(pAd) )
return;
#endif /* MT7601 */
#ifdef TXBF_SUPPORT
/* TODO: we didn't do RxAnt evaluate for 3x3 chips */
if (IS_RT3883(pAd) || IS_RT2883(pAd))
return;
#endif /* TXBF_SUPPORT */
#ifdef DOT11_N_SUPPORT
#ifdef GREENAP_SUPPORT
if (pAd->ApCfg.bGreenAPActive == TRUE)
rtmp_bbp_set_rxpath(pAd, 1);
else
#endif /* GREENAP_SUPPORT */
#endif /* DOT11_N_SUPPORT */
rtmp_bbp_set_rxpath(pAd, pAd->Antenna.field.RxPath);
TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
pAd->RalinkCounters.OneSecTxRetryOkCount +
pAd->RalinkCounters.OneSecTxFailCount;
if (TxTotalCnt > 50)
{
RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
pAd->Mlme.bLowThroughput = FALSE;
}
else
{
RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
pAd->Mlme.bLowThroughput = TRUE;
}
}
/*
========================================================================
Routine Description:
After evaluation, check antenna link status
Arguments:
pAd - Adapter pointer
Return Value:
None
========================================================================
*/
VOID APAsicRxAntEvalTimeout(
PRTMP_ADAPTER pAd)
{
CHAR larger = -127, rssi0, rssi1, rssi2;
#ifdef RALINK_ATE
if (ATE_ON(pAd))
return;
#endif /* RALINK_ATE */
/* if the traffic is low, use average rssi as the criteria */
if (pAd->Mlme.bLowThroughput == TRUE)
{
rssi0 = pAd->ApCfg.RssiSample.LastRssi0;
rssi1 = pAd->ApCfg.RssiSample.LastRssi1;
rssi2 = pAd->ApCfg.RssiSample.LastRssi2;
}
else
{
rssi0 = pAd->ApCfg.RssiSample.AvgRssi0;
rssi1 = pAd->ApCfg.RssiSample.AvgRssi1;
rssi2 = pAd->ApCfg.RssiSample.AvgRssi2;
}
if(pAd->Antenna.field.RxPath == 3)
{
larger = max(rssi0, rssi1);
#ifdef DOT11N_SS3_SUPPORT
if (pAd->CommonCfg.RxStream >= 3)
pAd->Mlme.RealRxPath = 3;
else
#endif /* DOT11N_SS3_SUPPORT */
{
if (larger > (rssi2 + 20))
pAd->Mlme.RealRxPath = 2;
else
pAd->Mlme.RealRxPath = 3;
}
}
/* Disable the below to fix 1T/2R issue. It's suggested by Rory at 2007/7/11. */
#ifdef DOT11_N_SUPPORT
#ifdef GREENAP_SUPPORT
if (pAd->ApCfg.bGreenAPActive == TRUE)
rtmp_bbp_set_rxpath(pAd, 1);
else
#endif /* GREENAP_SUPPORT */
#endif /* DOT11_N_SUPPORT */
rtmp_bbp_set_rxpath(pAd, pAd->Mlme.RealRxPath);
}
/*
========================================================================
Routine Description:
After evaluation, check antenna link status
Arguments:
pAd - Adapter pointer
Return Value:
None
========================================================================
*/
VOID APAsicAntennaAvg(
IN PRTMP_ADAPTER pAd,
IN UCHAR AntSelect,
IN SHORT* RssiAvg)
{
SHORT realavgrssi;
LONG realavgrssi1;
ULONG recvPktNum = pAd->RxAnt.RcvPktNum[AntSelect];
realavgrssi1 = pAd->RxAnt.Pair1AvgRssiGroup1[AntSelect];
if(realavgrssi1 == 0)
{
*RssiAvg = 0;
return;
}
realavgrssi = (SHORT) (realavgrssi1 / recvPktNum);
pAd->RxAnt.Pair1AvgRssiGroup1[0] = 0;
pAd->RxAnt.Pair1AvgRssiGroup1[1] = 0;
pAd->RxAnt.Pair1AvgRssiGroup2[0] = 0;
pAd->RxAnt.Pair1AvgRssiGroup2[1] = 0;
pAd->RxAnt.RcvPktNum[0] = 0;
pAd->RxAnt.RcvPktNum[1] = 0;
*RssiAvg = realavgrssi - 256;
}