diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index 92044f91b43c..e1e336ae2b55 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -13983,6 +13983,45 @@ enum hdd_external_acs_freq_band { #define CFG_RX_CHAIN_MASK_5G_MAX (3) #define CFG_RX_CHAIN_MASK_5G_DEFAULT (0) +/* + * + * btm_offload_config - Configure BTM + * @Min: 0x00000000 + * @Max: 0xFFFFFFFF + * @Default: 0x00000000 + * + * This ini is used to configure BTM + * + * Bit 0: Enable/Disable the BTM offload. Set this to 1 will + * enable and 0 will disable BTM offload. + * + * BIT 2, 1: Action on non matching candidate with cache. If a BTM request + * is received from AP then the candidate AP's may/may-not be present in + * the firmware scan cache . Based on below config firmware will decide + * whether to forward BTM frame to host or consume with firmware and proceed + * with Roaming to candidate AP. + * 00 scan and consume + * 01 no scan and forward to host + * 10, 11 reserved + * + * BIT 5, 4, 3: Roaming handoff decisions on multiple candidates match + * 000 match if exact BSSIDs are found + * 001 match if at least one top priority BSSID only + * 010, 011, 100, 101, 110, 111 reserved + * + * BIT 6-31: Reserved + * + * Supported Feature: STA + * + * Usage: External + * + * + */ +#define CFG_BTM_ENABLE_NAME "btm_offload_config" +#define CFG_BTM_ENABLE_MIN (0x00000000) +#define CFG_BTM_ENABLE_MAX (0xffffffff) +#define CFG_BTM_ENABLE_DEFAULT (0x00000001) + /* * Type declarations */ @@ -14876,6 +14915,7 @@ struct hdd_config { uint8_t rx_chain_mask_2g; uint8_t tx_chain_mask_5g; uint8_t rx_chain_mask_5g; + uint32_t btm_offload_config; }; #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 79de8445cefc..d906f323e6e1 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -5409,6 +5409,13 @@ struct reg_table_entry g_registry_table[] = { CFG_RX_CHAIN_MASK_5G_DEFAULT, CFG_RX_CHAIN_MASK_5G_MIN, CFG_RX_CHAIN_MASK_5G_MAX), + + REG_VARIABLE(CFG_BTM_ENABLE_NAME, WLAN_PARAM_HexInteger, + struct hdd_config, btm_offload_config, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BTM_ENABLE_DEFAULT, + CFG_BTM_ENABLE_MIN, + CFG_BTM_ENABLE_MAX), }; @@ -7238,6 +7245,8 @@ void hdd_cfg_print(struct hdd_context *hdd_ctx) hdd_debug("Name = [%s] Value = [%u]", CFG_ENABLE_PHY_REG, hdd_ctx->config->enable_phy_reg_retention); + hdd_debug("Name = [btm_offload_config] value = [0x%x]", + hdd_ctx->config->btm_offload_config); } @@ -9062,6 +9071,8 @@ QDF_STATUS hdd_set_sme_config(struct hdd_context *hdd_ctx) (pConfig->rssi_assoc_reject_enabled * WMI_VDEV_OCE_REASSOC_REJECT_FEATURE_BITMAP); smeConfig->csrConfig.oce_feature_bitmap = val; + smeConfig->csrConfig.btm_offload_config = + hdd_ctx->config->btm_offload_config; smeConfig->csrConfig.mbo_thresholds.mbo_candidate_rssi_thres = hdd_ctx->config->mbo_candidate_rssi_thres; diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 9ef879ebaf9e..35f5759a6de6 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -3271,6 +3271,7 @@ typedef struct sSirRoamOffloadScanReq { bool is_fils_connection; struct roam_fils_params roam_fils_params; #endif + uint32_t btm_offload_config; } tSirRoamOffloadScanReq, *tpSirRoamOffloadScanReq; typedef struct sSirRoamOffloadScanRsp { diff --git a/core/mac/src/pe/lim/lim_link_monitoring_algo.c b/core/mac/src/pe/lim/lim_link_monitoring_algo.c index f7a5dd64bf2e..929a00cfa12e 100644 --- a/core/mac/src/pe/lim/lim_link_monitoring_algo.c +++ b/core/mac/src/pe/lim/lim_link_monitoring_algo.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -265,6 +265,22 @@ void lim_delete_sta_context(tpAniSirGlobal mac_ctx, msg->addr2, session_entry, false); break; + case HAL_DEL_STA_REASON_CODE_BTM_DISASSOC_IMMINENT: + if (session_entry->limMlmState != + eLIM_MLM_LINK_ESTABLISHED_STATE) { + pe_err("BTM request received in state %s", + lim_mlm_state_str(session_entry->limMlmState)); + qdf_mem_free(msg); + lim_msg->bodyptr = NULL; + return; + } + lim_send_deauth_mgmt_frame(mac_ctx, + eSIR_MAC_DISASSOC_DUE_TO_INACTIVITY_REASON, + session_entry->bssId, session_entry, false); + lim_tear_down_link_with_ap(mac_ctx, session_entry->peSessionId, + eSIR_MAC_UNSPEC_FAILURE_REASON); + break; + default: pe_err("Unknown reason code"); break; diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h index 99a96b831c8f..a312d7f794c5 100644 --- a/core/sme/inc/csr_api.h +++ b/core/sme/inc/csr_api.h @@ -1369,6 +1369,7 @@ typedef struct tagCsrConfigParam { struct sir_score_config bss_score_params; uint8_t oce_feature_bitmap; struct csr_mbo_thresholds mbo_thresholds; + uint32_t btm_offload_config; } tCsrConfigParam; /* Tush */ diff --git a/core/sme/inc/csr_internal.h b/core/sme/inc/csr_internal.h index 4f720a5e5860..41fa8f2bb765 100644 --- a/core/sme/inc/csr_internal.h +++ b/core/sme/inc/csr_internal.h @@ -637,6 +637,7 @@ struct csr_config { struct sir_score_config bss_score_params; uint8_t oce_feature_bitmap; struct csr_mbo_thresholds mbo_thresholds; + uint32_t btm_offload_config; }; struct csr_channel_powerinfo { diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index b5ced7474cad..41050407b15d 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -2996,6 +2996,8 @@ QDF_STATUS csr_change_default_config_param(tpAniSirGlobal pMac, qdf_mem_copy(&pMac->roam.configParam.bss_score_params, &pParam->bss_score_params, sizeof(struct sir_score_config)); + pMac->roam.configParam.btm_offload_config = + pParam->btm_offload_config; csr_update_he_config_param(pMac, pParam); } @@ -3265,6 +3267,7 @@ QDF_STATUS csr_get_config_param(tpAniSirGlobal pMac, tCsrConfigParam *pParam) qdf_mem_copy(&pParam->bss_score_params, &pMac->roam.configParam.bss_score_params, sizeof(struct sir_score_config)); + pParam->btm_offload_config = pMac->roam.configParam.btm_offload_config; pParam->mbo_thresholds.mbo_candidate_rssi_thres = pMac->roam.configParam.mbo_thresholds. @@ -18069,6 +18072,8 @@ csr_create_roam_scan_offload_request(tpAniSirGlobal mac_ctx, mac_ctx->roam.configParam.rssi_channel_penalization; req_buf->lca_config_params.num_disallowed_aps = mac_ctx->roam.configParam.num_disallowed_aps; + req_buf->btm_offload_config = + mac_ctx->roam.configParam.btm_offload_config; #ifdef WLAN_FEATURE_ROAM_OFFLOAD QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, diff --git a/core/wma/inc/wma_if.h b/core/wma/inc/wma_if.h index e74afd79d94e..7849b0a97379 100644 --- a/core/wma/inc/wma_if.h +++ b/core/wma/inc/wma_if.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -599,7 +599,8 @@ typedef enum eDelStaReasonCode { HAL_DEL_STA_REASON_CODE_KEEP_ALIVE = 0x1, HAL_DEL_STA_REASON_CODE_TIM_BASED = 0x2, HAL_DEL_STA_REASON_CODE_RA_BASED = 0x3, - HAL_DEL_STA_REASON_CODE_UNKNOWN_A2 = 0x4 + HAL_DEL_STA_REASON_CODE_UNKNOWN_A2 = 0x4, + HAL_DEL_STA_REASON_CODE_BTM_DISASSOC_IMMINENT = 0x5 } tDelStaReasonCode; typedef enum eSmpsModeValue { diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c index 863696720b5d..5040eacec18b 100644 --- a/core/wma/src/wma_scan_roam.c +++ b/core/wma/src/wma_scan_roam.c @@ -1851,6 +1851,35 @@ QDF_STATUS wma_roam_scan_offload_command(tp_wma_handle wma_handle, command, vdev_id); } +/** + * wma_roam_scan_btm_offload() - Send BTM offload config + * @wma_handle: wma handle + * @roam_req: roam request parameters + * + * This function is used to send BTM offload config to fw + * + * Return: QDF status + */ +static QDF_STATUS wma_roam_scan_btm_offload(tp_wma_handle wma_handle, + tSirRoamOffloadScanReq *roam_req) +{ + struct wmi_btm_config *params; + QDF_STATUS status; + + params = qdf_mem_malloc(sizeof(struct wmi_btm_config)); + if (!params) { + WMA_LOGE("Memory alloc failed for btm params"); + return QDF_STATUS_E_FAILURE; + } + + params->vdev_id = roam_req->sessionId; + params->btm_offload_config = roam_req->btm_offload_config; + status = wmi_unified_send_btm_config(wma_handle->wmi_handle, params); + qdf_mem_free(params); + + return status; +} + /** * wma_process_roaming_config() - process roam request * @wma_handle: wma handle @@ -1989,6 +2018,11 @@ QDF_STATUS wma_process_roaming_config(tp_wma_handle wma_handle, WMA_LOGE("Sending start for roam scan filter failed"); break; } + qdf_status = wma_roam_scan_btm_offload(wma_handle, roam_req); + if (qdf_status != QDF_STATUS_SUCCESS) { + WMA_LOGE("Sending BTM config to fw failed"); + break; + } break; case ROAM_SCAN_OFFLOAD_STOP: @@ -5982,6 +6016,31 @@ void wma_roam_better_ap_handler(tp_wma_handle wma, uint32_t vdev_id) } } +/** + * wma_handle_btm_disassoc_imminent_msg() - Send del sta msg to lim on receiving + * BTM request from AP with disassoc imminent reason + * @wma_handle: wma handle + * @vdev_id: vdev id + * + * Return: None + */ +static void wma_handle_btm_disassoc_imminent_msg(tp_wma_handle wma_handle, + uint32_t vdev_id) +{ + tpDeleteStaContext del_sta_ctx; + + del_sta_ctx = + (tDeleteStaContext *)qdf_mem_malloc(sizeof(tDeleteStaContext)); + if (!del_sta_ctx) { + WMA_LOGE("Memory alloc failed for del sta context"); + return; + } + del_sta_ctx->vdev_id = vdev_id; + del_sta_ctx->reasonCode = HAL_DEL_STA_REASON_CODE_BTM_DISASSOC_IMMINENT; + wma_send_msg(wma_handle, SIR_LIM_DELETE_STA_CONTEXT_IND, + (void *)del_sta_ctx, 0); +} + /** * wma_roam_event_callback() - roam event callback * @handle: wma handle @@ -6027,6 +6086,18 @@ int wma_roam_event_callback(WMA_HANDLE handle, uint8_t *event_buf, QDF_PROTO_TYPE_EVENT, QDF_ROAM_EVENTID)); switch (wmi_event->reason) { + case WMI_ROAM_REASON_BTM: + /* + * This event is received from firmware if firmware is unable to + * find candidate AP after roam scan and BTM request from AP + * has disassoc imminent bit set. + */ + WMA_LOGD("Kickout due to btm request"); + wma_sta_kickout_event(HOST_STA_KICKOUT_REASON_BTM, + wmi_event->vdev_id, NULL); + wma_handle_btm_disassoc_imminent_msg(wma_handle, + wmi_event->vdev_id); + break; case WMI_ROAM_REASON_BMISS: WMA_LOGD("Beacon Miss for vdevid %x", wmi_event->vdev_id); wma_beacon_miss_handler(wma_handle, wmi_event->vdev_id,