Exemple #1
0
static inline UCHAR SelectClearChannelRandom(
	IN PRTMP_ADAPTER pAd
	)
{
	UCHAR cnt, ch = 0, i, RadomIdx;
	/*BOOLEAN bFindIt = FALSE;*/
	UINT8	TempChList[MAX_NUM_OF_CHANNELS] = {0};
	
	if (pAd->CommonCfg.bIEEE80211H)
	{
		cnt = 0;
		
		/* Filter out an available channel list */
		for (i = 0; i < pAd->ChannelListNum; i++)
		{
			/* Check DFS channel RemainingTimeForUse */
			if (pAd->ChannelList[i].RemainingTimeForUse)
				continue;

			/* Check skip channel list */
			if (AutoChannelSkipListCheck(pAd, pAd->ChannelList[i].Channel) == TRUE)
				continue;

#ifdef DOT11_N_SUPPORT
			/* Check N-group of BW40 */
			if (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40 &&
				!(pAd->ChannelList[i].Flags & CHANNEL_40M_CAP))
				continue;
#endif /* DOT11_N_SUPPORT */

			/* Store available channel to temp list */
			TempChList[cnt++] = pAd->ChannelList[i].Channel;
		}

		/* Randomly select a channel from temp list */
		if (cnt)
		{
			RadomIdx = RandomByte2(pAd)%cnt;
			ch = TempChList[RadomIdx];
		}
		else
		{
			ch = FirstChannel(pAd);
		}
		
	}
	else
	{
		ch = pAd->ChannelList[RandomByte2(pAd)%pAd->ChannelListNum].Channel;
		if (ch == 0)
			ch = FirstChannel(pAd);
	}
	DBGPRINT(RT_DEBUG_TRACE,("%s(): Select Channel %d\n", __FUNCTION__, ch));
	return ch;

}
static inline UCHAR SelectClearChannelRandom(
	IN PRTMP_ADAPTER pAd
	)
{
    UCHAR cnt, ch = 0, i;
	BOOLEAN bFindIt = FALSE;
	
	if (pAd->CommonCfg.bIEEE80211H)
	{
		cnt = 0;
		while(TRUE)
		{
			cnt++;
			ch = pAd->ChannelList[RandomByte2(pAd)%pAd->ChannelListNum].Channel;

			if (ch == 0)
				ch = FirstChannel(pAd);

				// have no avaiable channel now. force pick first channel here.
			if (cnt == pAd->ChannelListNum)
			{
				ch = FirstChannel(pAd);
				break;
			}
#ifdef A_BAND_SUPPORT
			if (RadarChannelCheck(pAd, ch))
				continue;
#endif
			for (i=0; i<pAd->ChannelListNum; i++)
			{
				if (pAd->ChannelList[i].Channel == ch)
				{
					if (pAd->ChannelList[i].RemainingTimeForUse == 0)
						bFindIt = TRUE;
						break;
				}
			}
				
			if (bFindIt == TRUE)
				break;
		};
	}
	else
	{
		ch = pAd->ChannelList[RandomByte2(pAd)%pAd->ChannelListNum].Channel;
		if (ch == 0)
			ch = FirstChannel(pAd);
	}
	printk("Random in A band. Select Channel %d\n",ch);
	return ch;

}
Exemple #3
0
UCHAR get_channel_by_reference(
	IN PRTMP_ADAPTER pAd,
	IN UINT8 mode)
{
	UCHAR ch = 0;
	INT ch_idx;

	switch (mode)
	{
		case 1: 
		{
			USHORT min_time = 0xFFFF;
			/* select channel with least RemainingTimeForUse */
			for ( ch_idx = 0; ch_idx <  pAd->ChannelListNum; ch_idx++)
			{
				if (pAd->ChannelList[ch_idx].RemainingTimeForUse < min_time)
				{
					min_time = pAd->ChannelList[ch_idx].RemainingTimeForUse;
					ch = pAd->ChannelList[ch_idx].Channel;
				}
			}
			break;
		}

		default:
		{
			ch = FirstChannel(pAd);
			break;
		}
	}	

    MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("%s(): mode = %u, ch = %u\n",
							 __FUNCTION__, mode, ch));
	return ch;
}
Exemple #4
0
/* 
	==========================================================================
	Description:

	Return:
		scan_channel - channel to scan.
	Note:
		return 0 if no more next channel
	==========================================================================
 */
UCHAR RTMPFindScanChannel(
	IN PRTMP_ADAPTER pAd, 
	UINT8			  LastScanChannel)
{
	UCHAR scan_channel = 0;
#ifdef CONFIG_AP_SUPPORT
#ifdef AP_PARTIAL_SCAN_SUPPORT
	IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
	{
		if (pAd->ApCfg.bPartialScanning == TRUE)
		{
			scan_channel = FindPartialScanChannel(pAd);
			return scan_channel;
		}
	}
#endif /* AP_PARTIAL_SCAN_SUPPORT */
#endif /* CONFIG_AP_SUPPORT */

	if (LastScanChannel == 0)
		scan_channel = FirstChannel(pAd);
	else
		scan_channel = NextChannel(pAd, LastScanChannel);

	return scan_channel;
}
Exemple #5
0
static VOID ApCliMlmeScanReqAction(
	IN RTMP_ADAPTER *pAd,
	IN MLME_QUEUE_ELEM *Elem)
{
	BOOLEAN Cancelled;
	UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen, ScanType, BssType;

	/* Suspend MSDU transmission here */
	RTMPSuspendMsduTransmission(pAd);

	/* first check the parameter sanity */
	if (MlmeScanReqSanity(pAd, Elem->Msg, Elem->MsgLen, &BssType, (PCHAR)Ssid, &SsidLen, &ScanType))
	{
		DBGPRINT(RT_DEBUG_TRACE, ("%s(): mlme scan req action!\n", __FUNCTION__));
		NdisGetSystemUpTime(&pAd->ApCfg.LastScanTime);

		RTMPCancelTimer(&pAd->MlmeAux.APScanTimer, &Cancelled);

		/* record desired BSS parameters */
		pAd->MlmeAux.BssType = BssType;
		pAd->MlmeAux.ScanType = ScanType;
		pAd->MlmeAux.SsidLen = SsidLen;
		NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen);

		/* start from the first channel */
#ifdef AP_PARTIAL_SCAN_SUPPORT
		pAd->MlmeAux.Channel = RTMPFindScanChannel(pAd, 0);
#else
		pAd->MlmeAux.Channel = FirstChannel(pAd);
#endif /* AP_PARTIAL_SCAN_SUPPORT */

		/* Let BBP register at 20MHz to do scan */
		bbp_set_bw(pAd, BW_20);
		DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n"));

#ifdef CONFIG_AP_SUPPORT
		IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
		{
			if (pAd->ApCfg.bAutoChannelAtBootup == TRUE)/* iwpriv set auto channel selection */
			{
				APAutoChannelInit(pAd);	
				pAd->ApCfg.AutoChannel_Channel = pAd->ChannelList[0].Channel;
			}
#ifdef SMART_MESH
			Set_Scan_False_CCA(pAd, 0, CCA_RESET);
#endif /* SMART_MESH */		
		}
#endif /* CONFIG_AP_SUPPORT */
		ScanNextChannel(pAd, OPMODE_AP, INT_APCLI);
	}
Exemple #6
0
UCHAR get_channel_by_reference(
	IN PRTMP_ADAPTER pAd,
	IN UINT8 mode)
{
	UCHAR ch = 0;
	INT ch_idx;

	switch (mode)
	{
		case 1: 
		{
			USHORT min_time = 0xFFFF;
			/* select channel with least RemainingTimeForUse */
			for ( ch_idx = 0; ch_idx <  pAd->ChannelListNum; ch_idx++)
			{
				if (pAd->ChannelList[ch_idx].RemainingTimeForUse < min_time)
				{
#ifdef DOT11_N_SUPPORT
					/* If the channel not in 40MHz/80MHz group, ignore it. */
					if (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40 &&
						!(pAd->ChannelList[ch_idx].Flags & CHANNEL_40M_CAP))
						continue;
#ifdef DOT11_VHT_AC
					if (pAd->CommonCfg.vht_bw == VHT_BW_80 &&
						!(pAd->ChannelList[ch_idx].Flags & CHANNEL_80M_CAP))
						continue;
#endif /* DOT11_VHT_AC */
#endif /* DOT11_N_SUPPORT */

					min_time = pAd->ChannelList[ch_idx].RemainingTimeForUse;
					ch = pAd->ChannelList[ch_idx].Channel;
				}
			}
			break;
		}

		default:
		{
			ch = FirstChannel(pAd);
			break;
		}
	}	

    DBGPRINT(RT_DEBUG_TRACE,("%s(): mode = %u, ch = %u\n",
							 __FUNCTION__, mode, ch));
	return ch;
}
static inline UCHAR SelectClearChannelApCnt(
	IN PRTMP_ADAPTER pAd
	)
{
    /*PBSSINFO pBssInfoTab = pAd->pBssInfoTab; */
	PCHANNELINFO pChannelInfo = pAd->pChannelInfo;
	/*BSSENTRY *pBss; */
	UCHAR channel_index = 0,dirty,base = 0;
	UCHAR final_channel = 0;

 
	if(pChannelInfo == NULL)
	{
		DBGPRINT(RT_DEBUG_ERROR, ("pAd->pChannelInfo equal NULL.\n"));
		return (FirstChannel(pAd));
	}
	
	/* Calculate Dirtiness */
	
	for (channel_index=0 ; channel_index < pAd->ChannelListNum ; channel_index++)
	{
		if (pChannelInfo->ApCnt[channel_index] > 0)
	    {
		    INT ll;
		    pChannelInfo->dirtyness[channel_index] += 30;

            /*5G */
		    if (pChannelInfo->IsABand)
		    {
			    int Channel = pAd->ChannelList[channel_index].Channel;
				
			    /*Make secondary channel dirty */
			    if(pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)
			    {
					if (Channel > 14)
					{
						if ((Channel == 36) || (Channel == 44) || (Channel == 52) || (Channel== 60) 
							|| (Channel == 100) || (Channel == 108) || (Channel == 116) 
							|| (Channel == 124) || (Channel == 132) || (Channel == 149) || (Channel == 157))
						{
							if (channel_index + 1 < MAX_NUM_OF_CHANNELS)
								if(pAd->ChannelList[channel_index+1].Channel - pAd->ChannelList[channel_index].Channel == 4)
									pChannelInfo->dirtyness[channel_index+1] += 1;
						}
						else if ((Channel == 40) || (Channel == 48) || (Channel == 56) || 
							(Channel == 64) || (Channel == 104) || (Channel == 112) ||
								(Channel == 120) || (Channel == 128) || (Channel == 136) || 
								(Channel== 153) || (Channel == 161))
						{
							if(channel_index - 1 >= 0)
								if(pAd->ChannelList[channel_index].Channel - pAd->ChannelList[channel_index-1].Channel == 4)
									pChannelInfo->dirtyness[channel_index-1] += 1;
						}
					}
				}
			}
			/*2.4G */
			if (!pChannelInfo->IsABand)
			{
				int ChanOffset = 0;

				if((pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)&&
				(pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_BELOW)) 
				{
				/*	
					BW is 40Mhz
					the distance between two channel to prevent interference
					is 4 channel width plus 4 channel width (secondary channel)
				*/
					ChanOffset = 8;
				}
				else
				{
				/*
					BW is 20Mhz
					The channel width of 2.4G band is 5Mhz.
					The distance between two channel to prevent interference is 4 channel width
				*/
					ChanOffset = 4;
				}
					
				for (ll = channel_index + 1; ll < (channel_index + ChanOffset + 1); ll++)
				{
					if (ll < MAX_NUM_OF_CHANNELS)
						pChannelInfo->dirtyness[ll]++;
				}

				if((pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)&&
					(pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_ABOVE)) 
				{
					/* BW is 40Mhz */
					ChanOffset = 8;
				}
				else
				{
					/* BW is 20Mhz */
					ChanOffset = 4;
				}

				for (ll = channel_index - 1; ll > (channel_index - ChanOffset - 1); ll--)
				{
					if (ll >= 0)
						pChannelInfo->dirtyness[ll]++;
				}
			}
    	}       
   }/* Calculate Dirtiness */

	AutoChannelSkipListSetDirty(pAd);
	
   printk("=====================================================\n");
   for (channel_index=0 ; channel_index < pAd->ChannelListNum ; channel_index++)
   /* debug messages */
		printk("Channel %d : Dirty = %ld, ApCnt=%ld, Busy Time = %d, Skip Channel = %s\n", 
				pAd->ChannelList[channel_index].Channel,
				pChannelInfo->dirtyness[channel_index], 
				pChannelInfo->ApCnt[channel_index],
				pChannelInfo->chanbusytime[channel_index],
				(pChannelInfo->SkipList[channel_index] == TRUE) ? "TRUE" : "FALSE");
	printk("=====================================================\n");
	pAd->ApCfg.AutoChannel_Channel = 0;
	
	/* RULE 1. pick up a good channel that no one used */
	
	for (channel_index=0 ; channel_index < pAd->ChannelListNum ; channel_index++)
	{
		if (pChannelInfo->SkipList[channel_index] == TRUE)
			continue;
		
#ifdef A_BAND_SUPPORT
		if ((pAd->ApCfg.bAvoidDfsChannel == TRUE)
				&&(pChannelInfo->IsABand == TRUE)
				&& RadarChannelCheck(pAd, pAd->ChannelList[channel_index].Channel))
			continue;
#endif
#ifdef AP_QLOAD_SUPPORT
		/* QLOAD ALARM */
		if (QBSS_LoadIsBusyTimeAccepted(pAd,
			pChannelInfo->chanbusytime[channel_index]) == FALSE)
			continue;
#endif /* AP_QLOAD_SUPPORT */
		 
		if (pChannelInfo->dirtyness[channel_index] == 0) break;
	}
	if (channel_index < pAd->ChannelListNum)
	{
		printk("Rule 1 APCnt : dirtiness == 0 (no one used and no interference) ==> Select Channel %d\n", pAd->ChannelList[channel_index].Channel);
		return pAd->ChannelList[channel_index].Channel;
	}

	/* RULE 2. if not available, then co-use a channel that's no interference (dirtyness=30) */
	/* RULE 3. if not available, then co-use a channel that has minimum interference (dirtyness=31,32) */
	for (dirty = 30; dirty <= 32; dirty++)
	{
		BOOLEAN candidate[MAX_NUM_OF_CHANNELS+1], candidate_num=0;
		UCHAR min_ApCnt = 255;
		final_channel = 0;	
		
		NdisZeroMemory(candidate, MAX_NUM_OF_CHANNELS+1);
		for (channel_index=0 ; channel_index < pAd->ChannelListNum ; channel_index++)
		{
			if (pChannelInfo->SkipList[channel_index] == TRUE)
				continue;
			
			if (pChannelInfo->dirtyness[channel_index] == dirty) 
			{ 
				candidate[channel_index]=TRUE; 
				candidate_num++; 
			}
		}
		/* if there's more than 1 candidate, pick up the channel with minimum RSSI */
		if (candidate_num)
		{
			for (channel_index=0 ; channel_index < pAd->ChannelListNum ; channel_index++)
			{

#ifdef AP_QLOAD_SUPPORT
				/* QLOAD ALARM */
				/* when busy time of a channel > threshold, skip it */
				/* TODO: Use weight for different references to do channel selection */
				if (QBSS_LoadIsBusyTimeAccepted(pAd,
					pChannelInfo->chanbusytime[channel_index]) == FALSE)
				{
					/* check next one */
					continue;
				}
#endif /* AP_QLOAD_SUPPORT */

				if (candidate[channel_index] && (pChannelInfo->ApCnt[channel_index] < min_ApCnt))
				{

					if((pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)
						&& (BW40_ChannelCheck(pAd->ChannelList[channel_index].Channel) == FALSE))
						continue;

#ifdef A_BAND_SUPPORT
					if ((pAd->ApCfg.bAvoidDfsChannel == TRUE)
							&&(pChannelInfo->IsABand == TRUE)
							&& RadarChannelCheck(pAd, pAd->ChannelList[channel_index].Channel))
						continue;
#endif

					final_channel = pAd->ChannelList[channel_index].Channel;
					min_ApCnt = pChannelInfo->ApCnt[channel_index];
				}
			}
			if (final_channel != 0)
			{
				printk("Rule 2 APCnt : minimum APCnt with  minimum interference(dirtiness: 30~32) ==> Select Channel %d\n", final_channel);
				printk(" Dirtiness = %d ,  Min ApCnt = %d\n", dirty, min_ApCnt);
				return final_channel;
			}
		}
	}
	/* RULE 3. still not available, pick up the random channel */
	base = RandomByte2(pAd);

	for (channel_index=0 ; channel_index < pAd->ChannelListNum ; channel_index++)
	{		
		final_channel = pAd->ChannelList[(base + channel_index) % pAd->ChannelListNum].Channel;
		
		if (AutoChannelSkipListCheck(pAd, final_channel))
			continue;
		
#ifdef A_BAND_SUPPORT
		if ((pAd->ApCfg.bAvoidDfsChannel == TRUE)
			&&(pChannelInfo->IsABand == TRUE)
			&& RadarChannelCheck(pAd, final_channel))
				continue;
#endif

		break;
	}
	printk("Rule 3 APCnt : Randomly Select  ==> Select Channel %d\n",final_channel);
	return final_channel;
}
/* 
	==========================================================================
	Description:
        This routine calaulates the dirtyness of all channels by the 
        CCA value  and Rssi. Store dirtyness to pChannelInfo strcut.
		This routine is called at iwpriv cmmand or initialization. It chooses and returns 
		a good channel whith less interference.
	Return:
		ch -  channel number that
	NOTE:
	==========================================================================
 */
static inline UCHAR SelectClearChannelCCA(
	IN PRTMP_ADAPTER pAd
	)
{
	#define CCA_THRESHOLD (100)

	PBSSINFO pBssInfoTab = pAd->pBssInfoTab;
	PCHANNELINFO pChannelInfo = pAd->pChannelInfo;
	INT ch = 1, channel_idx, BssTab_idx;
	BSSENTRY *pBss;
	UINT32 min_dirty, min_falsecca;
	int candidate_ch;

	UCHAR  ExChannel[2] = {0};
	UCHAR  candidate_ExChannel[2] = {0};
	UCHAR base;

	if(pBssInfoTab == NULL)
	{
		DBGPRINT(RT_DEBUG_ERROR, ("pAd->pBssInfoTab equal NULL.\n"));
		return (FirstChannel(pAd));
	}

	if(pChannelInfo == NULL)
	{
		DBGPRINT(RT_DEBUG_ERROR, ("pAd->pChannelInfo equal NULL.\n"));
		return (FirstChannel(pAd));
	}

	for (BssTab_idx = 0; BssTab_idx < pBssInfoTab->BssNr; BssTab_idx++)
	{
		pBss = &(pBssInfoTab->BssEntry[BssTab_idx]);
		channel_idx = GetChIdx(pAd, pBss->Channel);
		if (channel_idx < 0 )
			continue;


		if (pBss->Rssi >= RSSI_TO_DBM_OFFSET-50)
		{
			/* high signal >= -50 dbm */
			pChannelInfo->dirtyness[channel_idx] += 50;
		}
		else if (pBss->Rssi <= RSSI_TO_DBM_OFFSET-80)
		{
			/* low signal <= -80 dbm */
			pChannelInfo->dirtyness[channel_idx] += 30;
		}
		else
		{
			/* mid signal -50 ~ -80 dbm */
			pChannelInfo->dirtyness[channel_idx] += 40;
		}

		pChannelInfo->dirtyness[channel_idx] += 40;

		{
			INT BelowBound;
			INT AboveBound;
			INT loop;

			switch(pBss->ExtChOffset)
			{
				case EXTCHA_ABOVE:
					BelowBound = pChannelInfo->IsABand ? 1 : 4;
					AboveBound = pChannelInfo->IsABand ? 2 : 8;
					break;

				case EXTCHA_BELOW:
					BelowBound = pChannelInfo->IsABand ? 2 : 8;
					AboveBound = pChannelInfo->IsABand ? 1 : 4;
					break;

				default:
					BelowBound = pChannelInfo->IsABand ? 1 : 4;
					AboveBound = pChannelInfo->IsABand ? 1 : 4;
					break;
			}

			/* check neighbor channel */
			for (loop = (channel_idx+1); loop <= (channel_idx+AboveBound); loop++)
			{
				if (loop >= MAX_NUM_OF_CHANNELS)
					break;

				if (pAd->ChannelList[loop].Channel - pAd->ChannelList[loop-1].Channel > 4)
					break;

				pChannelInfo->dirtyness[loop] +=
					((9 - (loop - channel_idx)) * 4);
			}
			/* check neighbor channel */
			for (loop=(channel_idx-1); loop >= (channel_idx-BelowBound); loop--)
			{
				if (loop < 0)
					break;

				if (pAd->ChannelList[loop+1].Channel - pAd->ChannelList[loop].Channel > 4)
					continue;

				pChannelInfo->dirtyness[loop] +=
					((9 - (channel_idx - loop)) * 4);
			}
		}

		printk(" ch%d bssid=%02x:%02x:%02x:%02x:%02x:%02x\n",
			pBss->Channel, pBss->Bssid[0], pBss->Bssid[1], pBss->Bssid[2], pBss->Bssid[3], pBss->Bssid[4], pBss->Bssid[5]);
	}
	
	AutoChannelSkipListSetDirty(pAd);
	
	printk("======================RT309x=========================\n");
	for (channel_idx = 0; channel_idx < pAd->ChannelListNum; channel_idx++)
	{
		printk("Channel %d : Dirty = %ld, False CCA = %u, Busy Time = %u, Skip Channel = %s\n",
					pAd->ChannelList[channel_idx].Channel,
					pChannelInfo->dirtyness[channel_idx],
					pChannelInfo->FalseCCA[channel_idx],
					pChannelInfo->chanbusytime[channel_idx],
					(pChannelInfo->SkipList[channel_idx] == TRUE) ? "TRUE" : "FALSE");
	}
	printk("=====================================================\n");

	min_dirty = min_falsecca = 0xFFFFFFFF;

	/* 
	 * Rule 1. Pick up a good channel that False_CCA =< CCA_THRESHOLD 
	 *		   by dirtyness
	 */
	candidate_ch = -1;
	
	for (channel_idx = 0; channel_idx < pAd->ChannelListNum; channel_idx++)
	{
		if (pChannelInfo->SkipList[channel_idx] == TRUE)
			continue;

		if (pChannelInfo->FalseCCA[channel_idx] <= CCA_THRESHOLD)
		{
			UINT32 dirtyness = pChannelInfo->dirtyness[channel_idx];
			ch = pAd->ChannelList[channel_idx].Channel;

#ifdef AP_QLOAD_SUPPORT
			/* QLOAD ALARM */
			/* when busy time of a channel > threshold, skip it */
			/* TODO: Use weight for different references to do channel selection */
			if (QBSS_LoadIsBusyTimeAccepted(pAd,
				pChannelInfo->chanbusytime[channel_idx]) == FALSE)
			{
				/* check next one */
				continue;
			}
#endif /* AP_QLOAD_SUPPORT */

#ifdef DOT11_N_SUPPORT
			/*
				User require 40MHz Bandwidth.
				In the case, ignor all channel
				doesn't support 40MHz Bandwidth.
			*/
			if ((pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)
				&& (pChannelInfo->IsABand && (GetABandChOffset(ch) == 0)))
				continue;

			/*
				Need to Consider the dirtyness of extending channel
				in 40 MHz bandwidth channel.
			*/
			if (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)
			{
				if (pAd->pChannelInfo->IsABand)
				{
					if (((channel_idx + GetABandChOffset(ch)) >=0)
						&& ((channel_idx + GetABandChOffset(ch)) < pAd->ChannelListNum))
					{
						INT ChOffsetIdx = channel_idx + GetABandChOffset(ch);
						dirtyness += pChannelInfo->dirtyness[ChOffsetIdx];
					}
				}
				else
				{
					UCHAR ExChannel_idx = 0;
					if (pAd->ChannelList[channel_idx].Channel == 14)
					{
						dirtyness = 0xFFFFFFFF;
						break;
					}
					else
					{
						NdisZeroMemory(ExChannel, sizeof(ExChannel));
						if (((channel_idx - 4) >=0) && ((channel_idx - 4) < pAd->ChannelListNum))
						{
							dirtyness += pChannelInfo->dirtyness[channel_idx - 4];
							ExChannel[ExChannel_idx++] = pAd->ChannelList[channel_idx - 4].Channel;
					    }

						if (((channel_idx + 4) >=0) && ((channel_idx + 4) < pAd->ChannelListNum))
						{
						    dirtyness += pChannelInfo->dirtyness[channel_idx + 4];
						    ExChannel[ExChannel_idx++] = pAd->ChannelList[channel_idx + 4].Channel;
						}
					}
				}
			}
#endif /* DOT11_N_SUPPORT */

			if ((min_dirty > dirtyness))
			{
				min_dirty = dirtyness;
				candidate_ch = channel_idx;
				NdisMoveMemory(candidate_ExChannel, ExChannel, 2);
			}
		}
	}

	if (candidate_ch >= 0)
	{
		ch = pAd->ChannelList[candidate_ch].Channel;
		printk("Rule 1 CCA value : Min Dirtiness ==> Select Channel %d \n", ch);
		printk("Min Dirty = %u\n", min_dirty);
		printk("ExChannel = %d , %d\n", candidate_ExChannel[0], candidate_ExChannel[1]);
		printk("BW        = %s\n", (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)? "40" : "20");
		return ch;
	}

	/*
	 * Rule 2. Pick up a good channel that False_CCA > CCA_THRESHOLD 
	 *		   by FalseCCA (FalseCCA + Dirtyness)
	 */
	candidate_ch = -1;
	for (channel_idx = 0; channel_idx < pAd->ChannelListNum; channel_idx++)
	{
		if (pChannelInfo->SkipList[channel_idx] == TRUE)
			continue;
		
		if (pChannelInfo->FalseCCA[channel_idx] > CCA_THRESHOLD)
		{
			UINT32 falsecca = pChannelInfo->FalseCCA[channel_idx] + pChannelInfo->dirtyness[channel_idx];
			ch = pAd->ChannelList[channel_idx].Channel;

#ifdef DOT11_N_SUPPORT
			if ((pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)
				&& (pChannelInfo->IsABand && (GetABandChOffset(ch) == 0)))
				continue;
#endif /* DOT11_N_SUPPORT */

			if ((GetABandChOffset(ch) != 0)
					&& ((channel_idx + GetABandChOffset(ch)) >=0)
					&& ((channel_idx + GetABandChOffset(ch)) < pAd->ChannelListNum))
			{
				INT ChOffsetIdx = channel_idx + GetABandChOffset(ch);
				falsecca += (pChannelInfo->FalseCCA[ChOffsetIdx] +
							pChannelInfo->dirtyness[ChOffsetIdx]);
			}

#ifdef AP_QLOAD_SUPPORT
			/* QLOAD ALARM */
			/* when busy time of a channel > threshold, skip it */
			/* TODO: Use weight for different references to do channel selection */
			if (QBSS_LoadIsBusyTimeAccepted(pAd,
				pChannelInfo->chanbusytime[channel_idx]) == FALSE)
			{
				/* check next one */
				continue;
			}
#endif /* AP_QLOAD_SUPPORT */

			if ((min_falsecca > falsecca))
			{
				min_falsecca = falsecca;
				candidate_ch = channel_idx;
			}
		}
	}

	if (candidate_ch >= 0)
	{
		ch = pAd->ChannelList[candidate_ch].Channel;
		printk("Rule 2 CCA value : Min False CCA value ==> Select Channel %d, min falsecca = %d \n", ch, min_falsecca);
		return	ch;
	}

	base = RandomByte2(pAd);
	for (channel_idx=0 ; channel_idx < pAd->ChannelListNum ; channel_idx++)
	{
		ch = pAd->ChannelList[(base + channel_idx) % pAd->ChannelListNum].Channel;
	
		if (AutoChannelSkipListCheck(pAd, ch))
			continue;
		
#ifdef A_BAND_SUPPORT
		if ((pAd->ApCfg.bAvoidDfsChannel == TRUE)
			&& (pChannelInfo->IsABand == TRUE)
			&& RadarChannelCheck(pAd, ch))
			continue;
#endif

		break;
	}
	printk("Rule 3 CCA value : Randomly Select ==> Select Channel %d\n", ch);
	return ch;
}
Exemple #9
0
VOID MlmeScanReqAction(
	IN PRTMP_ADAPTER pAd,
	IN MLME_QUEUE_ELEM *Elem)
{
	UCHAR          Ssid[MAX_LEN_OF_SSID], SsidLen, ScanType, BssType, BBPValue = 0;
	BOOLEAN        TimerCancelled;
	ULONG		   Now;
	USHORT         Status;
	PHEADER_802_11 pHdr80211;
	PUCHAR         pOutBuffer = NULL;
	NDIS_STATUS    NStatus;

	
	
	if ( !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))
	{
		DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeScanReqAction before Startup\n"));
		return;
	}

	
	pAd->StaCfg.ScanCnt++;

#ifdef RTMP_MAC_PCI
    if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) &&
        (IDLE_ON(pAd)) &&
		(pAd->StaCfg.bRadio == TRUE) &&
		(RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)))
	{
	        if (pAd->StaCfg.PSControl.field.EnableNewPS == FALSE)
		{
			AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x02);
			AsicCheckCommanOk(pAd, PowerWakeCID);
			RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF);
			DBGPRINT(RT_DEBUG_TRACE, ("PSM - Issue Wake up command \n"));
		}
		else
		{
		RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE);
	}
	}
#endif 

	
	if (MlmeScanReqSanity(pAd,
						  Elem->Msg,
						  Elem->MsgLen,
						  &BssType,
						  (PCHAR)Ssid,
						  &SsidLen,
						  &ScanType))
	{

		
		
		
		RTMPSuspendMsduTransmission(pAd);

		
		
		
		
		
		if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && (INFRA_ON(pAd)))
		{
			NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer);
			if (NStatus	== NDIS_STATUS_SUCCESS)
			{
				pHdr80211 = (PHEADER_802_11) pOutBuffer;
				MgtMacHeaderInit(pAd, pHdr80211, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid);
				pHdr80211->Duration = 0;
				pHdr80211->FC.Type = BTYPE_DATA;
				pHdr80211->FC.PwrMgmt = PWR_SAVE;

				
				MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11));
				DBGPRINT(RT_DEBUG_TRACE, ("MlmeScanReqAction -- Send PSM Data frame for off channel RM\n"));
				MlmeFreeMemory(pAd, pOutBuffer);
				RTMPusecDelay(5000);
			}
		}

		NdisGetSystemUpTime(&Now);
		pAd->StaCfg.LastScanTime = Now;
		
		RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled);
		RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled);

		
		pAd->MlmeAux.BssType = BssType;
		pAd->MlmeAux.ScanType = ScanType;
		pAd->MlmeAux.SsidLen = SsidLen;
        NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID);
		NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen);

		
		pAd->MlmeAux.Channel = FirstChannel(pAd);

		
		RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
		BBPValue &= (~0x18);
		RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
		DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n"));
		ScanNextChannel(pAd);
	}
	else
	{
		DBGPRINT_ERR(("SYNC - MlmeScanReqAction() sanity check fail\n"));
		pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
		Status = MLME_INVALID_FORMAT;
		MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status);
	}
}
static inline UCHAR SelectClearChannelBusyTime(
	IN PRTMP_ADAPTER pAd
	)
{
	PCHANNELINFO pChannelInfo = pAd->pChannelInfo;
	INT ch = 1, channel_idx;
	UINT32 min_busytime;
	int candidate_ch;
	UCHAR base;

	if(pChannelInfo == NULL)
	{
		MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("pAd->pChannelInfo equal NULL.\n"));
		return (FirstChannel(pAd));
		
	}

	AutoChannelSkipListSetDirty(pAd);	
	
	MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("=====================================================\n"));
	for (channel_idx = 0; channel_idx < pAd->ChannelListNum; channel_idx++)
	{
		MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("Channel %d : Busy Time = %u, Skip Channel = %s\n",
					pAd->ChannelList[channel_idx].Channel,
					pChannelInfo->chanbusytime[channel_idx],
					(pChannelInfo->SkipList[channel_idx] == TRUE) ? "TRUE" : "FALSE"));
	}
	MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("=====================================================\n"));

	min_busytime = 0xFFFFFFFF;
	candidate_ch = -1;
	for (channel_idx = 0; channel_idx < pAd->ChannelListNum; channel_idx++)
	{
		if (pChannelInfo->SkipList[channel_idx] == TRUE)
			continue;

		if (pChannelInfo->chanbusytime[channel_idx] < min_busytime)
		{
			min_busytime = pChannelInfo->chanbusytime[channel_idx];
			candidate_ch = channel_idx;			
		}
		
	}	
	if (candidate_ch >= 0)
	{
		ch = pAd->ChannelList[candidate_ch].Channel;
		MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("Rule 3 Channel Busy time value : Min Channel Busy  ==> Select Channel %d \n", ch));
		MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("Min Channel Busy = %u\n", min_busytime));		
		MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("BW        = %s\n", (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)? "40" : "20"));
		return ch;
	}
	
	base = RandomByte2(pAd);
	for (channel_idx=0 ; channel_idx < pAd->ChannelListNum ; channel_idx++)
	{
		ch = pAd->ChannelList[(base + channel_idx) % pAd->ChannelListNum].Channel;
	
		if (AutoChannelSkipListCheck(pAd, ch))
			continue;
		
		if ((pAd->ApCfg.bAvoidDfsChannel == TRUE)
			&& (pChannelInfo->IsABand == TRUE)
			&& RadarChannelCheck(pAd, ch))
			continue;

		break;
	}
	MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("Randomly Select ==> Select Channel %d\n", ch));
	return ch;
}
Exemple #11
0
static inline UCHAR SelectClearChannelRandom(
	IN PRTMP_ADAPTER pAd
	)
{
	UCHAR cnt, ch = 0, i, RadomIdx;
	BOOLEAN bFindIt = FALSE;
	
	if (pAd->CommonCfg.bIEEE80211H)
	{
		cnt = 0;
		while(TRUE)
		{
			cnt++;
#ifdef DOT11_N_SUPPORT
			if (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)
			{
				/* Counting number of entries in the sub channel list */
				for (i = 0; i < pAd->ChannelListNum; i++)
					if (!pAd->ChannelListN[i].Channel)
						break;
				RadomIdx = RandomByte2(pAd)%i;				
				ch = pAd->ChannelListN[RadomIdx].Channel;
			}
			else
#endif /* DOT11_N_SUPPORT */		
			{
				RadomIdx = RandomByte2(pAd)%pAd->ChannelListNum;
				ch = pAd->ChannelList[RadomIdx].Channel;
			}	


			if (ch == 0)
				ch = FirstChannel(pAd);

				/* have no avaiable channel now. force pick first channel here. */
			if (cnt == pAd->ChannelListNum)
			{
				ch = FirstChannel(pAd);
				break;
			}

	

			for (i=0; i<pAd->ChannelListNum; i++)
			{
				if (pAd->ChannelList[i].Channel == ch)
				{
					if (pAd->ChannelList[i].RemainingTimeForUse == 0)
						bFindIt = TRUE;
						break;
				}
			}
				
			if (bFindIt == TRUE)
				break;
		};
	}
	else
	{
		ch = pAd->ChannelList[RandomByte2(pAd)%pAd->ChannelListNum].Channel;
		if (ch == 0)
			ch = FirstChannel(pAd);
	}
	printk("Random in A band. Select Channel %d\n",ch);
	return ch;

}