mlme.c

来自「Ralink RT61 SoftAP Driver source code. 」· C语言 代码 · 共 1,669 行 · 第 1/5 页

C
1,669
字号
	            (pEntry->TxQuality[CurrRate] <= 1) &&
	            (pEntry->TxQuality[UpRate] <= 1))
	        {
	            DBGPRINT(RT_DEBUG_TRACE,"2 test frames at UpRate = %d Mbps\n",RateIdToMbps[UpRate]);
	            // tag PID for later on per-client/WDS TX statistics caculation
	            PID = PTYPE_NULL_AT_HIGH_RATE + WDS_PAIRWISE_KEY_OFFSET + i; 
	            ApEnqueueNullFrame(pAd, pEntry->WdsAddr, UpRate, PID, MAIN_MBSSID, FALSE, FALSE, 0);
	            ApEnqueueNullFrame(pAd, pEntry->WdsAddr, UpRate, PID, MAIN_MBSSID, FALSE, FALSE, 0);
	        }

	        // perform DRS - consider TxRate Down frist, then rate up
	        //     rate down, if current TX rate's quality is not good
	        //     rate up, if UPRate's quality is very good
	        if ((pEntry->TxQuality[CurrRate] >= DRS_TX_QUALITY_WORST_BOUND) && (CurrRate != DownRate))
	        {
	            pEntry->CurrTxRate = DownRate;
	        }
	        else if ((pEntry->TxQuality[CurrRate] <=0) && (pEntry->TxQuality[UpRate] <=0) && (CurrRate != UpRate))
	        {
	            pEntry->CurrTxRate = UpRate;
	        }

	        // if rate-up happen, clear all bad history of all TX rates
	        if (pEntry->CurrTxRate > CurrRate)
	        {
	            DBGPRINT(RT_DEBUG_TRACE,"WDS: ++TX rate = %d Mbps\n", RateIdToMbps[UpRate]);
	            pEntry->CurrTxRateStableTime = 0;
	            pEntry->TxRateUpPenalty = 0;
	            NdisZeroMemory(pEntry->TxQuality, MAX_LEN_OF_SUPPORTED_RATES);
	        }
	        // if rate-down happen, only clear DownRate's bad history
	        else if (pEntry->CurrTxRate < CurrRate)
	        {
	            DBGPRINT(RT_DEBUG_TRACE,"WDS: --TX rate = %d Mbps\n", RateIdToMbps[DownRate]);

	            // shorter stable time require more penalty in next rate UP criteria
	            if (pEntry->CurrTxRateStableTime < 4)      // less then 4 sec
	                pEntry->TxRateUpPenalty = DRS_PENALTY; // add 8 sec penalty
	            else if (pEntry->CurrTxRateStableTime < 8) // less then 8 sec
	                pEntry->TxRateUpPenalty = 2;           // add 2 sec penalty
	            else
	                pEntry->TxRateUpPenalty = 0;           // no penalty

	            pEntry->CurrTxRateStableTime = 0;
	            pEntry->TxQuality[pEntry->CurrTxRate] = 0;
	        }
	        
	        // reset all OneSecxxx counters
	        pEntry->OneSecTxFailCount = 0;
	        pEntry->OneSecTxOkCount = 0;
	        pEntry->OneSecTxRetryOkCount = 0;
	    }
	}
#endif /* WDS_SUPPORT */

#ifdef APCLI_SUPPORT
	// AP Client tx rate tuning
	for(i=0; i<MAX_APCLI_ENTRY; i++)
	{
		USHORT TxTotalCnt, TxErrorRatio;
		BOOLEAN fUpgradeQuality = FALSE;
		RT_802_11_APCLI_ENTRY *pEntry = &pAd->ApCliTab.ApCliEntry[i];

		if(pEntry->Valid == FALSE || pEntry->Enable == FALSE)
			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];
			}
		}

		// calculate Tx with retry ratio when enough samples are available
		if(TxTotalCnt > 15)
		{
			TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) *100) / TxTotalCnt;

			// downgrade TX quality if retry+error ratio reached
			if(TxErrorRatio >= RateDownPER[CurrRate])
			{
				pEntry->TxQuality[CurrRate] = DRS_TX_QUALITY_WORST_BOUND;
			}
			// upgrade TX quality if retry+error ratio reached
			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
			}
		} else
		{
			TxErrorRatio = 0;  // too few samples

			// Downgrade TX quality upon any TX failure in the past second
			if(pEntry->OneSecTxFailCount)
			{
				if((pEntry->OneSecTxFailCount <= 1) && (pEntry->OneSecTxOkCount + pEntry->OneSecTxRetryOkCount))
				{
					pEntry->TxQuality[CurrRate] += 2;  // degrade quality
					if(pEntry->TxQuality[CurrRate] > DRS_TX_QUALITY_WORST_BOUND)
						pEntry->TxQuality[CurrRate] = DRS_TX_QUALITY_WORST_BOUND;
				} else // more than 2 failure, or no TX ok cases
				{
					pEntry->TxQuality[CurrRate] = DRS_TX_QUALITY_WORST_BOUND;
				}
			}
			// 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
			else if(pEntry->OneSecTxOkCount > pEntry->OneSecTxRetryOkCount)
			{
				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

			}
		}    

		DBGPRINT(RT_DEBUG_TRACE,"APCLI: Qty[%d]=%d PER=%d%% %d-sec, Qty[%d]=%d Pty=%d\n",
			RateIdToMbps[CurrRate], pEntry->TxQuality[CurrRate],
			TxErrorRatio, pEntry->CurrTxRateStableTime,
			RateIdToMbps[UpRate], pEntry->TxQuality[UpRate],
			pEntry->TxRateUpPenalty);

		// we're going to ugrade CurrRate to UpRate at next few seconds, 
		// but before that, we'd better try a NULL frame @ UpRate and 
		// see if UpRate is stable or not. If this NULL frame fails, it will
		// downgrade TxQuality[CurrRate], so that STA won't switch to
		// to UpRate in the next second
		if((fUpgradeQuality == TRUE)          &&
			(UpRate != CurrRate)               && 
			(pEntry->TxQuality[CurrRate] <= 1) &&
			(pEntry->TxQuality[UpRate] <= 1))
		{
			DBGPRINT(RT_DEBUG_TRACE,"2 test frames at UpRate = %d Mbps\n",RateIdToMbps[UpRate]);
			// tag PID for later on per-client/APCLI TX statistics caculation
			PID = PTYPE_NULL_AT_HIGH_RATE + APCLI_PAIRWISE_KEY_OFFSET + i; 
			ApEnqueueNullFrame(pAd, pEntry->ApCliBssid, UpRate, PID, MAIN_MBSSID, FALSE, FALSE, 0);
			ApEnqueueNullFrame(pAd, pEntry->ApCliBssid, UpRate, PID, MAIN_MBSSID, FALSE, FALSE, 0);
		}

		// perform DRS - consider TxRate Down frist, then rate up
		//     rate down, if current TX rate's quality is not good
		//     rate up, if UPRate's quality is very good
		if((pEntry->TxQuality[CurrRate] >= DRS_TX_QUALITY_WORST_BOUND) && (CurrRate != DownRate))
		{
			pEntry->CurrTxRate = DownRate;
		} else if((pEntry->TxQuality[CurrRate] <=0) && (pEntry->TxQuality[UpRate] <=0) && (CurrRate != UpRate))
		{
			pEntry->CurrTxRate = UpRate;
		}

		// if rate-up happen, clear all bad history of all TX rates
		if(pEntry->CurrTxRate > CurrRate)
		{
			DBGPRINT(RT_DEBUG_TRACE,"APCLI: ++TX rate = %d Mbps\n", RateIdToMbps[UpRate]);
			pEntry->CurrTxRateStableTime = 0;
			pEntry->TxRateUpPenalty = 0;
			NdisZeroMemory(pEntry->TxQuality, MAX_LEN_OF_SUPPORTED_RATES);
		}
		// if rate-down happen, only clear DownRate's bad history
		else if(pEntry->CurrTxRate < CurrRate)
		{
			DBGPRINT(RT_DEBUG_TRACE,"APCLI: --TX rate = %d Mbps\n", RateIdToMbps[DownRate]);

			// shorter stable time require more penalty in next rate UP criteria
			if(pEntry->CurrTxRateStableTime < 4)	  // less then 4 sec
				pEntry->TxRateUpPenalty = DRS_PENALTY; // add 8 sec penalty
			else if(pEntry->CurrTxRateStableTime < 8) // less then 8 sec
				pEntry->TxRateUpPenalty = 2;		   // add 2 sec penalty
			else
				pEntry->TxRateUpPenalty	= 0;		   // no penalty

			pEntry->CurrTxRateStableTime = 0;
			pEntry->TxQuality[pEntry->CurrTxRate] = 0;
		}

		// reset all OneSecxxx counters
		pEntry->OneSecTxFailCount = 0;
		pEntry->OneSecTxOkCount = 0;
		pEntry->OneSecTxRetryOkCount = 0;
	}
#endif /* APCLI_SUPPORT */

#if 0
	//if (pAd->Mlme.PeriodicRound % 5 == 2)
	{
		if ((pAd->PortCfg.PhyMode == PHY_11A) && (pAd->PortCfg.RadarDetect.IEEE80211H == TRUE) && RadarChannelCheck(pAd, pAd->PortCfg.Channel) && (pAd->PortCfg.RadarDetect.RDMode == RD_NORMAL_MODE))
		{
			UCHAR	Pattern = 0;
			
			if (AllTxTotalCnt > 400)
			{
				Pattern = 3;
			}
			else if (AllTxTotalCnt > 200)
			{
				Pattern = 2;
			}
			else if (AllTxTotalCnt > 50)
			{
				Pattern = 1;
			}
			else
			{
				Pattern = 0;
			}

			if (Pattern != pAd->PortCfg.RadarDetect.DetectPattern)
			{
				AsicSendCommandToMcu(pAd, 0x60, 0xff, 0x01, Pattern);
			}
			pAd->PortCfg.RadarDetect.DetectPattern = Pattern;
		}
	}
#endif
#if 1
	DBGPRINT(RT_DEBUG_INFO,"AllTxTotalCnt=%d, OneSecRxOkCnt=%d, dlstest=%d\n", AllTxTotalCnt, pAd->RalinkCounters.OneSecRxOkCnt, pAd->dfstest);

	if (pAd->dfstest == 0)
	{
		if ((pAd->PortCfg.PhyMode == PHY_11A) && (pAd->PortCfg.RadarDetect.IEEE80211H == TRUE) && RadarChannelCheck(pAd, pAd->PortCfg.Channel) && (pAd->PortCfg.RadarDetect.RDMode == RD_NORMAL_MODE))
		{
			if ((AllTxTotalCnt > 1201) || (pAd->RalinkCounters.OneSecRxOkCnt > 1001))
			{
				AsicSendCommandToMcu(pAd, 0x60, 0xff, 0x01, 0x03);
			}
			else if ((AllTxTotalCnt > 1200) || (pAd->RalinkCounters.OneSecRxOkCnt > 1000))
			{
				AsicSendCommandToMcu(pAd, 0x60, 0xff, 0x01, 0x02);
			}
			else if ((AllTxTotalCnt > 50) || (pAd->RalinkCounters.OneSecRxOkCnt > 50))
			{
				AsicSendCommandToMcu(pAd, 0x60, 0xff, 0x01, 0x01);
			}
			else
			{
				AsicSendCommandToMcu(pAd, 0x60, 0xff, 0x01, 0x00);
			}
		}
	}
	else
	{
		AsicSendCommandToMcu(pAd, 0x60, 0xff, 0x01, 0x01);
	}
#endif
}

VOID MlmeSetTxPreamble(
    IN PRTMP_ADAPTER pAd, 
    IN USHORT TxPreamble)
{
    TXRX_CSR4_STRUC csr4;
    
    //
	// Please refer to windows driver
	//
	//TxPreamble = Rt802_11PreambleLong;
    
    RTMP_IO_READ32(pAd, TXRX_CSR4, &csr4.word);
    if (TxPreamble == Rt802_11PreambleShort)
    {
        // NOTE: 1Mbps should always use long preamble
        DBGPRINT(RT_DEBUG_TRACE, "MlmeSetTxPreamble (= SHORT PREAMBLE)\n");
        pAd->PortCfg.TxPreambleInUsed = Rt802_11PreambleShort;
        csr4.field.AutoResponderPreamble = 1;
    }
    else
    {
        DBGPRINT(RT_DEBUG_TRACE, "MlmeSetTxPreamble (= LONG PREAMBLE)\n");
        pAd->PortCfg.TxPreambleInUsed = Rt802_11PreambleLong;
        csr4.field.AutoResponderPreamble = 0;
    }
    RTMP_IO_WRITE32(pAd, TXRX_CSR4, csr4.word);
}
    
// bLinkUp is to identify the inital link speed.
// TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
VOID MlmeUpdateTxRates(
    IN PRTMP_ADAPTER pAd)
{
    int i, j, num;
    ULONG BasicRateBitmap = 0;
    UCHAR CurrBasicRate = RATE_1;
//    UCHAR AutoRespTxPower = pAd->LatchBBPR94;

    // update basic rate bitmap according to pAdapter->PortCfg.BasicRateBitMap
    UpdateBasicRateBitmap(pAd);

	for (j=0; j<pAd->PortCfg.BssidNum; j++)
	{

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?