Browse Source

qcacld-3.0: Report more information in survey dump

qcacld-2.0 to qcacld-3.0 propagation

Currently host only report connected frequency and noise in
survey dump.
Add changes to report all supported frequencies, active time,
TX time, busy time and noise.

CRs-Fixed: 1061040
Change-Id: I2fa509f53b47d65ba0f4abbc438834b85b9c21f6
Kapil Gupta 8 years ago
parent
commit
4f0c0c1c50

+ 20 - 1
core/hdd/inc/wlan_hdd_main.h

@@ -1611,6 +1611,8 @@ struct hdd_context_s {
 	struct suspend_resume_stats suspend_resume_stats;
 	struct hdd_runtime_pm_context runtime_context;
 	bool roaming_in_progress;
+	struct scan_chan_info *chan_info;
+	struct mutex chan_info_lock;
 	/* bit map to set/reset TDLS by different sources */
 	unsigned long tdls_source_bitmap;
 	/* tdls source timer to enable/disable TDLS on p2p listen */
@@ -2192,5 +2194,22 @@ void hdd_set_roaming_in_progress(bool value);
 int wlan_hdd_sap_get_valid_channellist(hdd_adapter_t *adapter,
 				       uint32_t *channel_count,
 				       uint8_t *channel_list);
-
+/**
+ * wlan_hdd_init_chan_info() - initialize channel info variables
+ * @hdd_ctx: hdd ctx
+ *
+ * This API initialize channel info variables
+ *
+ * Return: None
+ */
+void wlan_hdd_init_chan_info(hdd_context_t *hdd_ctx);
+/**
+ * wlan_hdd_deinit_chan_info() - deinitialize channel info variables
+ * @hdd_ctx: hdd ctx
+ *
+ * This API deinitialize channel info variables
+ *
+ * Return: None
+ */
+void wlan_hdd_deinit_chan_info(hdd_context_t *hdd_ctx);
 #endif /* end #if !defined(WLAN_HDD_MAIN_H) */

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

@@ -7088,6 +7088,8 @@ QDF_STATUS hdd_set_sme_config(hdd_context_t *pHddCtx)
 		CSR_STA_ROAM_POLICY_DFS_ENABLED;
 	smeConfig->csrConfig.sta_roam_policy_params.skip_unsafe_channels = 0;
 
+	smeConfig->snr_monitor_enabled = pHddCtx->config->fEnableSNRMonitoring;
+
 	smeConfig->csrConfig.tx_aggregation_size =
 			pHddCtx->config->tx_aggregation_size;
 	smeConfig->csrConfig.rx_aggregation_size =

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

@@ -16505,6 +16505,145 @@ void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
 	return;
 }
 
+#define CNT_DIFF(cur, prev) \
+	((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
+#define MAX_COUNT 0xffffffff
+static void hdd_update_chan_info(hdd_context_t *hdd_ctx,
+			struct scan_chan_info *chan,
+			struct scan_chan_info *info, uint32_t cmd_flag)
+{
+	if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
+	   (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
+		hdd_err("cmd flag is invalid: %d", info->cmd_flag);
+
+	mutex_lock(&hdd_ctx->chan_info_lock);
+
+	if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
+		qdf_mem_zero(chan, sizeof(*chan));
+
+	chan->freq = info->freq;
+	chan->noise_floor = info->noise_floor;
+	chan->clock_freq = info->clock_freq;
+	chan->cmd_flag = info->cmd_flag;
+	chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
+
+	chan->rx_clear_count =
+			CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
+
+	chan->tx_frame_count =
+			CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
+
+	mutex_unlock(&hdd_ctx->chan_info_lock);
+
+}
+#undef CNT_DIFF
+#undef MAX_COUNT
+
+/**
+ * wlan_hdd_chan_info_cb() - channel info callback
+ * @chan_info: struct scan_chan_info
+ *
+ * Store channel info into HDD context
+ *
+ * Return: None.
+ */
+static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
+{
+	hdd_context_t *hdd_ctx;
+	struct scan_chan_info *chan;
+	uint8_t idx;
+
+	ENTER();
+
+	hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
+	if (wlan_hdd_validate_context(hdd_ctx) != 0) {
+		hdd_err("hdd_ctx is invalid");
+		return;
+	}
+
+	if (!hdd_ctx->chan_info) {
+		hdd_err("chan_info is NULL");
+		return;
+	}
+
+	chan = hdd_ctx->chan_info;
+	for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
+		if (chan[idx].freq == info->freq) {
+			hdd_update_chan_info(hdd_ctx, &chan[idx], info,
+				info->cmd_flag);
+			hdd_info("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
+				chan[idx].cmd_flag, chan[idx].freq,
+				chan[idx].noise_floor,
+				chan[idx].cycle_count, chan[idx].rx_clear_count,
+				chan[idx].clock_freq, chan[idx].cmd_flag,
+				chan[idx].tx_frame_count, idx);
+			if (chan[idx].freq == 0)
+				break;
+
+		}
+	}
+
+	EXIT();
+}
+
+/**
+ * wlan_hdd_init_chan_info() - init chan info in hdd context
+ * @hdd_ctx: HDD context pointer
+ *
+ * Return: none
+ */
+void wlan_hdd_init_chan_info(hdd_context_t *hdd_ctx)
+{
+	uint8_t num_2g, num_5g, index = 0;
+
+	if (!hdd_ctx->config->fEnableSNRMonitoring) {
+		hdd_info("SNR monitoring is disabled");
+		return;
+	}
+
+	hdd_ctx->chan_info =
+		qdf_mem_malloc(sizeof(struct scan_chan_info)
+					* QDF_MAX_NUM_CHAN);
+	if (hdd_ctx->chan_info == NULL) {
+		hdd_err("Failed to malloc for chan info");
+		return;
+	}
+	mutex_init(&hdd_ctx->chan_info_lock);
+
+	num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
+	for (; index < num_2g; index++) {
+		hdd_ctx->chan_info[index].freq =
+			hdd_channels_2_4_ghz[index].center_freq;
+	}
+
+	num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
+	for (; (index - num_2g) < num_5g; index++) {
+		if (cds_is_dsrc_channel(
+			hdd_channels_5_ghz[index - num_2g].center_freq))
+			continue;
+		hdd_ctx->chan_info[index].freq =
+			hdd_channels_5_ghz[index - num_2g].center_freq;
+	}
+	sme_set_chan_info_callback(hdd_ctx->hHal,
+				   &wlan_hdd_chan_info_cb);
+}
+
+/**
+ * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
+ * @hdd_ctx: hdd context pointer
+ *
+ * Return: none
+ */
+void wlan_hdd_deinit_chan_info(hdd_context_t *hdd_ctx)
+{
+	struct scan_chan_info *chan;
+
+	chan = hdd_ctx->chan_info;
+	hdd_ctx->chan_info = NULL;
+	if (chan)
+		qdf_mem_free(chan);
+}
+
 /**
  * struct cfg80211_ops - cfg80211_ops
  *

+ 3 - 0
core/hdd/src/wlan_hdd_main.c

@@ -4940,6 +4940,7 @@ static void hdd_wlan_exit(hdd_context_t *hdd_ctx)
 	cds_flush_work(&hdd_ctx->roc_req_work);
 
 	wlansap_global_deinit();
+	wlan_hdd_deinit_chan_info(hdd_ctx);
 	wiphy_unregister(wiphy);
 	wlan_hdd_cfg80211_deinit(wiphy);
 
@@ -8406,6 +8407,8 @@ int hdd_wlan_startup(struct device *dev)
 	if (hdd_ipa_init(hdd_ctx) == QDF_STATUS_E_FAILURE)
 		goto err_wiphy_unregister;
 
+	wlan_hdd_init_chan_info(hdd_ctx);
+
 	hdd_initialize_mac_address(hdd_ctx);
 
 	rtnl_held = hdd_hold_rtnl_lock();

+ 119 - 60
core/hdd/src/wlan_hdd_stats.c

@@ -2401,6 +2401,106 @@ struct net_device_stats *hdd_get_stats(struct net_device *dev)
 	ENTER_DEV(dev);
 	return &adapter->stats;
 }
+
+
+/*
+ * time = cycle_count * cycle
+ * cycle = 1 / clock_freq
+ * Since the unit of clock_freq reported from
+ * FW is MHZ, and we want to calculate time in
+ * ms level, the result is
+ * time = cycle / (clock_freq * 1000)
+ */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))
+static bool wlan_fill_survey_result(struct survey_info *survey, int opfreq,
+				    struct scan_chan_info *chan_info,
+				    struct ieee80211_channel *channels)
+{
+	uint64_t clock_freq = chan_info->clock_freq * 1000;
+
+	if (channels->center_freq != (uint16_t)chan_info->freq)
+		return false;
+
+	survey->channel = channels;
+	survey->noise = chan_info->noise_floor;
+	survey->filled = SURVEY_INFO_NOISE_DBM;
+
+	if (opfreq == chan_info->freq)
+		survey->filled |= SURVEY_INFO_IN_USE;
+
+	if (clock_freq == 0)
+		return true;
+
+	survey->time = chan_info->cycle_count / clock_freq;
+	survey->time_busy = chan_info->rx_clear_count / clock_freq;
+	survey->time_tx = chan_info->tx_frame_count / clock_freq;
+
+	survey->filled |= SURVEY_INFO_TIME |
+			  SURVEY_INFO_TIME_BUSY |
+			  SURVEY_INFO_TIME_TX;
+	return true;
+}
+#else
+static bool wlan_fill_survey_result(struct survey_info *survey, int opfreq,
+				    struct scan_chan_info *chan_info,
+				    struct ieee80211_channel *channels)
+{
+	uint64_t clock_freq = chan_info->clock_freq * 1000;
+
+	if (channels->center_freq != (uint16_t)chan_info->freq)
+		return false;
+
+	survey->channel = channels;
+	survey->noise = chan_info->noise_floor;
+	survey->filled = SURVEY_INFO_NOISE_DBM;
+
+	if (opfreq == chan_info->freq)
+		survey->filled |= SURVEY_INFO_IN_USE;
+
+	if (clock_freq == 0)
+		return true;
+
+	survey->channel_time = chan_info->cycle_count / clock_freq;
+	survey->channel_time_busy = chan_info->rx_clear_count / clock_freq;
+	survey->channel_time_tx = chan_info->tx_frame_count / clock_freq;
+
+	survey->filled |= SURVEY_INFO_CHANNEL_TIME |
+			  SURVEY_INFO_CHANNEL_TIME_BUSY |
+			  SURVEY_INFO_CHANNEL_TIME_TX;
+	return true;
+}
+#endif
+
+static bool wlan_hdd_update_survey_info(struct wiphy *wiphy,
+		hdd_adapter_t *pAdapter, struct survey_info *survey, int idx)
+{
+	bool filled = false;
+	int i, j = 0;
+	uint32_t channel = 0, opfreq; /* Initialization Required */
+	hdd_context_t *pHddCtx;
+
+	pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
+	sme_get_operation_channel(pHddCtx->hHal, &channel, pAdapter->sessionId);
+	hdd_wlan_get_freq(channel, &opfreq);
+
+	mutex_lock(&pHddCtx->chan_info_lock);
+
+	for (i = 0; i < IEEE80211_NUM_BANDS && !filled; i++) {
+		if (wiphy->bands[i] == NULL)
+			continue;
+
+		for (j = 0; j < wiphy->bands[i]->n_channels && !filled; j++) {
+			struct ieee80211_supported_band *band = wiphy->bands[i];
+			filled = wlan_fill_survey_result(survey, opfreq,
+				&pHddCtx->chan_info[idx],
+				&band->channels[j]);
+		}
+	}
+	mutex_unlock(&pHddCtx->chan_info_lock);
+
+	return filled;
+}
+
 /**
  * __wlan_hdd_cfg80211_dump_survey() - get survey related info
  * @wiphy: Pointer to wiphy
@@ -2417,86 +2517,45 @@ static int __wlan_hdd_cfg80211_dump_survey(struct wiphy *wiphy,
 	hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
 	hdd_context_t *pHddCtx;
 	hdd_station_ctx_t *pHddStaCtx;
-	tHalHandle halHandle;
-	uint32_t channel = 0, freq = 0; /* Initialization Required */
-	int8_t snr, rssi;
-	int status, i, j, filled = 0;
+	int status;
+	bool filled = false;
 
 	ENTER_DEV(dev);
 
-	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
-		hdd_err("Command not allowed in FTM mode");
+	hdd_info("dump survey index:%d", idx);
+	if (idx > QDF_MAX_NUM_CHAN - 1)
 		return -EINVAL;
-	}
 
 	pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
 	status = wlan_hdd_validate_context(pHddCtx);
-
 	if (0 != status)
 		return status;
 
-	pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
-
-	if (0 == pHddCtx->config->fEnableSNRMonitoring ||
-	    0 != pAdapter->survey_idx ||
-	    eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
-		/* The survey dump ops when implemented completely is expected
-		 * to return a survey of all channels and the ops is called by
-		 * the kernel with incremental values of the argument 'idx'
-		 * till it returns -ENONET. But we can only support the survey
-		 * for the operating channel for now. survey_idx is used to
-		 * track that the ops is called only once and then return
-		 * -ENONET for the next iteration
-		 */
-		pAdapter->survey_idx = 0;
-		return -ENONET;
+	if (pHddCtx->chan_info == NULL) {
+		hdd_err("chan_info is NULL");
+		return -EINVAL;
 	}
 
-	if (!pHddStaCtx->hdd_ReassocScenario) {
-		hdd_err("Roaming in progress, hence return");
-		return -ENONET;
+	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
+		hdd_err("Command not allowed in FTM mode");
+		return -EINVAL;
 	}
 
-	halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
-
-	wlan_hdd_get_snr(pAdapter, &snr);
-	wlan_hdd_get_rssi(pAdapter, &rssi);
-
-	MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
-			 TRACE_CODE_HDD_CFG80211_DUMP_SURVEY,
-			 pAdapter->sessionId, pAdapter->device_mode));
-
-	sme_get_operation_channel(halHandle, &channel, pAdapter->sessionId);
-	hdd_wlan_get_freq(channel, &freq);
+	pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
 
-	for (i = 0; i < NUM_NL80211_BANDS; i++) {
-		if (NULL == wiphy->bands[i])
-			continue;
+	if (pHddCtx->config->fEnableSNRMonitoring == 0)
+		return -ENONET;
 
-		for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
-			struct ieee80211_supported_band *band = wiphy->bands[i];
 
-			if (band->channels[j].center_freq == (uint16_t) freq) {
-				survey->channel = &band->channels[j];
-				/* The Rx BDs contain SNR values in dB for the
-				 * received frames while the supplicant expects
-				 * noise. So we calculate and return the value
-				 * of noise (dBm)
-				 *  SNR (dB) = RSSI (dBm) - NOISE (dBm)
-				 */
-				survey->noise = rssi - snr;
-				survey->filled = SURVEY_INFO_NOISE_DBM;
-				filled = 1;
-			}
-		}
+	if (pHddStaCtx->hdd_ReassocScenario) {
+		hdd_info("Roaming in progress, hence return");
+		return -ENONET;
 	}
 
-	if (filled)
-		pAdapter->survey_idx = 1;
-	else {
-		pAdapter->survey_idx = 0;
+	filled = wlan_hdd_update_survey_info(wiphy, pAdapter, survey, idx);
+
+	if (!filled)
 		return -ENONET;
-	}
 	EXIT();
 	return 0;
 }

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

@@ -969,6 +969,8 @@ typedef struct sAniSirGlobal {
 	bool sta_prefer_80MHz_over_160MHz;
 	struct wlan_objmgr_psoc *psoc;
 	enum  country_src reg_hint_src;
+	bool snr_monitor_enabled;
+	void (*chan_info_cb)(struct scan_chan_info *chan_info);
 } tAniSirGlobal;
 
 typedef enum {

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

@@ -6889,4 +6889,23 @@ struct wow_pulse_mode {
  */
 QDF_STATUS umac_send_mb_message_to_mac(void *msg);
 
+/**
+ * struct scan_chan_info - channel info
+ * @freq: radio frequence
+ * @cmd flag: cmd flag
+ * @noise_floor: noise floor
+ * @cycle_count: cycle count
+ * @rx_clear_count: rx clear count
+ * @tx_frame_count: TX frame count
+ * @clock_freq: clock frequence MHZ
+ */
+struct scan_chan_info {
+	uint32_t freq;
+	uint32_t cmd_flag;
+	uint32_t noise_floor;
+	uint32_t cycle_count;
+	uint32_t rx_clear_count;
+	uint32_t tx_frame_count;
+	uint32_t clock_freq;
+};
 #endif /* __SIR_API_H */

+ 12 - 0
core/sme/inc/sme_api.h

@@ -91,6 +91,7 @@ typedef void (*hdd_ftm_msg_processor)(void *);
 typedef struct _smeConfigParams {
 	tCsrConfigParam csrConfig;
 	struct rrm_config_param rrmConfig;
+	bool snr_monitor_enabled;
 } tSmeConfigParams, *tpSmeConfigParams;
 
 #ifdef FEATURE_WLAN_TDLS
@@ -1386,4 +1387,15 @@ void sme_set_cc_src(tHalHandle hal_handle, enum country_src);
 QDF_STATUS sme_set_wow_pulse(struct wow_pulse_mode *wow_pulse_set_info);
 #endif
 
+/**
+ * sme_set_chan_info_callback() - Register chan info callback
+ * @hal - MAC global handle
+ * @callback_routine - callback routine from HDD
+ *
+ * This API is invoked by HDD to register its callback to mac
+ *
+ * Return: QDF_STATUS
+ */
+void sme_set_chan_info_callback(tHalHandle hal_handle,
+			void (*callback)(struct scan_chan_info *chan_info));
 #endif /* #if !defined( __SME_API_H ) */

+ 16 - 0
core/sme/src/common/sme_api.c

@@ -1456,6 +1456,9 @@ QDF_STATUS sme_update_config(tHalHandle hHal, tpSmeConfigParams pSmeConfigParams
 		QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
 			  "Could not pass on WNI_CFG_SCAN_IN_POWERSAVE to CFG");
 	}
+
+	pMac->snr_monitor_enabled = pSmeConfigParams->snr_monitor_enabled;
+
 	return status;
 }
 
@@ -16439,6 +16442,19 @@ QDF_STATUS sme_create_mon_session(tHalHandle hal_handle, tSirMacAddr bss_id)
 	return status;
 }
 
+void sme_set_chan_info_callback(tHalHandle hal_handle,
+			void (*callback)(struct scan_chan_info *chan_info))
+{
+	tpAniSirGlobal mac;
+
+	if (hal_handle == NULL) {
+		QDF_ASSERT(0);
+		return;
+	}
+	mac = PMAC_STRUCT(hal_handle);
+	mac->chan_info_cb = callback;
+}
+
 /**
  * sme_set_adaptive_dwelltime_config() - Update Adaptive dwelltime configuration
  * @hal: The handle returned by macOpen

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

@@ -2358,4 +2358,17 @@ int wma_form_rx_packet(qdf_nbuf_t buf,
 QDF_STATUS wma_mgmt_unified_cmd_send(struct wlan_objmgr_vdev *vdev,
 				qdf_nbuf_t buf, uint32_t desc_id,
 				void *mgmt_tx_params);
+
+/**
+ * wma_chan_info_event_handler() - chan info event handler
+ * @handle: wma handle
+ * @event_buf: event handler data
+ * @len: length of @event_buf
+ *
+ * this function will handle the WMI_CHAN_INFO_EVENTID
+ *
+ * Return: int
+ */
+int wma_chan_info_event_handler(void *handle, uint8_t *event_buf,
+						uint32_t len);
 #endif

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

@@ -8671,3 +8671,49 @@ int wma_unified_power_debug_stats_event_handler(void *handle,
 	return 0;
 }
 #endif
+
+int wma_chan_info_event_handler(void *handle, uint8_t *event_buf,
+				uint32_t len)
+{
+	tp_wma_handle wma = (tp_wma_handle)handle;
+	WMI_CHAN_INFO_EVENTID_param_tlvs *param_buf;
+	wmi_chan_info_event_fixed_param *event;
+	struct scan_chan_info buf;
+	tpAniSirGlobal mac = NULL;
+
+	WMA_LOGD("%s: Enter", __func__);
+
+	if (wma != NULL && wma->cds_context != NULL)
+		mac = (tpAniSirGlobal)cds_get_context(QDF_MODULE_ID_PE);
+
+	if (!mac) {
+		WMA_LOGE("%s: Invalid mac context", __func__);
+		return -EINVAL;
+	}
+
+	WMA_LOGD("%s: monitor:%d", __func__, mac->snr_monitor_enabled);
+	if (mac->snr_monitor_enabled && mac->chan_info_cb) {
+		param_buf =
+			(WMI_CHAN_INFO_EVENTID_param_tlvs *)event_buf;
+		if (!param_buf) {
+			WMA_LOGA("%s: Invalid chan info event", __func__);
+			return -EINVAL;
+		}
+
+		event = param_buf->fixed_param;
+		if (!event) {
+			WMA_LOGA("%s: Invalid fixed param", __func__);
+			return -EINVAL;
+		}
+		buf.tx_frame_count = event->tx_frame_cnt;
+		buf.clock_freq = event->mac_clk_mhz;
+		buf.cmd_flag = event->cmd_flags;
+		buf.freq = event->freq;
+		buf.noise_floor = event->noise_floor;
+		buf.cycle_count = event->cycle_count;
+		buf.rx_clear_count = event->rx_clear_count;
+		mac->chan_info_cb(&buf);
+	}
+
+	return 0;
+}

+ 4 - 0
core/wma/src/wma_main.c

@@ -2338,6 +2338,10 @@ QDF_STATUS wma_open(struct wlan_objmgr_psoc *psoc, void *cds_context,
 				WMI_VDEV_ENCRYPT_DECRYPT_DATA_RESP_EVENTID,
 				wma_encrypt_decrypt_msg_handler,
 				WMA_RX_SERIALIZER_CTX);
+	wmi_unified_register_event_handler(wma_handle->wmi_handle,
+					   WMI_CHAN_INFO_EVENTID,
+					   wma_chan_info_event_handler,
+					   WMA_RX_SERIALIZER_CTX);
 	wma_ndp_register_all_event_handlers(wma_handle);
 	wma_target_if_open(wma_handle);
 	target_if_open(wma_get_psoc_from_scn_handle);

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

@@ -260,6 +260,10 @@ QDF_STATUS wma_get_buf_start_scan_cmd(tp_wma_handle wma_handle,
 	/* add DS param IE in probe req frame */
 	cmd->scan_ctrl_flags |= WMI_SCAN_ADD_DS_IE_IN_PROBE_REQ;
 
+	/* set flag to get chan stats */
+	if (pMac->snr_monitor_enabled)
+		cmd->scan_ctrl_flags |= WMI_SCAN_CHAN_STAT_EVENT;
+
 	/* do not add OFDM rates in 11B mode */
 	if (scan_req->dot11mode != WNI_CFG_DOT11_MODE_11B)
 		cmd->scan_ctrl_flags |= WMI_SCAN_ADD_OFDM_RATES;