diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index b21027ea765d..00159f743949 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -14133,6 +14133,189 @@ enum hdd_external_acs_freq_band { #define CFG_ENABLE_GCMP_MAX (1) #define CFG_ENABLE_GCMP_DEFAULT (0) +/* + * + * 11k_offload_enable_bitmask - Bitmask to enable 11k offload to FW + * @Min: 0 + * @Max: 1 + * @Default: 1 + * + * This ini is used to set which of the 11k features is offloaded to FW + * Currently Neighbor Report Request is supported for offload and is enabled + * by default + * B0: Offload 11k neighbor report requests + * B1-B31: Reserved + * + * Related : None + * + * Usage: External + * + * + */ + +#define CFG_OFFLOAD_11K_ENABLE_BITMASK_NAME "11k_offload_enable_bitmask" +#define CFG_OFFLOAD_11K_ENABLE_BITMASK_MIN (0) +#define CFG_OFFLOAD_11K_ENABLE_BITMASK_MAX (1) +#define CFG_OFFLOAD_11K_ENABLE_BITMASK_DEFAULT (1) + +#define OFFLOAD_11K_BITMASK_NEIGHBOR_REPORT_REQUEST 0x1 +/* + * + * nr_offload_params_bitmask - bitmask to specify which of the + * neighbor report offload params are valid in the ini + * frame + * @Min: 0 + * @Max: 63 + * @Default: 63 + * + * This ini specifies which of the neighbor report offload params are valid + * and should be considered by the FW. The bitmask is as follows + * B0: nr_offload_time_offset + * B1: nr_offload_low_rssi_offset + * B2: nr_offload_bmiss_count_trigger + * B3: nr_offload_per_threshold_offset + * B4: nr_offload_cache_timeout + * B5: nr_offload_max_req_cap + * B6-B7: Reserved + * + * Related : 11k_offload_enable_bitmask + * + * Usage: External + * + * + */ + +#define CFG_OFFLOAD_NEIGHBOR_REPORT_PARAMS_BITMASK_NAME \ + "nr_offload_params_bitmask" +#define CFG_OFFLOAD_NEIGHBOR_REPORT_PARAMS_BITMASK_MIN (0) +#define CFG_OFFLOAD_NEIGHBOR_REPORT_PARAMS_BITMASK_MAX (63) +#define CFG_OFFLOAD_NEIGHBOR_REPORT_PARAMS_BITMASK_DEFAULT (63) + +/* + * + * nr_offload_time_offset - time interval in seconds after the + * neighbor report offload command to send the first neighbor report request + * frame + * @Min: 30 + * @Max: 3600 + * @Default: 30 + * + * Related : nr_offload_params_bitmask + * + * Usage: External + * + * + */ +#define CFG_OFFLOAD_NEIGHBOR_REPORT_TIME_OFFSET_NAME \ + "nr_offload_time_offset" +#define CFG_OFFLOAD_NEIGHBOR_REPORT_TIME_OFFSET_MIN (0) +#define CFG_OFFLOAD_NEIGHBOR_REPORT_TIME_OFFSET_MAX (3600) +#define CFG_OFFLOAD_NEIGHBOR_REPORT_TIME_OFFSET_DEFAULT (30) + +/* + * + * nr_offload_low_rssi_offset - offset from the roam RSSI threshold + * to trigger the neighbor report request frame (in dBm) + * @Min: 4 + * @Max: 10 + * @Default: 4 + * + * Related : nr_offload_params_bitmask + * + * Usage: External + * + * + */ +#define CFG_OFFLOAD_NEIGHBOR_REPORT_LOW_RSSI_OFFSET_NAME \ + "nr_offload_low_rssi_offset" +#define CFG_OFFLOAD_NEIGHBOR_REPORT_LOW_RSSI_OFFSET_MIN (4) +#define CFG_OFFLOAD_NEIGHBOR_REPORT_LOW_RSSI_OFFSET_MAX (10) +#define CFG_OFFLOAD_NEIGHBOR_REPORT_LOW_RSSI_OFFSET_DEFAULT (4) + +/* + * + * nr_offload_bmiss_count_trigger - Number of beacon miss events to + * trigger a neighbor report request frame + * @Min: 1 + * @Max: 5 + * @Default: 1 + * + * Related : nr_offload_params_bitmask + * + * Usage: External + * + * + */ +#define CFG_OFFLOAD_NEIGHBOR_REPORT_BMISS_COUNT_TRIGGER_NAME \ + "nr_offload_bmiss_count_trigger" +#define CFG_OFFLOAD_NEIGHBOR_REPORT_BMISS_COUNT_TRIGGER_MIN (1) +#define CFG_OFFLOAD_NEIGHBOR_REPORT_BMISS_COUNT_TRIGGER_MAX (5) +#define CFG_OFFLOAD_NEIGHBOR_REPORT_BMISS_COUNT_TRIGGER_DEFAULT (1) + +/* + * + * nr_offload_per_threshold_offset - offset from PER threshold to + * trigger a neighbor report request frame (in %) + * @Min: 5 + * @Max: 20 + * @Default: 5 + * + * This ini is used to set the neighbor report offload parameter: + * + * Related : nr_offload_params_bitmask + * + * Usage: External + * + * + */ +#define CFG_OFFLOAD_NEIGHBOR_REPORT_PER_THRESHOLD_OFFSET_NAME \ + "nr_offload_per_threshold_offset" +#define CFG_OFFLOAD_NEIGHBOR_REPORT_PER_THRESHOLD_OFFSET_MIN (5) +#define CFG_OFFLOAD_NEIGHBOR_REPORT_PER_THRESHOLD_OFFSET_MAX (20) +#define CFG_OFFLOAD_NEIGHBOR_REPORT_PER_THRESHOLD_OFFSET_DEFAULT (5) + +/* + * + * nr_offload_cache_timeout - time in seconds after which the + * neighbor report cache is marked as timed out and any of the triggers would + * cause a neighbor report request frame to be sent. + * @Min: 300 + * @Max: 86400 + * @Default: 1200 + * + * Related : nr_offload_params_bitmask + * + * Usage: External + * + * + */ +#define CFG_OFFLOAD_NEIGHBOR_REPORT_CACHE_TIMEOUT_NAME \ + "nr_offload_cache_timeout" +#define CFG_OFFLOAD_NEIGHBOR_REPORT_CACHE_TIMEOUT_MIN (300) +#define CFG_OFFLOAD_NEIGHBOR_REPORT_CACHE_TIMEOUT_MAX (86400) +#define CFG_OFFLOAD_NEIGHBOR_REPORT_CACHE_TIMEOUT_DEFAULT (1200) + +/* + * + * nr_offload_max_req_cap - Max number of neighbor + * report requests that can be sent to a connected peer in the current session. + * This counter is reset once a successful roam happens or at cache timeout + * @Min: 3 + * @Max: 10 + * @Default: 3 + * + * Related : nr_offload_params_bitmask + * + * Usage: External + * + * + */ +#define CFG_OFFLOAD_NEIGHBOR_REPORT_MAX_REQ_CAP_NAME \ + "nr_offload_max_req_cap" +#define CFG_OFFLOAD_NEIGHBOR_REPORT_MAX_REQ_CAP_MIN (3) +#define CFG_OFFLOAD_NEIGHBOR_REPORT_MAX_REQ_CAP_MAX (300) +#define CFG_OFFLOAD_NEIGHBOR_REPORT_MAX_REQ_CAP_DEFAULT (3) + /* * Type declarations */ @@ -15033,6 +15216,15 @@ struct hdd_config { uint32_t btm_max_attempt_cnt; uint32_t btm_sticky_time; bool gcmp_enabled; + bool is_11k_offload_supported; + uint32_t offload_11k_enable_bitmask; + uint32_t neighbor_report_offload_params_bitmask; + uint32_t neighbor_report_offload_time_offset; + uint32_t neighbor_report_offload_low_rssi_offset; + uint32_t neighbor_report_offload_bmiss_count_trigger; + uint32_t neighbor_report_offload_per_threshold_offset; + uint32_t neighbor_report_offload_cache_timeout; + uint32_t neighbor_report_offload_max_req_cap; }; #define VAR_OFFSET(_Struct, _Var) (offsetof(_Struct, _Var)) diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index 19c5c28352d5..9787d07d5b37 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -5453,6 +5453,72 @@ struct reg_table_entry g_registry_table[] = { CFG_ENABLE_GCMP_DEFAULT, CFG_ENABLE_GCMP_MIN, CFG_ENABLE_GCMP_MAX), + + REG_VARIABLE(CFG_OFFLOAD_11K_ENABLE_BITMASK_NAME, + WLAN_PARAM_Integer, + struct hdd_config, offload_11k_enable_bitmask, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_OFFLOAD_11K_ENABLE_BITMASK_DEFAULT, + CFG_OFFLOAD_11K_ENABLE_BITMASK_MIN, + CFG_OFFLOAD_11K_ENABLE_BITMASK_MAX), + + REG_VARIABLE(CFG_OFFLOAD_NEIGHBOR_REPORT_PARAMS_BITMASK_NAME, + WLAN_PARAM_Integer, + struct hdd_config, neighbor_report_offload_params_bitmask, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_OFFLOAD_NEIGHBOR_REPORT_PARAMS_BITMASK_DEFAULT, + CFG_OFFLOAD_NEIGHBOR_REPORT_PARAMS_BITMASK_MIN, + CFG_OFFLOAD_NEIGHBOR_REPORT_PARAMS_BITMASK_MAX), + + REG_VARIABLE(CFG_OFFLOAD_NEIGHBOR_REPORT_TIME_OFFSET_NAME, + WLAN_PARAM_Integer, + struct hdd_config, neighbor_report_offload_time_offset, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_OFFLOAD_NEIGHBOR_REPORT_TIME_OFFSET_DEFAULT, + CFG_OFFLOAD_NEIGHBOR_REPORT_TIME_OFFSET_MIN, + CFG_OFFLOAD_NEIGHBOR_REPORT_TIME_OFFSET_MAX), + + REG_VARIABLE(CFG_OFFLOAD_NEIGHBOR_REPORT_LOW_RSSI_OFFSET_NAME, + WLAN_PARAM_Integer, + struct hdd_config, neighbor_report_offload_low_rssi_offset, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_OFFLOAD_NEIGHBOR_REPORT_LOW_RSSI_OFFSET_DEFAULT, + CFG_OFFLOAD_NEIGHBOR_REPORT_LOW_RSSI_OFFSET_MIN, + CFG_OFFLOAD_NEIGHBOR_REPORT_LOW_RSSI_OFFSET_MAX), + + REG_VARIABLE(CFG_OFFLOAD_NEIGHBOR_REPORT_BMISS_COUNT_TRIGGER_NAME, + WLAN_PARAM_Integer, + struct hdd_config, + neighbor_report_offload_bmiss_count_trigger, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_OFFLOAD_NEIGHBOR_REPORT_BMISS_COUNT_TRIGGER_DEFAULT, + CFG_OFFLOAD_NEIGHBOR_REPORT_BMISS_COUNT_TRIGGER_MIN, + CFG_OFFLOAD_NEIGHBOR_REPORT_BMISS_COUNT_TRIGGER_MAX), + + REG_VARIABLE(CFG_OFFLOAD_NEIGHBOR_REPORT_PER_THRESHOLD_OFFSET_NAME, + WLAN_PARAM_Integer, + struct hdd_config, + neighbor_report_offload_per_threshold_offset, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_OFFLOAD_NEIGHBOR_REPORT_PER_THRESHOLD_OFFSET_DEFAULT, + CFG_OFFLOAD_NEIGHBOR_REPORT_PER_THRESHOLD_OFFSET_MIN, + CFG_OFFLOAD_NEIGHBOR_REPORT_PER_THRESHOLD_OFFSET_MAX), + + REG_VARIABLE(CFG_OFFLOAD_NEIGHBOR_REPORT_CACHE_TIMEOUT_NAME, + WLAN_PARAM_Integer, + struct hdd_config, neighbor_report_offload_cache_timeout, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_OFFLOAD_NEIGHBOR_REPORT_CACHE_TIMEOUT_DEFAULT, + CFG_OFFLOAD_NEIGHBOR_REPORT_CACHE_TIMEOUT_MIN, + CFG_OFFLOAD_NEIGHBOR_REPORT_CACHE_TIMEOUT_MAX), + + REG_VARIABLE(CFG_OFFLOAD_NEIGHBOR_REPORT_MAX_REQ_CAP_NAME, + WLAN_PARAM_Integer, + struct hdd_config, neighbor_report_offload_max_req_cap, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_OFFLOAD_NEIGHBOR_REPORT_MAX_REQ_CAP_DEFAULT, + CFG_OFFLOAD_NEIGHBOR_REPORT_MAX_REQ_CAP_MIN, + CFG_OFFLOAD_NEIGHBOR_REPORT_MAX_REQ_CAP_MAX), }; @@ -6366,6 +6432,42 @@ static void hdd_cfg_print_sae(struct hdd_context *hdd_ctx) } #endif +/** + * hdd_cgf_print_11k_offload_params() - Print 11k offload related parameters + * @hdd_ctx: Pointer to HDD context + * + * Return: None + */ +static +void hdd_cfg_print_11k_offload_params(struct hdd_context *hdd_ctx) +{ + hdd_debug("Name = [%s] value = [%u]", + CFG_OFFLOAD_11K_ENABLE_BITMASK_NAME, + hdd_ctx->config->offload_11k_enable_bitmask); + hdd_debug("Name = [%s] value = [%u]", + CFG_OFFLOAD_NEIGHBOR_REPORT_PARAMS_BITMASK_NAME, + hdd_ctx->config->neighbor_report_offload_params_bitmask); + hdd_debug("Name = [%s] value = [%u]", + CFG_OFFLOAD_NEIGHBOR_REPORT_TIME_OFFSET_NAME, + hdd_ctx->config->neighbor_report_offload_time_offset); + hdd_debug("Name = [%s] value = [%u]", + CFG_OFFLOAD_NEIGHBOR_REPORT_LOW_RSSI_OFFSET_NAME, + hdd_ctx->config->neighbor_report_offload_low_rssi_offset); + hdd_debug("Name = [%s] value = [%u]", + CFG_OFFLOAD_NEIGHBOR_REPORT_BMISS_COUNT_TRIGGER_NAME, + hdd_ctx->config->neighbor_report_offload_bmiss_count_trigger); + hdd_debug("Name = [%s] value = [%u]", + CFG_OFFLOAD_NEIGHBOR_REPORT_PER_THRESHOLD_OFFSET_NAME, + hdd_ctx->config-> + neighbor_report_offload_per_threshold_offset); + hdd_debug("Name = [%s] value = [%u]", + CFG_OFFLOAD_NEIGHBOR_REPORT_CACHE_TIMEOUT_NAME, + hdd_ctx->config->neighbor_report_offload_cache_timeout); + hdd_debug("Name = [%s] value = [%u]", + CFG_OFFLOAD_NEIGHBOR_REPORT_MAX_REQ_CAP_NAME, + hdd_ctx->config->neighbor_report_offload_max_req_cap); +} + /** * hdd_cfg_print() - print the hdd configuration * @iniTable: pointer to hdd context @@ -7307,6 +7409,8 @@ void hdd_cfg_print(struct hdd_context *hdd_ctx) hdd_debug("Name = [%s] value = [%d]", CFG_ENABLE_GCMP_NAME, hdd_ctx->config->gcmp_enabled); + + hdd_cfg_print_11k_offload_params(hdd_ctx); } @@ -8690,6 +8794,36 @@ static void hdd_update_bss_score_params(struct hdd_config *config, config->oce_wan_score_slots15_to_12); } +/** + * hdd_update_11k_offload_params() - initializes the 11k offload related params + * + * @config: pointer to hdd_config structure + * @csr_config: pointer to the csr config structure + * + * Return: None + */ +static +void hdd_update_11k_offload_params(struct hdd_config *config, + tCsrConfigParam *csr_config) +{ + csr_config->offload_11k_enable_bitmask = + config->offload_11k_enable_bitmask; + csr_config->neighbor_report_offload.params_bitmask = + config->neighbor_report_offload_params_bitmask; + csr_config->neighbor_report_offload.time_offset = + config->neighbor_report_offload_time_offset; + csr_config->neighbor_report_offload.low_rssi_offset = + config->neighbor_report_offload_low_rssi_offset; + csr_config->neighbor_report_offload.bmiss_count_trigger = + config->neighbor_report_offload_bmiss_count_trigger; + csr_config->neighbor_report_offload.per_threshold_offset = + config->neighbor_report_offload_per_threshold_offset; + csr_config->neighbor_report_offload.neighbor_report_cache_timeout = + config->neighbor_report_offload_cache_timeout; + csr_config->neighbor_report_offload.max_neighbor_report_req_cap = + config->neighbor_report_offload_max_req_cap; +} + /** * hdd_set_sme_config() -initializes the sme configuration parameters * @@ -9150,6 +9284,9 @@ QDF_STATUS hdd_set_sme_config(struct hdd_context *hdd_ctx) hdd_update_bss_score_params(hdd_ctx->config, &smeConfig->csrConfig.bss_score_params); + hdd_update_11k_offload_params(hdd_ctx->config, + &smeConfig->csrConfig); + status = sme_update_config(hdd_ctx->hHal, smeConfig); if (!QDF_IS_STATUS_SUCCESS(status)) hdd_err("sme_update_config() failure: %d", status); diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index edc42b197d07..556b1fd14901 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -1875,6 +1875,9 @@ void hdd_update_tgt_cfg(void *context, void *param) hdd_ctx->is_fils_roaming_supported = cfg->services.is_fils_roaming_supported; + hdd_ctx->config->is_11k_offload_supported = + cfg->services.is_11k_offload_supported; + /* * now overwrite the target band capability with INI * setting if INI setting is a subset diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index 93164fe72e63..0ee4a92c90fa 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -6941,9 +6941,11 @@ static int __iw_setchar_getnone(struct net_device *dev, tRrmNeighborRspCallbackInfo callbackInfo; if (pConfig->fRrmEnable) { - hdd_debug("Neighbor Request"); + neighborReq.neighbor_report_offload = false; neighborReq.no_ssid = (s_priv_data.length - 1) ? false : true; + hdd_debug("Neighbor Request ssid present %d", + neighborReq.no_ssid); if (!neighborReq.no_ssid) { neighborReq.ssid.length = (s_priv_data.length - 1) > @@ -6953,14 +6955,25 @@ static int __iw_setchar_getnone(struct net_device *dev, neighborReq.ssid.length); } + /* + * If 11k offload is supported by FW and enabled + * in the ini, set the offload to true + */ + if (hdd_ctx->config->is_11k_offload_supported && + (hdd_ctx->config->offload_11k_enable_bitmask & + OFFLOAD_11K_BITMASK_NEIGHBOR_REPORT_REQUEST)) { + hdd_debug("Neighbor report offloaded to FW"); + neighborReq.neighbor_report_offload = true; + } + callbackInfo.neighborRspCallback = NULL; callbackInfo.neighborRspCallbackContext = NULL; - callbackInfo.timeout = 5000; /* 5 seconds */ - sme_neighbor_report_request(WLAN_HDD_GET_HAL_CTX - (adapter), - adapter->session_id, - &neighborReq, - &callbackInfo); + callbackInfo.timeout = 5000; /* 5 seconds */ + sme_neighbor_report_request( + WLAN_HDD_GET_HAL_CTX(adapter), + adapter->session_id, + &neighborReq, + &callbackInfo); } else { hdd_err("Ignoring neighbor request as RRM not enabled"); ret = -EINVAL; diff --git a/core/mac/inc/ani_global.h b/core/mac/inc/ani_global.h index 4660bf4eafa5..476319a0cf0d 100644 --- a/core/mac/inc/ani_global.h +++ b/core/mac/inc/ani_global.h @@ -959,6 +959,9 @@ typedef struct sAniSirGlobal { uint32_t peer_rssi; uint32_t peer_txrate; uint32_t peer_rxrate; + + /* 11k Offload Support */ + bool is_11k_offload_supported; } tAniSirGlobal; diff --git a/core/mac/src/include/sir_params.h b/core/mac/src/include/sir_params.h index 87ad81f6dd17..f25d0675abe4 100644 --- a/core/mac/src/include/sir_params.h +++ b/core/mac/src/include/sir_params.h @@ -694,6 +694,8 @@ struct sir_mgmt_msg { #define SIR_HAL_HLP_IE_INFO (SIR_HAL_ITC_MSG_TYPES_BEGIN + 392) #define SIR_HAL_OBSS_DETECTION_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 393) #define SIR_HAL_OBSS_DETECTION_INFO (SIR_HAL_ITC_MSG_TYPES_BEGIN + 394) +#define SIR_HAL_SET_11K_OFFLOAD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 395) +#define SIR_HAL_INVOKE_NEIGHBOR_REPORT (SIR_HAL_ITC_MSG_TYPES_BEGIN + 396) #define SIR_HAL_MSG_TYPES_END (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF) /* CFG message types */ diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h index 2526476d7303..296f103671e2 100644 --- a/core/sme/inc/csr_api.h +++ b/core/sme/inc/csr_api.h @@ -1140,6 +1140,32 @@ struct csr_mbo_thresholds { int8_t mbo_candidate_rssi_btc_thres; }; +/** + * struct csr_neighbor_report_offload_params - neighbor report offload params + * @params_bitmask: bitmask to specify which of the below are enabled + * @time_offset: time offset after 11k offload command to trigger a neighbor + * report request (in seconds) + * @low_rssi_offset: Offset from rssi threshold to trigger neighbor + * report request (in dBm) + * @bmiss_count_trigger: Number of beacon miss events to trigger neighbor + * report request + * @per_threshold_offset: offset from PER threshold to trigger neighbor + * report request (in %) + * @neighbor_report_cache_timeout: timeout after which new trigger can enable + * sending of a neighbor report request (in seconds) + * @max_neighbor_report_req_cap: max number of neighbor report requests that + * can be sent to the peer in the current session + */ +struct csr_neighbor_report_offload_params { + uint8_t params_bitmask; + uint32_t time_offset; + uint32_t low_rssi_offset; + uint32_t bmiss_count_trigger; + uint32_t per_threshold_offset; + uint32_t neighbor_report_cache_timeout; + uint32_t max_neighbor_report_req_cap; +}; + typedef struct tagCsrConfigParam { uint32_t FragmentationThreshold; /* keep this uint32_t. This gets converted to ePhyChannelBondState */ @@ -1377,6 +1403,8 @@ typedef struct tagCsrConfigParam { uint32_t btm_solicited_timeout; uint32_t btm_max_attempt_cnt; uint32_t btm_sticky_time; + uint32_t offload_11k_enable_bitmask; + struct csr_neighbor_report_offload_params neighbor_report_offload; } tCsrConfigParam; /* Tush */ diff --git a/core/sme/inc/csr_internal.h b/core/sme/inc/csr_internal.h index 56dbcc808711..2b3c586aea36 100644 --- a/core/sme/inc/csr_internal.h +++ b/core/sme/inc/csr_internal.h @@ -448,6 +448,17 @@ struct csr_neighbor_roamconfig { int32_t nhi_rssi_scan_rssi_ub; }; +/* + * Neighbor Report Params Bitmask + */ +#define NEIGHBOR_REPORT_PARAMS_TIME_OFFSET 0x01 +#define NEIGHBOR_REPORT_PARAMS_LOW_RSSI_OFFSET 0x02 +#define NEIGHBOR_REPORT_PARAMS_BMISS_COUNT_TRIGGER 0x04 +#define NEIGHBOR_REPORT_PARAMS_PER_THRESHOLD_OFFSET 0x08 +#define NEIGHBOR_REPORT_PARAMS_CACHE_TIMEOUT 0x10 +#define NEIGHBOR_REPORT_PARAMS_MAX_REQ_CAP 0x20 +#define NEIGHBOR_REPORT_PARAMS_ALL 0x3F + struct csr_config { uint32_t agingCount; uint32_t FragmentationThreshold; @@ -641,6 +652,8 @@ struct csr_config { uint32_t btm_solicited_timeout; uint32_t btm_max_attempt_cnt; uint32_t btm_sticky_time; + uint32_t offload_11k_enable_bitmask; + struct csr_neighbor_report_offload_params neighbor_report_offload; }; struct csr_channel_powerinfo { diff --git a/core/sme/inc/csr_neighbor_roam.h b/core/sme/inc/csr_neighbor_roam.h index 22ef0c3c7834..9847e3956d73 100644 --- a/core/sme/inc/csr_neighbor_roam.h +++ b/core/sme/inc/csr_neighbor_roam.h @@ -426,4 +426,30 @@ QDF_STATUS csr_roam_stop_wait_for_key_timer(tpAniSirGlobal pMac); QDF_STATUS csr_roam_copy_connected_profile(tpAniSirGlobal pMac, uint32_t sessionId, tCsrRoamProfile *pDstProfile); +/** + * csr_invoke_neighbor_report_request - Send neighbor report invoke command to + * WMA + * @mac_ctx: MAC context + * @session_id: session id + * + * API called from IW to invoke neighbor report request to WMA then to FW + * + * Return: QDF_STATUS + */ +QDF_STATUS csr_invoke_neighbor_report_request(uint8_t session_id, + struct sRrmNeighborReq *neighbor_report_req, + bool send_resp_to_host); + +/** + * csr_send_11k_offload_params - Update 11K offload params to FW + * @mac_ctx: MAC context + * @session_id: session id + * + * API to update 11k offload params to WMA then to FW + * + * Return: QDF_STATUS + */ +QDF_STATUS csr_send_11k_offload_params(tpAniSirGlobal mac_ctx, + uint8_t session_id); + #endif /* CSR_NEIGHBOR_ROAM_H */ diff --git a/core/sme/inc/sme_rrm_internal.h b/core/sme/inc/sme_rrm_internal.h index 91da47cf32cf..ae3c95e0aea9 100644 --- a/core/sme/inc/sme_rrm_internal.h +++ b/core/sme/inc/sme_rrm_internal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2012, 2014-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2012, 2014-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -99,6 +99,7 @@ typedef struct sRrmSMEContext { typedef struct sRrmNeighborReq { uint8_t no_ssid; tSirMacSSid ssid; + bool neighbor_report_offload; } tRrmNeighborReq, *tpRrmNeighborReq; #endif /* #if !defined( __SMERRMINTERNAL_H ) */ diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 04a54cfde1cd..8e945466839b 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -4905,6 +4905,13 @@ QDF_STATUS sme_neighbor_report_request(tHalHandle hHal, uint8_t sessionId, TRACE_CODE_SME_RX_HDD_NEIGHBOR_REPORTREQ, NO_SESSION, 0)); + if (pRrmNeighborReq->neighbor_report_offload) { + status = csr_invoke_neighbor_report_request(sessionId, + pRrmNeighborReq, + false); + return status; + } + if (QDF_STATUS_SUCCESS == sme_acquire_global_lock(&pMac->sme)) { status = sme_rrm_neighbor_report_request(hHal, sessionId, @@ -13795,9 +13802,11 @@ void sme_update_tgt_services(tHalHandle hal, struct wma_tgt_services *cfg) FL("mac_ctx->pmf_offload: %d"), mac_ctx->pmf_offload); mac_ctx->is_fils_roaming_supported = cfg->is_fils_roaming_supported; - sme_debug("mac_ctx->pmf_offload: %d fils_roam support %d", - mac_ctx->pmf_offload, mac_ctx->is_fils_roaming_supported); - + mac_ctx->is_11k_offload_supported = + cfg->is_11k_offload_supported; + sme_debug("pmf_offload: %d fils_roam support %d 11k_offload %d", + mac_ctx->pmf_offload, mac_ctx->is_fils_roaming_supported, + mac_ctx->is_11k_offload_supported); } /** diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 4cc3c3a0d037..406a62ebf999 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -2536,6 +2536,40 @@ static inline void csr_update_session_he_cap(tpAniSirGlobal mac_ctx, #endif +/** + * csr_set_11k_offload_config_param() - Update 11k neighbor report config + * + * @csr_config: pointer to csr_config in MAC context + * @pParam: pointer to config params from HDD + * + * Return: none + */ +static +void csr_set_11k_offload_config_param(struct csr_config *csr_config, + tCsrConfigParam *param) +{ + csr_config->offload_11k_enable_bitmask = + param->offload_11k_enable_bitmask; + csr_config->neighbor_report_offload.params_bitmask = + param->neighbor_report_offload.params_bitmask; + csr_config->neighbor_report_offload.time_offset = + param->neighbor_report_offload.time_offset; + csr_config->neighbor_report_offload.low_rssi_offset = + param->neighbor_report_offload.low_rssi_offset; + csr_config->neighbor_report_offload.bmiss_count_trigger = + param->neighbor_report_offload.bmiss_count_trigger; + csr_config->neighbor_report_offload.per_threshold_offset = + param->neighbor_report_offload.per_threshold_offset; + csr_config->neighbor_report_offload. + neighbor_report_cache_timeout = + param->neighbor_report_offload. + neighbor_report_cache_timeout; + csr_config->neighbor_report_offload. + max_neighbor_report_req_cap = + param->neighbor_report_offload. + max_neighbor_report_req_cap; +} + QDF_STATUS csr_change_default_config_param(tpAniSirGlobal pMac, tCsrConfigParam *pParam) { @@ -3064,10 +3098,44 @@ QDF_STATUS csr_change_default_config_param(tpAniSirGlobal pMac, pParam->btm_sticky_time; csr_update_he_config_param(pMac, pParam); + csr_set_11k_offload_config_param(&pMac->roam.configParam, + pParam); } return status; } +/** + * csr_get_11k_offload_config_param() - Get 11k neighbor report config + * + * @csr_config: pointer to csr_config in MAC context + * @pParam: pointer to config params from HDD + * + * Return: none + */ +static +void csr_get_11k_offload_config_param(struct csr_config *csr_config, + tCsrConfigParam *param) +{ + param->offload_11k_enable_bitmask = + csr_config->offload_11k_enable_bitmask; + param->neighbor_report_offload.params_bitmask = + csr_config->neighbor_report_offload.params_bitmask; + param->neighbor_report_offload.time_offset = + csr_config->neighbor_report_offload.time_offset; + param->neighbor_report_offload.low_rssi_offset = + csr_config->neighbor_report_offload.low_rssi_offset; + param->neighbor_report_offload.bmiss_count_trigger = + csr_config->neighbor_report_offload.bmiss_count_trigger; + param->neighbor_report_offload.per_threshold_offset = + csr_config->neighbor_report_offload.per_threshold_offset; + param->neighbor_report_offload.neighbor_report_cache_timeout = + csr_config->neighbor_report_offload. + neighbor_report_cache_timeout; + param->neighbor_report_offload.max_neighbor_report_req_cap = + csr_config->neighbor_report_offload. + max_neighbor_report_req_cap; +} + QDF_STATUS csr_get_config_param(tpAniSirGlobal pMac, tCsrConfigParam *pParam) { int i; @@ -3353,6 +3421,8 @@ QDF_STATUS csr_get_config_param(tpAniSirGlobal pMac, tCsrConfigParam *pParam) csr_get_he_config_param(pParam, pMac); + csr_get_11k_offload_config_param(&pMac->roam.configParam, pParam); + return QDF_STATUS_SUCCESS; } @@ -19191,6 +19261,177 @@ csr_roam_offload_scan(tpAniSirGlobal mac_ctx, uint8_t session_id, return status; } +#define NEIGHBOR_REPORT_PARAM_INVALID (0xFFFFFFFFU) + +QDF_STATUS csr_send_11k_offload_params(tpAniSirGlobal mac_ctx, + uint8_t session_id) +{ + struct csr_roam_session *session; + struct wmi_11k_offload_params *params; + struct scheduler_msg msg = {0}; + QDF_STATUS status; + struct csr_config *csr_config = &mac_ctx->roam.configParam; + struct csr_neighbor_report_offload_params *neighbor_report_offload = + &csr_config->neighbor_report_offload; + + if ((csr_config->offload_11k_enable_bitmask & + WMI_11K_OFFLOAD_BITMAP_NEIGHBOR_REPORT_REQ) == 0) { + sme_debug("Neighbor report offload not enabled"); + return QDF_STATUS_E_FAILURE; + } + + if ((neighbor_report_offload->params_bitmask & + NEIGHBOR_REPORT_PARAMS_ALL) == 0) { + sme_err("No valid neighbor report offload params %x", + neighbor_report_offload->params_bitmask); + return QDF_STATUS_E_FAILURE; + } + + status = sme_acquire_global_lock(&mac_ctx->sme); + if (QDF_IS_STATUS_ERROR(status)) { + sme_err("sme_acquire_global_lock failed"); + return status; + } + + session = CSR_GET_SESSION(mac_ctx, session_id); + if (!session) { + sme_release_global_lock(&mac_ctx->sme); + sme_err("Session not found"); + return QDF_STATUS_E_FAILURE; + } + + if (!session->connectedProfile.SSID.length) { + sme_err("SSID Len 0"); + sme_release_global_lock(&mac_ctx->sme); + return QDF_STATUS_E_FAILURE; + } + + params = qdf_mem_malloc(sizeof(*params)); + + if (!params) { + sme_release_global_lock(&mac_ctx->sme); + sme_err("Memory allocation failure"); + return QDF_STATUS_E_NOMEM; + } + + params->vdev_id = session_id; + params->offload_11k_bitmask = csr_config->offload_11k_enable_bitmask; + + /* + * First initialize all params to NEIGHBOR_REPORT_PARAM_INVALID + * Then set the values that are enabled + */ + params->neighbor_report_params.time_offset = + NEIGHBOR_REPORT_PARAM_INVALID; + params->neighbor_report_params.low_rssi_offset = + NEIGHBOR_REPORT_PARAM_INVALID; + params->neighbor_report_params.bmiss_count_trigger = + NEIGHBOR_REPORT_PARAM_INVALID; + params->neighbor_report_params.per_threshold_offset = + NEIGHBOR_REPORT_PARAM_INVALID; + params->neighbor_report_params.neighbor_report_cache_timeout = + NEIGHBOR_REPORT_PARAM_INVALID; + params->neighbor_report_params.max_neighbor_report_req_cap = + NEIGHBOR_REPORT_PARAM_INVALID; + + if (neighbor_report_offload->params_bitmask & + NEIGHBOR_REPORT_PARAMS_TIME_OFFSET) + params->neighbor_report_params.time_offset = + neighbor_report_offload->time_offset; + + if (neighbor_report_offload->params_bitmask & + NEIGHBOR_REPORT_PARAMS_LOW_RSSI_OFFSET) + params->neighbor_report_params.low_rssi_offset = + neighbor_report_offload->low_rssi_offset; + + if (neighbor_report_offload->params_bitmask & + NEIGHBOR_REPORT_PARAMS_BMISS_COUNT_TRIGGER) + params->neighbor_report_params.bmiss_count_trigger = + neighbor_report_offload->bmiss_count_trigger; + + if (neighbor_report_offload->params_bitmask & + NEIGHBOR_REPORT_PARAMS_PER_THRESHOLD_OFFSET) + params->neighbor_report_params.per_threshold_offset = + neighbor_report_offload->per_threshold_offset; + + if (neighbor_report_offload->params_bitmask & + NEIGHBOR_REPORT_PARAMS_CACHE_TIMEOUT) + params->neighbor_report_params.neighbor_report_cache_timeout = + neighbor_report_offload->neighbor_report_cache_timeout; + + if (neighbor_report_offload->params_bitmask & + NEIGHBOR_REPORT_PARAMS_MAX_REQ_CAP) + params->neighbor_report_params.max_neighbor_report_req_cap = + neighbor_report_offload->max_neighbor_report_req_cap; + + params->neighbor_report_params.ssid.length = + session->connectedProfile.SSID.length; + qdf_mem_copy(params->neighbor_report_params.ssid.mac_ssid, + session->connectedProfile.SSID.ssId, + session->connectedProfile.SSID.length); + sme_release_global_lock(&mac_ctx->sme); + + sme_debug("Sending SIR_HAL_SET_11K_OFFLOAD"); + + msg.type = SIR_HAL_SET_11K_OFFLOAD; + msg.reserved = 0; + msg.bodyptr = params; + + if (QDF_STATUS_SUCCESS != scheduler_post_msg(QDF_MODULE_ID_WMA, &msg)) { + sme_err("Not able to post message to WMA"); + qdf_mem_free(params); + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS csr_invoke_neighbor_report_request(uint8_t session_id, + struct sRrmNeighborReq *neighbor_report_req, + bool send_resp_to_host) +{ + struct wmi_invoke_neighbor_report_params *invoke_params; + struct scheduler_msg msg = {0}; + + if (!neighbor_report_req) { + sme_err("Invalid params"); + return QDF_STATUS_E_INVAL; + } + + invoke_params = qdf_mem_malloc(sizeof(*invoke_params)); + if (!invoke_params) { + sme_err("Memory allocation failure"); + return QDF_STATUS_E_NOMEM; + } + + invoke_params->vdev_id = session_id; + invoke_params->send_resp_to_host = send_resp_to_host; + + if (!neighbor_report_req->no_ssid) { + invoke_params->ssid.length = neighbor_report_req->ssid.length; + qdf_mem_copy(invoke_params->ssid.mac_ssid, + neighbor_report_req->ssid.ssId, + neighbor_report_req->ssid.length); + } else { + invoke_params->ssid.length = 0; + } + + sme_debug("Sending SIR_HAL_INVOKE_NEIGHBOR_REPORT"); + + msg.type = SIR_HAL_INVOKE_NEIGHBOR_REPORT; + msg.reserved = 0; + msg.bodyptr = invoke_params; + + if (QDF_STATUS_SUCCESS != scheduler_post_msg(QDF_MODULE_ID_WMA, &msg)) { + sme_err("Not able to post message to WMA"); + qdf_mem_free(invoke_params); + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} + + QDF_STATUS csr_roam_offload_scan_rsp_hdlr(tpAniSirGlobal pMac, tpSirRoamOffloadScanRsp scanOffloadRsp) diff --git a/core/sme/src/csr/csr_neighbor_roam.c b/core/sme/src/csr/csr_neighbor_roam.c index 6f4408155db6..a80446f87119 100644 --- a/core/sme/src/csr/csr_neighbor_roam.c +++ b/core/sme/src/csr/csr_neighbor_roam.c @@ -1136,7 +1136,6 @@ QDF_STATUS csr_neighbor_roam_indicate_connect( csr_neighbor_roam_reset_init_state_control_info(pMac, session_id); csr_neighbor_roam_info_ctx_init(pMac, session_id); - return status; } #endif @@ -1161,6 +1160,7 @@ QDF_STATUS csr_neighbor_roam_indicate_connect( csr_neighbor_roam_reset_init_state_control_info(pMac, session_id); csr_neighbor_roam_info_ctx_init(pMac, session_id); + csr_send_11k_offload_params(pMac, session_id); break; default: sme_err("Connect evt received in invalid state %s Ignoring", diff --git a/core/wma/inc/wma_tgt_cfg.h b/core/wma/inc/wma_tgt_cfg.h index 011ec3d1ef1f..65fba44bf52d 100644 --- a/core/wma/inc/wma_tgt_cfg.h +++ b/core/wma/inc/wma_tgt_cfg.h @@ -73,6 +73,7 @@ struct wma_tgt_services { bool get_peer_info_enabled; bool is_fils_roaming_supported; bool is_fw_mawc_capable; + bool is_11k_offload_supported; }; /** diff --git a/core/wma/inc/wma_types.h b/core/wma/inc/wma_types.h index c1586659e0fd..b8c9c9aa45a9 100644 --- a/core/wma/inc/wma_types.h +++ b/core/wma/inc/wma_types.h @@ -474,6 +474,8 @@ #define WMA_SET_LIMIT_OFF_CHAN SIR_HAL_SET_LIMIT_OFF_CHAN #define WMA_OBSS_DETECTION_REQ SIR_HAL_OBSS_DETECTION_REQ #define WMA_OBSS_DETECTION_INFO SIR_HAL_OBSS_DETECTION_INFO +#define WMA_SET_11K_OFFLOAD SIR_HAL_SET_11K_OFFLOAD +#define WMA_INVOKE_NEIGHBOR_REPORT SIR_HAL_INVOKE_NEIGHBOR_REPORT /* Bit 6 will be used to control BD rate for Management frames */ #define HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME 0x40 diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index ef4bf056bc53..9fd57e2fb0ee 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -4706,6 +4706,10 @@ static inline void wma_update_target_services(tp_wma_handle wh, wmi_service_mawc_support)) cfg->is_fw_mawc_capable = true; + if (WMI_SERVICE_EXT_IS_ENABLED(wh->wmi_service_bitmap, + wh->wmi_service_ext_bitmap, + WMI_SERVICE_11K_NEIGHBOUR_REPORT_SUPPORT)) + cfg->is_11k_offload_supported = true; } /** @@ -7398,6 +7402,59 @@ static void wma_set_del_pmkid_cache(WMA_HANDLE handle, WMA_LOGE("failed to send set/del pmkid cmd to fw"); } +/** + * wma_send_offload_11k_params() - API to send 11k offload params to FW + * @handle: WMA handle + * @params: Pointer to 11k offload params + * + * Return: None + */ +static +void wma_send_offload_11k_params(WMA_HANDLE handle, + struct wmi_11k_offload_params *params) +{ + QDF_STATUS status; + tp_wma_handle wma_handle = (tp_wma_handle) handle; + + if (!wma_handle || !wma_handle->wmi_handle) { + WMA_LOGE("WMA is closed, cannot send 11k offload cmd"); + return; + } + + status = wmi_unified_offload_11k_cmd(wma_handle->wmi_handle, params); + + if (status != QDF_STATUS_SUCCESS) + WMA_LOGE("failed to send 11k offload command"); +} + +/** + * wma_send_invoke_neighbor_report() - API to send invoke neighbor report + * command to fw + * + * @handle: WMA handle + * @params: Pointer to invoke neighbor report params + * + * Return: None + */ +static +void wma_send_invoke_neighbor_report(WMA_HANDLE handle, + struct wmi_invoke_neighbor_report_params *params) +{ + QDF_STATUS status; + tp_wma_handle wma_handle = (tp_wma_handle) handle; + + if (!wma_handle || !wma_handle->wmi_handle) { + WMA_LOGE("WMA is closed, cannot send invoke neighbor report"); + return; + } + + status = wmi_unified_invoke_neighbor_report_cmd(wma_handle->wmi_handle, + params); + + if (status != QDF_STATUS_SUCCESS) + WMA_LOGE("failed to send invoke neighbor report command"); +} + QDF_STATUS wma_set_rx_reorder_timeout_val(tp_wma_handle wma_handle, struct sir_set_rx_reorder_timeout_val *reorder_timeout) { @@ -8413,6 +8470,14 @@ static QDF_STATUS wma_mc_process_msg(struct scheduler_msg *msg) wma_send_obss_detection_cfg(wma_handle, msg->bodyptr); qdf_mem_free(msg->bodyptr); break; + case WMA_SET_11K_OFFLOAD: + wma_send_offload_11k_params(wma_handle, msg->bodyptr); + qdf_mem_free(msg->bodyptr); + break; + case WMA_INVOKE_NEIGHBOR_REPORT: + wma_send_invoke_neighbor_report(wma_handle, msg->bodyptr); + qdf_mem_free(msg->bodyptr); + break; default: WMA_LOGE("Unhandled WMA message of type %d", msg->type); if (msg->bodyptr)