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 + -
显示快捷键?