Эх сурвалжийг харах

qcacld-3.0: PNO Channel prediction

Reduce the number of channels to scan in PNO mode
based on the initial scan memory and the movement
of the client STA using Tanimoto distance

CRs-Fixed: 932355
Change-Id: I1b5448af801fb37324b77cd13c6009f1d859dd61
Varun Reddy Yeturu 9 жил өмнө
parent
commit
ac9d7ed0b4

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

@@ -2654,6 +2654,51 @@ enum dot11p_mode {
 #define CFG_ROAM_SCAN_HI_RSSI_UB_MIN               (-76)
 #define CFG_ROAM_SCAN_HI_RSSI_UB_MAX               (-30)
 #define CFG_ROAM_SCAN_HI_RSSI_UB_DEFAULT           (-45)
+/*
+ * gPNOChannelPrediction will allow user to enable/disable the
+ * PNO channel prediction feature.
+ * In current PNO implementation, scan is always done until all configured
+ * channels are scanned. If we can determine DUT is stationary based on
+ * scanning a subset of channels, we may cancel the remaining channels.
+ * Hence, we can save additional power consumption.
+ */
+#define CFG_PNO_CHANNEL_PREDICTION_NAME      "gPNOChannelPrediction"
+#define CFG_PNO_CHANNEL_PREDICTION_MIN       (0)
+#define CFG_PNO_CHANNEL_PREDICTION_MAX       (1)
+#define CFG_PNO_CHANNEL_PREDICTION_DEFAULT   (0)
+/*
+ * The top K number of channels are used for tanimoto distance
+ * calculation. These are the top channels on which the probability
+ * of finding the AP's is extremely high. This number is intended
+ * for tweaking the internal algorithm for experiments. This should
+ * not be changed externally.
+ */
+#define CFG_TOP_K_NUM_OF_CHANNELS_NAME      "gTopKNumOfChannels"
+#define CFG_TOP_K_NUM_OF_CHANNELS_MIN       (1)
+#define CFG_TOP_K_NUM_OF_CHANNELS_MAX       (5)
+#define CFG_TOP_K_NUM_OF_CHANNELS_DEFAULT   (3)
+/*
+ * This is the threshold value to determine that the STA is
+ * stationary. If the tanimoto distance is less than this
+ * value, then the device is considered to be stationary.
+ * This parameter is intended to tweak the internal algorithm
+ * for experiments. This should not be changed externally.
+ */
+#define CFG_STATIONARY_THRESHOLD_NAME      "gStationaryThreshold"
+#define CFG_STATIONARY_THRESHOLD_MIN       (0)
+#define CFG_STATIONARY_THRESHOLD_MAX       (100)
+#define CFG_STATIONARY_THRESHOLD_DEFAULT   (10)
+/*
+ * The following parameter is the periodic timer upon which
+ * a full scan needs to be triggered when PNO channel prediction
+ * feature is enabled. This parameter is intended to tweak the
+ * internal algortihm for experiments. This should not be changed
+ * externally.
+ */
+#define CFG_CHANNEL_PREDICTION_FULL_SCAN_MS_NAME      "gChPredictionFullScanMs"
+#define CFG_CHANNEL_PREDICTION_FULL_SCAN_MS_MIN       (30000)
+#define CFG_CHANNEL_PREDICTION_FULL_SCAN_MS_MAX       (0x7fffffff)
+#define CFG_CHANNEL_PREDICTION_FULL_SCAN_MS_DEFAULT   (60000)
 
 /*---------------------------------------------------------------------------
    Type declarations
@@ -3213,6 +3258,12 @@ struct hdd_config {
 	bool     tx_chain_mask_cck;
 	uint8_t  tx_chain_mask_1ss;
 	uint16_t  self_gen_frm_pwr;
+#ifdef FEATURE_WLAN_SCAN_PNO
+	bool pno_channel_prediction;
+	uint8_t top_k_num_of_channels;
+	uint8_t stationary_thresh;
+	uint32_t channel_prediction_full_scan;
+#endif
 };
 
 #define VAR_OFFSET(_Struct, _Var) (offsetof(_Struct, _Var))
@@ -3347,5 +3398,13 @@ CDF_STATUS hdd_string_to_u8_array(char *str, uint8_t *intArray, uint8_t *len,
 void hdd_cfg_print(hdd_context_t *pHddCtx);
 
 CDF_STATUS hdd_update_nss(hdd_context_t *hdd_ctx, uint8_t nss);
+#ifdef FEATURE_WLAN_SCAN_PNO
+void hdd_set_pno_channel_prediction_config(
+	tpSmeConfigParams sme_config, hdd_context_t *hdd_ctx);
+#else
+static inline void hdd_set_pno_channel_prediction_config(
+	tpSmeConfigParams sme_config, hdd_context_t *hdd_ctx)
+{}
+#endif
 
 #endif

+ 70 - 4
core/hdd/src/wlan_hdd_cfg.c

@@ -3465,6 +3465,36 @@ REG_TABLE_ENTRY g_registry_table[] = {
 		     CFG_DUAL_MAC_FEATURE_DISABLE_DEFAULT,
 		     CFG_DUAL_MAC_FEATURE_DISABLE_MIN,
 		     CFG_DUAL_MAC_FEATURE_DISABLE_MAX),
+#ifdef FEATURE_WLAN_SCAN_PNO
+	REG_VARIABLE(CFG_PNO_CHANNEL_PREDICTION_NAME, WLAN_PARAM_Integer,
+		     struct hdd_config, pno_channel_prediction,
+		     VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+		     CFG_PNO_CHANNEL_PREDICTION_DEFAULT,
+		     CFG_PNO_CHANNEL_PREDICTION_MIN,
+		     CFG_PNO_CHANNEL_PREDICTION_MAX),
+
+	REG_VARIABLE(CFG_TOP_K_NUM_OF_CHANNELS_NAME, WLAN_PARAM_Integer,
+		     struct hdd_config, top_k_num_of_channels,
+		     VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+		     CFG_TOP_K_NUM_OF_CHANNELS_DEFAULT,
+		     CFG_TOP_K_NUM_OF_CHANNELS_MIN,
+		     CFG_TOP_K_NUM_OF_CHANNELS_MAX),
+
+	REG_VARIABLE(CFG_STATIONARY_THRESHOLD_NAME, WLAN_PARAM_Integer,
+		     struct hdd_config, stationary_thresh,
+		     VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+		     CFG_STATIONARY_THRESHOLD_DEFAULT,
+		     CFG_STATIONARY_THRESHOLD_MIN,
+		     CFG_STATIONARY_THRESHOLD_MAX),
+
+	REG_VARIABLE(CFG_CHANNEL_PREDICTION_FULL_SCAN_MS_NAME,
+		     WLAN_PARAM_Integer,
+		     struct hdd_config, channel_prediction_full_scan,
+		     VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+		     CFG_CHANNEL_PREDICTION_FULL_SCAN_MS_DEFAULT,
+		     CFG_CHANNEL_PREDICTION_FULL_SCAN_MS_MIN,
+		     CFG_CHANNEL_PREDICTION_FULL_SCAN_MS_MAX),
+#endif
 
 	REG_VARIABLE(CFG_TX_CHAIN_MASK_CCK, WLAN_PARAM_Integer,
 		     struct hdd_config, tx_chain_mask_cck,
@@ -5006,6 +5036,20 @@ void hdd_cfg_print(hdd_context_t *pHddCtx)
 		  "Name = [%s] value = [%u]",
 		  CFG_DUAL_MAC_FEATURE_DISABLE,
 		  pHddCtx->config->dual_mac_feature_disable);
+#ifdef FEATURE_WLAN_SCAN_PNO
+	hddLog(LOGE, "Name = [%s] Value = [%u]",
+			CFG_PNO_CHANNEL_PREDICTION_NAME,
+			pHddCtx->config->pno_channel_prediction);
+	hddLog(LOGE, "Name = [%s] Value = [%u]",
+			CFG_TOP_K_NUM_OF_CHANNELS_NAME,
+			pHddCtx->config->top_k_num_of_channels);
+	hddLog(LOGE, "Name = [%s] Value = [%u]",
+			CFG_STATIONARY_THRESHOLD_NAME,
+			pHddCtx->config->stationary_thresh);
+	hddLog(LOGE, "Name = [%s] Value = [%u]",
+			CFG_CHANNEL_PREDICTION_FULL_SCAN_MS_NAME,
+			pHddCtx->config->channel_prediction_full_scan);
+#endif
 }
 
 
@@ -6088,7 +6132,31 @@ bool hdd_update_config_dat(hdd_context_t *pHddCtx)
 	}
 	return fStatus;
 }
-
+#ifdef FEATURE_WLAN_SCAN_PNO
+/**
+ * hdd_set_pno_channel_prediction_config() - Set PNO configuration
+ * @sme_config:         Config params from SME Context
+ * @hdd_ctx:            Config params from HDD Context
+ *
+ * Copy the PNO Channel prediction feature configuration parameters
+ * from HDD context to SME context.
+ *
+ * Return: None
+ */
+void hdd_set_pno_channel_prediction_config(
+		tpSmeConfigParams sme_config, hdd_context_t *hdd_ctx)
+{
+	sme_config->dual_mac_feature_disable =
+		hdd_ctx->config->dual_mac_feature_disable;
+	sme_config->pno_channel_prediction =
+		hdd_ctx->config->pno_channel_prediction;
+	sme_config->top_k_num_of_channels =
+		hdd_ctx->config->top_k_num_of_channels;
+	sme_config->stationary_thresh = hdd_ctx->config->stationary_thresh;
+	sme_config->channel_prediction_full_scan =
+		hdd_ctx->config->channel_prediction_full_scan;
+}
+#endif
 /**
  * hdd_set_sme_config() -initializes the sme configuration parameters
  *
@@ -6392,9 +6460,7 @@ CDF_STATUS hdd_set_sme_config(hdd_context_t *pHddCtx)
 	/* Update 802.11p config */
 	smeConfig->csrConfig.enable_dot11p =
 		(pHddCtx->config->dot11p_mode != WLAN_HDD_11P_DISABLED);
-
-	smeConfig->dual_mac_feature_disable =
-		pHddCtx->config->dual_mac_feature_disable;
+	hdd_set_pno_channel_prediction_config(smeConfig, pHddCtx);
 
 	status = sme_update_config(pHddCtx->hHal, smeConfig);
 	if (!CDF_IS_STATUS_SUCCESS(status)) {

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

@@ -2715,6 +2715,12 @@ typedef struct sSirPNOScanReq {
 	uint8_t p24GProbeTemplate[SIR_PNO_MAX_PB_REQ_SIZE];
 	uint16_t us5GProbeTemplateLen;
 	uint8_t p5GProbeTemplate[SIR_PNO_MAX_PB_REQ_SIZE];
+#ifdef FEATURE_WLAN_SCAN_PNO
+	bool pno_channel_prediction;
+	uint8_t top_k_num_of_channels;
+	uint8_t stationary_thresh;
+	uint32_t channel_prediction_full_scan;
+#endif
 } tSirPNOScanReq, *tpSirPNOScanReq;
 
 /* Preferred Network Found Indication */

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

@@ -1263,6 +1263,12 @@ typedef struct tagCsrConfigParam {
 	/* 802.11p enable */
 	bool enable_dot11p;
 	uint8_t max_scan_count;
+#ifdef FEATURE_WLAN_SCAN_PNO
+	bool pno_channel_prediction;
+	uint8_t top_k_num_of_channels;
+	uint8_t stationary_thresh;
+	uint32_t channel_prediction_full_scan;
+#endif
 } tCsrConfigParam;
 
 /* Tush */

+ 6 - 0
core/sme/inc/csr_internal.h

@@ -645,6 +645,12 @@ typedef struct tagCsrConfig {
 	uint8_t is_sta_connection_in_5gz_enabled;
 	struct roam_ext_params roam_params;
 	bool sendDeauthBeforeCon;
+#ifdef FEATURE_WLAN_SCAN_PNO
+	bool pno_channel_prediction;
+	uint8_t top_k_num_of_channels;
+	uint8_t stationary_thresh;
+	uint32_t channel_prediction_full_scan;
+#endif
 } tCsrConfig;
 
 typedef struct tagCsrChannelPowerInfo {

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

@@ -84,6 +84,8 @@
 
 /* Macro to indicate invalid no of tspecs */
 #define INVALID_TSPEC 100
+#define SME_CONFIG_TO_ROAM_CONFIG 1
+#define ROAM_CONFIG_TO_SME_CONFIG 2
 
 /*--------------------------------------------------------------------------
   Type declarations
@@ -122,6 +124,12 @@ typedef struct _smeConfigParams {
 	bool policy_manager_enabled;
 	uint32_t fine_time_meas_cap;
 	uint32_t dual_mac_feature_disable;
+#ifdef FEATURE_WLAN_SCAN_PNO
+	bool pno_channel_prediction;
+	uint8_t top_k_num_of_channels;
+	uint8_t stationary_thresh;
+	uint32_t channel_prediction_full_scan;
+#endif
 } tSmeConfigParams, *tpSmeConfigParams;
 
 #ifdef FEATURE_WLAN_TDLS
@@ -225,6 +233,16 @@ CDF_STATUS sme_close_session(tHalHandle hHal, uint8_t sessionId,
 		void *pContext);
 CDF_STATUS sme_update_roam_params(tHalHandle hHal, uint8_t session_id,
 		struct roam_ext_params roam_params_src, int update_param);
+#ifdef FEATURE_WLAN_SCAN_PNO
+void sme_update_roam_pno_channel_prediction_config(
+		tHalHandle hal, tpSmeConfigParams sme_config,
+		uint8_t copy_from_to);
+#else
+static inline void sme_update_roam_pno_channel_prediction_config(
+		tHalHandle hal, tpSmeConfigParams sme_config,
+		uint8_t copy_from_to)
+{}
+#endif
 CDF_STATUS sme_update_config(tHalHandle hHal,
 		tpSmeConfigParams pSmeConfigParams);
 

+ 9 - 3
core/sme/inc/sme_power_save_api.h

@@ -82,13 +82,19 @@ CDF_STATUS sme_ps_open_per_session(tHalHandle hal_ctx, uint32_t session_id);
 void sme_auto_ps_entry_timer_expired(void *ps_param);
 CDF_STATUS sme_ps_close(tHalHandle hal_ctx);
 CDF_STATUS sme_ps_close_per_session(tHalHandle hal_ctx, uint32_t sessionId);
-
+#ifdef FEATURE_WLAN_SCAN_PNO
+void sme_set_pno_channel_prediction(tpSirPNOScanReq request_buf,
+		tpAniSirGlobal mac_ctx);
 CDF_STATUS sme_set_ps_preferred_network_list(tHalHandle hal_ctx,
 		tpSirPNOScanReq request,
 		uint8_t session_id,
-		preferred_network_found_ind_cb
-		callback_routine,
+		preferred_network_found_ind_cb callback_routine,
 		void *callback_context);
+#else
+static inline void sme_set_pno_channel_prediction(void *request_buf,
+		tpAniSirGlobal mac_ctx)
+{}
+#endif
 
 CDF_STATUS sme_is_auto_ps_timer_running(tHalHandle hal_ctx,
 		uint32_t session_id);

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

@@ -1347,6 +1347,8 @@ CDF_STATUS sme_update_config(tHalHandle hHal, tpSmeConfigParams pSmeConfigParams
 	pMac->fine_time_meas_cap = pSmeConfigParams->fine_time_meas_cap;
 	pMac->dual_mac_feature_disable =
 				pSmeConfigParams->dual_mac_feature_disable;
+	sme_update_roam_pno_channel_prediction_config(pMac, pSmeConfigParams,
+			SME_CONFIG_TO_ROAM_CONFIG);
 
 	return status;
 }
@@ -4188,6 +4190,8 @@ CDF_STATUS sme_get_config_param(tHalHandle hHal, tSmeConfigParams *pParam)
 		pParam->enable5gEBT = pMac->enable5gEBT;
 		pParam->f_sta_miracast_mcc_rest_time_val =
 			pMac->f_sta_miracast_mcc_rest_time_val;
+		sme_update_roam_pno_channel_prediction_config(pMac, pParam,
+				ROAM_CONFIG_TO_SME_CONFIG);
 		sme_release_global_lock(&pMac->sme);
 	}
 
@@ -6722,6 +6726,43 @@ uint16_t sme_check_concurrent_channel_overlap(tHalHandle hHal, uint16_t sap_ch,
 #endif
 
 #ifdef FEATURE_WLAN_SCAN_PNO
+/**
+ * sme_update_roam_pno_channel_prediction_config() - Update PNO config
+ * @sme_config:      config from SME context
+ * @hal:             Global Hal handle
+ * @copy_from_to:    Used to specify the source and destination
+ *
+ * Copy the PNO channel prediction configuration parameters from
+ * SME context to MAC context or vice-versa
+ *
+ * Return: None
+ */
+void sme_update_roam_pno_channel_prediction_config(
+		tHalHandle hal, tpSmeConfigParams sme_config,
+		uint8_t copy_from_to)
+{
+	tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
+	if (copy_from_to == SME_CONFIG_TO_ROAM_CONFIG) {
+		mac_ctx->roam.configParam.pno_channel_prediction =
+			sme_config->pno_channel_prediction;
+		mac_ctx->roam.configParam.top_k_num_of_channels =
+			sme_config->top_k_num_of_channels;
+		mac_ctx->roam.configParam.stationary_thresh =
+			sme_config->stationary_thresh;
+		mac_ctx->roam.configParam.channel_prediction_full_scan =
+			sme_config->channel_prediction_full_scan;
+	} else if (copy_from_to == ROAM_CONFIG_TO_SME_CONFIG) {
+		sme_config->pno_channel_prediction =
+			mac_ctx->roam.configParam.pno_channel_prediction;
+		sme_config->top_k_num_of_channels =
+			mac_ctx->roam.configParam.top_k_num_of_channels;
+		sme_config->stationary_thresh =
+			mac_ctx->roam.configParam.stationary_thresh;
+		sme_config->channel_prediction_full_scan =
+			mac_ctx->roam.configParam.channel_prediction_full_scan;
+	}
+
+}
 /******************************************************************************
 *
 * Name: sme_preferred_network_found_ind

+ 31 - 2
core/sme/src/common/sme_power_save.c

@@ -744,7 +744,36 @@ sme_prepare_probe_req_template(tpAniSirGlobal mac_ctx,
 	*pus_len = payload + sizeof(tSirMacMgmtHdr);
 	return eSIR_SUCCESS;
 } /* End sme_prepare_probe_req_template. */
-
+/**
+ * sme_set_pno_channel_prediction() - Prepare PNO buffer
+ * @request_buf:        Buffer to be filled up to send to WMA
+ * @mac_ctx:            MAC context
+ *
+ * Fill up the PNO buffer with the channel prediction configuration
+ * parameters and send them to WMA
+ *
+ * Return: None
+ **/
+void sme_set_pno_channel_prediction(tpSirPNOScanReq request_buf,
+		tpAniSirGlobal mac_ctx)
+{
+	request_buf->pno_channel_prediction =
+		mac_ctx->roam.configParam.pno_channel_prediction;
+	request_buf->top_k_num_of_channels =
+		mac_ctx->roam.configParam.top_k_num_of_channels;
+	request_buf->stationary_thresh =
+		mac_ctx->roam.configParam.stationary_thresh;
+	request_buf->channel_prediction_full_scan =
+		mac_ctx->roam.configParam.channel_prediction_full_scan;
+	CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG,
+			FL("channel_prediction: %d, top_k_num_of_channels: %d"),
+			request_buf->pno_channel_prediction,
+			request_buf->top_k_num_of_channels);
+	CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG,
+			FL("stationary_thresh: %d, ch_predict_full_scan: %d"),
+			request_buf->stationary_thresh,
+			request_buf->channel_prediction_full_scan);
+}
 CDF_STATUS sme_set_ps_preferred_network_list(tHalHandle hal_ctx,
 		tpSirPNOScanReq request,
 		uint8_t session_id,
@@ -877,7 +906,7 @@ CDF_STATUS sme_set_ps_preferred_network_list(tHalHandle hal_ctx,
 
 		request_buf->sessionId = session_id;
 	}
-
+	sme_set_pno_channel_prediction(request_buf, mac_ctx);
 	msg.type = WMA_SET_PNO_REQ;
 	msg.reserved = 0;
 	msg.bodyptr = request_buf;

+ 11 - 4
core/wma/inc/wma_internal.h

@@ -263,7 +263,17 @@ CDF_STATUS wma_pno_start(tp_wma_handle wma, tpSirPNOScanReq pno);
 CDF_STATUS wma_pno_stop(tp_wma_handle wma, uint8_t vdev_id);
 
 void wma_config_pno(tp_wma_handle wma, tpSirPNOScanReq pno);
-
+void wma_set_pno_channel_prediction(uint8_t *buf_ptr,
+		tpSirPNOScanReq pno);
+void wma_scan_cache_updated_ind(tp_wma_handle wma, uint8_t sessionId);
+#else
+static inline void wma_set_pno_channel_prediction(uint8_t *buf_ptr,
+		void *pno)
+{
+	WMA_LOGD("PNO Channel Prediction feature not supported");
+	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_FIXED_STRUC, 0);
+}
+#endif
 #if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
 CDF_STATUS wma_plm_start(tp_wma_handle wma, const tpSirPlmReq plm);
 
@@ -272,9 +282,6 @@ CDF_STATUS wma_plm_stop(tp_wma_handle wma, const tpSirPlmReq plm);
 void wma_config_plm(tp_wma_handle wma, tpSirPlmReq plm);
 #endif
 
-void wma_scan_cache_updated_ind(tp_wma_handle wma, uint8_t sessionId);
-#endif
-
 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
 void wma_set_ric_req(tp_wma_handle wma, void *msg, uint8_t is_add_ts);
 #endif

+ 63 - 6
core/wma/src/wma_scan_roam.c

@@ -3425,7 +3425,37 @@ send_resp:
 }
 
 #ifdef FEATURE_WLAN_SCAN_PNO
-
+/**
+ * wma_set_pno_channel_prediction() - Set PNO configuration
+ * @buf_ptr:      Buffer passed by upper layers
+ * @pno:          Buffer to be sent to the firmware
+ *
+ * Copy the PNO Channel prediction configuration parameters
+ * passed by the upper layers to a WMI format TLV and send it
+ * down to the firmware.
+ *
+ * Return: None
+ */
+void wma_set_pno_channel_prediction(uint8_t *buf_ptr,
+		tpSirPNOScanReq pno)
+{
+	nlo_channel_prediction_cfg *channel_prediction_cfg =
+		(nlo_channel_prediction_cfg *) buf_ptr;
+	WMITLV_SET_HDR(&channel_prediction_cfg->tlv_header,
+			WMITLV_TAG_ARRAY_BYTE,
+			WMITLV_GET_STRUCT_TLVLEN(nlo_channel_prediction_cfg));
+	channel_prediction_cfg->enable = pno->pno_channel_prediction;
+	channel_prediction_cfg->top_k_num = pno->top_k_num_of_channels;
+	channel_prediction_cfg->stationary_threshold = pno->stationary_thresh;
+	channel_prediction_cfg->full_scan_period_ms =
+		pno->channel_prediction_full_scan;
+	buf_ptr += sizeof(nlo_channel_prediction_cfg);
+	WMA_LOGD("enable: %d, top_k_num: %d, stat_thresh: %d, full_scan: %d",
+			channel_prediction_cfg->enable,
+			channel_prediction_cfg->top_k_num,
+			channel_prediction_cfg->stationary_threshold,
+			channel_prediction_cfg->full_scan_period_ms);
+}
 /**
  * wma_pno_start() - PNO start request
  * @wma: wma handle
@@ -3447,13 +3477,19 @@ CDF_STATUS wma_pno_start(tp_wma_handle wma, tpSirPNOScanReq pno)
 
 	WMA_LOGD("PNO Start");
 
-	len = sizeof(*cmd) + WMI_TLV_HDR_SIZE + /* TLV place holder for array of structures nlo_configured_parameters(nlo_list) */
-	      WMI_TLV_HDR_SIZE; /* TLV place holder for array of uint32_t channel_list */
+	/*
+	 * TLV place holder for array nlo_configured_parameters(nlo_list)
+	 * TLV place holder for array of uint32_t channel_list
+	 * TLV place holder for chnnl prediction cfg
+	 */
+	len = sizeof(*cmd) +
+		WMI_TLV_HDR_SIZE + WMI_TLV_HDR_SIZE + WMI_TLV_HDR_SIZE;
 
 	len += sizeof(uint32_t) * CDF_MIN(pno->aNetworks[0].ucChannelCount,
 					  WMI_NLO_MAX_CHAN);
 	len += sizeof(nlo_configured_parameters) *
 	       CDF_MIN(pno->ucNetworksCount, WMI_NLO_MAX_SSIDS);
+	len += sizeof(nlo_channel_prediction_cfg);
 
 	buf = wmi_buf_alloc(wma->wmi_handle, len);
 	if (!buf) {
@@ -3540,7 +3576,11 @@ CDF_STATUS wma_pno_start(tp_wma_handle wma, tpSirPNOScanReq pno)
 		WMA_LOGD("Ch[%d]: %d MHz", i, channel_list[i]);
 	}
 	buf_ptr += cmd->num_of_channels * sizeof(uint32_t);
-
+	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
+			sizeof(nlo_channel_prediction_cfg));
+	buf_ptr += WMI_TLV_HDR_SIZE;
+	wma_set_pno_channel_prediction(buf_ptr, pno);
+	buf_ptr += WMI_TLV_HDR_SIZE;
 	/* TODO: Discrete firmware doesn't have command/option to configure
 	 * App IE which comes from wpa_supplicant as of part PNO start request.
 	 */
@@ -3585,8 +3625,12 @@ CDF_STATUS wma_pno_stop(tp_wma_handle wma, uint8_t vdev_id)
 
 	WMA_LOGD("PNO Stop");
 
-	len += WMI_TLV_HDR_SIZE + /* TLV place holder for array of structures nlo_configured_parameters(nlo_list) */
-	       WMI_TLV_HDR_SIZE;  /* TLV place holder for array of uint32_t channel_list */
+	/*
+	 * TLV place holder for array of structures nlo_configured_parameters
+	 * TLV place holder for array of uint32_t channel_list
+	 * TLV place holder for chnl prediction cfg
+	 */
+	len += WMI_TLV_HDR_SIZE + WMI_TLV_HDR_SIZE + WMI_TLV_HDR_SIZE;
 	buf = wmi_buf_alloc(wma->wmi_handle, len);
 	if (!buf) {
 		WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
@@ -3611,6 +3655,10 @@ CDF_STATUS wma_pno_stop(tp_wma_handle wma, uint8_t vdev_id)
 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 0);
 	buf_ptr += WMI_TLV_HDR_SIZE;
 
+	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
+	buf_ptr += WMI_TLV_HDR_SIZE;
+
+
 	ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
 				   WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID);
 	if (ret) {
@@ -6198,6 +6246,8 @@ CDF_STATUS wma_set_epno_network_list(tp_wma_handle wma,
 	len = sizeof(*cmd) + WMI_TLV_HDR_SIZE;
 	len += sizeof(nlo_configured_parameters) *
 				CDF_MIN(req->num_networks, WMI_NLO_MAX_SSIDS);
+	len += WMI_TLV_HDR_SIZE; /* TLV for channel_list */
+	len += WMI_TLV_HDR_SIZE; /* TLV for channel prediction cfg*/
 
 	buf = wmi_buf_alloc(wma->wmi_handle, len);
 	if (!buf) {
@@ -6260,6 +6310,13 @@ CDF_STATUS wma_set_epno_network_list(tp_wma_handle wma,
 		WMA_LOGD("Auth bit field (%u)",
 				nlo_list[i].auth_type.auth_type);
 	}
+
+	buf_ptr += cmd->no_of_ssids * sizeof(nlo_configured_parameters);
+	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 0);
+	buf_ptr += WMI_TLV_HDR_SIZE;
+
+	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
+	buf_ptr += WMI_TLV_HDR_SIZE;
 	ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
 				   WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID);
 	if (ret) {