📄 mlme.c
字号:
TxNoRetryCnt = pAd->MACCounters[6];
TxOneRetryCnt = pAd->MACCounters[7];
TxMRetryCnt = pAd->MACCounters[8];
TxRetryOkCount = TxOneRetryCnt + TxMRetryCnt;
TxOkCount = TxNoRetryCnt + TxRetryOkCount;
TxTotalCnt = TxOkCount + TxFailCount;
if (TxTotalCnt > 100)
{
pAd->ScanAllowed = FALSE;
}
else
{
pAd->ScanAllowed = TRUE;
}
#if 1//steven:exclude CTS
if ((pAd->PortCfg.TxRate >= RATE_FIRST_OFDM_RATE) && (pAd->PortCfg.BGProtectionInUsed))
TxTotalCnt = TxTotalCnt / 2;
#endif
if (TxTotalCnt > TxFailCount)
TxRealOkCount = TxTotalCnt - TxFailCount;
else
TxRealOkCount = 0;
OldValue = pAd->WlanCounters.TransmittedFragmentCount.vv.LowPart;
pAd->WlanCounters.TransmittedFragmentCount.vv.LowPart += TxRealOkCount;
if (pAd->WlanCounters.TransmittedFragmentCount.vv.LowPart < OldValue)
{
pAd->WlanCounters.TransmittedFragmentCount.vv.HighPart++;
}
AsicBbpTuning(pAd);
if (pAd->MediaState == NdisMediaStateConnected)
{
if (TxTotalCnt < 5) // if too few TX samples, skip TX related statistics
{
TxPER = 0; // don't take TxPER into CQI consideration if too few sample
TxPRR = 0;
}
else
{
if (TxFailCount < TxTotalCnt)
{
USHORT temp = TxOneRetryCnt + TxMRetryCnt + TxFailCount;
TxPER = (TxFailCount * 100) / TxTotalCnt;
if (temp < TxTotalCnt)
TxPRR = (temp * 100) / TxTotalCnt;
else
TxPRR = 100;
}
else
TxPER = 100;
}
//
// calculate RX PER
//
RxFailCnt = pAd->MACCounters[0];
RxOkCnt = pAd->WlanCounters.ReceivedFragmentCount.vv.LowPart -
pAd->Mlme.PrevWlanCounters.ReceivedFragmentCount.vv.LowPart;
RxCnt = RxOkCnt + RxFailCnt;
if (RxCnt < 5)
RxPER = 0; // don't take RxPER into ChannelQuality consideration if too few sample
else
RxPER = (RxFailCnt * 100) / RxCnt;
if ((ADHOC_ON(pAd)) && (pAd->MediaState == NdisMediaStateConnected))
{
pAd->SentBeaconsCount += pAd->MACCounters[5];
pAd->ReceivedBeaconsCount += pAd->MACCounters[10];
if ((pAd->Mlme.PeriodicRound % 2) == 1)
{
TXRX_CSR18_STRUC Csr18;
USHORT temp;
DBGPRINT(RT_DEBUG_INFO, "SentBeaconsCount = %d ReceivedBeaconsCount = %d\n", pAd->SentBeaconsCount, pAd->ReceivedBeaconsCount);
if (pAd->BeaconIntervalChangeAllowed == TRUE)
{
if (2 * pAd->SentBeaconsCount > pAd->ReceivedBeaconsCount)
{
temp = (pAd->PortCfg.BeaconPeriod << 8) + 1;
Csr18.field.Offset = (temp & 0x000F);
Csr18.field.Interval = (temp >> 6);
RTUSBWriteMACRegister(pAd, TXRX_CSR18, Csr18.value);
DBGPRINT_RAW(RT_DEBUG_INFO, "TXRX_CSR18 = 0x%x\n", Csr18.value);
pAd->BeaconIntervalChangeAllowed = FALSE;
}
else if (pAd->ReceivedBeaconsCount > 9 * pAd->SentBeaconsCount)
{
temp = (pAd->PortCfg.BeaconPeriod << 8) - 5;
Csr18.field.Offset = (temp & 0x000F);
Csr18.field.Interval = (temp >> 6);
RTUSBWriteMACRegister(pAd, TXRX_CSR18, Csr18.value);
DBGPRINT_RAW(RT_DEBUG_INFO, "TXRX_CSR18 = 0x%x\n", Csr18.value);
pAd->BeaconIntervalChangeAllowed = FALSE;
}
else if (pAd->ReceivedBeaconsCount > 3 * pAd->SentBeaconsCount)
{
temp = (pAd->PortCfg.BeaconPeriod << 8) - 1;
Csr18.field.Offset = (temp & 0x000F);
Csr18.field.Interval = (temp >> 6);
RTUSBWriteMACRegister(pAd, TXRX_CSR18, Csr18.value);
DBGPRINT_RAW(RT_DEBUG_INFO, "TXRX_CSR18 = 0x%x\n", Csr18.value);
pAd->BeaconIntervalChangeAllowed = FALSE;
}
#if 0
else if (pAd->ReceivedBeaconsCount > 2 * pAd->SentBeaconsCount)
{
temp = (pAd->PortCfg.BeaconPeriod << 8) - 1;
Csr18.field.Offset = (temp & 0x000F);
Csr18.field.Interval = (temp >> 6);
RTUSBWriteMACRegister(pAd, TXRX_CSR18, Csr18.value);
DBGPRINT_RAW(RT_DEBUG_TRACE, ("TXRX_CSR18 = 0x%x\n", Csr18.value));
pAd->BeaconIntervalChangeAllowed = FALSE;
}
#endif
}
#if 0
else if (pAd->ReceivedBeaconsCount > 9 * pAd->SentBeaconsCount)
{
DBGPRINT_RAW(RT_DEBUG_TRACE, ("Do Nothing\n"));
}
#endif
else
{
temp = (pAd->PortCfg.BeaconPeriod << 8);
Csr18.field.Offset = (temp & 0x000F);
Csr18.field.Interval = (temp >> 6);
RTUSBWriteMACRegister(pAd, TXRX_CSR18, Csr18.value);
DBGPRINT_RAW(RT_DEBUG_INFO, "TXRX_CSR18 = 0x%x\n", Csr18.value);
pAd->BeaconIntervalChangeAllowed = TRUE;
}
pAd->SentBeaconsCount = 0;
pAd->ReceivedBeaconsCount = 0;
}
}
Now32 = jiffies;
{
// ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)
pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * pAd->PortCfg.LastRssi +
TX_WEIGHTING * (100 - TxPRR) +
RX_WEIGHTING* (100 - RxPER)) / 100;
if (pAd->Mlme.ChannelQuality >= 100)
pAd->Mlme.ChannelQuality = 100;
}
DBGPRINT(RT_DEBUG_INFO, "MMCHK - CQI= %d, (Tx Fail=%d/Retry=%d/Total=%d, Rx Fail=%d/Total=%d, RSSI=%d dbm)\n",
pAd->Mlme.ChannelQuality, TxFailCount, TxRetryOkCount, TxTotalCnt, RxFailCnt, RxCnt, pAd->PortCfg.LastRssi - pAd->BBPTuningParameters.RSSIToDbmOffset);
// latch current WLAN counters for next check-for-roaming usage
NdisMoveMemory(&pAd->Mlme.PrevWlanCounters, &pAd->WlanCounters, sizeof(COUNTER_802_11));
#if 1//steven:move this from MlmePeriodicExec
if (INFRA_ON(pAd))
{
if (CQI_IS_BAD(pAd->Mlme.ChannelQuality))
{
pAd->RalinkCounters.BadCQIAutoRecoveryCount ++;
DBGPRINT(RT_DEBUG_TRACE, "MMCHK - Bad CQI. Auto Recovery attempt #%d\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount);
MlmeAutoRecoverNetwork(pAd);
}
else if (CQI_IS_FAIR(pAd->Mlme.ChannelQuality) || CQI_IS_POOR(pAd->Mlme.ChannelQuality))
{
// perform aggresive roaming only when SECURITY OFF or WEP64/128;
// WPA and WPA-PSK has no aggresive roaming because re-negotiation
// between 802.1x supplicant and authenticator/AAA server is required
// but can't be guaranteed.
if (pAd->PortCfg.AuthMode < Ndis802_11AuthModeWPA)
MlmeCheckForRoaming(pAd, Now32);
}
}
#endif
pAd->PortCfg.CurrTxRateStableTime++;
CurrRate = pAd->PortCfg.TxRate;
do
{
USHORT TxErrorRatio;
BOOLEAN fUpgradeQuality = FALSE;
USHORT *pRateUpPER, *pRateDownPER;
if (pAd->PortCfg.EnableAutoRateSwitching == FALSE)
break;
// do nothing if no traffic in the past period
if (TxTotalCnt == 0)
{
// TxRateUpPenalty maybe too large, we don't want this penalty to affect
// next Chariot throughput test too much therefore zero it here.
pAd->PortCfg.TxRateUpPenalty = 0;
NdisZeroMemory(pAd->DrsCounters.TxQuality, MAX_LEN_OF_SUPPORTED_RATES);
NdisZeroMemory(pAd->DrsCounters.PER, MAX_LEN_OF_SUPPORTED_RATES);
break;
}
// decide the next upgrade rate and downgrade rate, if any
if (pAd->PortCfg.PhyMode == PHY_11BG_MIXED)
{
UpRate = Phy11BGNextRateUpward[CurrRate];
DownRate = Phy11BGNextRateDownward[CurrRate];
}
else if (pAd->PortCfg.PhyMode == PHY_11B)
{
UpRate = Phy11BNextRateUpward[CurrRate];
DownRate = Phy11BNextRateDownward[CurrRate];
}
else if (pAd->PortCfg.PhyMode == PHY_11A)
{
UpRate = Phy11ANextRateUpward[CurrRate];
DownRate = Phy11ANextRateDownward[CurrRate];
}
else // PHY_11ABG_MIXED
{
if (pAd->PortCfg.Channel > 14)
{
UpRate = Phy11ANextRateUpward[CurrRate];
DownRate = Phy11ANextRateDownward[CurrRate];
}
else
{
UpRate = Phy11BGNextRateUpward[CurrRate];
DownRate = Phy11BGNextRateDownward[CurrRate];
}
}
if (UpRate > pAd->PortCfg.MaxTxRate)
UpRate = pAd->PortCfg.MaxTxRate;
// decide TX quality based on Tx retry ratio when enough samples are available
if (TxTotalCnt > 15)
{
USHORT temp = TxRetryOkCount + TxFailCount;
if (temp < TxTotalCnt)
TxErrorRatio = (temp *100) / TxTotalCnt;
else
TxErrorRatio = 100;
pRateUpPER = &NewRateUpPER[0];
pRateDownPER = &NewRateDownPER[0];
// downgrade TX quality if retry+error ratio reached
if (TxErrorRatio >= pRateDownPER[CurrRate])
{
pAd->DrsCounters.TxQuality[CurrRate] = DRS_TX_QUALITY_WORST_BOUND;
}
// upgrade TX quality if retry+error ratio reached
else if (TxErrorRatio <= pRateUpPER[CurrRate])
{
fUpgradeQuality = TRUE;
if (pAd->DrsCounters.TxQuality[CurrRate])
pAd->DrsCounters.TxQuality[CurrRate] --; // quality very good in CurrRate
if (pAd->PortCfg.TxRateUpPenalty)
pAd->PortCfg.TxRateUpPenalty --;
else if (pAd->DrsCounters.TxQuality[UpRate])
pAd->DrsCounters.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 -
// 1. any TX failure in the past second
// 2. TX retry ratio too high when enough TX samples are available
if (TxFailCount)
{
if ((TxFailCount <= 1) &&
(TxRealOkCount + TxRetryOkCount))
{
pAd->DrsCounters.TxQuality[CurrRate] += 2; // degrade quality
if (pAd->DrsCounters.TxQuality[CurrRate] > DRS_TX_QUALITY_WORST_BOUND)
pAd->DrsCounters.TxQuality[CurrRate] = DRS_TX_QUALITY_WORST_BOUND;
}
else // more than 2 failure, or no TX ok cases
{
pAd->DrsCounters.TxQuality[CurrRate] = DRS_TX_QUALITY_WORST_BOUND; // quality bad
}
}
// upgrade TX quality if -
// 1. no TX failure but do have TX ok case, and
// 2. there's more one-time-ok cases than retry-ok cases in the past second
// 3. current rate's Tx retry ratio <= 10%
else if ((TxRealOkCount > TxRetryOkCount))
{
fUpgradeQuality = TRUE;
if (pAd->DrsCounters.TxQuality[CurrRate])
pAd->DrsCounters.TxQuality[CurrRate] --; // quality very good in CurrRate
if (pAd->PortCfg.TxRateUpPenalty)
pAd->PortCfg.TxRateUpPenalty --;
else if (pAd->DrsCounters.TxQuality[UpRate])
pAd->DrsCounters.TxQuality[UpRate] --; // may improve next UP rate's quality
}
}
pAd->DrsCounters.PER[CurrRate] = (UCHAR)TxErrorRatio;
if (pAd->DrsCounters.fNoisyEnvironment)
{
DBGPRINT_RAW(RT_DEBUG_TRACE,"DRS(noisy):");
}
else
{
DBGPRINT_RAW(RT_DEBUG_TRACE,"DRS:");
}
DBGPRINT_RAW(RT_DEBUG_TRACE,"Qty[%d]=%d PER=%d%% %d-sec, Qty[%d]=%d, Pty=%d\n",
RateIdToMbps[CurrRate], pAd->DrsCounters.TxQuality[CurrRate],
TxErrorRatio,
pAd->DrsCounters.CurrTxRateStableTime,
RateIdToMbps[UpRate], pAd->DrsCounters.TxQuality[UpRate],
pAd->DrsCounters.TxRateUpPenalty);
// 2004-3-13 special case: Claim noisy environment
// decide if there was a false "rate down" in the past 2 sec due to noisy
// environment. if so, we would rather switch back to the higher TX rate.
// criteria -
// 1. there's a higher rate available, AND
// 2. there was a rate-down happened, AND
// 3. current rate has 75% > PER > 25%, AND
// 4. comparing to UpRate, current rate didn't improve PER more than 5 %
if ((UpRate != CurrRate) &&
(pAd->DrsCounters.LastSecTxRateChangeAction == 2) &&
(((pAd->DrsCounters.PER[CurrRate] > 20) || (pAd->DrsCounters.fNoisyEnvironment)) &&
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -