mlme.c
来自「Ralink RT61 SoftAP Driver source code. 」· C语言 代码 · 共 1,669 行 · 第 1/5 页
C
1,669 行
case STA_CTRL_STATE_MACHINE:
apcliIfIndex = Elem->ifIndex;
if(isValidApCliIf(apcliIfIndex))
StaStateMachinePerformAction(pAd, &pAd->Mlme.ApCliCtrlMachine, Elem,
apcliIfIndex, &(pAd->ApCliTab.ApCliEntry[apcliIfIndex].CtrlCurrState));
break;
case STA_WPA_STATE_MACHINE:
apcliIfIndex = Elem->ifIndex;
if(isValidApCliIf(apcliIfIndex))
StaStateMachinePerformAction(pAd, &pAd->Mlme.ApCliWpaPskMachine, Elem,
apcliIfIndex, &(pAd->ApCliTab.ApCliEntry[apcliIfIndex].WpaPskCurrState));
break;
#endif
default:
DBGPRINT(RT_DEBUG_TRACE, "ERROR: Illegal machine in MlmeHandler()\n");
break;
} // end of switch
// free MLME element
Elem->Occupied = FALSE;
Elem->MsgLen = 0;
}
else {
DBGPRINT_ERR("MlmeHandler: MlmeQueue empty\n");
}
}
RTMP_SEM_LOCK(&pAd->Mlme.TaskLock, IrqFlags);
pAd->Mlme.bRunning = FALSE;
RTMP_SEM_UNLOCK(&pAd->Mlme.TaskLock, IrqFlags);
}
/*
==========================================================================
Description:
Destructor of MLME (Destroy queue, state machine, spin lock and timer)
Parameters:
Adapter - NIC Adapter pointer
Post:
The MLME task will no longer work properly
==========================================================================
*/
VOID MlmeHalt(
IN PRTMP_ADAPTER pAd)
{
DBGPRINT(RT_DEBUG_TRACE, "==> MlmeHalt\n");
// disable BEACON generation and other BEACON related hardware timers
AsicDisableSync(pAd);
// Cancel pending timers
RTMPCancelTimer(&pAd->Mlme.DFSPeriodicTimer);
RTMPCancelTimer(&pAd->Mlme.PeriodicTimer);
RTMPCancelTimer(&pAd->Mlme.SyncAux.ScanTimer);
#ifdef APCLI_SUPPORT
RTMPCancelTimer(&pAd->MlmeAux.ProbeTimer);
RTMPCancelTimer(&pAd->MlmeAux.ApCliAssocTimer);
RTMPCancelTimer(&pAd->MlmeAux.ApCliAuthTimer);
#endif
RTMPusecDelay(500000); // 0.5 sec to guarantee timer canceled
MlmeQueueDestroy(&pAd->Mlme.Queue);
NdisFreeSpinLock(&pAd->Mlme.TaskLock);
NdisFreeSpinLock(&pAd->Mlme.MemLock);
DBGPRINT(RT_DEBUG_TRACE, "<== MlmeHalt\n");
}
/*
==========================================================================
Description:
This routine is executed periodically to -
1. Decide if it's a right time to turn on PwrMgmt bit of all
outgoiing frames
2. Calculate ChannelQuality based on statistics of the last
period, so that TX rate won't toggling very frequently between a
successful TX and a failed TX.
3. If the calculated ChannelQuality indicated current connection not
healthy, then a ROAMing attempt is tried here.
==========================================================================
*/
VOID MlmePeriodicExec(
IN unsigned long data)
{
RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)data;
pAd->Mlme.Now32 = jiffies;
// add the most up-to-date h/w raw counters into software variable, so that
// the dynamic tuning mechanism below are based on most up-to-date information
// This function call is also needed when ATE turns on to reflect the statistics counter
NICUpdateRawCounters(pAd);
#ifdef RALINK_ATE
if (pAd->ate.bRxFer == 1)
{
pAd->ate.RxTotalCnt += pAd->ate.RxCntPerSec;
printk("MlmePeriodicExec: Rx packet cnt = %d/%d\n\n", pAd->ate.RxCntPerSec, pAd->ate.RxTotalCnt);
pAd->ate.RxCntPerSec = 0;
}
#endif
if ((RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) ||
(RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) ||
(RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)))
{
RTMPAddTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
return;
}
#ifdef RALINK_ATE
if(pAd->ate.Mode != ATE_APSTART)
{
RTMPAddTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
return;
}
#endif // RALINK_ATE
#ifdef DBG
{
extern void dbg_AggregatedRatio(PRTMP_ADAPTER pAd);
dbg_AggregatedRatio(pAd);
}
#endif
// check every 12 second. If no U2M in the past 12 second, then AvgRSSI is no longer a
// valid indication of the distance between this AP and its clients. In this case, we presume a
// mid AvgRSSI (say -60 dbm), so that no extreme TX power calibration and BBP R17 tuning
// rules will be applied.
if (pAd->Mlme.PeriodicRound % 12 == 2)
{
if (pAd->PortCfg.NumOfAvgRssiSample == 0)
{
pAd->PortCfg.AvgRssi = pAd->BbpRssiToDbmDelta + RSSI_FOR_MID_SENSIBILITY;
pAd->PortCfg.AvgRssiX8 = pAd->PortCfg.AvgRssi << 3;
pAd->PortCfg.AvgRssi2 = pAd->BbpRssiToDbmDelta + RSSI_FOR_MID_SENSIBILITY;
pAd->PortCfg.AvgRssi2X8 = pAd->PortCfg.AvgRssi2 << 3;
DBGPRINT(RT_DEBUG_TRACE,"MlmePeriodicExec: no traffic, Reset AsicBbpTuning\n");
AsicResetBbpTuning(pAd);
}
else
{
pAd->PortCfg.NumOfAvgRssiSample = 0;
}
}
// Request by David
//AsicAdjustTxPower(pAd);
// danamic tune BBP R17 to find a balance between sensibility and noise isolation
AsicBbpTuning(pAd);
//radar detect
if ((pAd->PortCfg.PhyMode == PHY_11A) && (pAd->PortCfg.RadarDetect.IEEE80211H == TRUE) && RadarChannelCheck(pAd, pAd->PortCfg.Channel))
RadarDetectPeriodic(pAd);
// walk through MAC table, see if switching TX rate is required
if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))
MlmeDynamicTxRateSwitching(pAd);
// MAC table maintenance
MacTableMaintenance(pAd);
ApUpdateCapabilityAndErpIe(pAd);
RTMPMaintainPMKIDCache(pAd);
#ifdef APCLI_SUPPORT
// check every 2 second. If # of U2M or beacon, probe_rsp less than 1 times in the past 2 second,
// then AvgRSSI is no longer a valid indication of the distance between this AP-Client and its AP.
if (pAd->Mlme.PeriodicRound % 2 == 0)
{
UCHAR index;
for(index = 0; index < MAX_APCLI_ENTRY; index++)
{
if ((pAd->ApCliTab.ApCliEntry[index].Valid == TRUE)
&& (pAd->ApCliTab.ApCliEntry[index].NumOfAvgRssiSample < 1))
{
DBGPRINT(RT_DEBUG_TRACE,"MlmePeriodicExec: no traffic and Beancon on ApCli%d, Probe-Response from root-AP.\n", index);
DBGPRINT(RT_DEBUG_TRACE,"MlmePeriodicExec: Reconnect the Root-Ap again.\n");
StaMlmeEnqueue(pAd, STA_CTRL_STATE_MACHINE, STA_CTRL_DISCONNECT_REQ, 0, NULL, index);
}
pAd->ApCliTab.ApCliEntry[index].NumOfAvgRssiSample = 0;
}
}
if (pAd->Mlme.PeriodicRound % 2 == 1)
ApCliIfUp(pAd);
#endif
// clear all OneSecxxx counters.
pAd->RalinkCounters.OneSecBeaconSentCnt = 0;
pAd->RalinkCounters.OneSecRxFcsErrCnt = 0;
pAd->RalinkCounters.OneSecRxOkCnt = 0;
pAd->RalinkCounters.OneSecTxFailCount = 0;
pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0;
pAd->RalinkCounters.OneSecTxRetryOkCount = 0;
// TODO: for debug only. to be removed
pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
pAd->RalinkCounters.OneSecTxDoneCount = 0;
pAd->RalinkCounters.OneSecTxAggregationCount = 0;
pAd->RalinkCounters.OneSecRxAggregationCount = 0;
pAd->Mlme.PeriodicRound ++;
MlmeHandler(pAd);
RTMPAddTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
}
/*
==========================================================================
Description:
Output:
NOTE:
call this routine every second
==========================================================================
*/
VOID MlmeDynamicTxRateSwitching(
IN PRTMP_ADAPTER pAd)
{
INT i;
UCHAR UpRate, DownRate, CurrRate;
UCHAR PID;
ULONG AllTxTotalCnt = 0;
//
// walk through MAC table, see if need to change AP's TX rate toward each entry
//
for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
{
USHORT TxTotalCnt, TxErrorRatio = 0;
BOOLEAN fUpgradeQuality = FALSE;
MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[i];
// only associated STA counts
if ((pEntry->Valid == FALSE) || (pEntry->Sst != SST_ASSOC))
continue;
if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_APSD_CAPABLE) && (pEntry->PsMode == PWR_SAVE))
continue;
pEntry->CurrTxRateStableTime ++;
TxTotalCnt = pEntry->OneSecTxOkCount + pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount;
AllTxTotalCnt += TxTotalCnt;
// skip those STA that has no traffic in the past period
if (TxTotalCnt == 0)
{
pEntry->TxRateUpPenalty = 0;
continue;
}
// decide the next upgrade rate and downgrade rate, if any
CurrRate = pEntry->CurrTxRate;
if (pAd->PortCfg.Channel > 14) // must be in 802.11A band
{
if (Phy11ANextRateUpward[CurrRate] <= pEntry->MaxSupportedRate)
UpRate = Phy11ANextRateUpward[CurrRate];
else
UpRate = CurrRate;
DownRate = Phy11ANextRateDownward[CurrRate];
}
else
{
if (pEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE)
{
if (Phy11BNextRateUpward[CurrRate] <= pEntry->MaxSupportedRate)
UpRate = Phy11BNextRateUpward[CurrRate];
else
UpRate = CurrRate;
DownRate = Phy11BNextRateDownward[CurrRate];
}
else
{
if (Phy11BGNextRateUpward[CurrRate] <= pEntry->MaxSupportedRate)
UpRate = Phy11BGNextRateUpward[CurrRate];
else
UpRate = CurrRate;
DownRate = Phy11BGNextRateDownward[CurrRate];
}
}
//
// PART 1. Decide TX Quality
// decide TX quality based on Tx PER when enough samples are available
//
if (TxTotalCnt > 15)
{
TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) *100) / TxTotalCnt;
// downgrade TX quality if PER >= Rate-Down threshold
if (TxErrorRatio >= RateDownPER[CurrRate])
{
pEntry->TxQuality[CurrRate] = DRS_TX_QUALITY_WORST_BOUND;
}
// upgrade TX quality if PER <= Rate-Up threshold
else if (TxErrorRatio <= RateUpPER[CurrRate])
{
fUpgradeQuality = TRUE;
if (pEntry->TxQuality[CurrRate])
pEntry->TxQuality[CurrRate] --; // quality very good in CurrRate
if (pEntry->TxRateUpPenalty)
pEntry->TxRateUpPenalty --;
else if (pEntry->TxQuality[UpRate])
pEntry->TxQuality[UpRate] --; // may improve next UP rate's quality
}
}
// if not enough TX samples, decide by heuristic rules
else
{
TxErrorRatio = 0;
// Downgrade TX quality upon any TX failure in the past second
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?