[WCNCR00145892] softap: add BW/SCO/S0/S1 config from cfg80211

[Description]
add bandwidth, secondary channel offset,
channel center frequency segment 0/1
config from cfg80211 for DFS.
In DFS verification, AP bandwidth,
secondary channel offset,
channel center frequency segment 0/1 have to align hosapd

Change-Id: I0703ffeefb722fb6c29bf5d672562255e385c511
Feature: softap
Signed-off-by: Litien Chang <litien.chang@mediatek.com>
CR-Id: WCNCR00145892
diff --git a/common/wlan_lib.c b/common/wlan_lib.c
index cff2fc4..0c448dd 100644
--- a/common/wlan_lib.c
+++ b/common/wlan_lib.c
@@ -6654,6 +6654,7 @@
 	prWifiVar->ucApBandwidth = (UINT_8) wlanCfgGetUint32(prAdapter, "ApBw", MAX_BW_160MHZ);
 	prWifiVar->ucAp2gBandwidth = (UINT_8) wlanCfgGetUint32(prAdapter, "Ap2gBw", MAX_BW_20MHZ);
 	prWifiVar->ucAp5gBandwidth = (UINT_8) wlanCfgGetUint32(prAdapter, "Ap5gBw", MAX_BW_80MHZ);
+	prWifiVar->ucApChnlDefFromCfg = (UINT_8) wlanCfgGetUint32(prAdapter, "ApChnlDefFromCfg", FEATURE_ENABLED);
 
 	prWifiVar->ucNSS = (UINT_8) wlanCfgGetUint32(prAdapter, "Nss", 2);
 
diff --git a/include/mgmt/cnm.h b/include/mgmt/cnm.h
index 5695b9c..ec4f6fe 100644
--- a/include/mgmt/cnm.h
+++ b/include/mgmt/cnm.h
@@ -239,6 +239,8 @@
 
 UINT_8 cnmGetBssMaxBw(P_ADAPTER_T prAdapter, UINT_8 ucBssIndex);
 
+UINT_8 cnmGetBssMaxBwToChnlBW(P_ADAPTER_T prAdapter, UINT_8 ucBssIndex);
+
 P_BSS_INFO_T cnmGetBssInfoAndInit(P_ADAPTER_T prAdapter, ENUM_NETWORK_TYPE_T eNetworkType, BOOLEAN fgIsP2pDevice);
 
 VOID cnmFreeBssInfo(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo);
diff --git a/include/mgmt/p2p_func.h b/include/mgmt/p2p_func.h
index 81ae4a0..d99f778 100644
--- a/include/mgmt/p2p_func.h
+++ b/include/mgmt/p2p_func.h
@@ -130,6 +130,8 @@
 
 WLAN_STATUS p2pFuncRoleToBssIdx(IN P_ADAPTER_T prAdapter, IN UINT_8 ucRoleIdx, OUT PUINT_8 pucBssIdx);
 
+P_P2P_ROLE_FSM_INFO_T p2pFuncGetRoleByBssIdx(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex);
+
 VOID
 p2pFuncSwitchOPMode(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prP2pBssInfo, IN ENUM_OP_MODE_T eOpMode, IN BOOLEAN
 		    fgSyncToFW);
diff --git a/include/mgmt/p2p_rlm.h b/include/mgmt/p2p_rlm.h
index 4a9cfb2..1692fae 100644
--- a/include/mgmt/p2p_rlm.h
+++ b/include/mgmt/p2p_rlm.h
@@ -71,6 +71,7 @@
  *                              C O N S T A N T S
  ********************************************************************************
  */
+#define CHANNEL_SPAN_20 20
 
 /*******************************************************************************
  *                                 M A C R O S
@@ -117,4 +118,9 @@
 
 ENUM_CHNL_EXT_T rlmDecideScoForAP(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo);
 
+ENUM_CHNL_EXT_T rlmGetScoForAP(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo);
+
+UINT_8 rlmGetVhtS1ForAP(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo);
+
+
 #endif
diff --git a/include/mgmt/p2p_role.h b/include/mgmt/p2p_role.h
index ea224ba..6a06975 100644
--- a/include/mgmt/p2p_role.h
+++ b/include/mgmt/p2p_role.h
@@ -260,6 +260,18 @@
 	RF_CHANNEL_INFO_T rChannelInfo;
 	ENUM_CHNL_EXT_T eChnlExt;
 
+	/* To record channel bandwidth from CFG80211 */
+	ENUM_MAX_BANDWIDTH_SETTING eChnlBw;
+
+	/* To record primary channel frequency (MHz) from CFG80211 */
+	UINT_16 u2PriChnlFreq;
+
+	/* To record Channel Center Frequency Segment 0 (MHz) from CFG80211 */
+	UINT_32 u4CenterFreq1;
+
+	/* To record Channel Center Frequency Segment 1 (MHz) from CFG80211 */
+	UINT_32 u4CenterFreq2;
+
 	/* For ASSOC Req. */
 	UINT_32 u4BufLength;
 	UINT_8 aucIEBuf[MAX_IE_LENGTH];
diff --git a/include/nic/adapter.h b/include/nic/adapter.h
index f00b541..94177e6 100644
--- a/include/nic/adapter.h
+++ b/include/nic/adapter.h
@@ -716,6 +716,11 @@
 	UINT_8 ucP2p5gBandwidth;
 	UINT_8 ucP2p2gBandwidth;
 
+	/* If enable, AP channel bandwidth Channel Center Frequency Segment 0/1 */
+	/* and secondary channel offset will align wifi.cfg */
+	/* Otherwise align cfg80211 */
+	UINT_8 ucApChnlDefFromCfg;
+
 	UINT_8 ucNSS;
 
 	UINT_8 ucRxMaxMpduLen;
diff --git a/include/nic/wlan_def.h b/include/nic/wlan_def.h
index 76948c3..5a138b9 100644
--- a/include/nic/wlan_def.h
+++ b/include/nic/wlan_def.h
@@ -613,6 +613,10 @@
 /* Provide supported channel list to other components in array format */
 typedef struct _RF_CHANNEL_INFO_T {
 	ENUM_BAND_T eBand;
+	UINT_32 u4CenterFreq1; /* To record Channel Center Frequency Segment 0 (MHz) from CFG80211 */
+	UINT_32 u4CenterFreq2; /* To record Channel Center Frequency Segment 1 (MHz) from CFG80211 */
+	UINT_16 u2PriChnlFreq; /* To record primary channel frequency (MHz) from CFG80211 */
+	UINT_8 ucChnlBw; /* To record channel bandwidth from CFG80211 */
 	UINT_8 ucChannelNum;
 } RF_CHANNEL_INFO_T, *P_RF_CHANNEL_INFO_T;
 
diff --git a/mgmt/cnm.c b/mgmt/cnm.c
index 3c47e49..fcfdf10 100644
--- a/mgmt/cnm.c
+++ b/mgmt/cnm.c
@@ -751,6 +751,9 @@
 
 		for (i = 0 ; i < BSS_P2P_NUM; i++) {
 
+			if (!prAdapter->rWifiVar.aprP2pRoleFsmInfo[i])
+				continue;
+
 			if (prAdapter->rWifiVar.aprP2pRoleFsmInfo[i]->ucBssIndex == ucBssIndex)
 				break;
 
@@ -870,6 +873,8 @@
 	UINT_8 ucMaxBandwidth = MAX_BW_80_80_MHZ; /*chip capability*/
 	P_BSS_DESC_T    prBssDesc = NULL;
 	ENUM_BAND_T eBand = BAND_NULL;
+	P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) NULL;
+	P_P2P_CONNECTION_REQ_INFO_T prP2pConnReqInfo = (P_P2P_CONNECTION_REQ_INFO_T) NULL;
 
 	prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex);
 
@@ -901,13 +906,19 @@
 		/* AP mode */
 		if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2PConnSettings[prBssInfo->u4PrivateData])) {
 
-			if (prBssInfo->eBand == BAND_2G4)
-				ucMaxBandwidth = prAdapter->rWifiVar.ucAp2gBandwidth;
-			else
-				ucMaxBandwidth = prAdapter->rWifiVar.ucAp5gBandwidth;
+			prP2pRoleFsmInfo = p2pFuncGetRoleByBssIdx(prAdapter, ucBssIndex);
+			if (!prAdapter->rWifiVar.ucApChnlDefFromCfg && prP2pRoleFsmInfo) {
+				prP2pConnReqInfo = &(prP2pRoleFsmInfo->rConnReqInfo);
+				ucMaxBandwidth = prP2pConnReqInfo->eChnlBw;
+			} else {
+				if (prBssInfo->eBand == BAND_2G4)
+					ucMaxBandwidth = prAdapter->rWifiVar.ucAp2gBandwidth;
+				else
+					ucMaxBandwidth = prAdapter->rWifiVar.ucAp5gBandwidth;
 
-			if (ucMaxBandwidth > prAdapter->rWifiVar.ucApBandwidth)
-				ucMaxBandwidth = prAdapter->rWifiVar.ucApBandwidth;
+				if (ucMaxBandwidth > prAdapter->rWifiVar.ucApBandwidth)
+					ucMaxBandwidth = prAdapter->rWifiVar.ucApBandwidth;
+			}
 		}
 		/* P2P mode */
 		else {
@@ -921,6 +932,13 @@
 	return ucMaxBandwidth;
 }
 
+
+UINT_8 cnmGetBssMaxBwToChnlBW(P_ADAPTER_T prAdapter, UINT_8 ucBssIndex)
+{
+	UINT_8 ucMaxBandwidth = cnmGetBssMaxBw(prAdapter, ucBssIndex);
+	return ucMaxBandwidth == MAX_BW_20MHZ ? ucMaxBandwidth:(ucMaxBandwidth - 1);
+}
+
 /*----------------------------------------------------------------------------*/
 /*!
 * @brief    Search available HW ID and BSS_INFO structure and initialize
diff --git a/mgmt/p2p_func.c b/mgmt/p2p_func.c
index 4bbacee..21aa21d 100644
--- a/mgmt/p2p_func.c
+++ b/mgmt/p2p_func.c
@@ -763,6 +763,29 @@
 	return rWlanStatus;
 }				/* p2pFuncRoleToBssIdx */
 
+P_P2P_ROLE_FSM_INFO_T p2pFuncGetRoleByBssIdx(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex)
+{
+	INT_32 i = 0;
+	P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T)NULL;
+
+	do {
+		ASSERT_BREAK((prAdapter != NULL));
+
+		for (i = 0 ; i < BSS_P2P_NUM; i++) {
+			if (!prAdapter->rWifiVar.aprP2pRoleFsmInfo[i])
+				continue;
+
+			if (prAdapter->rWifiVar.aprP2pRoleFsmInfo[i]->ucBssIndex == ucBssIndex)
+				break;
+		}
+		if (i < BSS_P2P_NUM)
+			prP2pRoleFsmInfo = prAdapter->rWifiVar.aprP2pRoleFsmInfo[i];
+
+	} while (FALSE);
+
+	return prP2pRoleFsmInfo;
+}
+
 /* /////////////////////////////////   MT6630 CODE END //////////////////////////////////////////////// */
 
 VOID
@@ -1546,6 +1569,10 @@
 
 		prP2pConnReqInfo->rChannelInfo.ucChannelNum = prRfChannelInfo->ucChannelNum;
 		prP2pConnReqInfo->rChannelInfo.eBand = prRfChannelInfo->eBand;
+		prP2pConnReqInfo->eChnlBw = prRfChannelInfo->ucChnlBw;
+		prP2pConnReqInfo->u2PriChnlFreq = prRfChannelInfo->u2PriChnlFreq;
+		prP2pConnReqInfo->u4CenterFreq1 = prRfChannelInfo->u4CenterFreq1;
+		prP2pConnReqInfo->u4CenterFreq2 = prRfChannelInfo->u4CenterFreq2;
 
 	} while (FALSE);
 }				/* p2pFuncSetChannel */
diff --git a/mgmt/p2p_rlm.c b/mgmt/p2p_rlm.c
index ff434ee..4d3dbc9 100644
--- a/mgmt/p2p_rlm.c
+++ b/mgmt/p2p_rlm.c
@@ -117,9 +117,7 @@
 /*----------------------------------------------------------------------------*/
 VOID rlmBssInitForAP(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo)
 {
-	ENUM_BAND_T eBand;
-	UINT_8 ucChannel, i;
-	ENUM_CHNL_EXT_T eSCO;
+	UINT_8 i;
 
 	ASSERT(prAdapter);
 	ASSERT(prBssInfo);
@@ -139,16 +137,8 @@
 	 * in order to remain in SCC case
 	 */
 	if (cnmBss40mBwPermitted(prAdapter, prBssInfo->ucBssIndex)) {
-		/* In this case, the first BSS's SCO is 40MHz and known, so AP can
-		 * apply 40MHz bandwidth, but the first BSS's SCO may be changed
-		 * later if its Beacon lost timeout occurs
-		 */
-		if (cnmPreferredChannel(prAdapter, &eBand, &ucChannel, &eSCO) &&
-		    eSCO != CHNL_EXT_SCN && ucChannel == prBssInfo->ucPrimaryChannel && eBand == prBssInfo->eBand) {
-			prBssInfo->eBssSCO = eSCO;
-		} else {
-			prBssInfo->eBssSCO = rlmDecideScoForAP(prAdapter, prBssInfo);
-		}
+
+		prBssInfo->eBssSCO = rlmGetScoForAP(prAdapter, prBssInfo);
 
 		if (prBssInfo->eBssSCO != CHNL_EXT_SCN) {
 			prBssInfo->fg40mBwAllowed = TRUE;
@@ -167,28 +157,19 @@
 			prBssInfo->u2VhtBasicMcsSet |= BITS(2 * i, (2 * i + 1));
 		prBssInfo->u2VhtBasicMcsSet &= (VHT_CAP_INFO_MCS_MAP_MCS9 << VHT_CAP_INFO_MCS_1SS_OFFSET);
 
-		if (cnmGetBssMaxBw(prAdapter, prBssInfo->ucBssIndex) < MAX_BW_80MHZ || prBssInfo->eBand == BAND_2G4) {
+		prBssInfo->ucVhtChannelWidth = cnmGetBssMaxBwToChnlBW(prAdapter, prBssInfo->ucBssIndex);
+		if (prBssInfo->ucVhtChannelWidth == VHT_OP_CHANNEL_WIDTH_80P80) {
+			/* TODO: BW80+80 support */
+			DBGLOG(RLM, WARN, "BW80+80 not support. Fallback  to VHT_OP_CHANNEL_WIDTH_20_40\n");
 			prBssInfo->ucVhtChannelWidth = VHT_OP_CHANNEL_WIDTH_20_40;
 			prBssInfo->ucVhtChannelFrequencyS1 = 0;
 			prBssInfo->ucVhtChannelFrequencyS2 = 0;
-		} else if (cnmGetBssMaxBw(prAdapter, prBssInfo->ucBssIndex) == MAX_BW_80MHZ) {
-			prBssInfo->ucVhtChannelWidth = VHT_OP_CHANNEL_WIDTH_80;
-			prBssInfo->ucVhtChannelFrequencyS1 =
-				nicGetVhtS1(prBssInfo->ucPrimaryChannel, VHT_OP_CHANNEL_WIDTH_80);
-			prBssInfo->ucVhtChannelFrequencyS2 = 0;
-		} else if (cnmGetBssMaxBw(prAdapter, prBssInfo->ucBssIndex) == MAX_BW_160MHZ) {
-			prBssInfo->ucVhtChannelWidth = VHT_OP_CHANNEL_WIDTH_160;
-			prBssInfo->ucVhtChannelFrequencyS1 =
-				nicGetVhtS1(prBssInfo->ucPrimaryChannel, VHT_OP_CHANNEL_WIDTH_160);
-			prBssInfo->ucVhtChannelFrequencyS2 = 0;
 		} else {
-			/* 4 TODO: / BW80+80 support */
-			DBGLOG(RLM, INFO, "Wrong AP BW parameter setting, back to BW20!!!\n");
-
-			prBssInfo->ucVhtChannelWidth = VHT_OP_CHANNEL_WIDTH_20_40;
-			prBssInfo->ucVhtChannelFrequencyS1 = 0;
+			prBssInfo->ucVhtChannelFrequencyS1 =
+				rlmGetVhtS1ForAP(prAdapter, prBssInfo);
 			prBssInfo->ucVhtChannelFrequencyS2 = 0;
 		}
+
 		/* If the S1 is invalid, force to change bandwidth */
 		if (prBssInfo->ucVhtChannelFrequencyS1 == 0)
 			prBssInfo->ucVhtChannelWidth = VHT_OP_CHANNEL_WIDTH_20_40;
@@ -1033,3 +1014,97 @@
 
 	return eSCO;
 }
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief: Get AP secondary channel offset from cfg80211 or wifi.cfg
+*
+* \param[in] prAdapter  Pointer of ADAPTER_T, prBssInfo Pointer of BSS_INFO_T,
+*
+* \return ENUM_CHNL_EXT_T AP secondary channel offset
+*/
+/*----------------------------------------------------------------------------*/
+ENUM_CHNL_EXT_T rlmGetScoForAP(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo)
+{
+	ENUM_BAND_T eBand;
+	UINT_8 ucChannel;
+	ENUM_CHNL_EXT_T eSCO;
+	INT_32 i4DeltaBw;
+	UINT_32 u4AndOneSCO;
+	P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) NULL;
+	P_P2P_CONNECTION_REQ_INFO_T prP2pConnReqInfo = (P_P2P_CONNECTION_REQ_INFO_T) NULL;
+
+	prP2pRoleFsmInfo = p2pFuncGetRoleByBssIdx(prAdapter, prBssInfo->ucBssIndex);
+
+	if (!prAdapter->rWifiVar.ucApChnlDefFromCfg && prP2pRoleFsmInfo) {
+		prP2pConnReqInfo = &(prP2pRoleFsmInfo->rConnReqInfo);
+		eSCO = CHNL_EXT_SCN;
+		if (cnmGetBssMaxBw(prAdapter, prBssInfo->ucBssIndex) == MAX_BW_40MHZ) {
+			/* If BW 40, compare S0 and primary channel freq */
+			if (prP2pConnReqInfo->u4CenterFreq1 > prP2pConnReqInfo->u2PriChnlFreq)
+				eSCO = CHNL_EXT_SCA;
+			else
+				eSCO = CHNL_EXT_SCB;
+		} else if (cnmGetBssMaxBw(prAdapter, prBssInfo->ucBssIndex) > MAX_BW_40MHZ) {
+			/* P: PriChnlFreq, A:CHNL_EXT_SCA, B: CHNL_EXT_SCB, -:BW SPAN 5M */
+			/* --|----|--CenterFreq1--|----|-- */
+			/* --|----|--CenterFreq1--B----P-- */
+			/* --|----|--CenterFreq1--P----A-- */
+			i4DeltaBw =  prP2pConnReqInfo->u2PriChnlFreq - prP2pConnReqInfo->u4CenterFreq1;
+			u4AndOneSCO = CHNL_EXT_SCB;
+			eSCO = CHNL_EXT_SCA;
+			if (i4DeltaBw < 0) {
+				/* --|----|--CenterFreq1--|----|-- */
+				/* --P----A--CenterFreq1--|----|-- */
+				/* --B----P--CenterFreq1--|----|-- */
+				u4AndOneSCO = CHNL_EXT_SCA;
+				eSCO = CHNL_EXT_SCB;
+				i4DeltaBw = -i4DeltaBw;
+			}
+			i4DeltaBw = i4DeltaBw - (CHANNEL_SPAN_20 >> 1);
+			if ((i4DeltaBw/CHANNEL_SPAN_20) & 1)
+				eSCO = u4AndOneSCO;
+		}
+	} else {
+		/* In this case, the first BSS's SCO is 40MHz and known, so AP can
+		 * apply 40MHz bandwidth, but the first BSS's SCO may be changed
+		 * later if its Beacon lost timeout occurs
+		 */
+		if (!(cnmPreferredChannel(prAdapter, &eBand, &ucChannel, &eSCO) &&
+		    eSCO != CHNL_EXT_SCN && ucChannel == prBssInfo->ucPrimaryChannel &&
+		    eBand == prBssInfo->eBand))
+			eSCO = rlmDecideScoForAP(prAdapter, prBssInfo);
+	}
+	return eSCO;
+}
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief: Get AP channel number of Channel Center Frequency Segment 0 from cfg80211 or wifi.cfg
+*
+* \param[in] prAdapter  Pointer of ADAPTER_T, prBssInfo Pointer of BSS_INFO_T,
+*
+* \return UINT_8 AP channel number of Channel Center Frequency Segment 0
+*/
+/*----------------------------------------------------------------------------*/
+UINT_8 rlmGetVhtS1ForAP(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo)
+{
+	UINT_32 ucFreq1Channel;
+	UINT_8 ucPrimaryChannel = prBssInfo->ucPrimaryChannel;
+	P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) NULL;
+	P_P2P_CONNECTION_REQ_INFO_T prP2pConnReqInfo = (P_P2P_CONNECTION_REQ_INFO_T) NULL;
+
+	prP2pRoleFsmInfo = p2pFuncGetRoleByBssIdx(prAdapter, prBssInfo->ucBssIndex);
+
+	if (prBssInfo->ucVhtChannelWidth == VHT_OP_CHANNEL_WIDTH_20_40)
+		return 0;
+
+	if (!prAdapter->rWifiVar.ucApChnlDefFromCfg && prP2pRoleFsmInfo) {
+		prP2pConnReqInfo = &(prP2pRoleFsmInfo->rConnReqInfo);
+		ucFreq1Channel = nicFreq2ChannelNum(prP2pConnReqInfo->u4CenterFreq1 * 1000);
+	} else
+		ucFreq1Channel = nicGetVhtS1(ucPrimaryChannel, prBssInfo->ucVhtChannelWidth);
+
+	return ucFreq1Channel;
+}
+
diff --git a/mgmt/p2p_role_state.c b/mgmt/p2p_role_state.c
index a2ca649..cde96ed 100644
--- a/mgmt/p2p_role_state.c
+++ b/mgmt/p2p_role_state.c
@@ -355,9 +355,6 @@
 					    IN P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo,
 					    OUT P_P2P_CHNL_REQ_INFO_T prChnlReqInfo)
 {
-	ENUM_BAND_T eBand;
-	UINT_8 ucChannel;
-	ENUM_CHNL_EXT_T eSCO;
 	ENUM_BAND_T eBandBackup;
 	UINT_8 ucChannelBackup;
 	ENUM_CHNL_EXT_T eSCOBackup;
@@ -382,12 +379,7 @@
 		prBssInfo->ucPrimaryChannel = prConnReqInfo->rChannelInfo.ucChannelNum;
 		prBssInfo->eBand = prConnReqInfo->rChannelInfo.eBand;
 
-		if (cnmPreferredChannel(prAdapter, &eBand, &ucChannel, &eSCO) &&
-		    eSCO != CHNL_EXT_SCN && ucChannel == prBssInfo->ucPrimaryChannel && eBand == prBssInfo->eBand) {
-			prBssInfo->eBssSCO = eSCO;
-		} else {
-			prBssInfo->eBssSCO = rlmDecideScoForAP(prAdapter, prBssInfo);
-		}
+		prBssInfo->eBssSCO = rlmGetScoForAP(prAdapter, prBssInfo);
 
 		ASSERT_BREAK((prAdapter != NULL) && (prConnReqInfo != NULL) && (prChnlReqInfo != NULL));
 		prChnlReqInfo->u8Cookie = 0;
@@ -399,14 +391,20 @@
 
 
 		/*rlmBssInitForAP would decide the real AP bandwidth*/
-		if (prBssInfo->eBand == BAND_5G)
-			prChnlReqInfo->eChannelWidth = CW_80MHZ;
-		else
-			prChnlReqInfo->eChannelWidth = CW_20_40MHZ;
-
-		prChnlReqInfo->ucCenterFreqS1 =
-			nicGetVhtS1(prBssInfo->ucPrimaryChannel, prChnlReqInfo->eChannelWidth);
-		prChnlReqInfo->ucCenterFreqS2 = 0;
+		prBssInfo->ucVhtChannelWidth =
+			cnmGetBssMaxBwToChnlBW(prAdapter, prBssInfo->ucBssIndex);
+		prChnlReqInfo->eChannelWidth = prBssInfo->ucVhtChannelWidth;
+		if (prChnlReqInfo->eChannelWidth == VHT_OP_CHANNEL_WIDTH_80P80) {
+			/* TODO: BW80+80 support */
+			DBGLOG(RLM, WARN, "BW80+80 not support. Fallback  to VHT_OP_CHANNEL_WIDTH_20_40\n");
+			prChnlReqInfo->eChannelWidth = VHT_OP_CHANNEL_WIDTH_20_40;
+			prChnlReqInfo->ucCenterFreqS1 = 0;
+			prChnlReqInfo->ucCenterFreqS2 = 0;
+		} else {
+			prChnlReqInfo->ucCenterFreqS1 =
+			rlmGetVhtS1ForAP(prAdapter, prBssInfo);
+			prChnlReqInfo->ucCenterFreqS2 = 0;
+		}
 
 		/* If the S1 is invalid, force to change bandwidth */
 		if ((prBssInfo->eBand == BAND_5G) &&
@@ -447,12 +445,7 @@
 		prBssInfo->ucPrimaryChannel = prConnReqInfo->rChannelInfo.ucChannelNum;
 		prBssInfo->eBand = prConnReqInfo->rChannelInfo.eBand;
 
-		if (cnmPreferredChannel(prAdapter, &eBand, &ucChannel, &eSCO) &&
-			eSCO != CHNL_EXT_SCN && ucChannel == prBssInfo->ucPrimaryChannel && eBand == prBssInfo->eBand) {
-			prBssInfo->eBssSCO = eSCO;
-		} else {
-			prBssInfo->eBssSCO = rlmDecideScoForAP(prAdapter, prBssInfo);
-		}
+		prBssInfo->eBssSCO = rlmGetScoForAP(prAdapter, prBssInfo);
 
 		prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, prBssInfo->u4PrivateData);
 
@@ -465,11 +458,21 @@
 				prAdapter->prGlueInfo->prP2PInfo[prP2pRoleFsmInfo->ucRoleIndex]->cac_time_ms;
 		prChnlReqInfo->eChnlReqType = CH_REQ_TYPE_DFS_CAC;
 
-		prChnlReqInfo->eChannelWidth = rChannelWidth;
+		prBssInfo->ucVhtChannelWidth =
+			cnmGetBssMaxBwToChnlBW(prAdapter, prBssInfo->ucBssIndex);
+		prChnlReqInfo->eChannelWidth = prBssInfo->ucVhtChannelWidth;
 
-		prChnlReqInfo->ucCenterFreqS1 =
-			nicGetVhtS1(prBssInfo->ucPrimaryChannel, prChnlReqInfo->eChannelWidth);
-		prChnlReqInfo->ucCenterFreqS2 = 0;
+		if (prChnlReqInfo->eChannelWidth == VHT_OP_CHANNEL_WIDTH_80P80) {
+			/* TODO: BW80+80 support */
+			DBGLOG(RLM, WARN, "BW80+80 not support. Fallback  to VHT_OP_CHANNEL_WIDTH_20_40\n");
+			prChnlReqInfo->eChannelWidth = VHT_OP_CHANNEL_WIDTH_20_40;
+			prChnlReqInfo->ucCenterFreqS1 = 0;
+			prChnlReqInfo->ucCenterFreqS2 = 0;
+		} else {
+			prChnlReqInfo->ucCenterFreqS1 =
+				rlmGetVhtS1ForAP(prAdapter, prBssInfo);
+			prChnlReqInfo->ucCenterFreqS2 = 0;
+		}
 
 		DBGLOG(P2P, TRACE, "p2pRoleStatePrepare_To_REQING_CHANNEL_STATE\n");
 
diff --git a/os/linux/gl_p2p_cfg80211.c b/os/linux/gl_p2p_cfg80211.c
index 63ef6fb..d783a11 100644
--- a/os/linux/gl_p2p_cfg80211.c
+++ b/os/linux/gl_p2p_cfg80211.c
@@ -119,16 +119,111 @@
 ********************************************************************************
 */
 
-BOOLEAN
-mtk_p2p_cfg80211func_channel_format_switch(IN struct ieee80211_channel *channel,
-					   IN enum nl80211_channel_type channel_type,
-					   IN P_RF_CHANNEL_INFO_T prRfChnlInfo, IN P_ENUM_CHNL_EXT_T prChnlSco);
-
 /*******************************************************************************
 *                              F U N C T I O N S
 ********************************************************************************
 */
 
+BOOLEAN
+mtk_p2p_cfg80211func_channel_sco_switch(IN enum nl80211_channel_type channel_type,
+					   IN P_ENUM_CHNL_EXT_T prChnlSco)
+{
+	BOOLEAN fgIsValid = FALSE;
+
+	do {
+		if (prChnlSco) {
+
+			switch (channel_type) {
+			case NL80211_CHAN_NO_HT:
+				*prChnlSco = CHNL_EXT_SCN;
+				break;
+			case NL80211_CHAN_HT20:
+				*prChnlSco = CHNL_EXT_SCN;
+				break;
+			case NL80211_CHAN_HT40MINUS:
+				*prChnlSco = CHNL_EXT_SCA;
+				break;
+			case NL80211_CHAN_HT40PLUS:
+				*prChnlSco = CHNL_EXT_SCB;
+				break;
+			default:
+				ASSERT(FALSE);
+				*prChnlSco = CHNL_EXT_SCN;
+				break;
+			}
+		}
+
+		fgIsValid = TRUE;
+	} while (FALSE);
+
+	return fgIsValid;
+}
+
+BOOLEAN
+mtk_p2p_cfg80211func_channel_format_switch(IN struct cfg80211_chan_def *channel_def,
+					   IN struct ieee80211_channel *channel,
+					   IN P_RF_CHANNEL_INFO_T prRfChnlInfo)
+{
+	BOOLEAN fgIsValid = FALSE;
+
+	do {
+		if (channel == NULL)
+			break;
+
+		if (prRfChnlInfo) {
+			prRfChnlInfo->ucChannelNum = nicFreq2ChannelNum(channel->center_freq * 1000);
+
+			switch (channel->band) {
+			case IEEE80211_BAND_2GHZ:
+				prRfChnlInfo->eBand = BAND_2G4;
+				break;
+			case IEEE80211_BAND_5GHZ:
+				prRfChnlInfo->eBand = BAND_5G;
+				break;
+			default:
+				prRfChnlInfo->eBand = BAND_2G4;
+				break;
+			}
+
+		}
+
+		if (channel_def && prRfChnlInfo) {
+
+			switch (channel_def->width) {
+			case NL80211_CHAN_WIDTH_20_NOHT:
+			case NL80211_CHAN_WIDTH_20:
+				prRfChnlInfo->ucChnlBw = MAX_BW_20MHZ;
+				break;
+			case NL80211_CHAN_WIDTH_40:
+				prRfChnlInfo->ucChnlBw = MAX_BW_40MHZ;
+				break;
+			case NL80211_CHAN_WIDTH_80:
+				prRfChnlInfo->ucChnlBw = MAX_BW_80MHZ;
+				break;
+			case NL80211_CHAN_WIDTH_80P80:
+				prRfChnlInfo->ucChnlBw = MAX_BW_80_80_MHZ;
+				break;
+			case NL80211_CHAN_WIDTH_160:
+				prRfChnlInfo->ucChnlBw = MAX_BW_160MHZ;
+				break;
+			default:
+				prRfChnlInfo->ucChnlBw = MAX_BW_20MHZ;
+				break;
+			}
+			prRfChnlInfo->u2PriChnlFreq = channel->center_freq;
+			prRfChnlInfo->u4CenterFreq1 = channel_def->center_freq1;
+			prRfChnlInfo->u4CenterFreq2 = channel_def->center_freq2;
+		}
+
+		fgIsValid = TRUE;
+
+	} while (FALSE);
+
+	return fgIsValid;
+}
+
+/* mtk_p2p_cfg80211func_channel_format_switch */
+
 INT_32 mtk_Netdev_To_RoleIdx(P_GLUE_INFO_T prGlueInfo, struct net_device *ndev, PUINT_8 pucRoleIdx)
 {
 	INT_32 i4Ret = -1;
@@ -1102,7 +1197,7 @@
 			break;
 
 		if (chandef) {
-			mtk_p2p_cfg80211func_channel_format_switch(chandef->chan, chandef->width, &rRfChnlInfo, NULL);
+			mtk_p2p_cfg80211func_channel_format_switch(chandef, chandef->chan, &rRfChnlInfo);
 
 			/* Follow the channel info from wifi.cfg prior to hostapd.conf */
 			{
@@ -1284,7 +1379,7 @@
 
 
 		if (chandef) {
-			mtk_p2p_cfg80211func_channel_format_switch(chandef->chan, chandef->width, &rRfChnlInfo, NULL);
+			mtk_p2p_cfg80211func_channel_format_switch(chandef, chandef->chan, &rRfChnlInfo);
 
 			p2pFuncSetChannel(prGlueInfo->prAdapter, ucRoleIdx, &rRfChnlInfo);
 		} else
@@ -1396,8 +1491,8 @@
 			break;
 
 		if (params) {
-			mtk_p2p_cfg80211func_channel_format_switch(params->chandef.chan,
-								params->chandef.width, &rRfChnlInfo, NULL);
+			mtk_p2p_cfg80211func_channel_format_switch(&params->chandef,
+								params->chandef.chan, &rRfChnlInfo);
 
 			p2pFuncSetChannel(prGlueInfo->prAdapter, ucRoleIdx, &rRfChnlInfo);
 		} else
@@ -1747,9 +1842,9 @@
 		prMsgChnlReq->u4Duration = duration;
 		prMsgChnlReq->eChnlReqType = CH_REQ_TYPE_P2P_LISTEN;
 
-		mtk_p2p_cfg80211func_channel_format_switch(chan,
-							   NL80211_CHAN_NO_HT,
-							   &prMsgChnlReq->rChannelInfo, &prMsgChnlReq->eChnlSco);
+		mtk_p2p_cfg80211func_channel_format_switch(NULL, chan,
+							   &prMsgChnlReq->rChannelInfo);
+		mtk_p2p_cfg80211func_channel_sco_switch(NL80211_CHAN_NO_HT, &prMsgChnlReq->eChnlSco);
 
 		mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChnlReq, MSG_SEND_METHOD_BUF);
 
@@ -1849,9 +1944,9 @@
 			DBGLOG(P2P, TRACE, "   Off channel TRUE\n");
 			prMsgTxReq->fgIsOffChannel = TRUE;
 
-			mtk_p2p_cfg80211func_channel_format_switch(params->chan,
-								   NL80211_CHAN_NO_HT,
-								   &prMsgTxReq->rChannelInfo, &prMsgTxReq->eChnlExt);
+			mtk_p2p_cfg80211func_channel_format_switch(NULL, params->chan,
+								   &prMsgTxReq->rChannelInfo);
+			mtk_p2p_cfg80211func_channel_sco_switch(NL80211_CHAN_NO_HT, &prMsgTxReq->eChnlExt);
 		} else {
 			prMsgTxReq->fgIsOffChannel = FALSE;
 		}
@@ -1958,9 +2053,9 @@
 			DBGLOG(P2P, TRACE, "   Off channel TRUE\n");
 			prMsgTxReq->fgIsOffChannel = TRUE;
 
-			mtk_p2p_cfg80211func_channel_format_switch(chan,
-								   NL80211_CHAN_NO_HT,
-								   &prMsgTxReq->rChannelInfo, &prMsgTxReq->eChnlExt);
+			mtk_p2p_cfg80211func_channel_format_switch(NULL, chan,
+								   &prMsgTxReq->rChannelInfo);
+			mtk_p2p_cfg80211func_channel_sco_switch(NL80211_CHAN_NO_HT, &prMsgTxReq->eChnlExt);
 		} else {
 			prMsgTxReq->fgIsOffChannel = FALSE;
 		}
@@ -2300,9 +2395,9 @@
 			}
 		}
 
-		mtk_p2p_cfg80211func_channel_format_switch(sme->channel,
-							   NL80211_CHAN_NO_HT,
-							   &prConnReqMsg->rChannelInfo, &prConnReqMsg->eChnlSco);
+		mtk_p2p_cfg80211func_channel_format_switch(NULL, sme->channel,
+							   &prConnReqMsg->rChannelInfo);
+		mtk_p2p_cfg80211func_channel_sco_switch(NL80211_CHAN_NO_HT, &prConnReqMsg->eChnlSco);
 
 		mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prConnReqMsg, MSG_SEND_METHOD_BUF);
 
@@ -2444,7 +2539,7 @@
 
 		prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy));
 
-		mtk_p2p_cfg80211func_channel_format_switch(chandef->chan, chandef->width, &rRfChnlInfo, NULL);
+		mtk_p2p_cfg80211func_channel_format_switch(chandef, chandef->chan, &rRfChnlInfo);
 
 		if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0)
 			break;
@@ -2575,65 +2670,6 @@
 
 }				/* mtk_p2p_cfg80211_mgmt_frame_register */
 
-BOOLEAN
-mtk_p2p_cfg80211func_channel_format_switch(IN struct ieee80211_channel *channel,
-					   IN enum nl80211_channel_type channel_type,
-					   IN P_RF_CHANNEL_INFO_T prRfChnlInfo, IN P_ENUM_CHNL_EXT_T prChnlSco)
-{
-	BOOLEAN fgIsValid = FALSE;
-
-	do {
-		if (channel == NULL)
-			break;
-
-		if (prRfChnlInfo) {
-			prRfChnlInfo->ucChannelNum = nicFreq2ChannelNum(channel->center_freq * 1000);
-
-			switch (channel->band) {
-			case IEEE80211_BAND_2GHZ:
-				prRfChnlInfo->eBand = BAND_2G4;
-				break;
-			case IEEE80211_BAND_5GHZ:
-				prRfChnlInfo->eBand = BAND_5G;
-				break;
-			default:
-				prRfChnlInfo->eBand = BAND_2G4;
-				break;
-			}
-
-		}
-
-		if (prChnlSco) {
-
-			switch (channel_type) {
-			case NL80211_CHAN_NO_HT:
-				*prChnlSco = CHNL_EXT_SCN;
-				break;
-			case NL80211_CHAN_HT20:
-				*prChnlSco = CHNL_EXT_SCN;
-				break;
-			case NL80211_CHAN_HT40MINUS:
-				*prChnlSco = CHNL_EXT_SCA;
-				break;
-			case NL80211_CHAN_HT40PLUS:
-				*prChnlSco = CHNL_EXT_SCB;
-				break;
-			default:
-				ASSERT(FALSE);
-				*prChnlSco = CHNL_EXT_SCN;
-				break;
-			}
-		}
-
-		fgIsValid = TRUE;
-
-	} while (FALSE);
-
-	return fgIsValid;
-}
-
-/* mtk_p2p_cfg80211func_channel_format_switch */
-
 #ifdef CONFIG_NL80211_TESTMODE
 
 #if KERNEL_VERSION(3, 12, 0) <= LINUX_VERSION_CODE