Przeglądaj źródła

qcacld-3.0: Add new params in ACS calc process

qcacld-2.0 to qcacld-3.0 propagation

Before this change the ACS calc process only consider the
channel's rssi and bss count in this channel, in this change
add noise floor, channel free statistics and tx power in the
ACS calc process.

Change-Id: I654e53fa2441e03723f150d973c124985c67f2b4
CRs-fixed: 1050316
gaolez 8 lat temu
rodzic
commit
e510894670

+ 54 - 0
core/hdd/inc/wlan_hdd_cfg.h

@@ -10611,6 +10611,58 @@ enum hdd_wext_control {
 #define CFG_ACTIVE_MC_BC_BPF_MODE_MAX     (ACTIVE_BPF_ENABLED)
 #define CFG_ACTIVE_MC_BC_BPF_MODE_DEFAULT (ACTIVE_BPF_DISABLED)
 
+/*
+ * <ini>
+ * acs_with_more_param- Enable acs calculation with more param.
+ * @Min: 0
+ * @Max: 1
+ * @Default: 0
+ *
+ * This ini is used to enable acs calculation with more param.
+ *
+ * Related: NA
+ *
+ * Supported Feature: ACS
+ *
+ * Usage: Internal/External
+ *
+ * </ini>
+ */
+
+#define CFG_ACS_WITH_MORE_PARAM_NAME    "acs_with_more_param"
+#define CFG_ACS_WITH_MORE_PARAM_MIN     (0)
+#define CFG_ACS_WITH_MORE_PARAM_MAX     (1)
+#define CFG_ACS_WITH_MORE_PARAM_DEFAULT (0)
+
+/*
+ * <ini>
+ * AutoChannelSelectWeight - ACS channel weight
+ * @Min: 0x1
+ * @Max: 0xFFFFFFFF
+ * @Default: 0x000000FF
+ *
+ * This ini is used to adjust weight of factors in
+ * acs algorithm.
+ *
+ * Supported Feature: ACS
+ *
+ * Usage: Internal/External
+ *
+ * bits 0-3:   rssi weight
+ * bits 4-7:   bss count weight
+ * bits 8-11:  noise floor weight
+ * bits 12-15: channel free weight
+ * bits 16-19: tx power range weight
+ * bits 20-23: tx power throughput weight
+ * bits 24-31: reserved
+ *
+ * </ini>
+ */
+#define CFG_AUTO_CHANNEL_SELECT_WEIGHT            "AutoChannelSelectWeight"
+#define CFG_AUTO_CHANNEL_SELECT_WEIGHT_MIN        (0x1)
+#define CFG_AUTO_CHANNEL_SELECT_WEIGHT_MAX        (0xFFFFFFFF)
+#define CFG_AUTO_CHANNEL_SELECT_WEIGHT_DEFAULT    (0x000000FF)
+
 #ifdef WLAN_FEATURE_11AX
 /* 11AX related INI configuration */
 /*
@@ -12021,6 +12073,8 @@ struct hdd_config {
 	uint8_t gDisableDfsJapanW53;
 	bool gEnableOverLapCh;
 	bool fRegChangeDefCountry;
+	bool acs_with_more_param;
+	uint32_t auto_channel_select_weight;
 	uint16_t max_ht_mcs_txdata;
 	bool sap_get_peer_info;
 	bool disable_abg_rate_txdata;

+ 19 - 0
core/hdd/src/wlan_hdd_cfg.c

@@ -2918,6 +2918,20 @@ struct reg_table_entry g_registry_table[] = {
 		     CFG_REG_CHANGE_DEF_COUNTRY_MIN,
 		     CFG_REG_CHANGE_DEF_COUNTRY_MAX),
 
+	REG_VARIABLE(CFG_ACS_WITH_MORE_PARAM_NAME, WLAN_PARAM_Integer,
+		     struct hdd_config, acs_with_more_param,
+		     VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+		     CFG_ACS_WITH_MORE_PARAM_DEFAULT,
+		     CFG_ACS_WITH_MORE_PARAM_MIN,
+		     CFG_ACS_WITH_MORE_PARAM_MAX),
+
+	REG_VARIABLE(CFG_AUTO_CHANNEL_SELECT_WEIGHT, WLAN_PARAM_HexInteger,
+		     struct hdd_config, auto_channel_select_weight,
+		     VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+		     CFG_AUTO_CHANNEL_SELECT_WEIGHT_DEFAULT,
+		     CFG_AUTO_CHANNEL_SELECT_WEIGHT_MIN,
+		     CFG_AUTO_CHANNEL_SELECT_WEIGHT_MAX),
+
 #ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL
 	REG_VARIABLE(CFG_LL_TX_FLOW_LWM, WLAN_PARAM_Integer,
 		     struct hdd_config, TxFlowLowWaterMark,
@@ -6286,6 +6300,9 @@ void hdd_cfg_print(struct hdd_context *pHddCtx)
 	hdd_debug("Name = [%s] Value = [%d]",
 		CFG_SAP_INTERNAL_RESTART_NAME,
 		pHddCtx->config->sap_internal_restart);
+	hdd_debug("Name = [%s] Value = [%d]",
+		  CFG_ACS_WITH_MORE_PARAM_NAME,
+		  pHddCtx->config->acs_with_more_param);
 	hdd_debug("Name = [%s] Value = [%u]",
 		CFG_AUTO_DETECT_POWER_FAIL_MODE_NAME,
 		pHddCtx->config->auto_pwr_save_fail_mode);
@@ -7897,6 +7914,8 @@ QDF_STATUS hdd_set_sme_config(struct hdd_context *pHddCtx)
 	smeConfig->csrConfig.sap_channel_avoidance =
 		pHddCtx->config->sap_channel_avoidance;
 #endif /* FEATURE_AP_MCC_CH_AVOIDANCE */
+	smeConfig->csrConfig.acs_with_more_param =
+		pHddCtx->config->acs_with_more_param;
 
 	smeConfig->csrConfig.f_prefer_non_dfs_on_radar =
 		pHddCtx->config->prefer_non_dfs_on_radar;

+ 4 - 0
core/hdd/src/wlan_hdd_cfg80211.c

@@ -2399,6 +2399,10 @@ static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
 		sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch,
 		sap_config->acs_cfg.band);
 
+	if (hdd_ctx->config->auto_channel_select_weight)
+		sap_config->auto_channel_select_weight =
+		    hdd_ctx->config->auto_channel_select_weight;
+
 	sap_config->acs_cfg.is_ht_enabled = ht_enabled;
 	sap_config->acs_cfg.is_vht_enabled = vht_enabled;
 

+ 2 - 0
core/mac/inc/ani_global.h

@@ -401,6 +401,8 @@ typedef struct sAniSirLim {
 	uint8_t abortScan;
 	tLimScanChnInfo scanChnInfo;
 
+	struct lim_scan_channel_status scan_channel_status;
+
 	/* ////////////////////////////////////     SCAN/LEARN RELATED START /////////////////////////////////////////// */
 	tSirMacAddr gSelfMacAddr;       /* added for BT-AMP Support */
 

+ 43 - 0
core/mac/inc/sir_api.h

@@ -2293,6 +2293,49 @@ typedef struct sLimScanChn {
 	uint8_t channelId;
 } tLimScanChn;
 
+/**
+ * struct lim_channel_status
+ * @channelfreq: Channel freq
+ * @noise_floor: Noise Floor value
+ * @rx_clear_count: rx clear count
+ * @cycle_count: cycle count
+ * @chan_tx_pwr_range: channel tx power per range in 0.5dBm steps
+ * @chan_tx_pwr_throughput: channel tx power per throughput
+ * @rx_frame_count: rx frame count (cumulative)
+ * @bss_rx_cycle_count: BSS rx cycle count
+ * @rx_11b_mode_data_duration: b-mode data rx time (units are microseconds)
+ * @tx_frame_count: BSS tx cycle count
+ * @mac_clk_mhz: sample frequency
+ * @channel_id: channel index
+ * @cmd_flags: indicate which stat event is this status coming from
+ */
+struct lim_channel_status {
+	uint32_t    channelfreq;
+	uint32_t    noise_floor;
+	uint32_t    rx_clear_count;
+	uint32_t    cycle_count;
+	uint32_t    chan_tx_pwr_range;
+	uint32_t    chan_tx_pwr_throughput;
+	uint32_t    rx_frame_count;
+	uint32_t    bss_rx_cycle_count;
+	uint32_t    rx_11b_mode_data_duration;
+	uint32_t    tx_frame_count;
+	uint32_t    mac_clk_mhz;
+	uint32_t    channel_id;
+	uint32_t    cmd_flags;
+};
+
+/**
+ * struct lim_scan_channel_status
+ * @total_channel: total number of be scanned channel
+ * @channel_status_list: channel status info store in this array
+ */
+struct lim_scan_channel_status {
+	uint8_t total_channel;
+	struct lim_channel_status
+		 channel_status_list[SIR_MAX_SUPPORTED_CHANNEL_LIST];
+};
+
 typedef struct sSmeGetScanChnRsp {
 	/* Message Type */
 	uint16_t mesgType;

+ 1 - 0
core/mac/src/include/sir_params.h

@@ -638,6 +638,7 @@ typedef struct sSirMbMsgP2p {
 #define SIR_HAL_SET_UDP_RESP_OFFLOAD        (SIR_HAL_ITC_MSG_TYPES_BEGIN + 370)
 
 #define SIR_HAL_SET_PER_ROAM_CONFIG_CMD     (SIR_HAL_ITC_MSG_TYPES_BEGIN + 371)
+#define SIR_HAL_RX_CHN_STATUS_EVENT         (SIR_HAL_ITC_MSG_TYPES_BEGIN + 372)
 
 #ifdef WLAN_FEATURE_LINK_LAYER_STATS
 #define SIR_HAL_LL_STATS_EXT_SET_THRESHOLD  (SIR_HAL_ITC_MSG_TYPES_BEGIN + 378)

+ 3 - 0
core/mac/src/pe/lim/lim_process_message_queue.c

@@ -1790,6 +1790,9 @@ static void lim_process_messages(tpAniSirGlobal mac_ctx,
 	case WMA_RX_SCAN_EVENT:
 		lim_process_rx_scan_event(mac_ctx, msg->bodyptr);
 		break;
+	case WMA_RX_CHN_STATUS_EVENT:
+		lim_process_rx_channel_status_event(mac_ctx, msg->bodyptr);
+		break;
 	case WMA_IBSS_PEER_INACTIVITY_IND:
 		lim_process_ibss_peer_inactivity(mac_ctx, msg->bodyptr);
 		qdf_mem_free((void *)(msg->bodyptr));

+ 23 - 0
core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c

@@ -3275,3 +3275,26 @@ void lim_process_rx_scan_event(tpAniSirGlobal pMac, void *buf)
 	}
 	qdf_mem_free(buf);
 }
+
+void lim_process_rx_channel_status_event(tpAniSirGlobal mac_ctx, void *buf)
+{
+	struct lim_channel_status *chan_status = buf;
+
+	if (NULL == chan_status) {
+		QDF_TRACE(QDF_MODULE_ID_PE,
+			  QDF_TRACE_LEVEL_ERROR,
+			  "%s: ACS evt report buf NULL", __func__);
+		return;
+	}
+
+	if (mac_ctx->sap.acs_with_more_param)
+		lim_add_channel_status_info(mac_ctx, chan_status,
+					    chan_status->channel_id);
+	else
+		QDF_TRACE(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_WARN,
+			  "%s: Error evt report", __func__);
+
+	qdf_mem_free(buf);
+
+	return;
+}

+ 10 - 0
core/mac/src/pe/lim/lim_types.h

@@ -940,6 +940,16 @@ tSirRetStatus lim_process_sme_del_all_tdls_peers(tpAniSirGlobal p_mac,
 }
 #endif
 
+/**
+ * lim_process_rx_channel_status_event() - processes
+ * event WDA_RX_CHN_STATUS_EVENT
+ * @mac_ctx Pointer to Global MAC structure
+ * @buf: Received message info
+ *
+ * Return: None
+ */
+void lim_process_rx_channel_status_event(tpAniSirGlobal mac_ctx, void *buf);
+
 /* / Bit value data structure */
 typedef enum sHalBitVal         /* For Bit operations */
 {

+ 54 - 0
core/mac/src/pe/lim/lim_utils.c

@@ -4971,6 +4971,60 @@ void lim_resset_scan_channel_info(tpAniSirGlobal pMac)
 	qdf_mem_set(&pMac->lim.scanChnInfo, sizeof(tLimScanChnInfo), 0);
 }
 
+void lim_add_channel_status_info(tpAniSirGlobal p_mac,
+				 struct lim_channel_status *channel_stat,
+				 uint8_t channel_id)
+{
+	uint8_t i;
+	bool found = false;
+	struct lim_scan_channel_status *channel_info =
+		&p_mac->lim.scan_channel_status;
+	struct lim_channel_status *channel_status_list =
+		channel_info->channel_status_list;
+	uint8_t total_channel = channel_info->total_channel;
+
+	if (!p_mac->sap.acs_with_more_param)
+		return;
+
+	for (i = 0; i < total_channel; i++) {
+		if (channel_status_list[i].channel_id == channel_id) {
+			if (channel_stat->cmd_flags ==
+			    WMI_CHAN_InFO_END_RESP &&
+			    channel_status_list[i].cmd_flags ==
+			    WMI_CHAN_InFO_START_RESP) {
+				/* adjust to delta value for counts */
+				channel_stat->rx_clear_count -=
+				    channel_status_list[i].rx_clear_count;
+				channel_stat->cycle_count -=
+				    channel_status_list[i].cycle_count;
+				channel_stat->rx_frame_count -=
+				    channel_status_list[i].rx_frame_count;
+				channel_stat->tx_frame_count -=
+				    channel_status_list[i].tx_frame_count;
+				channel_stat->bss_rx_cycle_count -=
+				    channel_status_list[i].bss_rx_cycle_count;
+			}
+			qdf_mem_copy(&channel_status_list[i], channel_stat,
+				     sizeof(*channel_status_list));
+			found = true;
+			break;
+		}
+	}
+
+	if (!found) {
+		if (total_channel < SIR_MAX_SUPPORTED_CHANNEL_LIST) {
+			qdf_mem_copy(&channel_status_list[total_channel++],
+				     channel_stat,
+				     sizeof(*channel_status_list));
+			channel_info->total_channel = total_channel;
+		} else {
+			pe_warn("Chan cnt exceed, channel_id=%d", channel_id);
+		}
+	}
+
+	return;
+}
+
 /**
  * @function :  lim_is_channel_valid_for_channel_switch()
  *

+ 13 - 0
core/mac/src/pe/lim/lim_utils.h

@@ -437,6 +437,19 @@ tSirRetStatus lim_post_sm_state_update(tpAniSirGlobal pMac,
 void lim_delete_sta_context(tpAniSirGlobal pMac, struct scheduler_msg *limMsg);
 void lim_delete_dialogue_token_list(tpAniSirGlobal pMac);
 void lim_resset_scan_channel_info(tpAniSirGlobal pMac);
+
+/**
+ * lim_add_channel_status_info() - store
+ * chan status info into Global MAC structure
+ * @p_mac: Pointer to Global MAC structure
+ * @channel_stat: Pointer to chan status info reported by firmware
+ * @channel_id: current channel id
+ *
+ * Return: None
+ */
+void lim_add_channel_status_info(tpAniSirGlobal p_mac,
+				 struct lim_channel_status *channel_stat,
+				 uint8_t channel_id);
 uint8_t lim_get_channel_from_beacon(tpAniSirGlobal pMac,
 		tpSchBeaconStruct pBeacon);
 tSirNwType lim_get_nw_type(tpAniSirGlobal pMac, uint8_t channelNum,

+ 1 - 0
core/mac/src/sys/legacy/src/utils/src/mac_trace.c

@@ -649,6 +649,7 @@ uint8_t *mac_trace_get_wma_msg_string(uint16_t wma_msg)
 		CASE_RETURN_STRING(WMA_NAN_REQUEST);
 #endif
 		CASE_RETURN_STRING(WMA_RX_SCAN_EVENT);
+		CASE_RETURN_STRING(WMA_RX_CHN_STATUS_EVENT);
 		CASE_RETURN_STRING(WMA_IBSS_PEER_INACTIVITY_IND);
 		CASE_RETURN_STRING(WMA_DEL_PERIODIC_TX_PTRN_IND);
 #ifdef FEATURE_WLAN_TDLS

+ 3 - 1
core/sap/inc/sap_api.h

@@ -72,7 +72,7 @@ extern "C" {
 #define       QDF_MAX_NO_OF_SAP_MODE       2    /* max # of SAP */
 #define       SAP_MAX_NUM_SESSION          5
 #define       SAP_MAX_OBSS_STA_CNT         1    /* max # of OBSS STA */
-#define       SAP_ACS_WEIGHT_MAX           (4444)
+#define       SAP_ACS_WEIGHT_MAX           (26664)
 
 /*--------------------------------------------------------------------------
  * reasonCode taken from 802.11 standard.
@@ -603,6 +603,7 @@ typedef struct sap_Config {
 #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
 	uint8_t cc_switch_mode;
 #endif
+	uint32_t auto_channel_select_weight;
 	struct sap_acs_cfg acs_cfg;
 	uint16_t probeRespIEsBufferLen;
 	/* buffer for addn ies comes from hostapd */
@@ -755,6 +756,7 @@ typedef struct tagSapStruct {
 #ifdef FEATURE_AP_MCC_CH_AVOIDANCE
 	bool sap_channel_avoidance;
 #endif /* FEATURE_AP_MCC_CH_AVOIDANCE */
+	bool acs_with_more_param;
 	bool enable_dfs_phy_error_logs;
 } tSapStruct, *tpSapStruct;
 

+ 390 - 34
core/sap/src/sap_ch_select.c

@@ -85,6 +85,49 @@
 #define GET_IE_LEN_IN_BSS_DESC(lenInBss) (lenInBss + sizeof(lenInBss) - \
 			((uintptr_t)OFFSET_OF(tSirBssDescription, ieFields)))
 
+#define ACS_WEIGHT_AMOUNT_LOCAL    240
+
+#define ACS_WEIGHT_AMOUNT_CONFIG(weights) \
+	(((weights) & 0xf) + \
+	(((weights) & 0xf0) >> 4) + \
+	(((weights) & 0xf00) >> 8) + \
+	(((weights) & 0xf000) >> 12) + \
+	(((weights) & 0xf0000) >> 16) + \
+	(((weights) & 0xf00000) >> 20))
+
+/*
+ * LSH/RSH 4 to enhance the accurate since
+ * need to do modulation to ACS_WEIGHT_AMOUNT_LOCAL.
+ */
+#define ACS_WEIGHT_COMPUTE(weights, weight, factor, base) \
+	(((((((((weight) << 4) * ACS_WEIGHT_AMOUNT_LOCAL * (factor)) + \
+	(ACS_WEIGHT_AMOUNT_CONFIG((weights)) >> 1)) / \
+	ACS_WEIGHT_AMOUNT_CONFIG((weights))) + \
+	((base) >> 1)) / (base)) + 8) >> 4)
+
+#define ACS_WEIGHT_CFG_TO_LOCAL(weights, weight) \
+	(((((((weight) << 4) * ACS_WEIGHT_AMOUNT_LOCAL) + \
+	(ACS_WEIGHT_AMOUNT_CONFIG((weights)) >> 1)) / \
+	ACS_WEIGHT_AMOUNT_CONFIG((weights))) + 8) >> 4)
+
+#define ACS_WEIGHT_SOFTAP_RSSI_CFG(weights) \
+	((weights) & 0xf)
+
+#define ACS_WEIGHT_SOFTAP_COUNT_CFG(weights) \
+	(((weights) & 0xf0) >> 4)
+
+#define ACS_WEIGHT_SOFTAP_NOISE_FLOOR_CFG(weights) \
+	(((weights) & 0xf00) >> 8)
+
+#define ACS_WEIGHT_SOFTAP_CHANNEL_FREE_CFG(weights) \
+	(((weights) & 0xf000) >> 12)
+
+#define ACS_WEIGHT_SOFTAP_TX_POWER_RANGE_CFG(weights) \
+	(((weights) & 0xf0000) >> 16)
+
+#define ACS_WEIGHT_SOFTAP_TX_POWER_THROUGHPUT_CFG(weights) \
+	(((weights) & 0xf00000) >> 20)
+
 #ifdef FEATURE_WLAN_CH_AVOID
 sapSafeChannelType safe_channels[NUM_CHANNELS] = {
 	{1, true},
@@ -491,6 +534,39 @@ void sap_cleanup_channel_list(void *p_cds_gctx)
 	}
 }
 
+/**
+ * sap_channel_in_acs_channel_list() - check if channel in acs channel list
+ * @channel_num: channel to check
+ * @sap_ctx: struct ptSapContext
+ * @spect_info_params: strcut tSapChSelSpectInfo
+ *
+ * This function checks if specified channel is in the configured ACS channel
+ * list.
+ *
+ * Return: channel number if in acs channel list or SAP_CHANNEL_NOT_SELECTED
+ */
+static
+uint8_t sap_channel_in_acs_channel_list(uint8_t channel_num,
+					ptSapContext sap_ctx,
+					tSapChSelSpectInfo *spect_info_params)
+{
+	uint8_t i = 0;
+
+	if ((NULL == sap_ctx->acs_cfg->ch_list) ||
+	    (NULL == spect_info_params))
+		return channel_num;
+
+	if (channel_num > 0 && channel_num <= 252) {
+		for (i = 0; i < sap_ctx->acs_cfg->ch_list_count; i++) {
+			if ((sap_ctx->acs_cfg->ch_list[i]) == channel_num)
+				return channel_num;
+		}
+		return SAP_CHANNEL_NOT_SELECTED;
+	} else {
+		return SAP_CHANNEL_NOT_SELECTED;
+	}
+}
+
 /**
  * sap_select_preferred_channel_from_channel_list() - to calc best cahnnel
  * @best_chnl: best channel already calculated among all the chanels
@@ -675,48 +751,59 @@ static bool sap_chan_sel_init(tHalHandle halHandle,
 	return true;
 }
 
-/*==========================================================================
-   FUNCTION    sapweight_rssi_count
-
-   DESCRIPTION
-    Function weightRssiCount calculates the channel weight due to rssi
+/**
+ * sapweight_rssi_count() - calculates the channel weight due to rssi
     and data count(here number of BSS observed)
-
-   DEPENDENCIES
-    NA.
-
-   PARAMETERS
-
-    IN
-    rssi        : Max signal strength receieved from a BSS for the channel
-    count       : Number of BSS observed in the channel
-
-   RETURN VALUE
-    uint32_t     : Calculated channel weight based on above two
-
-   SIDE EFFECTS
-   ============================================================================*/
-static uint32_t sapweight_rssi_count(int8_t rssi, uint16_t count)
+ * @sap_ctx     : Softap context
+ * @rssi        : Max signal strength receieved from a BSS for the channel
+ * @count       : Number of BSS observed in the channel
+ *
+ * Return: uint32_t Calculated channel weight based on above two
+ */
+static
+uint32_t sapweight_rssi_count(ptSapContext sap_ctx, int8_t rssi,
+			      uint16_t count)
 {
 	int32_t rssiWeight = 0;
 	int32_t countWeight = 0;
 	uint32_t rssicountWeight = 0;
+	uint8_t softap_rssi_weight_cfg, softap_count_weight_cfg;
+	uint8_t softap_rssi_weight_local, softap_count_weight_local;
+
+	softap_rssi_weight_cfg =
+	    ACS_WEIGHT_SOFTAP_RSSI_CFG(sap_ctx->auto_channel_select_weight);
+
+	softap_count_weight_cfg =
+	    ACS_WEIGHT_SOFTAP_COUNT_CFG(sap_ctx->auto_channel_select_weight);
+
+	softap_rssi_weight_local =
+	    ACS_WEIGHT_CFG_TO_LOCAL(sap_ctx->auto_channel_select_weight,
+				    softap_rssi_weight_cfg);
+
+	softap_count_weight_local =
+	    ACS_WEIGHT_CFG_TO_LOCAL(sap_ctx->auto_channel_select_weight,
+				    softap_count_weight_cfg);
 
 	/* Weight from RSSI */
-	rssiWeight = SOFTAP_RSSI_WEIGHT * (rssi - SOFTAP_MIN_RSSI)
-		     / (SOFTAP_MAX_RSSI - SOFTAP_MIN_RSSI);
+	rssiWeight = ACS_WEIGHT_COMPUTE(sap_ctx->auto_channel_select_weight,
+					softap_rssi_weight_cfg,
+					rssi - SOFTAP_MIN_RSSI,
+					SOFTAP_MAX_RSSI - SOFTAP_MIN_RSSI);
+
+	if (rssiWeight > softap_rssi_weight_local)
+		rssiWeight = softap_rssi_weight_local;
 
-	if (rssiWeight > SOFTAP_RSSI_WEIGHT)
-		rssiWeight = SOFTAP_RSSI_WEIGHT;
 	else if (rssiWeight < 0)
 		rssiWeight = 0;
 
 	/* Weight from data count */
-	countWeight = SOFTAP_COUNT_WEIGHT * (count - SOFTAP_MIN_COUNT)
-		      / (SOFTAP_MAX_COUNT - SOFTAP_MIN_COUNT);
+	countWeight = ACS_WEIGHT_COMPUTE(sap_ctx->auto_channel_select_weight,
+					 softap_count_weight_cfg,
+					 count - SOFTAP_MIN_COUNT,
+					 SOFTAP_MAX_COUNT - SOFTAP_MIN_COUNT);
 
-	if (countWeight > SOFTAP_COUNT_WEIGHT)
-		countWeight = SOFTAP_COUNT_WEIGHT;
+	if (countWeight > softap_count_weight_local)
+		countWeight = softap_count_weight_local;
 
 	rssicountWeight = rssiWeight + countWeight;
 
@@ -727,6 +814,265 @@ static uint32_t sapweight_rssi_count(int8_t rssi, uint16_t count)
 	return rssicountWeight;
 }
 
+/**
+ * sap_get_channel_status() - get channel info via channel number
+ * @p_mac: Pointer to Global MAC structure
+ * @channel_id: channel id
+ *
+ * Return: chan status info
+ */
+static struct lim_channel_status *sap_get_channel_status
+	(tpAniSirGlobal p_mac, uint32_t channel_id)
+{
+	return csr_get_channel_status(p_mac, channel_id);
+}
+
+/**
+ * sap_clear_channel_status() - clear chan info
+ * @p_mac: Pointer to Global MAC structure
+ *
+ * Return: none
+ */
+static void sap_clear_channel_status(tpAniSirGlobal p_mac)
+{
+	csr_clear_channel_status(p_mac);
+}
+
+/**
+ * sap_weight_channel_noise_floor() - compute noise floor weight
+ * @sap_ctx:  sap context
+ * @chn_stat: Pointer to chan status info
+ *
+ * Return: channel noise floor weight
+ */
+static uint32_t sap_weight_channel_noise_floor(ptSapContext sap_ctx,
+					       struct lim_channel_status
+						*channel_stat)
+{
+	uint32_t    noise_floor_weight;
+	uint8_t     softap_nf_weight_cfg;
+	uint8_t     softap_nf_weight_local;
+
+	softap_nf_weight_cfg =
+	    ACS_WEIGHT_SOFTAP_NOISE_FLOOR_CFG
+	    (sap_ctx->auto_channel_select_weight);
+
+	softap_nf_weight_local =
+	    ACS_WEIGHT_CFG_TO_LOCAL(sap_ctx->auto_channel_select_weight,
+				    softap_nf_weight_cfg);
+
+	if (channel_stat == NULL || channel_stat->channelfreq == 0) {
+		QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO,
+			  "In %s, sanity check failed return max weight",
+			  __func__);
+		return softap_nf_weight_local;
+	}
+
+	noise_floor_weight = (channel_stat->noise_floor == 0) ? 0 :
+			    (ACS_WEIGHT_COMPUTE(
+			     sap_ctx->auto_channel_select_weight,
+			     softap_nf_weight_cfg,
+			     channel_stat->noise_floor -
+			     SOFTAP_MIN_NF,
+			     SOFTAP_MAX_NF - SOFTAP_MIN_NF));
+
+	if (noise_floor_weight > softap_nf_weight_local)
+		noise_floor_weight = softap_nf_weight_local;
+	else if (noise_floor_weight < 0)
+		noise_floor_weight = 0;
+
+	QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO_HIGH,
+		  "In %s, nf=%d, nfwc=%d, nfwl=%d, nfw=%d",
+		  __func__, channel_stat->noise_floor,
+		  softap_nf_weight_cfg, softap_nf_weight_local,
+		  noise_floor_weight);
+
+	return noise_floor_weight;
+}
+
+/**
+ * sap_weight_channel_free() - compute channel free weight
+ * @sap_ctx:  sap context
+ * @chn_stat: Pointer to chan status info
+ *
+ * Return: channel free weight
+ */
+static uint32_t sap_weight_channel_free(ptSapContext sap_ctx,
+					struct lim_channel_status
+					*channel_stat)
+{
+	uint32_t     channel_free_weight;
+	uint8_t      softap_channel_free_weight_cfg;
+	uint8_t      softap_channel_free_weight_local;
+	uint32_t     rx_clear_count = 0;
+	uint32_t     cycle_count = 0;
+
+	softap_channel_free_weight_cfg =
+	    ACS_WEIGHT_SOFTAP_CHANNEL_FREE_CFG
+	    (sap_ctx->auto_channel_select_weight);
+
+	softap_channel_free_weight_local =
+	    ACS_WEIGHT_CFG_TO_LOCAL(sap_ctx->auto_channel_select_weight,
+				    softap_channel_free_weight_cfg);
+
+	if (channel_stat == NULL || channel_stat->channelfreq == 0) {
+		QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO,
+			  "In %s, sanity check failed return max weight",
+			  __func__);
+		return softap_channel_free_weight_local;
+	}
+
+	rx_clear_count = channel_stat->rx_clear_count -
+			channel_stat->tx_frame_count -
+			channel_stat->rx_frame_count;
+	cycle_count = channel_stat->cycle_count;
+
+	/* LSH 4, otherwise it is always 0. */
+	channel_free_weight = (cycle_count == 0) ? 0 :
+			 (ACS_WEIGHT_COMPUTE(
+			  sap_ctx->auto_channel_select_weight,
+			  softap_channel_free_weight_cfg,
+			 ((rx_clear_count << 8) +
+			 (cycle_count >> 1))/cycle_count -
+			 (SOFTAP_MIN_CHNFREE << 8),
+			 (SOFTAP_MAX_CHNFREE -
+			 SOFTAP_MIN_CHNFREE) << 8));
+
+	if (channel_free_weight > softap_channel_free_weight_local)
+		channel_free_weight = softap_channel_free_weight_local;
+
+	QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO_HIGH,
+		  "In %s, rcc=%d, cc=%d, tc=%d, rc=%d, cfwc=%d, cfwl=%d, cfw=%d",
+		  __func__, rx_clear_count, cycle_count,
+		 channel_stat->tx_frame_count,
+		 channel_stat->rx_frame_count,
+		  softap_channel_free_weight_cfg,
+		  softap_channel_free_weight_local,
+		  channel_free_weight);
+
+	return channel_free_weight;
+}
+
+/**
+ * sap_weight_channel_txpwr_range() - compute channel tx power range weight
+ * @sap_ctx:  sap context
+ * @chn_stat: Pointer to chan status info
+ *
+ * Return: tx power range weight
+ */
+static uint32_t sap_weight_channel_txpwr_range(ptSapContext sap_ctx,
+					       struct lim_channel_status
+					       *channel_stat)
+{
+	uint32_t     txpwr_weight_low_speed;
+	uint8_t      softap_txpwr_range_weight_cfg;
+	uint8_t      softap_txpwr_range_weight_local;
+
+	softap_txpwr_range_weight_cfg =
+	    ACS_WEIGHT_SOFTAP_TX_POWER_RANGE_CFG
+	    (sap_ctx->auto_channel_select_weight);
+
+	softap_txpwr_range_weight_local =
+	    ACS_WEIGHT_CFG_TO_LOCAL(sap_ctx->auto_channel_select_weight,
+				    softap_txpwr_range_weight_cfg);
+
+	if (channel_stat == NULL || channel_stat->channelfreq == 0) {
+		QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO,
+			  "In %s, sanity check failed return max weight",
+			  __func__);
+		return softap_txpwr_range_weight_local;
+	}
+
+	txpwr_weight_low_speed = (channel_stat->chan_tx_pwr_range == 0) ? 0 :
+				(ACS_WEIGHT_COMPUTE(
+				 sap_ctx->auto_channel_select_weight,
+				 softap_txpwr_range_weight_cfg,
+				 SOFTAP_MAX_TXPWR -
+				 channel_stat->chan_tx_pwr_range,
+				 SOFTAP_MAX_TXPWR - SOFTAP_MIN_TXPWR));
+
+	if (txpwr_weight_low_speed > softap_txpwr_range_weight_local)
+		txpwr_weight_low_speed = softap_txpwr_range_weight_local;
+
+	QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO_HIGH,
+		  "In %s, tpr=%d, tprwc=%d, tprwl=%d, tprw=%d",
+		  __func__, channel_stat->chan_tx_pwr_range,
+		  softap_txpwr_range_weight_cfg,
+		  softap_txpwr_range_weight_local,
+		  txpwr_weight_low_speed);
+
+	return txpwr_weight_low_speed;
+}
+
+/**
+ * sap_weight_channel_txpwr_tput() - compute channel tx power
+ * throughput weight
+ * @sap_ctx:  sap context
+ * @chn_stat: Pointer to chan status info
+ *
+ * Return: tx power throughput weight
+ */
+static uint32_t sap_weight_channel_txpwr_tput(ptSapContext sap_ctx,
+					      struct lim_channel_status
+					      *channel_stat)
+{
+	uint32_t     txpwr_weight_high_speed;
+	uint8_t      softap_txpwr_tput_weight_cfg;
+	uint8_t      softap_txpwr_tput_weight_local;
+
+	softap_txpwr_tput_weight_cfg =
+	    ACS_WEIGHT_SOFTAP_TX_POWER_THROUGHPUT_CFG
+	    (sap_ctx->auto_channel_select_weight);
+
+	softap_txpwr_tput_weight_local =
+	    ACS_WEIGHT_CFG_TO_LOCAL(sap_ctx->auto_channel_select_weight,
+				    softap_txpwr_tput_weight_cfg);
+
+	if (channel_stat == NULL || channel_stat->channelfreq == 0) {
+		QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO,
+			  "In %s, sanity check failed return max weight",
+			  __func__);
+		return softap_txpwr_tput_weight_local;
+	}
+
+	txpwr_weight_high_speed = (channel_stat->chan_tx_pwr_throughput == 0)
+				  ? 0 : (ACS_WEIGHT_COMPUTE(
+				  sap_ctx->auto_channel_select_weight,
+				  softap_txpwr_tput_weight_cfg,
+				  SOFTAP_MAX_TXPWR -
+				  channel_stat->chan_tx_pwr_throughput,
+				  SOFTAP_MAX_TXPWR - SOFTAP_MIN_TXPWR));
+
+	if (txpwr_weight_high_speed > softap_txpwr_tput_weight_local)
+		txpwr_weight_high_speed = softap_txpwr_tput_weight_local;
+
+	QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO_HIGH,
+		  "In %s, tpt=%d, tptwc=%d, tptwl=%d, tptw=%d",
+		  __func__, channel_stat->chan_tx_pwr_throughput,
+		  softap_txpwr_tput_weight_cfg,
+		  softap_txpwr_tput_weight_local,
+		  txpwr_weight_high_speed);
+
+	return txpwr_weight_high_speed;
+}
+
+/**
+ * sap_weight_channel_status() - compute chan status weight
+ * @sap_ctx:  sap context
+ * @chn_stat: Pointer to chan status info
+ *
+ * Return: chan status weight
+ */
+static
+uint32_t sap_weight_channel_status(ptSapContext sap_ctx,
+				   struct lim_channel_status *channel_stat)
+{
+	return sap_weight_channel_noise_floor(sap_ctx, channel_stat) +
+	       sap_weight_channel_free(sap_ctx, channel_stat) +
+	       sap_weight_channel_txpwr_range(sap_ctx, channel_stat) +
+	       sap_weight_channel_txpwr_tput(sap_ctx, channel_stat);
+}
+
 /**
  * sap_update_rssi_bsscount() - updates bss count and rssi effect.
  *
@@ -1356,9 +1702,13 @@ static void sap_compute_spect_weight(tSapChSelSpectInfo *pSpectInfoParams,
 			rssi -= PCL_RSSI_DISCOUNT;
 
 		pSpectCh->weight =
-			SAPDFS_NORMALISE_1000 * sapweight_rssi_count(rssi,
-								     pSpectCh->
-								     bssCount);
+			SAPDFS_NORMALISE_1000 *
+			(sapweight_rssi_count(sap_ctx, rssi,
+			 pSpectCh->bssCount) + sap_weight_channel_status(
+			 sap_ctx, sap_get_channel_status(pMac,
+							 pSpectCh->chNum)));
+		if (pSpectCh->weight > SAP_ACS_WEIGHT_MAX)
+			pSpectCh->weight = SAP_ACS_WEIGHT_MAX;
 		pSpectCh->weight_copy = pSpectCh->weight;
 
 		/* ------ Debug Info ------ */
@@ -1369,6 +1719,7 @@ static void sap_compute_spect_weight(tSapChSelSpectInfo *pSpectInfoParams,
 		/* ------ Debug Info ------ */
 		pSpectCh++;
 	}
+	sap_clear_channel_status(pMac);
 	qdf_mem_free(pBeaconStruct);
 }
 
@@ -2237,7 +2588,12 @@ uint8_t sap_select_channel(tHalHandle hal, ptSapContext sap_ctx,
 	sap_update_unsafe_channel_list(hal, sap_ctx);
 #endif
 
-	if (NULL == scan_result) {
+	/*
+	 * If ACS weight is not enabled on noise_floor/channel_free/tx_power,
+	 * then skip acs process if no bss found.
+	 */
+	if (NULL == scan_result &&
+	    !(sap_ctx->auto_channel_select_weight & 0xffff00)) {
 		QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO_HIGH,
 			  FL("No external AP present"));
 
@@ -2342,7 +2698,7 @@ uint8_t sap_select_channel(tHalHandle hal, ptSapContext sap_ctx,
 			continue;
 
 		tmp_ch_num = spect_info->pSpectCh[count].chNum;
-		tmp_ch_num = sap_select_preferred_channel_from_channel_list(
+		tmp_ch_num = sap_channel_in_acs_channel_list(
 					tmp_ch_num, sap_ctx, spect_info);
 		if (tmp_ch_num == SAP_CHANNEL_NOT_SELECTED)
 			continue;

+ 8 - 3
core/sap/src/sap_ch_select.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2015, 2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -60,8 +60,13 @@
 #define SOFTAP_MAX_RSSI         (0)
 #define SOFTAP_MIN_COUNT        (0)
 #define SOFTAP_MAX_COUNT        (60)
-#define SOFTAP_RSSI_WEIGHT      (20)
-#define SOFTAP_COUNT_WEIGHT     (20)
+
+#define SOFTAP_MIN_NF           (-120)
+#define SOFTAP_MAX_NF           (-60)
+#define SOFTAP_MIN_CHNFREE      (0)
+#define SOFTAP_MAX_CHNFREE      (1)
+#define SOFTAP_MIN_TXPWR        (0)
+#define SOFTAP_MAX_TXPWR        (63)
 
 #define SAP_DEFAULT_24GHZ_CHANNEL     (6)
 #define SAP_DEFAULT_5GHZ_CHANNEL      (40)

+ 1 - 1
core/sap/src/sap_internal.h

@@ -224,7 +224,7 @@ typedef struct sSapContext {
 	 * on a DFS channel and a RADAR is detected on the channel.
 	 */
 	tAll5GChannelList SapAllChnlList;
-
+	uint32_t auto_channel_select_weight;
 	tSapAcsChannelInfo acsBestChannelInfo;
 	bool enableOverLapCh;
 	struct sap_acs_cfg *acs_cfg;

+ 4 - 0
core/sap/src/sap_module.c

@@ -702,6 +702,8 @@ wlansap_set_scan_acs_channel_params(tsap_Config_t *pconfig,
 #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
 	psap_ctx->cc_switch_mode = pconfig->cc_switch_mode;
 #endif
+	psap_ctx->auto_channel_select_weight =
+		 pconfig->auto_channel_select_weight;
 	psap_ctx->pUsrContext = pusr_context;
 	psap_ctx->enableOverLapCh = pconfig->enOverLapCh;
 	psap_ctx->acs_cfg = &pconfig->acs_cfg;
@@ -891,6 +893,8 @@ QDF_STATUS wlansap_start_bss(void *pCtx,     /* pwextCtx */
 #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
 	pSapCtx->cc_switch_mode = pConfig->cc_switch_mode;
 #endif
+	pSapCtx->auto_channel_select_weight =
+		 pConfig->auto_channel_select_weight;
 	pSapCtx->pUsrContext = pUsrContext;
 	pSapCtx->enableOverLapCh = pConfig->enOverLapCh;
 	pSapCtx->acs_cfg = &pConfig->acs_cfg;

+ 18 - 0
core/sme/inc/csr_api.h

@@ -1301,6 +1301,7 @@ typedef struct tagCsrConfigParam {
 #ifdef FEATURE_AP_MCC_CH_AVOIDANCE
 	bool sap_channel_avoidance;
 #endif /* FEATURE_AP_MCC_CH_AVOIDANCE */
+	bool acs_with_more_param;
 	uint8_t f_prefer_non_dfs_on_radar;
 	bool is_ps_enabled;
 	uint32_t auto_bmps_timer_val;
@@ -1777,4 +1778,21 @@ static inline void csr_roam_fill_tdls_info(tpAniSirGlobal mac_ctx, tCsrRoamInfo
 #endif
 void csr_packetdump_timer_stop(void);
 
+/**
+ * csr_get_channel_status() - get chan info via channel number
+ * @p_mac: Pointer to Global MAC structure
+ * @channel_id: channel id
+ *
+ * Return: chan status info
+ */
+struct lim_channel_status *csr_get_channel_status(void *p_mac,
+						  uint32_t channel_id);
+
+/**
+ * csr_clear_channel_status() - clear chan info
+ * @p_mac: Pointer to Global MAC structure
+ *
+ * Return: none
+ */
+void csr_clear_channel_status(void *p_mac);
 #endif

+ 3 - 0
core/sme/src/csr/csr_api_roam.c

@@ -2779,6 +2779,8 @@ QDF_STATUS csr_change_default_config_param(tpAniSirGlobal pMac,
 		pMac->sap.sap_channel_avoidance =
 			pParam->sap_channel_avoidance;
 #endif /* FEATURE_AP_MCC_CH_AVOIDANCE */
+		pMac->sap.acs_with_more_param =
+			pParam->acs_with_more_param;
 
 		pMac->f_prefer_non_dfs_on_radar =
 			pParam->f_prefer_non_dfs_on_radar;
@@ -3016,6 +3018,7 @@ QDF_STATUS csr_get_config_param(tpAniSirGlobal pMac, tCsrConfigParam *pParam)
 #ifdef FEATURE_AP_MCC_CH_AVOIDANCE
 	pParam->sap_channel_avoidance = pMac->sap.sap_channel_avoidance;
 #endif /* FEATURE_AP_MCC_CH_AVOIDANCE */
+	pParam->acs_with_more_param = pMac->sap.acs_with_more_param;
 	pParam->max_intf_count = pMac->sme.max_intf_count;
 	pParam->enableSelfRecovery = pMac->sme.enableSelfRecovery;
 	pParam->f_prefer_non_dfs_on_radar =

+ 37 - 0
core/sme/src/csr/csr_util.c

@@ -6475,6 +6475,43 @@ void csr_disconnect_all_active_sessions(tpAniSirGlobal pMac)
 	}
 }
 
+struct lim_channel_status *csr_get_channel_status(
+	void *p_mac, uint32_t channel_id)
+{
+	uint8_t i;
+	struct lim_scan_channel_status *channel_status;
+	tpAniSirGlobal mac_ptr = (tpAniSirGlobal)p_mac;
+
+	if (!mac_ptr->sap.acs_with_more_param)
+		return NULL;
+
+	channel_status = (struct lim_scan_channel_status *)
+				&mac_ptr->lim.scan_channel_status;
+	for (i = 0; i < channel_status->total_channel; i++) {
+		if (channel_status->channel_status_list[i].channel_id ==
+		    channel_id)
+			return &channel_status->channel_status_list[i];
+	}
+	cds_err("Channel %d status info not exist", channel_id);
+
+	return NULL;
+}
+
+void csr_clear_channel_status(void *p_mac)
+{
+	tpAniSirGlobal mac_ptr = (tpAniSirGlobal)p_mac;
+	struct lim_scan_channel_status *channel_status;
+
+	if (!mac_ptr->sap.acs_with_more_param)
+		return;
+
+	channel_status = (struct lim_scan_channel_status *)
+			&mac_ptr->lim.scan_channel_status;
+	channel_status->total_channel = 0;
+
+	return;
+}
+
 bool csr_is_channel_present_in_list(uint8_t *pChannelList,
 				    int numChannels, uint8_t channel)
 {

+ 3 - 0
core/wma/inc/wma.h

@@ -240,6 +240,9 @@ enum ds_mode {
 #define WMA_EXTSCAN_BURST_DURATION      150
 #endif
 
+#define WMA_CHAN_START_RESP          0
+#define WMA_CHAN_END_RESP            1
+
 #define WMA_BCN_BUF_MAX_SIZE 2500
 #define WMA_NOA_IE_SIZE(num_desc) (2 + (13 * (num_desc)))
 #define WMA_MAX_NOA_DESCRIPTORS 4

+ 1 - 0
core/wma/inc/wma_types.h

@@ -322,6 +322,7 @@
 #define WMA_STOP_SCAN_OFFLOAD_REQ  SIR_HAL_STOP_SCAN_OFFLOAD_REQ
 #define WMA_UPDATE_CHAN_LIST_REQ    SIR_HAL_UPDATE_CHAN_LIST_REQ
 #define WMA_RX_SCAN_EVENT           SIR_HAL_RX_SCAN_EVENT
+#define WMA_RX_CHN_STATUS_EVENT     SIR_HAL_RX_CHN_STATUS_EVENT
 #define WMA_IBSS_PEER_INACTIVITY_IND SIR_HAL_IBSS_PEER_INACTIVITY_IND
 
 #define WMA_CLI_SET_CMD             SIR_HAL_CLI_SET_CMD

+ 49 - 0
core/wma/src/wma_features.c

@@ -5270,6 +5270,7 @@ int wma_chan_info_event_handler(void *handle, uint8_t *event_buf,
 	wmi_chan_info_event_fixed_param *event;
 	struct scan_chan_info buf;
 	tpAniSirGlobal mac = NULL;
+	struct lim_channel_status *channel_status;
 
 	WMA_LOGD("%s: Enter", __func__);
 
@@ -5305,6 +5306,54 @@ int wma_chan_info_event_handler(void *handle, uint8_t *event_buf,
 		mac->chan_info_cb(&buf);
 	}
 
+	if (mac->sap.acs_with_more_param &&
+	    mac->sme.currDeviceMode == QDF_SAP_MODE) {
+		param_buf = (WMI_CHAN_INFO_EVENTID_param_tlvs *) event_buf;
+		if (!param_buf)  {
+			WMA_LOGE("Invalid chan info event buffer");
+			return -EINVAL;
+		}
+		event = param_buf->fixed_param;
+		channel_status =
+			qdf_mem_malloc(sizeof(*channel_status));
+		if (!channel_status) {
+			WMA_LOGE(FL("Mem alloc fail"));
+			return -ENOMEM;
+		}
+		WMA_LOGD(FL("freq=%d nf=%d rxcnt=%u cyccnt=%u tx_r=%d tx_t=%d"),
+			 event->freq,
+			 event->noise_floor,
+			 event->rx_clear_count,
+			 event->cycle_count,
+			 event->chan_tx_pwr_range,
+			 event->chan_tx_pwr_tp);
+
+		channel_status->channelfreq = event->freq;
+		channel_status->noise_floor = event->noise_floor;
+		channel_status->rx_clear_count =
+			 event->rx_clear_count;
+		channel_status->cycle_count = event->cycle_count;
+		channel_status->chan_tx_pwr_range =
+			 event->chan_tx_pwr_range;
+		channel_status->chan_tx_pwr_throughput =
+			 event->chan_tx_pwr_tp;
+		channel_status->rx_frame_count =
+			 event->rx_frame_count;
+		channel_status->bss_rx_cycle_count =
+			event->my_bss_rx_cycle_count;
+		channel_status->rx_11b_mode_data_duration =
+			event->rx_11b_mode_data_duration;
+		channel_status->tx_frame_count = event->tx_frame_cnt;
+		channel_status->mac_clk_mhz = event->mac_clk_mhz;
+		channel_status->channel_id =
+			cds_freq_to_chan(event->freq);
+		channel_status->cmd_flags =
+			event->cmd_flags;
+
+		wma_send_msg(handle, WMA_RX_CHN_STATUS_EVENT,
+			     (void *)channel_status, 0);
+	}
+
 	return 0;
 }
 

+ 8 - 0
core/wma/src/wma_scan_roam.c

@@ -303,6 +303,14 @@ QDF_STATUS wma_get_buf_start_scan_cmd(tp_wma_handle wma_handle,
 		cmd->scan_f_add_tpc_ie_in_probe = true;
 		cmd->scan_f_filter_prb_req = true;
 
+		if (pMac->sap.acs_with_more_param) {
+			/* add chan stat info report tag */
+			if (pMac->sme.currDeviceMode == QDF_SAP_MODE) {
+				cmd->scan_f_chan_stat_evnt = true;
+				WMA_LOGD("set ACS ctrl BIT");
+			}
+		}
+
 		/*
 		 * Decide burst_duration and dwell_time_active based on
 		 * what type of devices are active.