diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index 9b8095a43e88..2f4be4dfd64a 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/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 diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index 734bd4ba4e5d..bf57226f1c2c 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/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)) { diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 4be197e1b629..28b2e8a7b965 100644 --- a/core/mac/inc/sir_api.h +++ b/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 */ diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h index 117240d9a75a..caa878751c4f 100644 --- a/core/sme/inc/csr_api.h +++ b/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 */ diff --git a/core/sme/inc/csr_internal.h b/core/sme/inc/csr_internal.h index e12fc255d23e..d06b9e23103a 100644 --- a/core/sme/inc/csr_internal.h +++ b/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 { diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index 1da4dcf32876..7c20e05f5c92 100644 --- a/core/sme/inc/sme_api.h +++ b/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); diff --git a/core/sme/inc/sme_power_save_api.h b/core/sme/inc/sme_power_save_api.h index e4fa67b7e167..95a2db56b0ac 100644 --- a/core/sme/inc/sme_power_save_api.h +++ b/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); diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 98a1f2607fc9..111433369f9b 100644 --- a/core/sme/src/common/sme_api.c +++ b/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 diff --git a/core/sme/src/common/sme_power_save.c b/core/sme/src/common/sme_power_save.c index a08ce2bdb4ec..ba4ec34ea34c 100644 --- a/core/sme/src/common/sme_power_save.c +++ b/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; diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index a737fa2f10ec..9e9ef25ba5f5 100644 --- a/core/wma/inc/wma_internal.h +++ b/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 diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c index 708202473f97..82627bc0757b 100644 --- a/core/wma/src/wma_scan_roam.c +++ b/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) {