[WCNCR00146538] p2p: update ACS algorithm

[Description]
Change the ACS algorithm.
1. Update dirtyness index 1 calculation:
   Calculate the scanned AP's affect by its primary channel
2. Update dirtyness index 2 calculation:
   Calculate the scanned AP's affect by its working BW

Change-Id: I261931c1a1778275483e848acb641b0c1a1dc030
Feature: p2p
Signed-off-by: Awk Jiang <awk.jiang@mediatek.com>
CR-Id: WCNCR00146538
diff --git a/common/wlan_lib.c b/common/wlan_lib.c
index e6e0bc7..438c704 100644
--- a/common/wlan_lib.c
+++ b/common/wlan_lib.c
@@ -171,6 +171,14 @@
 #define COMPRESSION_OPTION_MASK     BIT(4)
 #endif
 
+#if CFG_AUTO_CHANNEL_SEL_SUPPORT
+#define ACS_AP_RSSI_LEVEL_HIGH -50
+#define ACS_AP_RSSI_LEVEL_LOW -80
+#define ACS_DIRTYNESS_LEVEL_HIGH 52
+#define ACS_DIRTYNESS_LEVEL_MID 40
+#define ACS_DIRTYNESS_LEVEL_LOW 32
+#endif
+
 /*******************************************************************************
 *                                 M A C R O S
 ********************************************************************************
@@ -8781,147 +8789,165 @@
 
 /*----------------------------------------------------------------------------*/
 /*!
-* \brief This routine is called to calculate the channel dirtyness based on scanned APs.
+* \brief Add dirtyness to neighbor channels of a BSS to estimate channel quality.
 *
-* \param[in]  pvAdapter        Pointer to the Adapter structure.
-*
-* \retval WLAN_STATUS_PENDING
-* \retval WLAN_STATUS_FAILURE
+* \param[in]  prAdapter        Pointer to the Adapter structure.
+* \param[in]  prBssDesc        Pointer to the BSS description.
+* \param[in]  u4Dirtyness      Expected dirtyness value.
+* \param[in]  ucCentralChannel Central channel of the given BSS.
+* \param[in]  ucCoveredRange   With ucCoveredRange and ucCentralChannel,
+*                              all the affected channels can be enumerated.
 */
 /*----------------------------------------------------------------------------*/
+static VOID
+wlanAddDirtynessToAffectedChannels(P_ADAPTER_T prAdapter,
+	P_BSS_DESC_T prBssDesc, UINT_32 u4Dirtyness, UINT_8 ucCentralChannel,
+	UINT_8 ucCoveredRange)
+{
+	INT_32 i4Loop;
+	UINT_8 ucChannel;
+	BOOL bIs5GChl = ucCentralChannel > 14;
+	UINT_8 ucLeftNeighborChannel, ucRightNeighborChannel;
+	P_PARAM_GET_CHN_INFO prGetChnLoad = &(prAdapter->rWifiVar.rChnLoadInfo);
+
+	ucLeftNeighborChannel = ucCentralChannel > (ucCoveredRange + 1) ?
+		ucCentralChannel - ucCoveredRange - 1 : 0;
+	ucRightNeighborChannel = ucCentralChannel + ucCoveredRange + 1;
+
+	if (bIs5GChl) {
+		ucLeftNeighborChannel -= 1;
+		ucRightNeighborChannel += 1;
+	}
+
+	DBGLOG(SCN, TRACE, "central ch %d, affect ch %d to %d\n", ucCentralChannel,
+		ucLeftNeighborChannel, ucRightNeighborChannel);
+
+	for (i4Loop = 0; i4Loop < MAX_CHN_NUM; i4Loop++) {
+		ucChannel = prGetChnLoad->rEachChnLoad[i4Loop].ucChannel;
+
+		if (ucChannel == 0 || ucChannel < ucLeftNeighborChannel)
+			continue;
+
+		if (ucChannel > ucRightNeighborChannel)
+			break;
+
+		if (ucChannel == ucLeftNeighborChannel ||
+			ucChannel == ucRightNeighborChannel) {
+			prGetChnLoad->rEachChnLoad[i4Loop].u4Dirtyness += (u4Dirtyness >> 1);
+			DBGLOG(SCN, TRACE, "Add dirtyness %d, to ch %d\n",
+				(u4Dirtyness >> 1), ucChannel);
+		} else {
+			prGetChnLoad->rEachChnLoad[i4Loop].u4Dirtyness += u4Dirtyness;
+			DBGLOG(SCN, TRACE, "Add dirtyness %d, to ch %d\n",
+				u4Dirtyness, ucChannel);
+		}
+	}
+
+}
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief For a scanned BSS, add dirtyness to the channels 1)around its primary
+*        channels and 2) in its working BW to represent the quality degrade.
+*
+* \param[in]  prAdapter        Pointer to the Adapter structure.
+* \param[in]  prBssDesc        Pointer to the BSS description.
+* \param[in]  u4Dirtyness      Expected dirtyness value.
+* \param[in]  bIsIndexOne      True means index 1, False means index 2.
+*/
+/*----------------------------------------------------------------------------*/
+static VOID
+wlanCalculateChannelDirtyness(IN P_ADAPTER_T prAdapter,
+	P_BSS_DESC_T prBssDesc, UINT_32 u4Dirtyness, BOOL bIsIndexOne)
+{
+	UINT_8 ucCoveredRange = 0, ucCentralChannel = 0, ucCentralChannel2 = 0;
+
+	if (bIsIndexOne) {
+		DBGLOG(SCN, TRACE, "Process dirtyness index 1\n");
+		ucCentralChannel = prBssDesc->ucChannelNum;
+		ucCoveredRange = 2;
+	} else {
+		DBGLOG(SCN, TRACE, "Process dirtyness index 2, ");
+		switch (prBssDesc->eChannelWidth) {
+		case CW_20_40MHZ:
+			if (prBssDesc->eSco == CHNL_EXT_SCA) {
+				DBGLOG(SCN, TRACE, "BW40\n");
+				ucCentralChannel = prBssDesc->ucChannelNum + 2;
+				ucCoveredRange = 4;
+			} else if (prBssDesc->eSco == CHNL_EXT_SCB) {
+				DBGLOG(SCN, TRACE, "BW40\n");
+				ucCentralChannel = prBssDesc->ucChannelNum - 2;
+				ucCoveredRange = 4;
+			} else {
+				DBGLOG(SCN, TRACE, "BW20\n");
+				ucCentralChannel = prBssDesc->ucChannelNum;
+				ucCoveredRange = 2;
+			}
+			break;
+		case CW_80MHZ:
+			DBGLOG(SCN, TRACE, "BW80\n");
+			ucCentralChannel = prBssDesc->ucCenterFreqS1;
+			ucCoveredRange = 8;
+			break;
+		case CW_160MHZ:
+			DBGLOG(SCN, TRACE, "BW160\n");
+			ucCentralChannel = prBssDesc->ucCenterFreqS1;
+			ucCoveredRange = 16;
+			break;
+		case CW_80P80MHZ:
+			DBGLOG(SCN, TRACE, "BW8080\n");
+			ucCentralChannel = prBssDesc->ucCenterFreqS1;
+			ucCentralChannel2 = prBssDesc->ucCenterFreqS2;
+			ucCoveredRange = 8;
+			break;
+		default:
+			ucCentralChannel = prBssDesc->ucChannelNum;
+			ucCoveredRange = 2;
+			break;
+		};
+	}
+
+	wlanAddDirtynessToAffectedChannels(prAdapter, prBssDesc, u4Dirtyness,
+		ucCentralChannel, ucCoveredRange);
+
+	/* 80 + 80 secondary 80 case */
+	if (bIsIndexOne || ucCentralChannel2 == 0)
+		return;
+
+	wlanAddDirtynessToAffectedChannels(prAdapter, prBssDesc, u4Dirtyness,
+		ucCentralChannel2, ucCoveredRange);
+}
+
 WLAN_STATUS
-wlanCalculateChannelDirtyness(IN P_ADAPTER_T prAdapter)
+wlanCalculateAllChannelDirtyness(IN P_ADAPTER_T prAdapter)
 {
 	WLAN_STATUS rResult = WLAN_STATUS_SUCCESS;
 	PARAM_RSSI i4Rssi = 0;
 	P_BSS_DESC_T prBssDesc = NULL;
 	UINT_8 ucIdx = 0;
-	P_PARAM_GET_CHN_INFO prGetChnLoad = &(prAdapter->rWifiVar.rChnLoadInfo);
+	UINT_32 u4Dirtyness = 0;
 	P_LINK_T prBSSDescList = &(prAdapter->rWifiVar.rScanInfo.rBSSDescList);
 
-
 	LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) {
 		i4Rssi = RCPI_TO_dBm(prBssDesc->ucRCPI);
 		ucIdx = wlanGetChannelIndex(prBssDesc->ucChannelNum);
 
-		if (i4Rssi >= -50)
-			prGetChnLoad->rEachChnLoad[ucIdx].u4Dirtyness += 50;
-		else if (i4Rssi >= -80)
-			prGetChnLoad->rEachChnLoad[ucIdx].u4Dirtyness += 40;
+		if (i4Rssi >= ACS_AP_RSSI_LEVEL_HIGH)
+			u4Dirtyness = ACS_DIRTYNESS_LEVEL_HIGH;
+		else if (i4Rssi >= ACS_AP_RSSI_LEVEL_LOW)
+			u4Dirtyness = ACS_DIRTYNESS_LEVEL_MID;
 		else
-			prGetChnLoad->rEachChnLoad[ucIdx].u4Dirtyness += 30;
+			u4Dirtyness = ACS_DIRTYNESS_LEVEL_LOW;
 
-		{
-			INT_32 i4Loop;
-			UINT_8 ucCoveredRange = 6, ucCentralChannel, ucCentralChannel2 = 0,
-				ucChannelSpace = 19, ucCoveredChannel, ucCentralDistance;
-			BOOL bIs5GChl = prBssDesc->ucChannelNum > 14, bIsBw20;
-			UINT_8 ucBwWeight = 2, ucLeftChannel, ucRightChannel;
+		DBGLOG(SCN, TRACE, "Found an AP(%s), primary ch %d\n",
+			prBssDesc->aucSSID, prBssDesc->ucChannelNum);
 
-			/**
-			 * ucCoveredRange = (BW/2) / 5 + 2, which means the AP will affect
-			 * its covering channels and the neighboring 10MHz channels-
-			 *
-			 * For example, a scanned HT20 AP center ch and primary ch is ch 5,
-			 * BW20 will cover ch 3~7. In this case, we will add ch 1~2 and ch 8~9
-			 * as the affected channels and add some dirtyness to those channels.
-			 */
+		/* dirtyness index1 */
+		wlanCalculateChannelDirtyness(prAdapter, prBssDesc, u4Dirtyness, TRUE);
 
-			switch (prBssDesc->eChannelWidth) {
-			case CW_20_40MHZ:
-				if (prBssDesc->eSco == CHNL_EXT_SCA)
-					ucCentralChannel = prBssDesc->ucChannelNum + 2;
-				else if (prBssDesc->eSco == CHNL_EXT_SCB)
-					ucCentralChannel = prBssDesc->ucChannelNum - 2;
-				else {
-					ucCentralChannel = prBssDesc->ucChannelNum;
-					ucCoveredRange = 4;
-					bIsBw20 = TRUE;
-				}
-				break;
-			case CW_80MHZ:
-				ucCentralChannel = prBssDesc->ucCenterFreqS1;
-				ucCoveredRange = 10;
-				break;
-			case CW_160MHZ:
-				ucCentralChannel = prBssDesc->ucCenterFreqS1;
-				ucCoveredRange = 18;
-				break;
-			case CW_80P80MHZ:
-				ucCentralChannel = prBssDesc->ucCenterFreqS1;
-				ucCentralChannel2 = prBssDesc->ucCenterFreqS2;
-				ucCoveredRange = 10;
-				break;
-			default:
-				ucCentralChannel = prBssDesc->ucChannelNum;
-				ucCoveredRange = 4;
-				break;
-			};
-
-			ucLeftChannel = ucCentralChannel - ucCoveredRange;
-			ucRightChannel = ucCentralChannel + ucCoveredRange;
-
-			if (bIs5GChl) {
-				if (!bIsBw20) {
-					ucLeftChannel -= 4;
-					ucRightChannel += 4;
-				}
-			} else {
-				/* Above calcuation may cause overflow */
-				if (ucLeftChannel > 14)
-					ucLeftChannel = 1;
-			}
-
-			DBGLOG(SCN, TRACE, "Found AP(%02x:%02x:%02x:%02x:%02x:%02x) BW %d, ",
-				prBssDesc->aucBSSID[0], prBssDesc->aucBSSID[1],
-				prBssDesc->aucBSSID[2], prBssDesc->aucBSSID[3],
-				prBssDesc->aucBSSID[4], prBssDesc->aucBSSID[5],
-				(ucCoveredRange - 2) * 10);
-
-			DBGLOG(SCN, TRACE,
-				"primary ch %d, center ch %d, covered ch %d to %d\n",
-				prBssDesc->ucChannelNum, ucCentralChannel,
-				ucLeftChannel, ucRightChannel);
-
-			for (i4Loop = 0; i4Loop < MAX_CHN_NUM; i4Loop++) {
-				ucCoveredChannel = prGetChnLoad->rEachChnLoad[i4Loop].ucChannel;
-				if (ucCoveredChannel < ucLeftChannel)
-					continue;
-				if (ucCoveredChannel > ucRightChannel)
-					break;
-				ucCentralDistance = ucCentralChannel > ucCoveredChannel ?
-					ucCentralChannel - ucCoveredChannel :
-					ucCoveredChannel - ucCentralChannel;
-
-				prGetChnLoad->rEachChnLoad[i4Loop].u4Dirtyness +=
-					((ucChannelSpace - (ucCentralDistance)) * ucBwWeight);
-
-				DBGLOG(SCN, TRACE, "Add dirtyness %d, to ch %d\n",
-					((ucChannelSpace - (ucCentralDistance)) * ucBwWeight),
-					ucCoveredChannel);
-			}
-
-			/* 80 + 80 secondary 80 case */
-			if (ucCentralChannel2 != 0) {
-				ucLeftChannel = ucCentralChannel2 - ucCoveredRange - 4;
-				ucRightChannel = ucCentralChannel2 + ucCoveredRange + 4;
-
-				for (i4Loop = 0; i4Loop < MAX_CHN_NUM; i4Loop++) {
-					ucCoveredChannel = prGetChnLoad->rEachChnLoad[i4Loop].ucChannel;
-					if (ucCoveredChannel < ucLeftChannel)
-						continue;
-					if (ucCoveredChannel > ucRightChannel)
-						break;
-
-					ucCentralDistance = ucCentralChannel2 > ucCoveredChannel ?
-					ucCentralChannel - ucCoveredChannel :
-					ucCoveredChannel - ucCentralChannel;
-
-					prGetChnLoad->rEachChnLoad[i4Loop].u4Dirtyness +=
-						((ucChannelSpace - (ucCentralDistance)) * ucBwWeight);
-				}
-			}
-		}
+		/* dirtyness index2 */
+		wlanCalculateChannelDirtyness(prAdapter, prBssDesc,
+			u4Dirtyness >> 1, FALSE);
 	}
 
 	return rResult;
@@ -9010,8 +9036,8 @@
 
 	for (ucIdx = 0; ucIdx < prChnLoadInfo->ucAvailChnNum; ++ucIdx)
 		DBGLOG(SCN, INFO, "[ACS]channel=%d, dirtyness=%d\n",
-		prChnLoadInfo->rChnRankList[ucIdx].ucChannel,
-	    prChnLoadInfo->rChnRankList[ucIdx].u4Dirtyness);
+			prChnLoadInfo->rChnRankList[ucIdx].ucChannel,
+			prChnLoadInfo->rChnRankList[ucIdx].u4Dirtyness);
 
 }
 #endif
diff --git a/include/wlan_oid.h b/include/wlan_oid.h
index 98d485a..69f9ae7 100644
--- a/include/wlan_oid.h
+++ b/include/wlan_oid.h
@@ -2709,7 +2709,7 @@
 wlanoidQueryLteSafeChannel(IN P_ADAPTER_T prAdapter,
 			   IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen);
 WLAN_STATUS
-wlanCalculateChannelDirtyness(IN P_ADAPTER_T prAdapter);
+wlanCalculateAllChannelDirtyness(IN P_ADAPTER_T prAdapter);
 UINT_8
 wlanGetChannelIndex(IN UINT_8 channel);
 VOID
diff --git a/mgmt/scan.c b/mgmt/scan.c
index c000de9..5fbfcfa 100644
--- a/mgmt/scan.c
+++ b/mgmt/scan.c
@@ -2599,7 +2599,7 @@
 
 		}
 #if CFG_AUTO_CHANNEL_SEL_SUPPORT
-		wlanCalculateChannelDirtyness(prAdapter);
+		wlanCalculateAllChannelDirtyness(prAdapter);
 		wlanSortChannel(prAdapter);
 
 		prAdapter->rWifiVar.rChnLoadInfo.fgDataReadyBit = TRUE;