diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h
index 0953bbbe1347..d0bc954c8520 100644
--- a/core/hdd/inc/wlan_hdd_cfg.h
+++ b/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)
+/*
+ *
+ * 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
+ *
+ *
+ */
+
+#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)
+
+/*
+ *
+ * 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
+ *
+ *
+ */
+#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;
diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c
index bb69ca2c3e1e..8b80512c0b77 100644
--- a/core/hdd/src/wlan_hdd_cfg.c
+++ b/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;
diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c
index 3b2179838edd..fef166bd0366 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.c
+++ b/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;
diff --git a/core/mac/inc/ani_global.h b/core/mac/inc/ani_global.h
index 014b32c9b7ec..1ece5dbf5ae2 100644
--- a/core/mac/inc/ani_global.h
+++ b/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 */
diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h
index 26d7e93add67..841fab3b198e 100644
--- a/core/mac/inc/sir_api.h
+++ b/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;
diff --git a/core/mac/src/include/sir_params.h b/core/mac/src/include/sir_params.h
index 4aa9d011b7d0..00885482097e 100644
--- a/core/mac/src/include/sir_params.h
+++ b/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)
diff --git a/core/mac/src/pe/lim/lim_process_message_queue.c b/core/mac/src/pe/lim/lim_process_message_queue.c
index ce20dbc8886c..e7b51857a2c2 100644
--- a/core/mac/src/pe/lim/lim_process_message_queue.c
+++ b/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));
diff --git a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c
index 2aeee5534cd2..43a875065140 100644
--- a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c
+++ b/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;
+}
diff --git a/core/mac/src/pe/lim/lim_types.h b/core/mac/src/pe/lim/lim_types.h
index bc9f36be8019..8122b77c44a3 100644
--- a/core/mac/src/pe/lim/lim_types.h
+++ b/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 */
{
diff --git a/core/mac/src/pe/lim/lim_utils.c b/core/mac/src/pe/lim/lim_utils.c
index e6229f54d5cf..d76b2584bd6d 100644
--- a/core/mac/src/pe/lim/lim_utils.c
+++ b/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()
*
diff --git a/core/mac/src/pe/lim/lim_utils.h b/core/mac/src/pe/lim/lim_utils.h
index c4445a324698..c2300416686c 100644
--- a/core/mac/src/pe/lim/lim_utils.h
+++ b/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,
diff --git a/core/mac/src/sys/legacy/src/utils/src/mac_trace.c b/core/mac/src/sys/legacy/src/utils/src/mac_trace.c
index 7fd1c412a90a..c96f9491aa21 100644
--- a/core/mac/src/sys/legacy/src/utils/src/mac_trace.c
+++ b/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
diff --git a/core/sap/inc/sap_api.h b/core/sap/inc/sap_api.h
index fdc7a2ecc870..fb8826096e02 100644
--- a/core/sap/inc/sap_api.h
+++ b/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;
diff --git a/core/sap/src/sap_ch_select.c b/core/sap/src/sap_ch_select.c
index 1d9abc89e90f..e0751120441a 100644
--- a/core/sap/src/sap_ch_select.c
+++ b/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;
diff --git a/core/sap/src/sap_ch_select.h b/core/sap/src/sap_ch_select.h
index 8fe2d1738c6e..25def474a12b 100644
--- a/core/sap/src/sap_ch_select.h
+++ b/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)
diff --git a/core/sap/src/sap_internal.h b/core/sap/src/sap_internal.h
index 0116e47c4f7b..34d0ea122321 100644
--- a/core/sap/src/sap_internal.h
+++ b/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;
diff --git a/core/sap/src/sap_module.c b/core/sap/src/sap_module.c
index 2b57054a8375..0b8afddaac62 100644
--- a/core/sap/src/sap_module.c
+++ b/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;
diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h
index f843636e7771..2cb3e6098138 100644
--- a/core/sme/inc/csr_api.h
+++ b/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
diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c
index 70be835eaaf8..b14769dab73e 100644
--- a/core/sme/src/csr/csr_api_roam.c
+++ b/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 =
diff --git a/core/sme/src/csr/csr_util.c b/core/sme/src/csr/csr_util.c
index adcb52c12443..898bfa8d92b0 100644
--- a/core/sme/src/csr/csr_util.c
+++ b/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)
{
diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h
index e1b8e469a54c..94f5c2e8fc6c 100644
--- a/core/wma/inc/wma.h
+++ b/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
diff --git a/core/wma/inc/wma_types.h b/core/wma/inc/wma_types.h
index 5782df591f8f..0bfc7905d399 100644
--- a/core/wma/inc/wma_types.h
+++ b/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
diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c
index 2f3ed3c2e751..386c27af5276 100644
--- a/core/wma/src/wma_features.c
+++ b/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;
}
diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c
index fcadcbc3f8d7..182c3e1a4546 100644
--- a/core/wma/src/wma_scan_roam.c
+++ b/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.