diff --git a/components/action_oui/dispatcher/inc/wlan_action_oui_public_struct.h b/components/action_oui/dispatcher/inc/wlan_action_oui_public_struct.h index b7c5c063ed..586b45f4c9 100644 --- a/components/action_oui/dispatcher/inc/wlan_action_oui_public_struct.h +++ b/components/action_oui/dispatcher/inc/wlan_action_oui_public_struct.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -90,6 +90,10 @@ * @ACTION_OUI_DISABLE_AGGRESSIVE_TX: disable aggressive TX in firmware * @ACTION_OUI_FORCE_MAX_NSS: Force Max NSS connection with few IOT APs * @ACTION_OUI_DISABLE_AGGRESSIVE_EDCA: disable aggressive EDCA with the ap + * @ACTION_OUI_HOST_ONLY: host only action id start - placeholder. + * New Firmware related "ACTION" needs to be added before this placeholder. + * @ACTION_OUI_HOST_RECONN: reconnect to the same BSSID when wait for + * association response timeout from AP * @ACTION_OUI_MAXIMUM_ID: maximum number of action oui types */ enum action_oui_id { @@ -102,6 +106,8 @@ enum action_oui_id { ACTION_OUI_DISABLE_AGGRESSIVE_TX = 6, ACTION_OUI_FORCE_MAX_NSS = 7, ACTION_OUI_DISABLE_AGGRESSIVE_EDCA = 8, + ACTION_OUI_HOST_ONLY, + ACTION_OUI_HOST_RECONN = ACTION_OUI_HOST_ONLY, ACTION_OUI_MAXIMUM_ID }; diff --git a/components/action_oui/dispatcher/src/wlan_action_oui_ucfg_api.c b/components/action_oui/dispatcher/src/wlan_action_oui_ucfg_api.c index 4346a4fa6b..76782add6f 100644 --- a/components/action_oui/dispatcher/src/wlan_action_oui_ucfg_api.c +++ b/components/action_oui/dispatcher/src/wlan_action_oui_ucfg_api.c @@ -153,6 +153,8 @@ QDF_STATUS ucfg_action_oui_send(struct wlan_objmgr_psoc *psoc) } for (id = 0; id < ACTION_OUI_MAXIMUM_ID; id++) { + if (id >= ACTION_OUI_HOST_ONLY) + continue; status = action_oui_send(psoc_priv, id); if (!QDF_IS_STATUS_SUCCESS(status)) action_oui_err("Failed to send: %u", id); diff --git a/components/mlme/core/inc/wlan_mlme_main.h b/components/mlme/core/inc/wlan_mlme_main.h index c3817f5c2c..8e51a1a25a 100644 --- a/components/mlme/core/inc/wlan_mlme_main.h +++ b/components/mlme/core/inc/wlan_mlme_main.h @@ -137,6 +137,7 @@ struct wlan_mlme_roam { * @connection_fail: flag to indicate connection failed * @cac_required_for_new_channel: if CAC is required for new channel * @follow_ap_edca: if true, it is forced to follow the AP's edca. + * @reconn_after_assoc_timeout: reconnect to the same AP if association timeout * @assoc_type: vdev associate/reassociate type * @dynamic_cfg: current configuration of nss, chains for vdev. * @ini_cfg: Max configuration of nss, chains supported for vdev. @@ -154,6 +155,7 @@ struct mlme_legacy_priv { bool connection_fail; bool cac_required_for_new_channel; bool follow_ap_edca; + bool reconn_after_assoc_timeout; enum vdev_assoc_type assoc_type; struct wlan_mlme_nss_chains dynamic_cfg; struct wlan_mlme_nss_chains ini_cfg; @@ -339,6 +341,29 @@ void mlme_set_follow_ap_edca_flag(struct wlan_objmgr_vdev *vdev, bool flag); */ bool mlme_get_follow_ap_edca_flag(struct wlan_objmgr_vdev *vdev); +/** + * mlme_set_reconn_after_assoc_timeout_flag() - Set reconn after assoc timeout + * flag + * @psoc: soc object + * @vdev_id: vdev id + * @flag: enable or disable reconnect + * + * Return: void + */ +void mlme_set_reconn_after_assoc_timeout_flag(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, bool flag); + +/** + * mlme_get_reconn_after_assoc_timeout_flag() - Get reconn after assoc timeout + * flag + * @psoc: soc object + * @vdev_id: vdev id + * + * Return: true for enabling reconnect, otherwise false + */ +bool mlme_get_reconn_after_assoc_timeout_flag(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id); + /** * mlme_get_peer_disconnect_ies() - Get diconnect IEs from vdev object * @vdev: vdev pointer diff --git a/components/mlme/core/src/wlan_mlme_main.c b/components/mlme/core/src/wlan_mlme_main.c index 74b22d2c60..cfb07fae5e 100644 --- a/components/mlme/core/src/wlan_mlme_main.c +++ b/components/mlme/core/src/wlan_mlme_main.c @@ -2582,6 +2582,57 @@ bool mlme_get_follow_ap_edca_flag(struct wlan_objmgr_vdev *vdev) return mlme_priv->follow_ap_edca; } +void mlme_set_reconn_after_assoc_timeout_flag(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, bool flag) +{ + struct wlan_objmgr_vdev *vdev; + struct mlme_legacy_priv *mlme_priv; + + if (!psoc) + return; + + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, + WLAN_LEGACY_MAC_ID); + if (!vdev) + return; + mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); + if (!mlme_priv) { + mlme_legacy_err("vdev legacy private object is NULL"); + wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID); + return; + } + + mlme_priv->reconn_after_assoc_timeout = flag; + wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID); +} + +bool mlme_get_reconn_after_assoc_timeout_flag(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id) +{ + struct wlan_objmgr_vdev *vdev; + struct mlme_legacy_priv *mlme_priv; + bool reconn_after_assoc_timeout; + + if (!psoc) + return false; + + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, + WLAN_LEGACY_MAC_ID); + if (!vdev) + return false; + mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); + if (!mlme_priv) { + mlme_legacy_err("vdev legacy private object is NULL"); + wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID); + return false; + } + + reconn_after_assoc_timeout = mlme_priv->reconn_after_assoc_timeout; + wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID); + + return reconn_after_assoc_timeout; +} + void mlme_set_peer_pmf_status(struct wlan_objmgr_peer *peer, bool is_pmf_enabled) { diff --git a/core/hdd/inc/hdd_config.h b/core/hdd/inc/hdd_config.h index acb902394a..c399d68970 100644 --- a/core/hdd/inc/hdd_config.h +++ b/core/hdd/inc/hdd_config.h @@ -1224,6 +1224,39 @@ struct dhcp_server { "", \ "Used to specify action OUIs to control edca configuration") +/* + * + * gActionOUIReconnAssocTimeout - Used to specify action OUIs to + * reconnect to same BSSID when wait for association response timeout + * + * This ini is used to specify AP OUIs. Some of AP doesn't response our + * first association request, but it would response our second association + * request. Add such OUI configuration INI to apply reconnect logic when + * association timeout happends with such AP. + * For default: + * gActionOUIReconnAssocTimeout=00E04C 00 01 + * Explain: 00E04C: OUI + * 00: data length is 0 + * 01: info mask, only OUI present in Info mask + * Note: User should strictly add new action OUIs at the end of this + * default value. + * Refer to gEnableActionOUI for more detail about the format. + * + * Related: gEnableActionOUI + * + * Supported Feature: Action OUIs + * + * Usage: External + * + * + */ +#define CFG_ACTION_OUI_RECONN_ASSOCTIMEOUT CFG_INI_STRING( \ + "gActionOUIReconnAssocTimeout", \ + 0, \ + ACTION_OUI_MAX_STR_LEN, \ + "00E04C 00 01", \ + "Used to specify action OUIs to reconnect when assoc timeout") + /* End of action oui inis */ #ifdef ENABLE_MTRACE_LOG @@ -1552,6 +1585,7 @@ enum host_log_level { CFG(CFG_ACTION_OUI_FORCE_MAX_NSS) \ CFG(CFG_ACTION_OUI_DISABLE_AGGRESSIVE_EDCA) \ CFG(CFG_ACTION_OUI_SWITCH_TO_11N_MODE) \ + CFG(CFG_ACTION_OUI_RECONN_ASSOCTIMEOUT) \ CFG(CFG_ADVERTISE_CONCURRENT_OPERATION) \ CFG(CFG_BUG_ON_REINIT_FAILURE) \ CFG(CFG_DBS_SCAN_SELECTION) \ diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 2d9cd39976..e88508f091 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -10843,6 +10843,10 @@ static void hdd_cfg_params_init(struct hdd_context *hdd_ctx) cfg_get(psoc, CFG_ACTION_OUI_DISABLE_AGGRESSIVE_EDCA), ACTION_OUI_MAX_STR_LEN); + qdf_str_lcopy(config->action_oui_str[ACTION_OUI_HOST_RECONN], + cfg_get(psoc, CFG_ACTION_OUI_RECONN_ASSOCTIMEOUT), + ACTION_OUI_MAX_STR_LEN); + config->is_unit_test_framework_enabled = cfg_get(psoc, CFG_ENABLE_UNIT_TEST_FRAMEWORK); config->disable_channel = cfg_get(psoc, CFG_ENABLE_DISABLE_CHANNEL); diff --git a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c index 995276c7b4..579b95e486 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c @@ -1841,13 +1841,22 @@ void lim_process_assoc_failure_timeout(struct mac_context *mac_ctx, * when device has missed the assoc resp sent by peer. * By sending deauth try to clear the session created on peer device. */ - pe_debug("Sessionid: %d try sending deauth on channel freq %d to BSSID: " - QDF_MAC_ADDR_STR, session->peSessionId, - session->curr_op_freq, - QDF_MAC_ADDR_ARRAY(session->bssId)); - lim_send_deauth_mgmt_frame(mac_ctx, eSIR_MAC_UNSPEC_FAILURE_REASON, - session->bssId, session, false); - + if (msg_type == LIM_ASSOC && + mlme_get_reconn_after_assoc_timeout_flag(mac_ctx->psoc, + session->vdev_id)) { + pe_debug("vdev: %d skip sending deauth on channel freq %d to BSSID: " + QDF_MAC_ADDR_STR, session->vdev_id, + session->curr_op_freq, + QDF_MAC_ADDR_ARRAY(session->bssId)); + } else { + pe_debug("vdev: %d try sending deauth on channel freq %d to BSSID: " + QDF_MAC_ADDR_STR, session->vdev_id, + session->curr_op_freq, + QDF_MAC_ADDR_ARRAY(session->bssId)); + lim_send_deauth_mgmt_frame(mac_ctx, + eSIR_MAC_UNSPEC_FAILURE_REASON, + session->bssId, session, false); + } if ((LIM_IS_AP_ROLE(session)) || ((session->limMlmState != eLIM_MLM_WT_ASSOC_RSP_STATE) && (session->limMlmState != eLIM_MLM_WT_REASSOC_RSP_STATE) && diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 79bb558292..5b125d7bba 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -9481,6 +9481,7 @@ static void csr_roam_join_rsp_processor(struct mac_context *mac, uint32_t len = 0, roamId = 0, reason_code = 0; bool is_dis_pending; bool use_same_bss = false; + bool retry_same_bss = false; if (!pSmeJoinRsp) { sme_err("Sme Join Response is NULL"); @@ -9573,7 +9574,6 @@ static void csr_roam_join_rsp_processor(struct mac_context *mac, * AP. */ if (reason_code == eSIR_MAC_INVALID_PMKID) { - struct tag_csrscan_result *scan_result; pmksa = qdf_mem_malloc(sizeof(*pmksa)); if (!pmksa) return; @@ -9586,16 +9586,26 @@ static void csr_roam_join_rsp_processor(struct mac_context *mac, sme_roam_del_pmkid_from_cache(mac_handle, session_ptr->vdev_id, pmksa, false); qdf_mem_free(pmksa); - if (pCommand && pCommand->u.roamCmd.pRoamBssEntry) { - scan_result = - GET_BASE_ADDR(pCommand->u.roamCmd.pRoamBssEntry, - struct tag_csrscan_result, Link); - /* Retry with same BSSID without PMKID */ - if (!scan_result->retry_count) { - sme_info("Retry once again with same BSSID without PMKID"); - scan_result->retry_count = 1; - use_same_bss = true; - } + retry_same_bss = true; + } + if (pSmeJoinRsp->messageType == eWNI_SME_JOIN_RSP && + pSmeJoinRsp->status_code == eSIR_SME_ASSOC_TIMEOUT_RESULT_CODE && + mlme_get_reconn_after_assoc_timeout_flag(mac->psoc, + pSmeJoinRsp->vdev_id)) + retry_same_bss = true; + + if (retry_same_bss && pCommand && pCommand->u.roamCmd.pRoamBssEntry) { + struct tag_csrscan_result *scan_result; + + scan_result = + GET_BASE_ADDR(pCommand->u.roamCmd.pRoamBssEntry, + struct tag_csrscan_result, Link); + /* Retry with same BSSID without PMKID */ + if (!scan_result->retry_count) { + sme_info("Retry once with same BSSID, status %d reason %d", + pSmeJoinRsp->status_code, reason_code); + scan_result->retry_count = 1; + use_same_bss = true; } } @@ -15426,6 +15436,7 @@ QDF_STATUS csr_send_join_req_msg(struct mac_context *mac, uint32_t sessionId, uint8_t ap_nss; struct wlan_objmgr_vdev *vdev; bool follow_ap_edca; + bool reconn_after_assoc_timeout = false; if (!pSession) { sme_err("session %d not found", sessionId); @@ -15607,6 +15618,14 @@ QDF_STATUS csr_send_join_req_msg(struct mac_context *mac, uint32_t sessionId, &vendor_ap_search_attr, ACTION_OUI_DISABLE_AGGRESSIVE_EDCA); + if (messageType == eWNI_SME_JOIN_REQ && + ucfg_action_oui_search(mac->psoc, &vendor_ap_search_attr, + ACTION_OUI_HOST_RECONN)) + reconn_after_assoc_timeout = true; + mlme_set_reconn_after_assoc_timeout_flag( + mac->psoc, sessionId, + reconn_after_assoc_timeout); + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac->psoc, sessionId, WLAN_LEGACY_MAC_ID);